diff options
author | Miklos Szeredi <mszeredi@suse.cz> | 2008-03-26 17:11:34 -0400 |
---|---|---|
committer | Al Viro <viro@zeniv.linux.org.uk> | 2008-04-23 00:04:45 -0400 |
commit | 73cd49ecdde92fdce131938bdaff4993010d181b (patch) | |
tree | 90c9cd3597a915c1f820a3cd1fde1689e9a7ab1f /fs/namespace.c | |
parent | 9d1bc60138977d9c79471b344a64f2df13b2ccef (diff) |
[patch 3/7] vfs: mountinfo: add mount ID
Add a unique ID to each vfsmount using the IDR infrastructure. The
identifiers are reused after the vfsmount is freed.
Signed-off-by: Miklos Szeredi <mszeredi@suse.cz>
Signed-off-by: Al Viro <viro@zeniv.linux.org.uk>
Diffstat (limited to 'fs/namespace.c')
-rw-r--r-- | fs/namespace.c | 34 |
1 files changed, 34 insertions, 0 deletions
diff --git a/fs/namespace.c b/fs/namespace.c index 1bf302d0478b..8ca6317cb401 100644 --- a/fs/namespace.c +++ b/fs/namespace.c | |||
@@ -27,6 +27,7 @@ | |||
27 | #include <linux/mount.h> | 27 | #include <linux/mount.h> |
28 | #include <linux/ramfs.h> | 28 | #include <linux/ramfs.h> |
29 | #include <linux/log2.h> | 29 | #include <linux/log2.h> |
30 | #include <linux/idr.h> | ||
30 | #include <asm/uaccess.h> | 31 | #include <asm/uaccess.h> |
31 | #include <asm/unistd.h> | 32 | #include <asm/unistd.h> |
32 | #include "pnode.h" | 33 | #include "pnode.h" |
@@ -39,6 +40,7 @@ | |||
39 | __cacheline_aligned_in_smp DEFINE_SPINLOCK(vfsmount_lock); | 40 | __cacheline_aligned_in_smp DEFINE_SPINLOCK(vfsmount_lock); |
40 | 41 | ||
41 | static int event; | 42 | static int event; |
43 | static DEFINE_IDA(mnt_id_ida); | ||
42 | 44 | ||
43 | static struct list_head *mount_hashtable __read_mostly; | 45 | static struct list_head *mount_hashtable __read_mostly; |
44 | static struct kmem_cache *mnt_cache __read_mostly; | 46 | static struct kmem_cache *mnt_cache __read_mostly; |
@@ -58,10 +60,41 @@ static inline unsigned long hash(struct vfsmount *mnt, struct dentry *dentry) | |||
58 | 60 | ||
59 | #define MNT_WRITER_UNDERFLOW_LIMIT -(1<<16) | 61 | #define MNT_WRITER_UNDERFLOW_LIMIT -(1<<16) |
60 | 62 | ||
63 | /* allocation is serialized by namespace_sem */ | ||
64 | static int mnt_alloc_id(struct vfsmount *mnt) | ||
65 | { | ||
66 | int res; | ||
67 | |||
68 | retry: | ||
69 | ida_pre_get(&mnt_id_ida, GFP_KERNEL); | ||
70 | spin_lock(&vfsmount_lock); | ||
71 | res = ida_get_new(&mnt_id_ida, &mnt->mnt_id); | ||
72 | spin_unlock(&vfsmount_lock); | ||
73 | if (res == -EAGAIN) | ||
74 | goto retry; | ||
75 | |||
76 | return res; | ||
77 | } | ||
78 | |||
79 | static void mnt_free_id(struct vfsmount *mnt) | ||
80 | { | ||
81 | spin_lock(&vfsmount_lock); | ||
82 | ida_remove(&mnt_id_ida, mnt->mnt_id); | ||
83 | spin_unlock(&vfsmount_lock); | ||
84 | } | ||
85 | |||
61 | struct vfsmount *alloc_vfsmnt(const char *name) | 86 | struct vfsmount *alloc_vfsmnt(const char *name) |
62 | { | 87 | { |
63 | struct vfsmount *mnt = kmem_cache_zalloc(mnt_cache, GFP_KERNEL); | 88 | struct vfsmount *mnt = kmem_cache_zalloc(mnt_cache, GFP_KERNEL); |
64 | if (mnt) { | 89 | if (mnt) { |
90 | int err; | ||
91 | |||
92 | err = mnt_alloc_id(mnt); | ||
93 | if (err) { | ||
94 | kmem_cache_free(mnt_cache, mnt); | ||
95 | return NULL; | ||
96 | } | ||
97 | |||
65 | atomic_set(&mnt->mnt_count, 1); | 98 | atomic_set(&mnt->mnt_count, 1); |
66 | INIT_LIST_HEAD(&mnt->mnt_hash); | 99 | INIT_LIST_HEAD(&mnt->mnt_hash); |
67 | INIT_LIST_HEAD(&mnt->mnt_child); | 100 | INIT_LIST_HEAD(&mnt->mnt_child); |
@@ -353,6 +386,7 @@ EXPORT_SYMBOL(simple_set_mnt); | |||
353 | void free_vfsmnt(struct vfsmount *mnt) | 386 | void free_vfsmnt(struct vfsmount *mnt) |
354 | { | 387 | { |
355 | kfree(mnt->mnt_devname); | 388 | kfree(mnt->mnt_devname); |
389 | mnt_free_id(mnt); | ||
356 | kmem_cache_free(mnt_cache, mnt); | 390 | kmem_cache_free(mnt_cache, mnt); |
357 | } | 391 | } |
358 | 392 | ||