From da47c19e5c746829042933c8f945a71e2b62d6fc Mon Sep 17 00:00:00 2001 From: Yoshihisa Abe Date: Mon, 25 Oct 2010 02:03:46 -0400 Subject: [PATCH] Coda: replace BKL with mutex 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 Signed-off-by: Jan Harkes Signed-off-by: Linus Torvalds --- fs/coda/inode.c | 19 +++++----- fs/coda/psdev.c | 28 +++++++++------ fs/coda/upcall.c | 71 +++++++++++++++++++++----------------- include/linux/coda_psdev.h | 2 ++ 4 files changed, 70 insertions(+), 50 deletions(-) diff --git a/fs/coda/inode.c b/fs/coda/inode.c index b7fa3e3d772f..7993b96ca348 100644 --- a/fs/coda/inode.c +++ b/fs/coda/inode.c @@ -15,7 +15,7 @@ #include #include #include -#include +#include #include #include #include @@ -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"); } diff --git a/fs/coda/psdev.c b/fs/coda/psdev.c index 9a9248e632c6..62647a8595e4 100644 --- a/fs/coda/psdev.c +++ b/fs/coda/psdev.c @@ -35,7 +35,7 @@ #include #include #include -#include +#include #include #include #include @@ -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; diff --git a/fs/coda/upcall.c b/fs/coda/upcall.c index 4c258cb5266d..c3563cab9758 100644 --- a/fs/coda/upcall.c +++ b/fs/coda/upcall.c @@ -27,7 +27,7 @@ #include #include #include -#include +#include #include #include #include @@ -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) - iput(inode); + 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); + + /* 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; } diff --git a/include/linux/coda_psdev.h b/include/linux/coda_psdev.h index 1e60c5a41a5b..72f2d2f0af91 100644 --- a/include/linux/coda_psdev.h +++ b/include/linux/coda_psdev.h @@ -8,6 +8,7 @@ #ifdef __KERNEL__ #include +#include 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; };