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 <yoshiabe@cs.cmu.edu> Signed-off-by: Jan Harkes <jaharkes@cs.cmu.edu> Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
This commit is contained in:
parent
f7cc02b871
commit
da47c19e5c
|
@ -15,7 +15,7 @@
|
||||||
#include <linux/stat.h>
|
#include <linux/stat.h>
|
||||||
#include <linux/errno.h>
|
#include <linux/errno.h>
|
||||||
#include <linux/unistd.h>
|
#include <linux/unistd.h>
|
||||||
#include <linux/smp_lock.h>
|
#include <linux/mutex.h>
|
||||||
#include <linux/spinlock.h>
|
#include <linux/spinlock.h>
|
||||||
#include <linux/file.h>
|
#include <linux/file.h>
|
||||||
#include <linux/vfs.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)
|
static int coda_fill_super(struct super_block *sb, void *data, int silent)
|
||||||
{
|
{
|
||||||
struct inode *root = NULL;
|
struct inode *root = NULL;
|
||||||
struct venus_comm *vc = NULL;
|
struct venus_comm *vc;
|
||||||
struct CodaFid fid;
|
struct CodaFid fid;
|
||||||
int error;
|
int error;
|
||||||
int idx;
|
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);
|
printk(KERN_INFO "coda_read_super: device index: %i\n", idx);
|
||||||
|
|
||||||
vc = &coda_comms[idx];
|
vc = &coda_comms[idx];
|
||||||
lock_kernel();
|
mutex_lock(&vc->vc_mutex);
|
||||||
|
|
||||||
if (!vc->vc_inuse) {
|
if (!vc->vc_inuse) {
|
||||||
printk("coda_read_super: No pseudo device\n");
|
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;
|
goto unlock_out;
|
||||||
|
|
||||||
vc->vc_sb = sb;
|
vc->vc_sb = sb;
|
||||||
unlock_kernel();
|
mutex_unlock(&vc->vc_mutex);
|
||||||
|
|
||||||
sb->s_fs_info = vc;
|
sb->s_fs_info = vc;
|
||||||
sb->s_flags |= MS_NOATIME;
|
sb->s_flags |= MS_NOATIME;
|
||||||
|
@ -217,20 +217,23 @@ error:
|
||||||
if (root)
|
if (root)
|
||||||
iput(root);
|
iput(root);
|
||||||
|
|
||||||
lock_kernel();
|
mutex_lock(&vc->vc_mutex);
|
||||||
bdi_destroy(&vc->bdi);
|
bdi_destroy(&vc->bdi);
|
||||||
vc->vc_sb = NULL;
|
vc->vc_sb = NULL;
|
||||||
sb->s_fs_info = NULL;
|
sb->s_fs_info = NULL;
|
||||||
unlock_out:
|
unlock_out:
|
||||||
unlock_kernel();
|
mutex_unlock(&vc->vc_mutex);
|
||||||
return error;
|
return error;
|
||||||
}
|
}
|
||||||
|
|
||||||
static void coda_put_super(struct super_block *sb)
|
static void coda_put_super(struct super_block *sb)
|
||||||
{
|
{
|
||||||
bdi_destroy(&coda_vcp(sb)->bdi);
|
struct venus_comm *vcp = coda_vcp(sb);
|
||||||
coda_vcp(sb)->vc_sb = NULL;
|
mutex_lock(&vcp->vc_mutex);
|
||||||
|
bdi_destroy(&vcp->bdi);
|
||||||
|
vcp->vc_sb = NULL;
|
||||||
sb->s_fs_info = NULL;
|
sb->s_fs_info = NULL;
|
||||||
|
mutex_unlock(&vcp->vc_mutex);
|
||||||
|
|
||||||
printk("Coda: Bye bye.\n");
|
printk("Coda: Bye bye.\n");
|
||||||
}
|
}
|
||||||
|
|
|
@ -35,7 +35,7 @@
|
||||||
#include <linux/poll.h>
|
#include <linux/poll.h>
|
||||||
#include <linux/init.h>
|
#include <linux/init.h>
|
||||||
#include <linux/list.h>
|
#include <linux/list.h>
|
||||||
#include <linux/smp_lock.h>
|
#include <linux/mutex.h>
|
||||||
#include <linux/device.h>
|
#include <linux/device.h>
|
||||||
#include <asm/io.h>
|
#include <asm/io.h>
|
||||||
#include <asm/system.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;
|
unsigned int mask = POLLOUT | POLLWRNORM;
|
||||||
|
|
||||||
poll_wait(file, &vcp->vc_waitq, wait);
|
poll_wait(file, &vcp->vc_waitq, wait);
|
||||||
|
mutex_lock(&vcp->vc_mutex);
|
||||||
if (!list_empty(&vcp->vc_pending))
|
if (!list_empty(&vcp->vc_pending))
|
||||||
mask |= POLLIN | POLLRDNORM;
|
mask |= POLLIN | POLLRDNORM;
|
||||||
|
mutex_unlock(&vcp->vc_mutex);
|
||||||
|
|
||||||
return mask;
|
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. */
|
/* Look for the message on the processing queue. */
|
||||||
lock_kernel();
|
mutex_lock(&vcp->vc_mutex);
|
||||||
list_for_each(lh, &vcp->vc_processing) {
|
list_for_each(lh, &vcp->vc_processing) {
|
||||||
tmp = list_entry(lh, struct upc_req , uc_chain);
|
tmp = list_entry(lh, struct upc_req , uc_chain);
|
||||||
if (tmp->uc_unique == hdr.unique) {
|
if (tmp->uc_unique == hdr.unique) {
|
||||||
|
@ -152,7 +154,7 @@ static ssize_t coda_psdev_write(struct file *file, const char __user *buf,
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
unlock_kernel();
|
mutex_unlock(&vcp->vc_mutex);
|
||||||
|
|
||||||
if (!req) {
|
if (!req) {
|
||||||
printk("psdev_write: msg (%d, %d) not found\n",
|
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)
|
if (nbytes == 0)
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
lock_kernel();
|
mutex_lock(&vcp->vc_mutex);
|
||||||
|
|
||||||
add_wait_queue(&vcp->vc_waitq, &wait);
|
add_wait_queue(&vcp->vc_waitq, &wait);
|
||||||
set_current_state(TASK_INTERRUPTIBLE);
|
set_current_state(TASK_INTERRUPTIBLE);
|
||||||
|
@ -221,7 +223,9 @@ static ssize_t coda_psdev_read(struct file * file, char __user * buf,
|
||||||
retval = -ERESTARTSYS;
|
retval = -ERESTARTSYS;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
mutex_unlock(&vcp->vc_mutex);
|
||||||
schedule();
|
schedule();
|
||||||
|
mutex_lock(&vcp->vc_mutex);
|
||||||
}
|
}
|
||||||
|
|
||||||
set_current_state(TASK_RUNNING);
|
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));
|
CODA_FREE(req->uc_data, sizeof(struct coda_in_hdr));
|
||||||
kfree(req);
|
kfree(req);
|
||||||
out:
|
out:
|
||||||
unlock_kernel();
|
mutex_unlock(&vcp->vc_mutex);
|
||||||
return (count ? count : retval);
|
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)
|
if (idx < 0 || idx >= MAX_CODADEVS)
|
||||||
return -ENODEV;
|
return -ENODEV;
|
||||||
|
|
||||||
lock_kernel();
|
|
||||||
|
|
||||||
err = -EBUSY;
|
err = -EBUSY;
|
||||||
vcp = &coda_comms[idx];
|
vcp = &coda_comms[idx];
|
||||||
|
mutex_lock(&vcp->vc_mutex);
|
||||||
|
|
||||||
if (!vcp->vc_inuse) {
|
if (!vcp->vc_inuse) {
|
||||||
vcp->vc_inuse++;
|
vcp->vc_inuse++;
|
||||||
|
|
||||||
|
@ -284,7 +288,7 @@ static int coda_psdev_open(struct inode * inode, struct file * file)
|
||||||
err = 0;
|
err = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
unlock_kernel();
|
mutex_unlock(&vcp->vc_mutex);
|
||||||
return err;
|
return err;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -299,7 +303,7 @@ static int coda_psdev_release(struct inode * inode, struct file * file)
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
lock_kernel();
|
mutex_lock(&vcp->vc_mutex);
|
||||||
|
|
||||||
/* Wakeup clients so they can return. */
|
/* Wakeup clients so they can return. */
|
||||||
list_for_each_entry_safe(req, tmp, &vcp->vc_pending, uc_chain) {
|
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;
|
file->private_data = NULL;
|
||||||
vcp->vc_inuse--;
|
vcp->vc_inuse--;
|
||||||
unlock_kernel();
|
mutex_unlock(&vcp->vc_mutex);
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -353,9 +357,11 @@ static int init_coda_psdev(void)
|
||||||
err = PTR_ERR(coda_psdev_class);
|
err = PTR_ERR(coda_psdev_class);
|
||||||
goto out_chrdev;
|
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,
|
device_create(coda_psdev_class, NULL,
|
||||||
MKDEV(CODA_PSDEV_MAJOR, i), NULL, "cfs%d", i);
|
MKDEV(CODA_PSDEV_MAJOR, i), NULL, "cfs%d", i);
|
||||||
|
}
|
||||||
coda_sysctl_init();
|
coda_sysctl_init();
|
||||||
goto out;
|
goto out;
|
||||||
|
|
||||||
|
|
|
@ -27,7 +27,7 @@
|
||||||
#include <linux/errno.h>
|
#include <linux/errno.h>
|
||||||
#include <linux/string.h>
|
#include <linux/string.h>
|
||||||
#include <linux/slab.h>
|
#include <linux/slab.h>
|
||||||
#include <linux/smp_lock.h>
|
#include <linux/mutex.h>
|
||||||
#include <asm/uaccess.h>
|
#include <asm/uaccess.h>
|
||||||
#include <linux/vmalloc.h>
|
#include <linux/vmalloc.h>
|
||||||
#include <linux/vfs.h>
|
#include <linux/vfs.h>
|
||||||
|
@ -607,7 +607,8 @@ static void coda_unblock_signals(sigset_t *old)
|
||||||
(r)->uc_opcode != CODA_RELEASE) || \
|
(r)->uc_opcode != CODA_RELEASE) || \
|
||||||
(r)->uc_flags & CODA_REQ_READ))
|
(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);
|
DECLARE_WAITQUEUE(wait, current);
|
||||||
unsigned long timeout = jiffies + coda_timeout * HZ;
|
unsigned long timeout = jiffies + coda_timeout * HZ;
|
||||||
|
@ -640,10 +641,12 @@ static inline void coda_waitfor_upcall(struct upc_req *req)
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
mutex_unlock(&vcp->vc_mutex);
|
||||||
if (blocked)
|
if (blocked)
|
||||||
schedule_timeout(HZ);
|
schedule_timeout(HZ);
|
||||||
else
|
else
|
||||||
schedule();
|
schedule();
|
||||||
|
mutex_lock(&vcp->vc_mutex);
|
||||||
}
|
}
|
||||||
if (blocked)
|
if (blocked)
|
||||||
coda_unblock_signals(&old);
|
coda_unblock_signals(&old);
|
||||||
|
@ -671,7 +674,7 @@ static int coda_upcall(struct venus_comm *vcp,
|
||||||
struct upc_req *req = NULL, *sig_req;
|
struct upc_req *req = NULL, *sig_req;
|
||||||
int error;
|
int error;
|
||||||
|
|
||||||
lock_kernel();
|
mutex_lock(&vcp->vc_mutex);
|
||||||
|
|
||||||
if (!vcp->vc_inuse) {
|
if (!vcp->vc_inuse) {
|
||||||
printk(KERN_NOTICE "coda: Venus dead, not sending upcall\n");
|
printk(KERN_NOTICE "coda: Venus dead, not sending upcall\n");
|
||||||
|
@ -711,7 +714,7 @@ static int coda_upcall(struct venus_comm *vcp,
|
||||||
* ENODEV. */
|
* ENODEV. */
|
||||||
|
|
||||||
/* Go to sleep. Wake up on signals only after the timeout. */
|
/* 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... */
|
/* Op went through, interrupt or not... */
|
||||||
if (req->uc_flags & CODA_REQ_WRITE) {
|
if (req->uc_flags & CODA_REQ_WRITE) {
|
||||||
|
@ -765,7 +768,7 @@ static int coda_upcall(struct venus_comm *vcp,
|
||||||
|
|
||||||
exit:
|
exit:
|
||||||
kfree(req);
|
kfree(req);
|
||||||
unlock_kernel();
|
mutex_unlock(&vcp->vc_mutex);
|
||||||
return error;
|
return error;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -806,11 +809,11 @@ exit:
|
||||||
int coda_downcall(struct venus_comm *vcp, int opcode, union outputArgs *out)
|
int coda_downcall(struct venus_comm *vcp, int opcode, union outputArgs *out)
|
||||||
{
|
{
|
||||||
struct inode *inode = NULL;
|
struct inode *inode = NULL;
|
||||||
struct CodaFid *fid, *newfid;
|
struct CodaFid *fid = NULL, *newfid;
|
||||||
struct super_block *sb;
|
struct super_block *sb;
|
||||||
|
|
||||||
/* Handle invalidation requests. */
|
/* Handle invalidation requests. */
|
||||||
lock_kernel();
|
mutex_lock(&vcp->vc_mutex);
|
||||||
sb = vcp->vc_sb;
|
sb = vcp->vc_sb;
|
||||||
if (!sb || !sb->s_root)
|
if (!sb || !sb->s_root)
|
||||||
goto unlock_out;
|
goto unlock_out;
|
||||||
|
@ -829,47 +832,53 @@ int coda_downcall(struct venus_comm *vcp, int opcode, union outputArgs *out)
|
||||||
|
|
||||||
case CODA_ZAPDIR:
|
case CODA_ZAPDIR:
|
||||||
fid = &out->coda_zapdir.CodaFid;
|
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;
|
break;
|
||||||
|
|
||||||
case CODA_ZAPFILE:
|
case CODA_ZAPFILE:
|
||||||
fid = &out->coda_zapfile.CodaFid;
|
fid = &out->coda_zapfile.CodaFid;
|
||||||
inode = coda_fid_to_inode(fid, sb);
|
|
||||||
if (inode)
|
|
||||||
coda_flag_inode(inode, C_VATTR);
|
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case CODA_PURGEFID:
|
case CODA_PURGEFID:
|
||||||
fid = &out->coda_purgefid.CodaFid;
|
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;
|
break;
|
||||||
|
|
||||||
case CODA_REPLACE:
|
case CODA_REPLACE:
|
||||||
fid = &out->coda_replace.OldFid;
|
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;
|
break;
|
||||||
}
|
}
|
||||||
|
if (fid)
|
||||||
|
inode = coda_fid_to_inode(fid, sb);
|
||||||
|
|
||||||
unlock_out:
|
unlock_out:
|
||||||
unlock_kernel();
|
mutex_unlock(&vcp->vc_mutex);
|
||||||
|
|
||||||
if (inode)
|
if (!inode)
|
||||||
iput(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;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -8,6 +8,7 @@
|
||||||
|
|
||||||
#ifdef __KERNEL__
|
#ifdef __KERNEL__
|
||||||
#include <linux/backing-dev.h>
|
#include <linux/backing-dev.h>
|
||||||
|
#include <linux/mutex.h>
|
||||||
|
|
||||||
struct kstatfs;
|
struct kstatfs;
|
||||||
|
|
||||||
|
@ -20,6 +21,7 @@ struct venus_comm {
|
||||||
int vc_inuse;
|
int vc_inuse;
|
||||||
struct super_block *vc_sb;
|
struct super_block *vc_sb;
|
||||||
struct backing_dev_info bdi;
|
struct backing_dev_info bdi;
|
||||||
|
struct mutex vc_mutex;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue