mirror of
https://git.proxmox.com/git/mirror_zfs.git
synced 2024-12-26 11:19:32 +03:00
splat: Fix log buffer locking
The Fedora 3.6 debug kernel identified the following issue where we call copy_to_user() under a spin lock(). This used to be safe in older kernels but no longer appears to be true so the spin lock was changed to a mutex. None of this code is performance critical so allowing the process to sleep is harmless. Signed-off-by: Brian Behlendorf <behlendorf1@llnl.gov>
This commit is contained in:
parent
df870a697f
commit
0e149d4204
@ -71,7 +71,7 @@ splat_open(struct inode *inode, struct file *file)
|
||||
if (info == NULL)
|
||||
return -ENOMEM;
|
||||
|
||||
spin_lock_init(&info->info_lock);
|
||||
mutex_init(&info->info_lock);
|
||||
info->info_size = SPLAT_INFO_BUFFER_SIZE;
|
||||
info->info_buffer = (char *)vmalloc(SPLAT_INFO_BUFFER_SIZE);
|
||||
if (info->info_buffer == NULL) {
|
||||
@ -100,6 +100,7 @@ splat_release(struct inode *inode, struct file *file)
|
||||
ASSERT(info);
|
||||
ASSERT(info->info_buffer);
|
||||
|
||||
mutex_destroy(&info->info_lock);
|
||||
vfree(info->info_buffer);
|
||||
kfree(info);
|
||||
|
||||
@ -114,10 +115,10 @@ splat_buffer_clear(struct file *file, splat_cfg_t *kcfg, unsigned long arg)
|
||||
ASSERT(info);
|
||||
ASSERT(info->info_buffer);
|
||||
|
||||
spin_lock(&info->info_lock);
|
||||
mutex_lock(&info->info_lock);
|
||||
memset(info->info_buffer, 0, info->info_size);
|
||||
info->info_head = info->info_buffer;
|
||||
spin_unlock(&info->info_lock);
|
||||
mutex_unlock(&info->info_lock);
|
||||
|
||||
return 0;
|
||||
}
|
||||
@ -132,7 +133,7 @@ splat_buffer_size(struct file *file, splat_cfg_t *kcfg, unsigned long arg)
|
||||
ASSERT(info);
|
||||
ASSERT(info->info_buffer);
|
||||
|
||||
spin_lock(&info->info_lock);
|
||||
mutex_lock(&info->info_lock);
|
||||
if (kcfg->cfg_arg1 > 0) {
|
||||
|
||||
size = kcfg->cfg_arg1;
|
||||
@ -157,7 +158,7 @@ splat_buffer_size(struct file *file, splat_cfg_t *kcfg, unsigned long arg)
|
||||
if (copy_to_user((struct splat_cfg_t __user *)arg, kcfg, sizeof(*kcfg)))
|
||||
rc = -EFAULT;
|
||||
out:
|
||||
spin_unlock(&info->info_lock);
|
||||
mutex_unlock(&info->info_lock);
|
||||
|
||||
return rc;
|
||||
}
|
||||
@ -508,7 +509,7 @@ static ssize_t splat_write(struct file *file, const char __user *buf,
|
||||
ASSERT(info);
|
||||
ASSERT(info->info_buffer);
|
||||
|
||||
spin_lock(&info->info_lock);
|
||||
mutex_lock(&info->info_lock);
|
||||
|
||||
/* Write beyond EOF */
|
||||
if (*ppos >= info->info_size) {
|
||||
@ -528,7 +529,7 @@ static ssize_t splat_write(struct file *file, const char __user *buf,
|
||||
*ppos += count;
|
||||
rc = count;
|
||||
out:
|
||||
spin_unlock(&info->info_lock);
|
||||
mutex_unlock(&info->info_lock);
|
||||
return rc;
|
||||
}
|
||||
|
||||
@ -545,7 +546,7 @@ static ssize_t splat_read(struct file *file, char __user *buf,
|
||||
ASSERT(info);
|
||||
ASSERT(info->info_buffer);
|
||||
|
||||
spin_lock(&info->info_lock);
|
||||
mutex_lock(&info->info_lock);
|
||||
|
||||
/* Read beyond EOF */
|
||||
if (*ppos >= info->info_size)
|
||||
@ -563,7 +564,7 @@ static ssize_t splat_read(struct file *file, char __user *buf,
|
||||
*ppos += count;
|
||||
rc = count;
|
||||
out:
|
||||
spin_unlock(&info->info_lock);
|
||||
mutex_unlock(&info->info_lock);
|
||||
return rc;
|
||||
}
|
||||
|
||||
@ -579,7 +580,7 @@ static loff_t splat_seek(struct file *file, loff_t offset, int origin)
|
||||
ASSERT(info);
|
||||
ASSERT(info->info_buffer);
|
||||
|
||||
spin_lock(&info->info_lock);
|
||||
mutex_lock(&info->info_lock);
|
||||
|
||||
switch (origin) {
|
||||
case 0: /* SEEK_SET - No-op just do it */
|
||||
@ -598,7 +599,7 @@ static loff_t splat_seek(struct file *file, loff_t offset, int origin)
|
||||
rc = offset;
|
||||
}
|
||||
|
||||
spin_unlock(&info->info_lock);
|
||||
mutex_unlock(&info->info_lock);
|
||||
|
||||
return rc;
|
||||
}
|
||||
|
@ -121,7 +121,7 @@ typedef struct splat_subsystem {
|
||||
#define SPLAT_INFO_BUFFER_REDZONE 256
|
||||
|
||||
typedef struct splat_info {
|
||||
spinlock_t info_lock;
|
||||
struct mutex info_lock;
|
||||
int info_size;
|
||||
char *info_buffer;
|
||||
char *info_head; /* Internal kernel use only */
|
||||
@ -136,7 +136,7 @@ typedef struct splat_info {
|
||||
ASSERT(_info_); \
|
||||
ASSERT(_info_->info_buffer); \
|
||||
\
|
||||
spin_lock(&_info_->info_lock); \
|
||||
mutex_lock(&_info_->info_lock); \
|
||||
\
|
||||
/* Don't allow the kernel to start a write in the red zone */ \
|
||||
if ((int)(_info_->info_head - _info_->info_buffer) > \
|
||||
@ -148,7 +148,7 @@ typedef struct splat_info {
|
||||
_info_->info_head += _rc_; \
|
||||
} \
|
||||
\
|
||||
spin_unlock(&_info_->info_lock); \
|
||||
mutex_unlock(&_info_->info_lock); \
|
||||
_rc_; \
|
||||
})
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user