diff options
author | Miklos Szeredi <mszeredi@suse.cz> | 2008-03-27 08:06:24 -0400 |
---|---|---|
committer | Al Viro <viro@zeniv.linux.org.uk> | 2008-04-23 00:04:57 -0400 |
commit | a1a2c409b666befc58c2db9c7fbddf200f153470 (patch) | |
tree | 3ea8e4c8f1311436939492d70de23dcf185994de /fs/proc | |
parent | 719f5d7f0b90ac2c8f8ca4232eb322b266fea01e (diff) |
[patch 5/7] vfs: mountinfo: allow using process root
Allow /proc/<pid>/mountinfo to use the root of <pid> to calculate
mountpoints.
- move definition of 'struct proc_mounts' to <linux/mnt_namespace.h>
- add the process's namespace and root to this structure
- pass a pointer to 'struct proc_mounts' into seq_operations
In addition the following cleanups are made:
- use a common open function for /proc/<pid>/{mounts,mountstat}
- surround namespace.c part of these proc files with #ifdef CONFIG_PROC_FS
- make the seq_operations structures const
Signed-off-by: Miklos Szeredi <mszeredi@suse.cz>
Signed-off-by: Al Viro <viro@zeniv.linux.org.uk>
Diffstat (limited to 'fs/proc')
-rw-r--r-- | fs/proc/base.c | 108 |
1 files changed, 51 insertions, 57 deletions
diff --git a/fs/proc/base.c b/fs/proc/base.c index 7313c62e3e9d..a04b3db7a296 100644 --- a/fs/proc/base.c +++ b/fs/proc/base.c | |||
@@ -502,17 +502,14 @@ static const struct inode_operations proc_def_inode_operations = { | |||
502 | .setattr = proc_setattr, | 502 | .setattr = proc_setattr, |
503 | }; | 503 | }; |
504 | 504 | ||
505 | extern const struct seq_operations mounts_op; | 505 | static int mounts_open_common(struct inode *inode, struct file *file, |
506 | struct proc_mounts { | 506 | const struct seq_operations *op) |
507 | struct seq_file m; | ||
508 | int event; | ||
509 | }; | ||
510 | |||
511 | static int mounts_open(struct inode *inode, struct file *file) | ||
512 | { | 507 | { |
513 | struct task_struct *task = get_proc_task(inode); | 508 | struct task_struct *task = get_proc_task(inode); |
514 | struct nsproxy *nsp; | 509 | struct nsproxy *nsp; |
515 | struct mnt_namespace *ns = NULL; | 510 | struct mnt_namespace *ns = NULL; |
511 | struct fs_struct *fs = NULL; | ||
512 | struct path root; | ||
516 | struct proc_mounts *p; | 513 | struct proc_mounts *p; |
517 | int ret = -EINVAL; | 514 | int ret = -EINVAL; |
518 | 515 | ||
@@ -525,40 +522,61 @@ static int mounts_open(struct inode *inode, struct file *file) | |||
525 | get_mnt_ns(ns); | 522 | get_mnt_ns(ns); |
526 | } | 523 | } |
527 | rcu_read_unlock(); | 524 | rcu_read_unlock(); |
528 | 525 | if (ns) | |
526 | fs = get_fs_struct(task); | ||
529 | put_task_struct(task); | 527 | put_task_struct(task); |
530 | } | 528 | } |
531 | 529 | ||
532 | if (ns) { | 530 | if (!ns) |
533 | ret = -ENOMEM; | 531 | goto err; |
534 | p = kmalloc(sizeof(struct proc_mounts), GFP_KERNEL); | 532 | if (!fs) |
535 | if (p) { | 533 | goto err_put_ns; |
536 | file->private_data = &p->m; | 534 | |
537 | ret = seq_open(file, &mounts_op); | 535 | read_lock(&fs->lock); |
538 | if (!ret) { | 536 | root = fs->root; |
539 | p->m.private = ns; | 537 | path_get(&root); |
540 | p->event = ns->event; | 538 | read_unlock(&fs->lock); |
541 | return 0; | 539 | put_fs_struct(fs); |
542 | } | 540 | |
543 | kfree(p); | 541 | ret = -ENOMEM; |
544 | } | 542 | p = kmalloc(sizeof(struct proc_mounts), GFP_KERNEL); |
545 | put_mnt_ns(ns); | 543 | if (!p) |
546 | } | 544 | goto err_put_path; |
545 | |||
546 | file->private_data = &p->m; | ||
547 | ret = seq_open(file, op); | ||
548 | if (ret) | ||
549 | goto err_free; | ||
550 | |||
551 | p->m.private = p; | ||
552 | p->ns = ns; | ||
553 | p->root = root; | ||
554 | p->event = ns->event; | ||
555 | |||
556 | return 0; | ||
557 | |||
558 | err_free: | ||
559 | kfree(p); | ||
560 | err_put_path: | ||
561 | path_put(&root); | ||
562 | err_put_ns: | ||
563 | put_mnt_ns(ns); | ||
564 | err: | ||
547 | return ret; | 565 | return ret; |
548 | } | 566 | } |
549 | 567 | ||
550 | static int mounts_release(struct inode *inode, struct file *file) | 568 | static int mounts_release(struct inode *inode, struct file *file) |
551 | { | 569 | { |
552 | struct seq_file *m = file->private_data; | 570 | struct proc_mounts *p = file->private_data; |
553 | struct mnt_namespace *ns = m->private; | 571 | path_put(&p->root); |
554 | put_mnt_ns(ns); | 572 | put_mnt_ns(p->ns); |
555 | return seq_release(inode, file); | 573 | return seq_release(inode, file); |
556 | } | 574 | } |
557 | 575 | ||
558 | static unsigned mounts_poll(struct file *file, poll_table *wait) | 576 | static unsigned mounts_poll(struct file *file, poll_table *wait) |
559 | { | 577 | { |
560 | struct proc_mounts *p = file->private_data; | 578 | struct proc_mounts *p = file->private_data; |
561 | struct mnt_namespace *ns = p->m.private; | 579 | struct mnt_namespace *ns = p->ns; |
562 | unsigned res = 0; | 580 | unsigned res = 0; |
563 | 581 | ||
564 | poll_wait(file, &ns->poll, wait); | 582 | poll_wait(file, &ns->poll, wait); |
@@ -573,6 +591,11 @@ static unsigned mounts_poll(struct file *file, poll_table *wait) | |||
573 | return res; | 591 | return res; |
574 | } | 592 | } |
575 | 593 | ||
594 | static int mounts_open(struct inode *inode, struct file *file) | ||
595 | { | ||
596 | return mounts_open_common(inode, file, &mounts_op); | ||
597 | } | ||
598 | |||
576 | static const struct file_operations proc_mounts_operations = { | 599 | static const struct file_operations proc_mounts_operations = { |
577 | .open = mounts_open, | 600 | .open = mounts_open, |
578 | .read = seq_read, | 601 | .read = seq_read, |
@@ -581,38 +604,9 @@ static const struct file_operations proc_mounts_operations = { | |||
581 | .poll = mounts_poll, | 604 | .poll = mounts_poll, |
582 | }; | 605 | }; |
583 | 606 | ||
584 | extern const struct seq_operations mountstats_op; | ||
585 | static int mountstats_open(struct inode *inode, struct file *file) | 607 | static int mountstats_open(struct inode *inode, struct file *file) |
586 | { | 608 | { |
587 | int ret = seq_open(file, &mountstats_op); | 609 | return mounts_open_common(inode, file, &mountstats_op); |
588 | |||
589 | if (!ret) { | ||
590 | struct seq_file *m = file->private_data; | ||
591 | struct nsproxy *nsp; | ||
592 | struct mnt_namespace *mnt_ns = NULL; | ||
593 | struct task_struct *task = get_proc_task(inode); | ||
594 | |||
595 | if (task) { | ||
596 | rcu_read_lock(); | ||
597 | nsp = task_nsproxy(task); | ||
598 | if (nsp) { | ||
599 | mnt_ns = nsp->mnt_ns; | ||
600 | if (mnt_ns) | ||
601 | get_mnt_ns(mnt_ns); | ||
602 | } | ||
603 | rcu_read_unlock(); | ||
604 | |||
605 | put_task_struct(task); | ||
606 | } | ||
607 | |||
608 | if (mnt_ns) | ||
609 | m->private = mnt_ns; | ||
610 | else { | ||
611 | seq_release(inode, file); | ||
612 | ret = -EINVAL; | ||
613 | } | ||
614 | } | ||
615 | return ret; | ||
616 | } | 610 | } |
617 | 611 | ||
618 | static const struct file_operations proc_mountstats_operations = { | 612 | static const struct file_operations proc_mountstats_operations = { |