summaryrefslogtreecommitdiffstats
path: root/fs/ecryptfs/kthread.c
diff options
context:
space:
mode:
Diffstat (limited to 'fs/ecryptfs/kthread.c')
-rw-r--r--fs/ecryptfs/kthread.c73
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;
}