aboutsummaryrefslogtreecommitdiffstats
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 0dbe58a8b172..809e67d05ca3 100644
--- a/fs/ecryptfs/kthread.c
+++ b/fs/ecryptfs/kthread.c
@@ -27,7 +27,12 @@
27#include <linux/mount.h> 27#include <linux/mount.h>
28#include "ecryptfs_kernel.h" 28#include "ecryptfs_kernel.h"
29 29
30struct kmem_cache *ecryptfs_open_req_cache; 30struct ecryptfs_open_req {
31 struct file **lower_file;
32 struct path path;
33 struct completion done;
34 struct list_head kthread_ctl_list;
35};
31 36
32static struct ecryptfs_kthread_ctl { 37static struct ecryptfs_kthread_ctl {
33#define ECRYPTFS_KTHREAD_ZOMBIE 0x00000001 38#define ECRYPTFS_KTHREAD_ZOMBIE 0x00000001
@@ -67,18 +72,10 @@ static int ecryptfs_threadfn(void *ignored)
67 req = list_first_entry(&ecryptfs_kthread_ctl.req_list, 72 req = list_first_entry(&ecryptfs_kthread_ctl.req_list,
68 struct ecryptfs_open_req, 73 struct ecryptfs_open_req,
69 kthread_ctl_list); 74 kthread_ctl_list);
70 mutex_lock(&req->mux);
71 list_del(&req->kthread_ctl_list); 75 list_del(&req->kthread_ctl_list);
72 if (!(req->flags & ECRYPTFS_REQ_ZOMBIE)) { 76 *req->lower_file = dentry_open(&req->path,
73 dget(req->lower_dentry); 77 (O_RDWR | O_LARGEFILE), current_cred());
74 mntget(req->lower_mnt); 78 complete(&req->done);
75 (*req->lower_file) = dentry_open(
76 req->lower_dentry, req->lower_mnt,
77 (O_RDWR | O_LARGEFILE), current_cred());
78 req->flags |= ECRYPTFS_REQ_PROCESSED;
79 }
80 wake_up(&req->wait);
81 mutex_unlock(&req->mux);
82 } 79 }
83 mutex_unlock(&ecryptfs_kthread_ctl.mux); 80 mutex_unlock(&ecryptfs_kthread_ctl.mux);
84 } 81 }
@@ -111,10 +108,9 @@ void ecryptfs_destroy_kthread(void)
111 ecryptfs_kthread_ctl.flags |= ECRYPTFS_KTHREAD_ZOMBIE; 108 ecryptfs_kthread_ctl.flags |= ECRYPTFS_KTHREAD_ZOMBIE;
112 list_for_each_entry(req, &ecryptfs_kthread_ctl.req_list, 109 list_for_each_entry(req, &ecryptfs_kthread_ctl.req_list,
113 kthread_ctl_list) { 110 kthread_ctl_list) {
114 mutex_lock(&req->mux); 111 list_del(&req->kthread_ctl_list);
115 req->flags |= ECRYPTFS_REQ_ZOMBIE; 112 *req->lower_file = ERR_PTR(-EIO);
116 wake_up(&req->wait); 113 complete(&req->done);
117 mutex_unlock(&req->mux);
118 } 114 }
119 mutex_unlock(&ecryptfs_kthread_ctl.mux); 115 mutex_unlock(&ecryptfs_kthread_ctl.mux);
120 kthread_stop(ecryptfs_kthread); 116 kthread_stop(ecryptfs_kthread);
@@ -136,34 +132,26 @@ int ecryptfs_privileged_open(struct file **lower_file,
136 struct vfsmount *lower_mnt, 132 struct vfsmount *lower_mnt,
137 const struct cred *cred) 133 const struct cred *cred)
138{ 134{
139 struct ecryptfs_open_req *req; 135 struct ecryptfs_open_req req;
140 int flags = O_LARGEFILE; 136 int flags = O_LARGEFILE;
141 int rc = 0; 137 int rc = 0;
142 138
139 init_completion(&req.done);
140 req.lower_file = lower_file;
141 req.path.dentry = lower_dentry;
142 req.path.mnt = lower_mnt;
143
143 /* Corresponding dput() and mntput() are done when the 144 /* Corresponding dput() and mntput() are done when the
144 * lower file is fput() when all eCryptfs files for the inode are 145 * lower file is fput() when all eCryptfs files for the inode are
145 * released. */ 146 * released. */
146 dget(lower_dentry);
147 mntget(lower_mnt);
148 flags |= IS_RDONLY(lower_dentry->d_inode) ? O_RDONLY : O_RDWR; 147 flags |= IS_RDONLY(lower_dentry->d_inode) ? O_RDONLY : O_RDWR;
149 (*lower_file) = dentry_open(lower_dentry, lower_mnt, flags, cred); 148 (*lower_file) = dentry_open(&req.path, flags, cred);
150 if (!IS_ERR(*lower_file)) 149 if (!IS_ERR(*lower_file))
151 goto out; 150 goto out;
152 if ((flags & O_ACCMODE) == O_RDONLY) { 151 if ((flags & O_ACCMODE) == O_RDONLY) {
153 rc = PTR_ERR((*lower_file)); 152 rc = PTR_ERR((*lower_file));
154 goto out; 153 goto out;
155 } 154 }
156 req = kmem_cache_alloc(ecryptfs_open_req_cache, GFP_KERNEL);
157 if (!req) {
158 rc = -ENOMEM;
159 goto out;
160 }
161 mutex_init(&req->mux);
162 req->lower_file = lower_file;
163 req->lower_dentry = lower_dentry;
164 req->lower_mnt = lower_mnt;
165 init_waitqueue_head(&req->wait);
166 req->flags = 0;
167 mutex_lock(&ecryptfs_kthread_ctl.mux); 155 mutex_lock(&ecryptfs_kthread_ctl.mux);
168 if (ecryptfs_kthread_ctl.flags & ECRYPTFS_KTHREAD_ZOMBIE) { 156 if (ecryptfs_kthread_ctl.flags & ECRYPTFS_KTHREAD_ZOMBIE) {
169 rc = -EIO; 157 rc = -EIO;
@@ -171,27 +159,14 @@ int ecryptfs_privileged_open(struct file **lower_file,
171 printk(KERN_ERR "%s: We are in the middle of shutting down; " 159 printk(KERN_ERR "%s: We are in the middle of shutting down; "
172 "aborting privileged request to open lower file\n", 160 "aborting privileged request to open lower file\n",
173 __func__); 161 __func__);
174 goto out_free; 162 goto out;
175 } 163 }
176 list_add_tail(&req->kthread_ctl_list, &ecryptfs_kthread_ctl.req_list); 164 list_add_tail(&req.kthread_ctl_list, &ecryptfs_kthread_ctl.req_list);
177 mutex_unlock(&ecryptfs_kthread_ctl.mux); 165 mutex_unlock(&ecryptfs_kthread_ctl.mux);
178 wake_up(&ecryptfs_kthread_ctl.wait); 166 wake_up(&ecryptfs_kthread_ctl.wait);
179 wait_event(req->wait, (req->flags != 0)); 167 wait_for_completion(&req.done);
180 mutex_lock(&req->mux); 168 if (IS_ERR(*lower_file))
181 BUG_ON(req->flags == 0); 169 rc = PTR_ERR(*lower_file);
182 if (req->flags & ECRYPTFS_REQ_DROPPED
183 || req->flags & ECRYPTFS_REQ_ZOMBIE) {
184 rc = -EIO;
185 printk(KERN_WARNING "%s: Privileged open request dropped\n",
186 __func__);
187 goto out_unlock;
188 }
189 if (IS_ERR(*req->lower_file))
190 rc = PTR_ERR(*req->lower_file);
191out_unlock:
192 mutex_unlock(&req->mux);
193out_free:
194 kmem_cache_free(ecryptfs_open_req_cache, req);
195out: 170out:
196 return rc; 171 return rc;
197} 172}