From f7cc02b8715618e179242ba9cc10bdc5146ae565 Mon Sep 17 00:00:00 2001 From: Yoshihisa Abe Date: Mon, 25 Oct 2010 02:03:45 -0400 Subject: Coda: push BKL regions into coda_upcall() Now that shared inode state is locked using the cii->c_lock, the BKL is only used to protect the upcall queues used to communicate with the userspace cache manager. The remaining state is all local and we can push the lock further down into coda_upcall(). Signed-off-by: Yoshihisa Abe Signed-off-by: Jan Harkes Signed-off-by: Linus Torvalds --- include/linux/coda_psdev.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'include/linux/coda_psdev.h') diff --git a/include/linux/coda_psdev.h b/include/linux/coda_psdev.h index 284b520934a0..1e60c5a41a5b 100644 --- a/include/linux/coda_psdev.h +++ b/include/linux/coda_psdev.h @@ -63,7 +63,7 @@ int venus_symlink(struct super_block *sb, struct CodaFid *fid, int venus_access(struct super_block *sb, struct CodaFid *fid, int mask); int venus_pioctl(struct super_block *sb, struct CodaFid *fid, unsigned int cmd, struct PioctlData *data); -int coda_downcall(int opcode, union outputArgs *out, struct super_block *sb); +int coda_downcall(struct venus_comm *vcp, int opcode, union outputArgs *out); int venus_fsync(struct super_block *sb, struct CodaFid *fid); int venus_statfs(struct dentry *dentry, struct kstatfs *sfs); -- cgit v1.2.3 From da47c19e5c746829042933c8f945a71e2b62d6fc Mon Sep 17 00:00:00 2001 From: Yoshihisa Abe Date: Mon, 25 Oct 2010 02:03:46 -0400 Subject: 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(-) (limited to 'include/linux/coda_psdev.h') 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) + 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; } 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; }; -- cgit v1.2.3