diff options
Diffstat (limited to 'fs/namespace.c')
-rw-r--r-- | fs/namespace.c | 26 |
1 files changed, 22 insertions, 4 deletions
diff --git a/fs/namespace.c b/fs/namespace.c index 4a86b8595164..3dc283fd4716 100644 --- a/fs/namespace.c +++ b/fs/namespace.c | |||
@@ -42,6 +42,8 @@ __cacheline_aligned_in_smp DEFINE_SPINLOCK(vfsmount_lock); | |||
42 | static int event; | 42 | static int event; |
43 | static DEFINE_IDA(mnt_id_ida); | 43 | static DEFINE_IDA(mnt_id_ida); |
44 | static DEFINE_IDA(mnt_group_ida); | 44 | static DEFINE_IDA(mnt_group_ida); |
45 | static int mnt_id_start = 0; | ||
46 | static int mnt_group_start = 1; | ||
45 | 47 | ||
46 | static struct list_head *mount_hashtable __read_mostly; | 48 | static struct list_head *mount_hashtable __read_mostly; |
47 | static struct kmem_cache *mnt_cache __read_mostly; | 49 | static struct kmem_cache *mnt_cache __read_mostly; |
@@ -69,7 +71,9 @@ static int mnt_alloc_id(struct vfsmount *mnt) | |||
69 | retry: | 71 | retry: |
70 | ida_pre_get(&mnt_id_ida, GFP_KERNEL); | 72 | ida_pre_get(&mnt_id_ida, GFP_KERNEL); |
71 | spin_lock(&vfsmount_lock); | 73 | spin_lock(&vfsmount_lock); |
72 | res = ida_get_new(&mnt_id_ida, &mnt->mnt_id); | 74 | res = ida_get_new_above(&mnt_id_ida, mnt_id_start, &mnt->mnt_id); |
75 | if (!res) | ||
76 | mnt_id_start = mnt->mnt_id + 1; | ||
73 | spin_unlock(&vfsmount_lock); | 77 | spin_unlock(&vfsmount_lock); |
74 | if (res == -EAGAIN) | 78 | if (res == -EAGAIN) |
75 | goto retry; | 79 | goto retry; |
@@ -79,8 +83,11 @@ retry: | |||
79 | 83 | ||
80 | static void mnt_free_id(struct vfsmount *mnt) | 84 | static void mnt_free_id(struct vfsmount *mnt) |
81 | { | 85 | { |
86 | int id = mnt->mnt_id; | ||
82 | spin_lock(&vfsmount_lock); | 87 | spin_lock(&vfsmount_lock); |
83 | ida_remove(&mnt_id_ida, mnt->mnt_id); | 88 | ida_remove(&mnt_id_ida, id); |
89 | if (mnt_id_start > id) | ||
90 | mnt_id_start = id; | ||
84 | spin_unlock(&vfsmount_lock); | 91 | spin_unlock(&vfsmount_lock); |
85 | } | 92 | } |
86 | 93 | ||
@@ -91,10 +98,18 @@ static void mnt_free_id(struct vfsmount *mnt) | |||
91 | */ | 98 | */ |
92 | static int mnt_alloc_group_id(struct vfsmount *mnt) | 99 | static int mnt_alloc_group_id(struct vfsmount *mnt) |
93 | { | 100 | { |
101 | int res; | ||
102 | |||
94 | if (!ida_pre_get(&mnt_group_ida, GFP_KERNEL)) | 103 | if (!ida_pre_get(&mnt_group_ida, GFP_KERNEL)) |
95 | return -ENOMEM; | 104 | return -ENOMEM; |
96 | 105 | ||
97 | return ida_get_new_above(&mnt_group_ida, 1, &mnt->mnt_group_id); | 106 | res = ida_get_new_above(&mnt_group_ida, |
107 | mnt_group_start, | ||
108 | &mnt->mnt_group_id); | ||
109 | if (!res) | ||
110 | mnt_group_start = mnt->mnt_group_id + 1; | ||
111 | |||
112 | return res; | ||
98 | } | 113 | } |
99 | 114 | ||
100 | /* | 115 | /* |
@@ -102,7 +117,10 @@ static int mnt_alloc_group_id(struct vfsmount *mnt) | |||
102 | */ | 117 | */ |
103 | void mnt_release_group_id(struct vfsmount *mnt) | 118 | void mnt_release_group_id(struct vfsmount *mnt) |
104 | { | 119 | { |
105 | ida_remove(&mnt_group_ida, mnt->mnt_group_id); | 120 | int id = mnt->mnt_group_id; |
121 | ida_remove(&mnt_group_ida, id); | ||
122 | if (mnt_group_start > id) | ||
123 | mnt_group_start = id; | ||
106 | mnt->mnt_group_id = 0; | 124 | mnt->mnt_group_id = 0; |
107 | } | 125 | } |
108 | 126 | ||