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 | /* |
