diff options
author | Al Viro <viro@zeniv.linux.org.uk> | 2005-11-07 17:15:49 -0500 |
---|---|---|
committer | Linus Torvalds <torvalds@g5.osdl.org> | 2005-11-07 21:18:10 -0500 |
commit | 5addc5dd8836aa061f6efc4a0d9ba6323726297a (patch) | |
tree | a5ce3703bbb421c93482b6043ebd57137276808f /fs/namespace.c | |
parent | 1abe77b0fc4b485927f1f798ae81a752677e1d05 (diff) |
[PATCH] make /proc/mounts pollable
Signed-off-by: Al Viro <viro@zeniv.linux.org.uk>
Signed-off-by: Linus Torvalds <torvalds@osdl.org>
Diffstat (limited to 'fs/namespace.c')
-rw-r--r-- | fs/namespace.c | 30 |
1 files changed, 29 insertions, 1 deletions
diff --git a/fs/namespace.c b/fs/namespace.c index 611f777bbd61..d1aca685aacf 100644 --- a/fs/namespace.c +++ b/fs/namespace.c | |||
@@ -37,7 +37,9 @@ static inline int sysfs_init(void) | |||
37 | #endif | 37 | #endif |
38 | 38 | ||
39 | /* spinlock for vfsmount related operations, inplace of dcache_lock */ | 39 | /* spinlock for vfsmount related operations, inplace of dcache_lock */ |
40 | __cacheline_aligned_in_smp DEFINE_SPINLOCK(vfsmount_lock); | 40 | __cacheline_aligned_in_smp DEFINE_SPINLOCK(vfsmount_lock); |
41 | |||
42 | static int event; | ||
41 | 43 | ||
42 | static struct list_head *mount_hashtable; | 44 | static struct list_head *mount_hashtable; |
43 | static int hash_mask __read_mostly, hash_bits __read_mostly; | 45 | static int hash_mask __read_mostly, hash_bits __read_mostly; |
@@ -111,6 +113,22 @@ static inline int check_mnt(struct vfsmount *mnt) | |||
111 | return mnt->mnt_namespace == current->namespace; | 113 | return mnt->mnt_namespace == current->namespace; |
112 | } | 114 | } |
113 | 115 | ||
116 | static void touch_namespace(struct namespace *ns) | ||
117 | { | ||
118 | if (ns) { | ||
119 | ns->event = ++event; | ||
120 | wake_up_interruptible(&ns->poll); | ||
121 | } | ||
122 | } | ||
123 | |||
124 | static void __touch_namespace(struct namespace *ns) | ||
125 | { | ||
126 | if (ns && ns->event != event) { | ||
127 | ns->event = event; | ||
128 | wake_up_interruptible(&ns->poll); | ||
129 | } | ||
130 | } | ||
131 | |||
114 | static void detach_mnt(struct vfsmount *mnt, struct nameidata *old_nd) | 132 | static void detach_mnt(struct vfsmount *mnt, struct nameidata *old_nd) |
115 | { | 133 | { |
116 | old_nd->dentry = mnt->mnt_mountpoint; | 134 | old_nd->dentry = mnt->mnt_mountpoint; |
@@ -384,6 +402,7 @@ static void umount_tree(struct vfsmount *mnt) | |||
384 | for (p = mnt; p; p = next_mnt(p, mnt)) { | 402 | for (p = mnt; p; p = next_mnt(p, mnt)) { |
385 | list_del(&p->mnt_list); | 403 | list_del(&p->mnt_list); |
386 | list_add(&p->mnt_list, &kill); | 404 | list_add(&p->mnt_list, &kill); |
405 | __touch_namespace(p->mnt_namespace); | ||
387 | p->mnt_namespace = NULL; | 406 | p->mnt_namespace = NULL; |
388 | } | 407 | } |
389 | 408 | ||
@@ -473,6 +492,7 @@ static int do_umount(struct vfsmount *mnt, int flags) | |||
473 | 492 | ||
474 | down_write(¤t->namespace->sem); | 493 | down_write(¤t->namespace->sem); |
475 | spin_lock(&vfsmount_lock); | 494 | spin_lock(&vfsmount_lock); |
495 | event++; | ||
476 | 496 | ||
477 | retval = -EBUSY; | 497 | retval = -EBUSY; |
478 | if (atomic_read(&mnt->mnt_count) == 2 || flags & MNT_DETACH) { | 498 | if (atomic_read(&mnt->mnt_count) == 2 || flags & MNT_DETACH) { |
@@ -634,6 +654,7 @@ static int graft_tree(struct vfsmount *mnt, struct nameidata *nd) | |||
634 | list_splice(&head, current->namespace->list.prev); | 654 | list_splice(&head, current->namespace->list.prev); |
635 | mntget(mnt); | 655 | mntget(mnt); |
636 | err = 0; | 656 | err = 0; |
657 | touch_namespace(current->namespace); | ||
637 | } | 658 | } |
638 | spin_unlock(&vfsmount_lock); | 659 | spin_unlock(&vfsmount_lock); |
639 | out_unlock: | 660 | out_unlock: |
@@ -771,6 +792,7 @@ static int do_move_mount(struct nameidata *nd, char *old_name) | |||
771 | 792 | ||
772 | detach_mnt(old_nd.mnt, &parent_nd); | 793 | detach_mnt(old_nd.mnt, &parent_nd); |
773 | attach_mnt(old_nd.mnt, nd); | 794 | attach_mnt(old_nd.mnt, nd); |
795 | touch_namespace(current->namespace); | ||
774 | 796 | ||
775 | /* if the mount is moved, it should no longer be expire | 797 | /* if the mount is moved, it should no longer be expire |
776 | * automatically */ | 798 | * automatically */ |
@@ -877,6 +899,7 @@ static void expire_mount(struct vfsmount *mnt, struct list_head *mounts) | |||
877 | struct nameidata old_nd; | 899 | struct nameidata old_nd; |
878 | 900 | ||
879 | /* delete from the namespace */ | 901 | /* delete from the namespace */ |
902 | touch_namespace(mnt->mnt_namespace); | ||
880 | list_del_init(&mnt->mnt_list); | 903 | list_del_init(&mnt->mnt_list); |
881 | mnt->mnt_namespace = NULL; | 904 | mnt->mnt_namespace = NULL; |
882 | detach_mnt(mnt, &old_nd); | 905 | detach_mnt(mnt, &old_nd); |
@@ -1114,6 +1137,8 @@ int copy_namespace(int flags, struct task_struct *tsk) | |||
1114 | atomic_set(&new_ns->count, 1); | 1137 | atomic_set(&new_ns->count, 1); |
1115 | init_rwsem(&new_ns->sem); | 1138 | init_rwsem(&new_ns->sem); |
1116 | INIT_LIST_HEAD(&new_ns->list); | 1139 | INIT_LIST_HEAD(&new_ns->list); |
1140 | init_waitqueue_head(&new_ns->poll); | ||
1141 | new_ns->event = 0; | ||
1117 | 1142 | ||
1118 | down_write(&tsk->namespace->sem); | 1143 | down_write(&tsk->namespace->sem); |
1119 | /* First pass: copy the tree topology */ | 1144 | /* First pass: copy the tree topology */ |
@@ -1377,6 +1402,7 @@ asmlinkage long sys_pivot_root(const char __user *new_root, const char __user *p | |||
1377 | detach_mnt(user_nd.mnt, &root_parent); | 1402 | detach_mnt(user_nd.mnt, &root_parent); |
1378 | attach_mnt(user_nd.mnt, &old_nd); /* mount old root on put_old */ | 1403 | attach_mnt(user_nd.mnt, &old_nd); /* mount old root on put_old */ |
1379 | attach_mnt(new_nd.mnt, &root_parent); /* mount new_root on / */ | 1404 | attach_mnt(new_nd.mnt, &root_parent); /* mount new_root on / */ |
1405 | touch_namespace(current->namespace); | ||
1380 | spin_unlock(&vfsmount_lock); | 1406 | spin_unlock(&vfsmount_lock); |
1381 | chroot_fs_refs(&user_nd, &new_nd); | 1407 | chroot_fs_refs(&user_nd, &new_nd); |
1382 | security_sb_post_pivotroot(&user_nd, &new_nd); | 1408 | security_sb_post_pivotroot(&user_nd, &new_nd); |
@@ -1413,6 +1439,8 @@ static void __init init_mount_tree(void) | |||
1413 | atomic_set(&namespace->count, 1); | 1439 | atomic_set(&namespace->count, 1); |
1414 | INIT_LIST_HEAD(&namespace->list); | 1440 | INIT_LIST_HEAD(&namespace->list); |
1415 | init_rwsem(&namespace->sem); | 1441 | init_rwsem(&namespace->sem); |
1442 | init_waitqueue_head(&namespace->poll); | ||
1443 | namespace->event = 0; | ||
1416 | list_add(&mnt->mnt_list, &namespace->list); | 1444 | list_add(&mnt->mnt_list, &namespace->list); |
1417 | namespace->root = mnt; | 1445 | namespace->root = mnt; |
1418 | mnt->mnt_namespace = namespace; | 1446 | mnt->mnt_namespace = namespace; |