diff options
Diffstat (limited to 'fs/ecryptfs/kthread.c')
| -rw-r--r-- | fs/ecryptfs/kthread.c | 73 | 
1 files changed, 24 insertions, 49 deletions
diff --git a/fs/ecryptfs/kthread.c b/fs/ecryptfs/kthread.c index 0dbe58a8b17..809e67d05ca 100644 --- a/fs/ecryptfs/kthread.c +++ b/fs/ecryptfs/kthread.c @@ -27,7 +27,12 @@  #include <linux/mount.h>  #include "ecryptfs_kernel.h" -struct kmem_cache *ecryptfs_open_req_cache; +struct ecryptfs_open_req { +	struct file **lower_file; +	struct path path; +	struct completion done; +	struct list_head kthread_ctl_list; +};  static struct ecryptfs_kthread_ctl {  #define ECRYPTFS_KTHREAD_ZOMBIE 0x00000001 @@ -67,18 +72,10 @@ static int ecryptfs_threadfn(void *ignored)  			req = list_first_entry(&ecryptfs_kthread_ctl.req_list,  					       struct ecryptfs_open_req,  					       kthread_ctl_list); -			mutex_lock(&req->mux);  			list_del(&req->kthread_ctl_list); -			if (!(req->flags & ECRYPTFS_REQ_ZOMBIE)) { -				dget(req->lower_dentry); -				mntget(req->lower_mnt); -				(*req->lower_file) = dentry_open( -					req->lower_dentry, req->lower_mnt, -					(O_RDWR | O_LARGEFILE), current_cred()); -				req->flags |= ECRYPTFS_REQ_PROCESSED; -			} -			wake_up(&req->wait); -			mutex_unlock(&req->mux); +			*req->lower_file = dentry_open(&req->path, +				(O_RDWR | O_LARGEFILE), current_cred()); +			complete(&req->done);  		}  		mutex_unlock(&ecryptfs_kthread_ctl.mux);  	} @@ -111,10 +108,9 @@ void ecryptfs_destroy_kthread(void)  	ecryptfs_kthread_ctl.flags |= ECRYPTFS_KTHREAD_ZOMBIE;  	list_for_each_entry(req, &ecryptfs_kthread_ctl.req_list,  			    kthread_ctl_list) { -		mutex_lock(&req->mux); -		req->flags |= ECRYPTFS_REQ_ZOMBIE; -		wake_up(&req->wait); -		mutex_unlock(&req->mux); +		list_del(&req->kthread_ctl_list); +		*req->lower_file = ERR_PTR(-EIO); +		complete(&req->done);  	}  	mutex_unlock(&ecryptfs_kthread_ctl.mux);  	kthread_stop(ecryptfs_kthread); @@ -136,34 +132,26 @@ int ecryptfs_privileged_open(struct file **lower_file,  			     struct vfsmount *lower_mnt,  			     const struct cred *cred)  { -	struct ecryptfs_open_req *req; +	struct ecryptfs_open_req req;  	int flags = O_LARGEFILE;  	int rc = 0; +	init_completion(&req.done); +	req.lower_file = lower_file; +	req.path.dentry = lower_dentry; +	req.path.mnt = lower_mnt; +  	/* Corresponding dput() and mntput() are done when the  	 * lower file is fput() when all eCryptfs files for the inode are  	 * released. */ -	dget(lower_dentry); -	mntget(lower_mnt);  	flags |= IS_RDONLY(lower_dentry->d_inode) ? O_RDONLY : O_RDWR; -	(*lower_file) = dentry_open(lower_dentry, lower_mnt, flags, cred); +	(*lower_file) = dentry_open(&req.path, flags, cred);  	if (!IS_ERR(*lower_file))  		goto out;  	if ((flags & O_ACCMODE) == O_RDONLY) {  		rc = PTR_ERR((*lower_file));  		goto out;  	} -	req = kmem_cache_alloc(ecryptfs_open_req_cache, GFP_KERNEL); -	if (!req) { -		rc = -ENOMEM; -		goto out; -	} -	mutex_init(&req->mux); -	req->lower_file = lower_file; -	req->lower_dentry = lower_dentry; -	req->lower_mnt = lower_mnt; -	init_waitqueue_head(&req->wait); -	req->flags = 0;  	mutex_lock(&ecryptfs_kthread_ctl.mux);  	if (ecryptfs_kthread_ctl.flags & ECRYPTFS_KTHREAD_ZOMBIE) {  		rc = -EIO; @@ -171,27 +159,14 @@ int ecryptfs_privileged_open(struct file **lower_file,  		printk(KERN_ERR "%s: We are in the middle of shutting down; "  		       "aborting privileged request to open lower file\n",  			__func__); -		goto out_free; +		goto out;  	} -	list_add_tail(&req->kthread_ctl_list, &ecryptfs_kthread_ctl.req_list); +	list_add_tail(&req.kthread_ctl_list, &ecryptfs_kthread_ctl.req_list);  	mutex_unlock(&ecryptfs_kthread_ctl.mux);  	wake_up(&ecryptfs_kthread_ctl.wait); -	wait_event(req->wait, (req->flags != 0)); -	mutex_lock(&req->mux); -	BUG_ON(req->flags == 0); -	if (req->flags & ECRYPTFS_REQ_DROPPED -	    || req->flags & ECRYPTFS_REQ_ZOMBIE) { -		rc = -EIO; -		printk(KERN_WARNING "%s: Privileged open request dropped\n", -		       __func__); -		goto out_unlock; -	} -	if (IS_ERR(*req->lower_file)) -		rc = PTR_ERR(*req->lower_file); -out_unlock: -	mutex_unlock(&req->mux); -out_free: -	kmem_cache_free(ecryptfs_open_req_cache, req); +	wait_for_completion(&req.done); +	if (IS_ERR(*lower_file)) +		rc = PTR_ERR(*lower_file);  out:  	return rc;  }  |