diff options
author | Jonathan Herman <hermanjl@cs.unc.edu> | 2013-01-17 16:15:55 -0500 |
---|---|---|
committer | Jonathan Herman <hermanjl@cs.unc.edu> | 2013-01-17 16:15:55 -0500 |
commit | 8dea78da5cee153b8af9c07a2745f6c55057fe12 (patch) | |
tree | a8f4d49d63b1ecc92f2fddceba0655b2472c5bd9 /fs/ecryptfs/kthread.c | |
parent | 406089d01562f1e2bf9f089fd7637009ebaad589 (diff) |
Patched in Tegra support.
Diffstat (limited to 'fs/ecryptfs/kthread.c')
-rw-r--r-- | fs/ecryptfs/kthread.c | 81 |
1 files changed, 53 insertions, 28 deletions
diff --git a/fs/ecryptfs/kthread.c b/fs/ecryptfs/kthread.c index f1ea610362c..69f994a7d52 100644 --- a/fs/ecryptfs/kthread.c +++ b/fs/ecryptfs/kthread.c | |||
@@ -27,12 +27,7 @@ | |||
27 | #include <linux/mount.h> | 27 | #include <linux/mount.h> |
28 | #include "ecryptfs_kernel.h" | 28 | #include "ecryptfs_kernel.h" |
29 | 29 | ||
30 | struct ecryptfs_open_req { | 30 | struct kmem_cache *ecryptfs_open_req_cache; |
31 | struct file **lower_file; | ||
32 | struct path path; | ||
33 | struct completion done; | ||
34 | struct list_head kthread_ctl_list; | ||
35 | }; | ||
36 | 31 | ||
37 | static struct ecryptfs_kthread_ctl { | 32 | static struct ecryptfs_kthread_ctl { |
38 | #define ECRYPTFS_KTHREAD_ZOMBIE 0x00000001 | 33 | #define ECRYPTFS_KTHREAD_ZOMBIE 0x00000001 |
@@ -72,10 +67,18 @@ static int ecryptfs_threadfn(void *ignored) | |||
72 | req = list_first_entry(&ecryptfs_kthread_ctl.req_list, | 67 | req = list_first_entry(&ecryptfs_kthread_ctl.req_list, |
73 | struct ecryptfs_open_req, | 68 | struct ecryptfs_open_req, |
74 | kthread_ctl_list); | 69 | kthread_ctl_list); |
70 | mutex_lock(&req->mux); | ||
75 | list_del(&req->kthread_ctl_list); | 71 | list_del(&req->kthread_ctl_list); |
76 | *req->lower_file = dentry_open(&req->path, | 72 | if (!(req->flags & ECRYPTFS_REQ_ZOMBIE)) { |
77 | (O_RDWR | O_LARGEFILE), current_cred()); | 73 | dget(req->lower_dentry); |
78 | complete(&req->done); | 74 | mntget(req->lower_mnt); |
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); | ||
79 | } | 82 | } |
80 | mutex_unlock(&ecryptfs_kthread_ctl.mux); | 83 | mutex_unlock(&ecryptfs_kthread_ctl.mux); |
81 | } | 84 | } |
@@ -102,15 +105,16 @@ int __init ecryptfs_init_kthread(void) | |||
102 | 105 | ||
103 | void ecryptfs_destroy_kthread(void) | 106 | void ecryptfs_destroy_kthread(void) |
104 | { | 107 | { |
105 | struct ecryptfs_open_req *req, *tmp; | 108 | struct ecryptfs_open_req *req; |
106 | 109 | ||
107 | mutex_lock(&ecryptfs_kthread_ctl.mux); | 110 | mutex_lock(&ecryptfs_kthread_ctl.mux); |
108 | ecryptfs_kthread_ctl.flags |= ECRYPTFS_KTHREAD_ZOMBIE; | 111 | ecryptfs_kthread_ctl.flags |= ECRYPTFS_KTHREAD_ZOMBIE; |
109 | list_for_each_entry_safe(req, tmp, &ecryptfs_kthread_ctl.req_list, | 112 | list_for_each_entry(req, &ecryptfs_kthread_ctl.req_list, |
110 | kthread_ctl_list) { | 113 | kthread_ctl_list) { |
111 | list_del(&req->kthread_ctl_list); | 114 | mutex_lock(&req->mux); |
112 | *req->lower_file = ERR_PTR(-EIO); | 115 | req->flags |= ECRYPTFS_REQ_ZOMBIE; |
113 | complete(&req->done); | 116 | wake_up(&req->wait); |
117 | mutex_unlock(&req->mux); | ||
114 | } | 118 | } |
115 | mutex_unlock(&ecryptfs_kthread_ctl.mux); | 119 | mutex_unlock(&ecryptfs_kthread_ctl.mux); |
116 | kthread_stop(ecryptfs_kthread); | 120 | kthread_stop(ecryptfs_kthread); |
@@ -132,26 +136,34 @@ int ecryptfs_privileged_open(struct file **lower_file, | |||
132 | struct vfsmount *lower_mnt, | 136 | struct vfsmount *lower_mnt, |
133 | const struct cred *cred) | 137 | const struct cred *cred) |
134 | { | 138 | { |
135 | struct ecryptfs_open_req req; | 139 | struct ecryptfs_open_req *req; |
136 | int flags = O_LARGEFILE; | 140 | int flags = O_LARGEFILE; |
137 | int rc = 0; | 141 | int rc = 0; |
138 | 142 | ||
139 | init_completion(&req.done); | ||
140 | req.lower_file = lower_file; | ||
141 | req.path.dentry = lower_dentry; | ||
142 | req.path.mnt = lower_mnt; | ||
143 | |||
144 | /* Corresponding dput() and mntput() are done when the | 143 | /* Corresponding dput() and mntput() are done when the |
145 | * lower file is fput() when all eCryptfs files for the inode are | 144 | * lower file is fput() when all eCryptfs files for the inode are |
146 | * released. */ | 145 | * released. */ |
146 | dget(lower_dentry); | ||
147 | mntget(lower_mnt); | ||
147 | flags |= IS_RDONLY(lower_dentry->d_inode) ? O_RDONLY : O_RDWR; | 148 | flags |= IS_RDONLY(lower_dentry->d_inode) ? O_RDONLY : O_RDWR; |
148 | (*lower_file) = dentry_open(&req.path, flags, cred); | 149 | (*lower_file) = dentry_open(lower_dentry, lower_mnt, flags, cred); |
149 | if (!IS_ERR(*lower_file)) | 150 | if (!IS_ERR(*lower_file)) |
150 | goto out; | 151 | goto out; |
151 | if ((flags & O_ACCMODE) == O_RDONLY) { | 152 | if (flags & O_RDONLY) { |
152 | rc = PTR_ERR((*lower_file)); | 153 | rc = PTR_ERR((*lower_file)); |
153 | goto out; | 154 | goto out; |
154 | } | 155 | } |
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; | ||
155 | mutex_lock(&ecryptfs_kthread_ctl.mux); | 167 | mutex_lock(&ecryptfs_kthread_ctl.mux); |
156 | if (ecryptfs_kthread_ctl.flags & ECRYPTFS_KTHREAD_ZOMBIE) { | 168 | if (ecryptfs_kthread_ctl.flags & ECRYPTFS_KTHREAD_ZOMBIE) { |
157 | rc = -EIO; | 169 | rc = -EIO; |
@@ -159,14 +171,27 @@ int ecryptfs_privileged_open(struct file **lower_file, | |||
159 | printk(KERN_ERR "%s: We are in the middle of shutting down; " | 171 | printk(KERN_ERR "%s: We are in the middle of shutting down; " |
160 | "aborting privileged request to open lower file\n", | 172 | "aborting privileged request to open lower file\n", |
161 | __func__); | 173 | __func__); |
162 | goto out; | 174 | goto out_free; |
163 | } | 175 | } |
164 | list_add_tail(&req.kthread_ctl_list, &ecryptfs_kthread_ctl.req_list); | 176 | list_add_tail(&req->kthread_ctl_list, &ecryptfs_kthread_ctl.req_list); |
165 | mutex_unlock(&ecryptfs_kthread_ctl.mux); | 177 | mutex_unlock(&ecryptfs_kthread_ctl.mux); |
166 | wake_up(&ecryptfs_kthread_ctl.wait); | 178 | wake_up(&ecryptfs_kthread_ctl.wait); |
167 | wait_for_completion(&req.done); | 179 | wait_event(req->wait, (req->flags != 0)); |
168 | if (IS_ERR(*lower_file)) | 180 | mutex_lock(&req->mux); |
169 | rc = PTR_ERR(*lower_file); | 181 | BUG_ON(req->flags == 0); |
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); | ||
191 | out_unlock: | ||
192 | mutex_unlock(&req->mux); | ||
193 | out_free: | ||
194 | kmem_cache_free(ecryptfs_open_req_cache, req); | ||
170 | out: | 195 | out: |
171 | return rc; | 196 | return rc; |
172 | } | 197 | } |