Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit da47c19e authored by Yoshihisa Abe's avatar Yoshihisa Abe Committed by Linus Torvalds
Browse files

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: default avatarYoshihisa Abe <yoshiabe@cs.cmu.edu>
Signed-off-by: default avatarJan Harkes <jaharkes@cs.cmu.edu>
Signed-off-by: default avatarLinus Torvalds <torvalds@linux-foundation.org>
parent f7cc02b8
Loading
Loading
Loading
Loading
+11 −8
Original line number Original line Diff line number Diff line
@@ -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 @@ static int coda_fill_super(struct super_block *sb, void *data, int silent)
	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");
}
}
+17 −11
Original line number Original line Diff line number Diff line
@@ -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;


+40 −31
Original line number Original line Diff line number Diff line
@@ -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 @@ static int coda_upcall(struct venus_comm *vcp,
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,46 +832,52 @@ 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;
		break;

	case CODA_ZAPFILE:
		fid = &out->coda_zapfile.CodaFid;
		break;

	case CODA_PURGEFID:
		fid = &out->coda_purgefid.CodaFid;
		break;

	case CODA_REPLACE:
		fid = &out->coda_replace.OldFid;
		break;
	}
	if (fid)
		inode = coda_fid_to_inode(fid, sb);
		inode = coda_fid_to_inode(fid, sb);
		if (inode) {

unlock_out:
	mutex_unlock(&vcp->vc_mutex);

	if (!inode)
		return 0;

	switch (opcode) {
	case CODA_ZAPDIR:
		coda_flag_inode_children(inode, C_PURGE);
		coda_flag_inode_children(inode, C_PURGE);
		coda_flag_inode(inode, C_VATTR);
		coda_flag_inode(inode, C_VATTR);
		}
		break;
		break;


	case CODA_ZAPFILE:
	case CODA_ZAPFILE:
		fid = &out->coda_zapfile.CodaFid;
		inode = coda_fid_to_inode(fid, sb);
		if (inode)
		coda_flag_inode(inode, C_VATTR);
		coda_flag_inode(inode, C_VATTR);
		break;
		break;


	case CODA_PURGEFID:
	case CODA_PURGEFID:
		fid = &out->coda_purgefid.CodaFid;
		inode = coda_fid_to_inode(fid, sb);
		if (inode) {
		coda_flag_inode_children(inode, C_PURGE);
		coda_flag_inode_children(inode, C_PURGE);


		/* catch the dentries later if some are still busy */
		/* catch the dentries later if some are still busy */
		coda_flag_inode(inode, C_PURGE);
		coda_flag_inode(inode, C_PURGE);
		d_prune_aliases(inode);
		d_prune_aliases(inode);

		}
		break;
		break;


	case CODA_REPLACE:
	case CODA_REPLACE:
		fid = &out->coda_replace.OldFid;
		newfid = &out->coda_replace.NewFid;
		newfid = &out->coda_replace.NewFid;
		inode = coda_fid_to_inode(fid, sb);
		if (inode)
		coda_replace_fid(inode, fid, newfid);
		coda_replace_fid(inode, fid, newfid);
		break;
		break;
	}
	}

unlock_out:
	unlock_kernel();

	if (inode)
	iput(inode);
	iput(inode);
	return 0;
	return 0;
}
}
+2 −0
Original line number Original line Diff line number Diff line
@@ -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;
};
};