diff options
-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 |