]> granicus.if.org Git - spl/commitdiff
splat: Fix log buffer locking
authorBrian Behlendorf <behlendorf1@llnl.gov>
Fri, 2 Nov 2012 22:31:04 +0000 (15:31 -0700)
committerBrian Behlendorf <behlendorf1@llnl.gov>
Tue, 6 Nov 2012 22:48:56 +0000 (14:48 -0800)
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>
module/splat/splat-ctl.c
module/splat/splat-internal.h

index 53bf51dd629c57af9db66896a81436753d1ae833..c68281a84733024dcce35749ba537db84db49183 100644 (file)
@@ -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;
 }
index b15db65e2fe072e6721f250a2829f1227666dd6d..14303a1057de151e76a63993e2cbfb36c5badb03 100644 (file)
@@ -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_;                                                           \
 })