aboutsummaryrefslogtreecommitdiffstats
path: root/fs/proc/namespaces.c
diff options
context:
space:
mode:
Diffstat (limited to 'fs/proc/namespaces.c')
-rw-r--r--fs/proc/namespaces.c87
1 files changed, 24 insertions, 63 deletions
diff --git a/fs/proc/namespaces.c b/fs/proc/namespaces.c
index 54bdc6701e9f..49a7fff2e83a 100644
--- a/fs/proc/namespaces.c
+++ b/fs/proc/namespaces.c
@@ -187,13 +187,12 @@ static const struct inode_operations proc_ns_link_inode_operations = {
187 .setattr = proc_setattr, 187 .setattr = proc_setattr,
188}; 188};
189 189
190static struct dentry *proc_ns_instantiate(struct inode *dir, 190static int proc_ns_instantiate(struct inode *dir,
191 struct dentry *dentry, struct task_struct *task, const void *ptr) 191 struct dentry *dentry, struct task_struct *task, const void *ptr)
192{ 192{
193 const struct proc_ns_operations *ns_ops = ptr; 193 const struct proc_ns_operations *ns_ops = ptr;
194 struct inode *inode; 194 struct inode *inode;
195 struct proc_inode *ei; 195 struct proc_inode *ei;
196 struct dentry *error = ERR_PTR(-ENOENT);
197 196
198 inode = proc_pid_make_inode(dir->i_sb, task); 197 inode = proc_pid_make_inode(dir->i_sb, task);
199 if (!inode) 198 if (!inode)
@@ -208,90 +207,52 @@ static struct dentry *proc_ns_instantiate(struct inode *dir,
208 d_add(dentry, inode); 207 d_add(dentry, inode);
209 /* Close the race of the process dying before we return the dentry */ 208 /* Close the race of the process dying before we return the dentry */
210 if (pid_revalidate(dentry, 0)) 209 if (pid_revalidate(dentry, 0))
211 error = NULL; 210 return 0;
212out: 211out:
213 return error; 212 return -ENOENT;
214}
215
216static int proc_ns_fill_cache(struct file *filp, void *dirent,
217 filldir_t filldir, struct task_struct *task,
218 const struct proc_ns_operations *ops)
219{
220 return proc_fill_cache(filp, dirent, filldir,
221 ops->name, strlen(ops->name),
222 proc_ns_instantiate, task, ops);
223} 213}
224 214
225static int proc_ns_dir_readdir(struct file *filp, void *dirent, 215static int proc_ns_dir_readdir(struct file *file, struct dir_context *ctx)
226 filldir_t filldir)
227{ 216{
228 int i; 217 struct task_struct *task = get_proc_task(file_inode(file));
229 struct dentry *dentry = filp->f_path.dentry;
230 struct inode *inode = dentry->d_inode;
231 struct task_struct *task = get_proc_task(inode);
232 const struct proc_ns_operations **entry, **last; 218 const struct proc_ns_operations **entry, **last;
233 ino_t ino;
234 int ret;
235 219
236 ret = -ENOENT;
237 if (!task) 220 if (!task)
238 goto out_no_task; 221 return -ENOENT;
239 222
240 ret = 0; 223 if (!dir_emit_dots(file, ctx))
241 i = filp->f_pos; 224 goto out;
242 switch (i) { 225 if (ctx->pos >= 2 + ARRAY_SIZE(ns_entries))
243 case 0: 226 goto out;
244 ino = inode->i_ino; 227 entry = ns_entries + (ctx->pos - 2);
245 if (filldir(dirent, ".", 1, i, ino, DT_DIR) < 0) 228 last = &ns_entries[ARRAY_SIZE(ns_entries) - 1];
246 goto out; 229 while (entry <= last) {
247 i++; 230 const struct proc_ns_operations *ops = *entry;
248 filp->f_pos++; 231 if (!proc_fill_cache(file, ctx, ops->name, strlen(ops->name),
249 /* fall through */ 232 proc_ns_instantiate, task, ops))
250 case 1: 233 break;
251 ino = parent_ino(dentry); 234 ctx->pos++;
252 if (filldir(dirent, "..", 2, i, ino, DT_DIR) < 0) 235 entry++;
253 goto out;
254 i++;
255 filp->f_pos++;
256 /* fall through */
257 default:
258 i -= 2;
259 if (i >= ARRAY_SIZE(ns_entries)) {
260 ret = 1;
261 goto out;
262 }
263 entry = ns_entries + i;
264 last = &ns_entries[ARRAY_SIZE(ns_entries) - 1];
265 while (entry <= last) {
266 if (proc_ns_fill_cache(filp, dirent, filldir,
267 task, *entry) < 0)
268 goto out;
269 filp->f_pos++;
270 entry++;
271 }
272 } 236 }
273
274 ret = 1;
275out: 237out:
276 put_task_struct(task); 238 put_task_struct(task);
277out_no_task: 239 return 0;
278 return ret;
279} 240}
280 241
281const struct file_operations proc_ns_dir_operations = { 242const struct file_operations proc_ns_dir_operations = {
282 .read = generic_read_dir, 243 .read = generic_read_dir,
283 .readdir = proc_ns_dir_readdir, 244 .iterate = proc_ns_dir_readdir,
284}; 245};
285 246
286static struct dentry *proc_ns_dir_lookup(struct inode *dir, 247static struct dentry *proc_ns_dir_lookup(struct inode *dir,
287 struct dentry *dentry, unsigned int flags) 248 struct dentry *dentry, unsigned int flags)
288{ 249{
289 struct dentry *error; 250 int error;
290 struct task_struct *task = get_proc_task(dir); 251 struct task_struct *task = get_proc_task(dir);
291 const struct proc_ns_operations **entry, **last; 252 const struct proc_ns_operations **entry, **last;
292 unsigned int len = dentry->d_name.len; 253 unsigned int len = dentry->d_name.len;
293 254
294 error = ERR_PTR(-ENOENT); 255 error = -ENOENT;
295 256
296 if (!task) 257 if (!task)
297 goto out_no_task; 258 goto out_no_task;
@@ -310,7 +271,7 @@ static struct dentry *proc_ns_dir_lookup(struct inode *dir,
310out: 271out:
311 put_task_struct(task); 272 put_task_struct(task);
312out_no_task: 273out_no_task:
313 return error; 274 return ERR_PTR(error);
314} 275}
315 276
316const struct inode_operations proc_ns_dir_inode_operations = { 277const struct inode_operations proc_ns_dir_inode_operations = {