diff options
Diffstat (limited to 'fs/namespace.c')
-rw-r--r-- | fs/namespace.c | 64 |
1 files changed, 41 insertions, 23 deletions
diff --git a/fs/namespace.c b/fs/namespace.c index 2fa9fdf7d6f5..1d83302f30c3 100644 --- a/fs/namespace.c +++ b/fs/namespace.c | |||
@@ -172,7 +172,7 @@ clone_mnt(struct vfsmount *old, struct dentry *root) | |||
172 | return mnt; | 172 | return mnt; |
173 | } | 173 | } |
174 | 174 | ||
175 | void __mntput(struct vfsmount *mnt) | 175 | static inline void __mntput(struct vfsmount *mnt) |
176 | { | 176 | { |
177 | struct super_block *sb = mnt->mnt_sb; | 177 | struct super_block *sb = mnt->mnt_sb; |
178 | dput(mnt->mnt_root); | 178 | dput(mnt->mnt_root); |
@@ -180,7 +180,46 @@ void __mntput(struct vfsmount *mnt) | |||
180 | deactivate_super(sb); | 180 | deactivate_super(sb); |
181 | } | 181 | } |
182 | 182 | ||
183 | EXPORT_SYMBOL(__mntput); | 183 | void mntput_no_expire(struct vfsmount *mnt) |
184 | { | ||
185 | repeat: | ||
186 | if (atomic_dec_and_lock(&mnt->mnt_count, &vfsmount_lock)) { | ||
187 | if (likely(!mnt->mnt_pinned)) { | ||
188 | spin_unlock(&vfsmount_lock); | ||
189 | __mntput(mnt); | ||
190 | return; | ||
191 | } | ||
192 | atomic_add(mnt->mnt_pinned + 1, &mnt->mnt_count); | ||
193 | mnt->mnt_pinned = 0; | ||
194 | spin_unlock(&vfsmount_lock); | ||
195 | acct_auto_close_mnt(mnt); | ||
196 | security_sb_umount_close(mnt); | ||
197 | goto repeat; | ||
198 | } | ||
199 | } | ||
200 | |||
201 | EXPORT_SYMBOL(mntput_no_expire); | ||
202 | |||
203 | void mnt_pin(struct vfsmount *mnt) | ||
204 | { | ||
205 | spin_lock(&vfsmount_lock); | ||
206 | mnt->mnt_pinned++; | ||
207 | spin_unlock(&vfsmount_lock); | ||
208 | } | ||
209 | |||
210 | EXPORT_SYMBOL(mnt_pin); | ||
211 | |||
212 | void mnt_unpin(struct vfsmount *mnt) | ||
213 | { | ||
214 | spin_lock(&vfsmount_lock); | ||
215 | if (mnt->mnt_pinned) { | ||
216 | atomic_inc(&mnt->mnt_count); | ||
217 | mnt->mnt_pinned--; | ||
218 | } | ||
219 | spin_unlock(&vfsmount_lock); | ||
220 | } | ||
221 | |||
222 | EXPORT_SYMBOL(mnt_unpin); | ||
184 | 223 | ||
185 | /* iterator */ | 224 | /* iterator */ |
186 | static void *m_start(struct seq_file *m, loff_t *pos) | 225 | static void *m_start(struct seq_file *m, loff_t *pos) |
@@ -435,16 +474,6 @@ static int do_umount(struct vfsmount *mnt, int flags) | |||
435 | down_write(¤t->namespace->sem); | 474 | down_write(¤t->namespace->sem); |
436 | spin_lock(&vfsmount_lock); | 475 | spin_lock(&vfsmount_lock); |
437 | 476 | ||
438 | if (atomic_read(&sb->s_active) == 1) { | ||
439 | /* last instance - try to be smart */ | ||
440 | spin_unlock(&vfsmount_lock); | ||
441 | lock_kernel(); | ||
442 | DQUOT_OFF(sb); | ||
443 | acct_auto_close(sb); | ||
444 | unlock_kernel(); | ||
445 | security_sb_umount_close(mnt); | ||
446 | spin_lock(&vfsmount_lock); | ||
447 | } | ||
448 | retval = -EBUSY; | 477 | retval = -EBUSY; |
449 | if (atomic_read(&mnt->mnt_count) == 2 || flags & MNT_DETACH) { | 478 | if (atomic_read(&mnt->mnt_count) == 2 || flags & MNT_DETACH) { |
450 | if (!list_empty(&mnt->mnt_list)) | 479 | if (!list_empty(&mnt->mnt_list)) |
@@ -850,17 +879,6 @@ static void expire_mount(struct vfsmount *mnt, struct list_head *mounts) | |||
850 | detach_mnt(mnt, &old_nd); | 879 | detach_mnt(mnt, &old_nd); |
851 | spin_unlock(&vfsmount_lock); | 880 | spin_unlock(&vfsmount_lock); |
852 | path_release(&old_nd); | 881 | path_release(&old_nd); |
853 | |||
854 | /* | ||
855 | * Now lay it to rest if this was the last ref on the superblock | ||
856 | */ | ||
857 | if (atomic_read(&mnt->mnt_sb->s_active) == 1) { | ||
858 | /* last instance - try to be smart */ | ||
859 | lock_kernel(); | ||
860 | DQUOT_OFF(mnt->mnt_sb); | ||
861 | acct_auto_close(mnt->mnt_sb); | ||
862 | unlock_kernel(); | ||
863 | } | ||
864 | mntput(mnt); | 882 | mntput(mnt); |
865 | } else { | 883 | } else { |
866 | /* | 884 | /* |