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 | |
| 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>
| -rw-r--r-- | fs/namespace.c | 34 | ||||
| -rw-r--r-- | include/linux/mount.h | 1 |
2 files changed, 35 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 | ||
diff --git a/include/linux/mount.h b/include/linux/mount.h index 87b24cea1863..f0dfb17ffccc 100644 --- a/include/linux/mount.h +++ b/include/linux/mount.h | |||
| @@ -56,6 +56,7 @@ struct vfsmount { | |||
| 56 | struct list_head mnt_slave; /* slave list entry */ | 56 | struct list_head mnt_slave; /* slave list entry */ |
| 57 | struct vfsmount *mnt_master; /* slave is on master->mnt_slave_list */ | 57 | struct vfsmount *mnt_master; /* slave is on master->mnt_slave_list */ |
| 58 | struct mnt_namespace *mnt_ns; /* containing namespace */ | 58 | struct mnt_namespace *mnt_ns; /* containing namespace */ |
| 59 | int mnt_id; /* mount identifier */ | ||
| 59 | /* | 60 | /* |
| 60 | * We put mnt_count & mnt_expiry_mark at the end of struct vfsmount | 61 | * We put mnt_count & mnt_expiry_mark at the end of struct vfsmount |
| 61 | * to let these frequently modified fields in a separate cache line | 62 | * to let these frequently modified fields in a separate cache line |
