Coda: replace BKL with mutex
Yoshihisa Abe [Mon, 25 Oct 2010 06:03:46 +0000 (02:03 -0400)]
Replace the BKL with a mutex to protect the venus_comm structure which
binds the mountpoint with the character device and holds the upcall
queues.

Signed-off-by: Yoshihisa Abe <yoshiabe@cs.cmu.edu>
Signed-off-by: Jan Harkes <jaharkes@cs.cmu.edu>
Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>

fs/coda/inode.c
fs/coda/psdev.c
fs/coda/upcall.c
include/linux/coda_psdev.h

index b7fa3e3..7993b96 100644 (file)
@@ -15,7 +15,7 @@
 #include <linux/stat.h>
 #include <linux/errno.h>
 #include <linux/unistd.h>
-#include <linux/smp_lock.h>
+#include <linux/mutex.h>
 #include <linux/spinlock.h>
 #include <linux/file.h>
 #include <linux/vfs.h>
@@ -145,7 +145,7 @@ static int get_device_index(struct coda_mount_data *data)
 static int coda_fill_super(struct super_block *sb, void *data, int silent)
 {
        struct inode *root = NULL;
-       struct venus_comm *vc = NULL;
+       struct venus_comm *vc;
        struct CodaFid fid;
        int error;
        int idx;
@@ -159,7 +159,7 @@ static int coda_fill_super(struct super_block *sb, void *data, int silent)
        printk(KERN_INFO "coda_read_super: device index: %i\n", idx);
 
        vc = &coda_comms[idx];
-       lock_kernel();
+       mutex_lock(&vc->vc_mutex);
 
        if (!vc->vc_inuse) {
                printk("coda_read_super: No pseudo device\n");
@@ -178,7 +178,7 @@ static int coda_fill_super(struct super_block *sb, void *data, int silent)
                goto unlock_out;
 
        vc->vc_sb = sb;
-       unlock_kernel();
+       mutex_unlock(&vc->vc_mutex);
 
        sb->s_fs_info = vc;
        sb->s_flags |= MS_NOATIME;
@@ -217,20 +217,23 @@ error:
        if (root)
                iput(root);
 
-       lock_kernel();
+       mutex_lock(&vc->vc_mutex);
        bdi_destroy(&vc->bdi);
        vc->vc_sb = NULL;
        sb->s_fs_info = NULL;
 unlock_out:
-       unlock_kernel();
+       mutex_unlock(&vc->vc_mutex);
        return error;
 }
 
 static void coda_put_super(struct super_block *sb)
 {
-       bdi_destroy(&coda_vcp(sb)->bdi);
-       coda_vcp(sb)->vc_sb = NULL;
+       struct venus_comm *vcp = coda_vcp(sb);
+       mutex_lock(&vcp->vc_mutex);
+       bdi_destroy(&vcp->bdi);
+       vcp->vc_sb = NULL;
        sb->s_fs_info = NULL;
+       mutex_unlock(&vcp->vc_mutex);
 
        printk("Coda: Bye bye.\n");
 }
index 9a9248e..62647a8 100644 (file)
@@ -35,7 +35,7 @@
 #include <linux/poll.h>
 #include <linux/init.h>
 #include <linux/list.h>
-#include <linux/smp_lock.h>
+#include <linux/mutex.h>
 #include <linux/device.h>
 #include <asm/io.h>
 #include <asm/system.h>
@@ -67,8 +67,10 @@ static unsigned int coda_psdev_poll(struct file *file, poll_table * wait)
        unsigned int mask = POLLOUT | POLLWRNORM;
 
        poll_wait(file, &vcp->vc_waitq, wait);
+       mutex_lock(&vcp->vc_mutex);
        if (!list_empty(&vcp->vc_pending))
                 mask |= POLLIN | POLLRDNORM;
+       mutex_unlock(&vcp->vc_mutex);
 
        return mask;
 }
@@ -143,7 +145,7 @@ static ssize_t coda_psdev_write(struct file *file, const char __user *buf,
        }
         
        /* Look for the message on the processing queue. */
-       lock_kernel();
+       mutex_lock(&vcp->vc_mutex);
        list_for_each(lh, &vcp->vc_processing) {
                tmp = list_entry(lh, struct upc_req , uc_chain);
                if (tmp->uc_unique == hdr.unique) {
@@ -152,7 +154,7 @@ static ssize_t coda_psdev_write(struct file *file, const char __user *buf,
                        break;
                }
        }
-       unlock_kernel();
+       mutex_unlock(&vcp->vc_mutex);
 
        if (!req) {
                printk("psdev_write: msg (%d, %d) not found\n", 
@@ -207,7 +209,7 @@ static ssize_t coda_psdev_read(struct file * file, char __user * buf,
        if (nbytes == 0)
                return 0;
 
-       lock_kernel();
+       mutex_lock(&vcp->vc_mutex);
 
        add_wait_queue(&vcp->vc_waitq, &wait);
        set_current_state(TASK_INTERRUPTIBLE);
@@ -221,7 +223,9 @@ static ssize_t coda_psdev_read(struct file * file, char __user * buf,
                        retval = -ERESTARTSYS;
                        break;
                }
+               mutex_unlock(&vcp->vc_mutex);
                schedule();
+               mutex_lock(&vcp->vc_mutex);
        }
 
        set_current_state(TASK_RUNNING);
@@ -254,7 +258,7 @@ static ssize_t coda_psdev_read(struct file * file, char __user * buf,
        CODA_FREE(req->uc_data, sizeof(struct coda_in_hdr));
        kfree(req);
 out:
-       unlock_kernel();
+       mutex_unlock(&vcp->vc_mutex);
        return (count ? count : retval);
 }
 
@@ -267,10 +271,10 @@ static int coda_psdev_open(struct inode * inode, struct file * file)
        if (idx < 0 || idx >= MAX_CODADEVS)
                return -ENODEV;
 
-       lock_kernel();
-
        err = -EBUSY;
        vcp = &coda_comms[idx];
+       mutex_lock(&vcp->vc_mutex);
+
        if (!vcp->vc_inuse) {
                vcp->vc_inuse++;
 
@@ -284,7 +288,7 @@ static int coda_psdev_open(struct inode * inode, struct file * file)
                err = 0;
        }
 
-       unlock_kernel();
+       mutex_unlock(&vcp->vc_mutex);
        return err;
 }
 
@@ -299,7 +303,7 @@ static int coda_psdev_release(struct inode * inode, struct file * file)
                return -1;
        }
 
-       lock_kernel();
+       mutex_lock(&vcp->vc_mutex);
 
        /* Wakeup clients so they can return. */
        list_for_each_entry_safe(req, tmp, &vcp->vc_pending, uc_chain) {
@@ -324,7 +328,7 @@ static int coda_psdev_release(struct inode * inode, struct file * file)
 
        file->private_data = NULL;
        vcp->vc_inuse--;
-       unlock_kernel();
+       mutex_unlock(&vcp->vc_mutex);
        return 0;
 }
 
@@ -353,9 +357,11 @@ static int init_coda_psdev(void)
                err = PTR_ERR(coda_psdev_class);
                goto out_chrdev;
        }               
-       for (i = 0; i < MAX_CODADEVS; i++)
+       for (i = 0; i < MAX_CODADEVS; i++) {
+               mutex_init(&(&coda_comms[i])->vc_mutex);
                device_create(coda_psdev_class, NULL,
                              MKDEV(CODA_PSDEV_MAJOR, i), NULL, "cfs%d", i);
+       }
        coda_sysctl_init();
        goto out;
 
index 4c258cb..c3563ca 100644 (file)
@@ -27,7 +27,7 @@
 #include <linux/errno.h>
 #include <linux/string.h>
 #include <linux/slab.h>
-#include <linux/smp_lock.h>
+#include <linux/mutex.h>
 #include <asm/uaccess.h>
 #include <linux/vmalloc.h>
 #include <linux/vfs.h>
@@ -607,7 +607,8 @@ static void coda_unblock_signals(sigset_t *old)
                                 (r)->uc_opcode != CODA_RELEASE) || \
                                (r)->uc_flags & CODA_REQ_READ))
 
-static inline void coda_waitfor_upcall(struct upc_req *req)
+static inline void coda_waitfor_upcall(struct venus_comm *vcp,
+                                      struct upc_req *req)
 {
        DECLARE_WAITQUEUE(wait, current);
        unsigned long timeout = jiffies + coda_timeout * HZ;
@@ -640,10 +641,12 @@ static inline void coda_waitfor_upcall(struct upc_req *req)
                        break;
                }
 
+               mutex_unlock(&vcp->vc_mutex);
                if (blocked)
                        schedule_timeout(HZ);
                else
                        schedule();
+               mutex_lock(&vcp->vc_mutex);
        }
        if (blocked)
                coda_unblock_signals(&old);
@@ -671,7 +674,7 @@ static int coda_upcall(struct venus_comm *vcp,
        struct upc_req *req = NULL, *sig_req;
        int error;
 
-       lock_kernel();
+       mutex_lock(&vcp->vc_mutex);
 
        if (!vcp->vc_inuse) {
                printk(KERN_NOTICE "coda: Venus dead, not sending upcall\n");
@@ -711,7 +714,7 @@ static int coda_upcall(struct venus_comm *vcp,
         * ENODEV.  */
 
        /* Go to sleep.  Wake up on signals only after the timeout. */
-       coda_waitfor_upcall(req);
+       coda_waitfor_upcall(vcp, req);
 
        /* Op went through, interrupt or not... */
        if (req->uc_flags & CODA_REQ_WRITE) {
@@ -765,7 +768,7 @@ static int coda_upcall(struct venus_comm *vcp,
 
 exit:
        kfree(req);
-       unlock_kernel();
+       mutex_unlock(&vcp->vc_mutex);
        return error;
 }
 
@@ -806,11 +809,11 @@ exit:
 int coda_downcall(struct venus_comm *vcp, int opcode, union outputArgs *out)
 {
        struct inode *inode = NULL;
-       struct CodaFid *fid, *newfid;
+       struct CodaFid *fid = NULL, *newfid;
        struct super_block *sb;
 
        /* Handle invalidation requests. */
-       lock_kernel();
+       mutex_lock(&vcp->vc_mutex);
        sb = vcp->vc_sb;
        if (!sb || !sb->s_root)
                goto unlock_out;
@@ -829,47 +832,53 @@ int coda_downcall(struct venus_comm *vcp, int opcode, union outputArgs *out)
 
        case CODA_ZAPDIR:
                fid = &out->coda_zapdir.CodaFid;
-               inode = coda_fid_to_inode(fid, sb);
-               if (inode) {
-                       coda_flag_inode_children(inode, C_PURGE);
-                       coda_flag_inode(inode, C_VATTR);
-               }
                break;
 
        case CODA_ZAPFILE:
                fid = &out->coda_zapfile.CodaFid;
-               inode = coda_fid_to_inode(fid, sb);
-               if (inode)
-                       coda_flag_inode(inode, C_VATTR);
                break;
 
        case CODA_PURGEFID:
                fid = &out->coda_purgefid.CodaFid;
-               inode = coda_fid_to_inode(fid, sb);
-               if (inode) {
-                       coda_flag_inode_children(inode, C_PURGE);
-
-                       /* catch the dentries later if some are still busy */
-                       coda_flag_inode(inode, C_PURGE);
-                       d_prune_aliases(inode);
-
-               }
                break;
 
        case CODA_REPLACE:
                fid = &out->coda_replace.OldFid;
-               newfid = &out->coda_replace.NewFid;
-               inode = coda_fid_to_inode(fid, sb);
-               if (inode)
-                       coda_replace_fid(inode, fid, newfid);
                break;
        }
+       if (fid)
+               inode = coda_fid_to_inode(fid, sb);
 
 unlock_out:
-       unlock_kernel();
+       mutex_unlock(&vcp->vc_mutex);
+
+       if (!inode)
+               return 0;
+
+       switch (opcode) {
+       case CODA_ZAPDIR:
+               coda_flag_inode_children(inode, C_PURGE);
+               coda_flag_inode(inode, C_VATTR);
+               break;
+
+       case CODA_ZAPFILE:
+               coda_flag_inode(inode, C_VATTR);
+               break;
+
+       case CODA_PURGEFID:
+               coda_flag_inode_children(inode, C_PURGE);
 
-       if (inode)
-               iput(inode);
+               /* catch the dentries later if some are still busy */
+               coda_flag_inode(inode, C_PURGE);
+               d_prune_aliases(inode);
+               break;
+
+       case CODA_REPLACE:
+               newfid = &out->coda_replace.NewFid;
+               coda_replace_fid(inode, fid, newfid);
+               break;
+       }
+       iput(inode);
        return 0;
 }
 
index 1e60c5a..72f2d2f 100644 (file)
@@ -8,6 +8,7 @@
 
 #ifdef __KERNEL__
 #include <linux/backing-dev.h>
+#include <linux/mutex.h>
 
 struct kstatfs;
 
@@ -20,6 +21,7 @@ struct venus_comm {
        int                 vc_inuse;
        struct super_block *vc_sb;
        struct backing_dev_info bdi;
+       struct mutex        vc_mutex;
 };