diff options
author | Ram Pai <linuxram@us.ibm.com> | 2005-11-07 17:17:51 -0500 |
---|---|---|
committer | Linus Torvalds <torvalds@g5.osdl.org> | 2005-11-07 21:18:10 -0500 |
commit | 390c684367de37e1c2f9005cf92f7a746c69fdd3 (patch) | |
tree | 23cf8783db5fdec3717c79f989c6872955679036 | |
parent | 36341f64569b0c4572478237ec5ed318f0762510 (diff) |
[PATCH] making namespace_sem global
This removes the per-namespace semaphore in favor of a global semaphore.
This can have an effect on namespace scalability.
Signed-off-by: Miklos Szeredi <miklos@szeredi.hu>
Signed-off-by: Ram Pai <linuxram@us.ibm.com>
Signed-off-by: Al Viro <viro@zeniv.linux.org.uk>
Signed-off-by: Linus Torvalds <torvalds@osdl.org>
-rw-r--r-- | fs/namespace.c | 46 | ||||
-rw-r--r-- | include/linux/namespace.h | 1 |
2 files changed, 23 insertions, 24 deletions
diff --git a/fs/namespace.c b/fs/namespace.c index 65f9c0ecc21c..4abee9ab009f 100644 --- a/fs/namespace.c +++ b/fs/namespace.c | |||
@@ -46,6 +46,7 @@ static int event; | |||
46 | static struct list_head *mount_hashtable; | 46 | static struct list_head *mount_hashtable; |
47 | static int hash_mask __read_mostly, hash_bits __read_mostly; | 47 | static int hash_mask __read_mostly, hash_bits __read_mostly; |
48 | static kmem_cache_t *mnt_cache; | 48 | static kmem_cache_t *mnt_cache; |
49 | static struct rw_semaphore namespace_sem; | ||
49 | 50 | ||
50 | static inline unsigned long hash(struct vfsmount *mnt, struct dentry *dentry) | 51 | static inline unsigned long hash(struct vfsmount *mnt, struct dentry *dentry) |
51 | { | 52 | { |
@@ -250,7 +251,7 @@ static void *m_start(struct seq_file *m, loff_t *pos) | |||
250 | struct list_head *p; | 251 | struct list_head *p; |
251 | loff_t l = *pos; | 252 | loff_t l = *pos; |
252 | 253 | ||
253 | down_read(&n->sem); | 254 | down_read(&namespace_sem); |
254 | list_for_each(p, &n->list) | 255 | list_for_each(p, &n->list) |
255 | if (!l--) | 256 | if (!l--) |
256 | return list_entry(p, struct vfsmount, mnt_list); | 257 | return list_entry(p, struct vfsmount, mnt_list); |
@@ -267,8 +268,7 @@ static void *m_next(struct seq_file *m, void *v, loff_t *pos) | |||
267 | 268 | ||
268 | static void m_stop(struct seq_file *m, void *v) | 269 | static void m_stop(struct seq_file *m, void *v) |
269 | { | 270 | { |
270 | struct namespace *n = m->private; | 271 | up_read(&namespace_sem); |
271 | up_read(&n->sem); | ||
272 | } | 272 | } |
273 | 273 | ||
274 | static inline void mangle(struct seq_file *m, const char *s) | 274 | static inline void mangle(struct seq_file *m, const char *s) |
@@ -487,7 +487,7 @@ static int do_umount(struct vfsmount *mnt, int flags) | |||
487 | return retval; | 487 | return retval; |
488 | } | 488 | } |
489 | 489 | ||
490 | down_write(¤t->namespace->sem); | 490 | down_write(&namespace_sem); |
491 | spin_lock(&vfsmount_lock); | 491 | spin_lock(&vfsmount_lock); |
492 | event++; | 492 | event++; |
493 | 493 | ||
@@ -500,7 +500,7 @@ static int do_umount(struct vfsmount *mnt, int flags) | |||
500 | spin_unlock(&vfsmount_lock); | 500 | spin_unlock(&vfsmount_lock); |
501 | if (retval) | 501 | if (retval) |
502 | security_sb_umount_busy(mnt); | 502 | security_sb_umount_busy(mnt); |
503 | up_write(¤t->namespace->sem); | 503 | up_write(&namespace_sem); |
504 | release_mounts(&umount_list); | 504 | release_mounts(&umount_list); |
505 | return retval; | 505 | return retval; |
506 | } | 506 | } |
@@ -678,7 +678,7 @@ static int do_loopback(struct nameidata *nd, char *old_name, int recurse) | |||
678 | if (err) | 678 | if (err) |
679 | return err; | 679 | return err; |
680 | 680 | ||
681 | down_write(¤t->namespace->sem); | 681 | down_write(&namespace_sem); |
682 | err = -EINVAL; | 682 | err = -EINVAL; |
683 | if (!check_mnt(nd->mnt) || !check_mnt(old_nd.mnt)) | 683 | if (!check_mnt(nd->mnt) || !check_mnt(old_nd.mnt)) |
684 | goto out; | 684 | goto out; |
@@ -702,7 +702,7 @@ static int do_loopback(struct nameidata *nd, char *old_name, int recurse) | |||
702 | } | 702 | } |
703 | 703 | ||
704 | out: | 704 | out: |
705 | up_write(¤t->namespace->sem); | 705 | up_write(&namespace_sem); |
706 | path_release(&old_nd); | 706 | path_release(&old_nd); |
707 | return err; | 707 | return err; |
708 | } | 708 | } |
@@ -750,7 +750,7 @@ static int do_move_mount(struct nameidata *nd, char *old_name) | |||
750 | if (err) | 750 | if (err) |
751 | return err; | 751 | return err; |
752 | 752 | ||
753 | down_write(¤t->namespace->sem); | 753 | down_write(&namespace_sem); |
754 | while (d_mountpoint(nd->dentry) && follow_down(&nd->mnt, &nd->dentry)) | 754 | while (d_mountpoint(nd->dentry) && follow_down(&nd->mnt, &nd->dentry)) |
755 | ; | 755 | ; |
756 | err = -EINVAL; | 756 | err = -EINVAL; |
@@ -795,7 +795,7 @@ out2: | |||
795 | out1: | 795 | out1: |
796 | up(&nd->dentry->d_inode->i_sem); | 796 | up(&nd->dentry->d_inode->i_sem); |
797 | out: | 797 | out: |
798 | up_write(¤t->namespace->sem); | 798 | up_write(&namespace_sem); |
799 | if (!err) | 799 | if (!err) |
800 | path_release(&parent_nd); | 800 | path_release(&parent_nd); |
801 | path_release(&old_nd); | 801 | path_release(&old_nd); |
@@ -834,7 +834,7 @@ int do_add_mount(struct vfsmount *newmnt, struct nameidata *nd, | |||
834 | { | 834 | { |
835 | int err; | 835 | int err; |
836 | 836 | ||
837 | down_write(¤t->namespace->sem); | 837 | down_write(&namespace_sem); |
838 | /* Something was mounted here while we slept */ | 838 | /* Something was mounted here while we slept */ |
839 | while (d_mountpoint(nd->dentry) && follow_down(&nd->mnt, &nd->dentry)) | 839 | while (d_mountpoint(nd->dentry) && follow_down(&nd->mnt, &nd->dentry)) |
840 | ; | 840 | ; |
@@ -862,11 +862,11 @@ int do_add_mount(struct vfsmount *newmnt, struct nameidata *nd, | |||
862 | list_add_tail(&newmnt->mnt_expire, fslist); | 862 | list_add_tail(&newmnt->mnt_expire, fslist); |
863 | spin_unlock(&vfsmount_lock); | 863 | spin_unlock(&vfsmount_lock); |
864 | } | 864 | } |
865 | up_write(¤t->namespace->sem); | 865 | up_write(&namespace_sem); |
866 | return 0; | 866 | return 0; |
867 | 867 | ||
868 | unlock: | 868 | unlock: |
869 | up_write(¤t->namespace->sem); | 869 | up_write(&namespace_sem); |
870 | mntput(newmnt); | 870 | mntput(newmnt); |
871 | return err; | 871 | return err; |
872 | } | 872 | } |
@@ -958,9 +958,9 @@ void mark_mounts_for_expiry(struct list_head *mounts) | |||
958 | get_namespace(namespace); | 958 | get_namespace(namespace); |
959 | 959 | ||
960 | spin_unlock(&vfsmount_lock); | 960 | spin_unlock(&vfsmount_lock); |
961 | down_write(&namespace->sem); | 961 | down_write(&namespace_sem); |
962 | expire_mount(mnt, mounts, &umounts); | 962 | expire_mount(mnt, mounts, &umounts); |
963 | up_write(&namespace->sem); | 963 | up_write(&namespace_sem); |
964 | release_mounts(&umounts); | 964 | release_mounts(&umounts); |
965 | mntput(mnt); | 965 | mntput(mnt); |
966 | put_namespace(namespace); | 966 | put_namespace(namespace); |
@@ -1127,17 +1127,16 @@ int copy_namespace(int flags, struct task_struct *tsk) | |||
1127 | goto out; | 1127 | goto out; |
1128 | 1128 | ||
1129 | atomic_set(&new_ns->count, 1); | 1129 | atomic_set(&new_ns->count, 1); |
1130 | init_rwsem(&new_ns->sem); | ||
1131 | INIT_LIST_HEAD(&new_ns->list); | 1130 | INIT_LIST_HEAD(&new_ns->list); |
1132 | init_waitqueue_head(&new_ns->poll); | 1131 | init_waitqueue_head(&new_ns->poll); |
1133 | new_ns->event = 0; | 1132 | new_ns->event = 0; |
1134 | 1133 | ||
1135 | down_write(&tsk->namespace->sem); | 1134 | down_write(&namespace_sem); |
1136 | /* First pass: copy the tree topology */ | 1135 | /* First pass: copy the tree topology */ |
1137 | new_ns->root = copy_tree(namespace->root, namespace->root->mnt_root, | 1136 | new_ns->root = copy_tree(namespace->root, namespace->root->mnt_root, |
1138 | CL_EXPIRE); | 1137 | CL_EXPIRE); |
1139 | if (!new_ns->root) { | 1138 | if (!new_ns->root) { |
1140 | up_write(&tsk->namespace->sem); | 1139 | up_write(&namespace_sem); |
1141 | kfree(new_ns); | 1140 | kfree(new_ns); |
1142 | goto out; | 1141 | goto out; |
1143 | } | 1142 | } |
@@ -1171,7 +1170,7 @@ int copy_namespace(int flags, struct task_struct *tsk) | |||
1171 | p = next_mnt(p, namespace->root); | 1170 | p = next_mnt(p, namespace->root); |
1172 | q = next_mnt(q, new_ns->root); | 1171 | q = next_mnt(q, new_ns->root); |
1173 | } | 1172 | } |
1174 | up_write(&tsk->namespace->sem); | 1173 | up_write(&namespace_sem); |
1175 | 1174 | ||
1176 | tsk->namespace = new_ns; | 1175 | tsk->namespace = new_ns; |
1177 | 1176 | ||
@@ -1356,7 +1355,7 @@ asmlinkage long sys_pivot_root(const char __user * new_root, | |||
1356 | user_nd.mnt = mntget(current->fs->rootmnt); | 1355 | user_nd.mnt = mntget(current->fs->rootmnt); |
1357 | user_nd.dentry = dget(current->fs->root); | 1356 | user_nd.dentry = dget(current->fs->root); |
1358 | read_unlock(¤t->fs->lock); | 1357 | read_unlock(¤t->fs->lock); |
1359 | down_write(¤t->namespace->sem); | 1358 | down_write(&namespace_sem); |
1360 | down(&old_nd.dentry->d_inode->i_sem); | 1359 | down(&old_nd.dentry->d_inode->i_sem); |
1361 | error = -EINVAL; | 1360 | error = -EINVAL; |
1362 | if (!check_mnt(user_nd.mnt)) | 1361 | if (!check_mnt(user_nd.mnt)) |
@@ -1407,7 +1406,7 @@ asmlinkage long sys_pivot_root(const char __user * new_root, | |||
1407 | path_release(&parent_nd); | 1406 | path_release(&parent_nd); |
1408 | out2: | 1407 | out2: |
1409 | up(&old_nd.dentry->d_inode->i_sem); | 1408 | up(&old_nd.dentry->d_inode->i_sem); |
1410 | up_write(¤t->namespace->sem); | 1409 | up_write(&namespace_sem); |
1411 | path_release(&user_nd); | 1410 | path_release(&user_nd); |
1412 | path_release(&old_nd); | 1411 | path_release(&old_nd); |
1413 | out1: | 1412 | out1: |
@@ -1434,7 +1433,6 @@ static void __init init_mount_tree(void) | |||
1434 | panic("Can't allocate initial namespace"); | 1433 | panic("Can't allocate initial namespace"); |
1435 | atomic_set(&namespace->count, 1); | 1434 | atomic_set(&namespace->count, 1); |
1436 | INIT_LIST_HEAD(&namespace->list); | 1435 | INIT_LIST_HEAD(&namespace->list); |
1437 | init_rwsem(&namespace->sem); | ||
1438 | init_waitqueue_head(&namespace->poll); | 1436 | init_waitqueue_head(&namespace->poll); |
1439 | namespace->event = 0; | 1437 | namespace->event = 0; |
1440 | list_add(&mnt->mnt_list, &namespace->list); | 1438 | list_add(&mnt->mnt_list, &namespace->list); |
@@ -1459,6 +1457,8 @@ void __init mnt_init(unsigned long mempages) | |||
1459 | unsigned int nr_hash; | 1457 | unsigned int nr_hash; |
1460 | int i; | 1458 | int i; |
1461 | 1459 | ||
1460 | init_rwsem(&namespace_sem); | ||
1461 | |||
1462 | mnt_cache = kmem_cache_create("mnt_cache", sizeof(struct vfsmount), | 1462 | mnt_cache = kmem_cache_create("mnt_cache", sizeof(struct vfsmount), |
1463 | 0, SLAB_HWCACHE_ALIGN | SLAB_PANIC, NULL, NULL); | 1463 | 0, SLAB_HWCACHE_ALIGN | SLAB_PANIC, NULL, NULL); |
1464 | 1464 | ||
@@ -1507,11 +1507,11 @@ void __put_namespace(struct namespace *namespace) | |||
1507 | LIST_HEAD(umount_list); | 1507 | LIST_HEAD(umount_list); |
1508 | namespace->root = NULL; | 1508 | namespace->root = NULL; |
1509 | spin_unlock(&vfsmount_lock); | 1509 | spin_unlock(&vfsmount_lock); |
1510 | down_write(&namespace->sem); | 1510 | down_write(&namespace_sem); |
1511 | spin_lock(&vfsmount_lock); | 1511 | spin_lock(&vfsmount_lock); |
1512 | umount_tree(root, &umount_list); | 1512 | umount_tree(root, &umount_list); |
1513 | spin_unlock(&vfsmount_lock); | 1513 | spin_unlock(&vfsmount_lock); |
1514 | up_write(&namespace->sem); | 1514 | up_write(&namespace_sem); |
1515 | release_mounts(&umount_list); | 1515 | release_mounts(&umount_list); |
1516 | kfree(namespace); | 1516 | kfree(namespace); |
1517 | } | 1517 | } |
diff --git a/include/linux/namespace.h b/include/linux/namespace.h index 6f0f25d64c38..6731977c4c13 100644 --- a/include/linux/namespace.h +++ b/include/linux/namespace.h | |||
@@ -9,7 +9,6 @@ struct namespace { | |||
9 | atomic_t count; | 9 | atomic_t count; |
10 | struct vfsmount * root; | 10 | struct vfsmount * root; |
11 | struct list_head list; | 11 | struct list_head list; |
12 | struct rw_semaphore sem; | ||
13 | wait_queue_head_t poll; | 12 | wait_queue_head_t poll; |
14 | int event; | 13 | int event; |
15 | }; | 14 | }; |