diff options
author | Al Viro <viro@zeniv.linux.org.uk> | 2011-11-24 22:37:54 -0500 |
---|---|---|
committer | Al Viro <viro@zeniv.linux.org.uk> | 2012-01-03 22:57:05 -0500 |
commit | 83adc7532229f1909cf37c429780f02f06fe05ee (patch) | |
tree | 7f7a36fea3f903c7f9c3f3860bc395a2ba7ad806 /fs/namespace.c | |
parent | a73324da7af4052e1d1ddec6a5980f552420e58b (diff) |
vfs: spread struct mount - work with counters
Signed-off-by: Al Viro <viro@zeniv.linux.org.uk>
Diffstat (limited to 'fs/namespace.c')
-rw-r--r-- | fs/namespace.c | 124 |
1 files changed, 64 insertions, 60 deletions
diff --git a/fs/namespace.c b/fs/namespace.c index ec798e77b726..a13165c871c2 100644 --- a/fs/namespace.c +++ b/fs/namespace.c | |||
@@ -141,13 +141,13 @@ void mnt_release_group_id(struct mount *mnt) | |||
141 | /* | 141 | /* |
142 | * vfsmount lock must be held for read | 142 | * vfsmount lock must be held for read |
143 | */ | 143 | */ |
144 | static inline void mnt_add_count(struct vfsmount *mnt, int n) | 144 | static inline void mnt_add_count(struct mount *mnt, int n) |
145 | { | 145 | { |
146 | #ifdef CONFIG_SMP | 146 | #ifdef CONFIG_SMP |
147 | this_cpu_add(mnt->mnt_pcp->mnt_count, n); | 147 | this_cpu_add(mnt->mnt.mnt_pcp->mnt_count, n); |
148 | #else | 148 | #else |
149 | preempt_disable(); | 149 | preempt_disable(); |
150 | mnt->mnt_count += n; | 150 | mnt->mnt.mnt_count += n; |
151 | preempt_enable(); | 151 | preempt_enable(); |
152 | #endif | 152 | #endif |
153 | } | 153 | } |
@@ -155,19 +155,19 @@ static inline void mnt_add_count(struct vfsmount *mnt, int n) | |||
155 | /* | 155 | /* |
156 | * vfsmount lock must be held for write | 156 | * vfsmount lock must be held for write |
157 | */ | 157 | */ |
158 | unsigned int mnt_get_count(struct vfsmount *mnt) | 158 | unsigned int mnt_get_count(struct mount *mnt) |
159 | { | 159 | { |
160 | #ifdef CONFIG_SMP | 160 | #ifdef CONFIG_SMP |
161 | unsigned int count = 0; | 161 | unsigned int count = 0; |
162 | int cpu; | 162 | int cpu; |
163 | 163 | ||
164 | for_each_possible_cpu(cpu) { | 164 | for_each_possible_cpu(cpu) { |
165 | count += per_cpu_ptr(mnt->mnt_pcp, cpu)->mnt_count; | 165 | count += per_cpu_ptr(mnt->mnt.mnt_pcp, cpu)->mnt_count; |
166 | } | 166 | } |
167 | 167 | ||
168 | return count; | 168 | return count; |
169 | #else | 169 | #else |
170 | return mnt->mnt_count; | 170 | return mnt->mnt.mnt_count; |
171 | #endif | 171 | #endif |
172 | } | 172 | } |
173 | 173 | ||
@@ -253,32 +253,32 @@ int __mnt_is_readonly(struct vfsmount *mnt) | |||
253 | } | 253 | } |
254 | EXPORT_SYMBOL_GPL(__mnt_is_readonly); | 254 | EXPORT_SYMBOL_GPL(__mnt_is_readonly); |
255 | 255 | ||
256 | static inline void mnt_inc_writers(struct vfsmount *mnt) | 256 | static inline void mnt_inc_writers(struct mount *mnt) |
257 | { | 257 | { |
258 | #ifdef CONFIG_SMP | 258 | #ifdef CONFIG_SMP |
259 | this_cpu_inc(mnt->mnt_pcp->mnt_writers); | 259 | this_cpu_inc(mnt->mnt.mnt_pcp->mnt_writers); |
260 | #else | 260 | #else |
261 | mnt->mnt_writers++; | 261 | mnt->mnt.mnt_writers++; |
262 | #endif | 262 | #endif |
263 | } | 263 | } |
264 | 264 | ||
265 | static inline void mnt_dec_writers(struct vfsmount *mnt) | 265 | static inline void mnt_dec_writers(struct mount *mnt) |
266 | { | 266 | { |
267 | #ifdef CONFIG_SMP | 267 | #ifdef CONFIG_SMP |
268 | this_cpu_dec(mnt->mnt_pcp->mnt_writers); | 268 | this_cpu_dec(mnt->mnt.mnt_pcp->mnt_writers); |
269 | #else | 269 | #else |
270 | mnt->mnt_writers--; | 270 | mnt->mnt.mnt_writers--; |
271 | #endif | 271 | #endif |
272 | } | 272 | } |
273 | 273 | ||
274 | static unsigned int mnt_get_writers(struct vfsmount *mnt) | 274 | static unsigned int mnt_get_writers(struct mount *mnt) |
275 | { | 275 | { |
276 | #ifdef CONFIG_SMP | 276 | #ifdef CONFIG_SMP |
277 | unsigned int count = 0; | 277 | unsigned int count = 0; |
278 | int cpu; | 278 | int cpu; |
279 | 279 | ||
280 | for_each_possible_cpu(cpu) { | 280 | for_each_possible_cpu(cpu) { |
281 | count += per_cpu_ptr(mnt->mnt_pcp, cpu)->mnt_writers; | 281 | count += per_cpu_ptr(mnt->mnt.mnt_pcp, cpu)->mnt_writers; |
282 | } | 282 | } |
283 | 283 | ||
284 | return count; | 284 | return count; |
@@ -297,7 +297,7 @@ static unsigned int mnt_get_writers(struct vfsmount *mnt) | |||
297 | */ | 297 | */ |
298 | /** | 298 | /** |
299 | * mnt_want_write - get write access to a mount | 299 | * mnt_want_write - get write access to a mount |
300 | * @mnt: the mount on which to take a write | 300 | * @m: the mount on which to take a write |
301 | * | 301 | * |
302 | * This tells the low-level filesystem that a write is | 302 | * This tells the low-level filesystem that a write is |
303 | * about to be performed to it, and makes sure that | 303 | * about to be performed to it, and makes sure that |
@@ -305,8 +305,9 @@ static unsigned int mnt_get_writers(struct vfsmount *mnt) | |||
305 | * the write operation is finished, mnt_drop_write() | 305 | * the write operation is finished, mnt_drop_write() |
306 | * must be called. This is effectively a refcount. | 306 | * must be called. This is effectively a refcount. |
307 | */ | 307 | */ |
308 | int mnt_want_write(struct vfsmount *mnt) | 308 | int mnt_want_write(struct vfsmount *m) |
309 | { | 309 | { |
310 | struct mount *mnt = real_mount(m); | ||
310 | int ret = 0; | 311 | int ret = 0; |
311 | 312 | ||
312 | preempt_disable(); | 313 | preempt_disable(); |
@@ -317,7 +318,7 @@ int mnt_want_write(struct vfsmount *mnt) | |||
317 | * incremented count after it has set MNT_WRITE_HOLD. | 318 | * incremented count after it has set MNT_WRITE_HOLD. |
318 | */ | 319 | */ |
319 | smp_mb(); | 320 | smp_mb(); |
320 | while (mnt->mnt_flags & MNT_WRITE_HOLD) | 321 | while (mnt->mnt.mnt_flags & MNT_WRITE_HOLD) |
321 | cpu_relax(); | 322 | cpu_relax(); |
322 | /* | 323 | /* |
323 | * After the slowpath clears MNT_WRITE_HOLD, mnt_is_readonly will | 324 | * After the slowpath clears MNT_WRITE_HOLD, mnt_is_readonly will |
@@ -325,7 +326,7 @@ int mnt_want_write(struct vfsmount *mnt) | |||
325 | * MNT_WRITE_HOLD is cleared. | 326 | * MNT_WRITE_HOLD is cleared. |
326 | */ | 327 | */ |
327 | smp_rmb(); | 328 | smp_rmb(); |
328 | if (__mnt_is_readonly(mnt)) { | 329 | if (__mnt_is_readonly(m)) { |
329 | mnt_dec_writers(mnt); | 330 | mnt_dec_writers(mnt); |
330 | ret = -EROFS; | 331 | ret = -EROFS; |
331 | goto out; | 332 | goto out; |
@@ -354,7 +355,7 @@ int mnt_clone_write(struct vfsmount *mnt) | |||
354 | if (__mnt_is_readonly(mnt)) | 355 | if (__mnt_is_readonly(mnt)) |
355 | return -EROFS; | 356 | return -EROFS; |
356 | preempt_disable(); | 357 | preempt_disable(); |
357 | mnt_inc_writers(mnt); | 358 | mnt_inc_writers(real_mount(mnt)); |
358 | preempt_enable(); | 359 | preempt_enable(); |
359 | return 0; | 360 | return 0; |
360 | } | 361 | } |
@@ -388,7 +389,7 @@ EXPORT_SYMBOL_GPL(mnt_want_write_file); | |||
388 | void mnt_drop_write(struct vfsmount *mnt) | 389 | void mnt_drop_write(struct vfsmount *mnt) |
389 | { | 390 | { |
390 | preempt_disable(); | 391 | preempt_disable(); |
391 | mnt_dec_writers(mnt); | 392 | mnt_dec_writers(real_mount(mnt)); |
392 | preempt_enable(); | 393 | preempt_enable(); |
393 | } | 394 | } |
394 | EXPORT_SYMBOL_GPL(mnt_drop_write); | 395 | EXPORT_SYMBOL_GPL(mnt_drop_write); |
@@ -399,12 +400,12 @@ void mnt_drop_write_file(struct file *file) | |||
399 | } | 400 | } |
400 | EXPORT_SYMBOL(mnt_drop_write_file); | 401 | EXPORT_SYMBOL(mnt_drop_write_file); |
401 | 402 | ||
402 | static int mnt_make_readonly(struct vfsmount *mnt) | 403 | static int mnt_make_readonly(struct mount *mnt) |
403 | { | 404 | { |
404 | int ret = 0; | 405 | int ret = 0; |
405 | 406 | ||
406 | br_write_lock(vfsmount_lock); | 407 | br_write_lock(vfsmount_lock); |
407 | mnt->mnt_flags |= MNT_WRITE_HOLD; | 408 | mnt->mnt.mnt_flags |= MNT_WRITE_HOLD; |
408 | /* | 409 | /* |
409 | * After storing MNT_WRITE_HOLD, we'll read the counters. This store | 410 | * After storing MNT_WRITE_HOLD, we'll read the counters. This store |
410 | * should be visible before we do. | 411 | * should be visible before we do. |
@@ -430,21 +431,21 @@ static int mnt_make_readonly(struct vfsmount *mnt) | |||
430 | if (mnt_get_writers(mnt) > 0) | 431 | if (mnt_get_writers(mnt) > 0) |
431 | ret = -EBUSY; | 432 | ret = -EBUSY; |
432 | else | 433 | else |
433 | mnt->mnt_flags |= MNT_READONLY; | 434 | mnt->mnt.mnt_flags |= MNT_READONLY; |
434 | /* | 435 | /* |
435 | * MNT_READONLY must become visible before ~MNT_WRITE_HOLD, so writers | 436 | * MNT_READONLY must become visible before ~MNT_WRITE_HOLD, so writers |
436 | * that become unheld will see MNT_READONLY. | 437 | * that become unheld will see MNT_READONLY. |
437 | */ | 438 | */ |
438 | smp_wmb(); | 439 | smp_wmb(); |
439 | mnt->mnt_flags &= ~MNT_WRITE_HOLD; | 440 | mnt->mnt.mnt_flags &= ~MNT_WRITE_HOLD; |
440 | br_write_unlock(vfsmount_lock); | 441 | br_write_unlock(vfsmount_lock); |
441 | return ret; | 442 | return ret; |
442 | } | 443 | } |
443 | 444 | ||
444 | static void __mnt_unmake_readonly(struct vfsmount *mnt) | 445 | static void __mnt_unmake_readonly(struct mount *mnt) |
445 | { | 446 | { |
446 | br_write_lock(vfsmount_lock); | 447 | br_write_lock(vfsmount_lock); |
447 | mnt->mnt_flags &= ~MNT_READONLY; | 448 | mnt->mnt.mnt_flags &= ~MNT_READONLY; |
448 | br_write_unlock(vfsmount_lock); | 449 | br_write_unlock(vfsmount_lock); |
449 | } | 450 | } |
450 | 451 | ||
@@ -590,18 +591,18 @@ static void attach_mnt(struct mount *mnt, struct path *path) | |||
590 | list_add_tail(&mnt->mnt.mnt_child, &path->mnt->mnt_mounts); | 591 | list_add_tail(&mnt->mnt.mnt_child, &path->mnt->mnt_mounts); |
591 | } | 592 | } |
592 | 593 | ||
593 | static inline void __mnt_make_longterm(struct vfsmount *mnt) | 594 | static inline void __mnt_make_longterm(struct mount *mnt) |
594 | { | 595 | { |
595 | #ifdef CONFIG_SMP | 596 | #ifdef CONFIG_SMP |
596 | atomic_inc(&mnt->mnt_longterm); | 597 | atomic_inc(&mnt->mnt.mnt_longterm); |
597 | #endif | 598 | #endif |
598 | } | 599 | } |
599 | 600 | ||
600 | /* needs vfsmount lock for write */ | 601 | /* needs vfsmount lock for write */ |
601 | static inline void __mnt_make_shortterm(struct vfsmount *mnt) | 602 | static inline void __mnt_make_shortterm(struct mount *mnt) |
602 | { | 603 | { |
603 | #ifdef CONFIG_SMP | 604 | #ifdef CONFIG_SMP |
604 | atomic_dec(&mnt->mnt_longterm); | 605 | atomic_dec(&mnt->mnt.mnt_longterm); |
605 | #endif | 606 | #endif |
606 | } | 607 | } |
607 | 608 | ||
@@ -611,15 +612,15 @@ static inline void __mnt_make_shortterm(struct vfsmount *mnt) | |||
611 | static void commit_tree(struct mount *mnt) | 612 | static void commit_tree(struct mount *mnt) |
612 | { | 613 | { |
613 | struct mount *parent = mnt->mnt_parent; | 614 | struct mount *parent = mnt->mnt_parent; |
614 | struct vfsmount *m; | 615 | struct mount *m; |
615 | LIST_HEAD(head); | 616 | LIST_HEAD(head); |
616 | struct mnt_namespace *n = parent->mnt.mnt_ns; | 617 | struct mnt_namespace *n = parent->mnt.mnt_ns; |
617 | 618 | ||
618 | BUG_ON(parent == mnt); | 619 | BUG_ON(parent == mnt); |
619 | 620 | ||
620 | list_add_tail(&head, &mnt->mnt.mnt_list); | 621 | list_add_tail(&head, &mnt->mnt.mnt_list); |
621 | list_for_each_entry(m, &head, mnt_list) { | 622 | list_for_each_entry(m, &head, mnt.mnt_list) { |
622 | m->mnt_ns = n; | 623 | m->mnt.mnt_ns = n; |
623 | __mnt_make_longterm(m); | 624 | __mnt_make_longterm(m); |
624 | } | 625 | } |
625 | 626 | ||
@@ -740,9 +741,10 @@ static struct mount *clone_mnt(struct mount *old, struct dentry *root, | |||
740 | return NULL; | 741 | return NULL; |
741 | } | 742 | } |
742 | 743 | ||
743 | static inline void mntfree(struct vfsmount *mnt) | 744 | static inline void mntfree(struct mount *mnt) |
744 | { | 745 | { |
745 | struct super_block *sb = mnt->mnt_sb; | 746 | struct vfsmount *m = &mnt->mnt; |
747 | struct super_block *sb = m->mnt_sb; | ||
746 | 748 | ||
747 | /* | 749 | /* |
748 | * This probably indicates that somebody messed | 750 | * This probably indicates that somebody messed |
@@ -755,18 +757,19 @@ static inline void mntfree(struct vfsmount *mnt) | |||
755 | * so mnt_get_writers() below is safe. | 757 | * so mnt_get_writers() below is safe. |
756 | */ | 758 | */ |
757 | WARN_ON(mnt_get_writers(mnt)); | 759 | WARN_ON(mnt_get_writers(mnt)); |
758 | fsnotify_vfsmount_delete(mnt); | 760 | fsnotify_vfsmount_delete(m); |
759 | dput(mnt->mnt_root); | 761 | dput(m->mnt_root); |
760 | free_vfsmnt(real_mount(mnt)); | 762 | free_vfsmnt(mnt); |
761 | deactivate_super(sb); | 763 | deactivate_super(sb); |
762 | } | 764 | } |
763 | 765 | ||
764 | static void mntput_no_expire(struct vfsmount *mnt) | 766 | static void mntput_no_expire(struct vfsmount *m) |
765 | { | 767 | { |
768 | struct mount *mnt = real_mount(m); | ||
766 | put_again: | 769 | put_again: |
767 | #ifdef CONFIG_SMP | 770 | #ifdef CONFIG_SMP |
768 | br_read_lock(vfsmount_lock); | 771 | br_read_lock(vfsmount_lock); |
769 | if (likely(atomic_read(&mnt->mnt_longterm))) { | 772 | if (likely(atomic_read(&mnt->mnt.mnt_longterm))) { |
770 | mnt_add_count(mnt, -1); | 773 | mnt_add_count(mnt, -1); |
771 | br_read_unlock(vfsmount_lock); | 774 | br_read_unlock(vfsmount_lock); |
772 | return; | 775 | return; |
@@ -785,11 +788,11 @@ put_again: | |||
785 | return; | 788 | return; |
786 | br_write_lock(vfsmount_lock); | 789 | br_write_lock(vfsmount_lock); |
787 | #endif | 790 | #endif |
788 | if (unlikely(mnt->mnt_pinned)) { | 791 | if (unlikely(mnt->mnt.mnt_pinned)) { |
789 | mnt_add_count(mnt, mnt->mnt_pinned + 1); | 792 | mnt_add_count(mnt, mnt->mnt.mnt_pinned + 1); |
790 | mnt->mnt_pinned = 0; | 793 | mnt->mnt.mnt_pinned = 0; |
791 | br_write_unlock(vfsmount_lock); | 794 | br_write_unlock(vfsmount_lock); |
792 | acct_auto_close_mnt(mnt); | 795 | acct_auto_close_mnt(m); |
793 | goto put_again; | 796 | goto put_again; |
794 | } | 797 | } |
795 | br_write_unlock(vfsmount_lock); | 798 | br_write_unlock(vfsmount_lock); |
@@ -810,7 +813,7 @@ EXPORT_SYMBOL(mntput); | |||
810 | struct vfsmount *mntget(struct vfsmount *mnt) | 813 | struct vfsmount *mntget(struct vfsmount *mnt) |
811 | { | 814 | { |
812 | if (mnt) | 815 | if (mnt) |
813 | mnt_add_count(mnt, 1); | 816 | mnt_add_count(real_mount(mnt), 1); |
814 | return mnt; | 817 | return mnt; |
815 | } | 818 | } |
816 | EXPORT_SYMBOL(mntget); | 819 | EXPORT_SYMBOL(mntget); |
@@ -827,7 +830,7 @@ void mnt_unpin(struct vfsmount *mnt) | |||
827 | { | 830 | { |
828 | br_write_lock(vfsmount_lock); | 831 | br_write_lock(vfsmount_lock); |
829 | if (mnt->mnt_pinned) { | 832 | if (mnt->mnt_pinned) { |
830 | mnt_add_count(mnt, 1); | 833 | mnt_add_count(real_mount(mnt), 1); |
831 | mnt->mnt_pinned--; | 834 | mnt->mnt_pinned--; |
832 | } | 835 | } |
833 | br_write_unlock(vfsmount_lock); | 836 | br_write_unlock(vfsmount_lock); |
@@ -1150,7 +1153,7 @@ int may_umount_tree(struct vfsmount *mnt) | |||
1150 | /* write lock needed for mnt_get_count */ | 1153 | /* write lock needed for mnt_get_count */ |
1151 | br_write_lock(vfsmount_lock); | 1154 | br_write_lock(vfsmount_lock); |
1152 | for (p = real_mount(mnt); p; p = next_mnt(p, mnt)) { | 1155 | for (p = real_mount(mnt); p; p = next_mnt(p, mnt)) { |
1153 | actual_refs += mnt_get_count(&p->mnt); | 1156 | actual_refs += mnt_get_count(p); |
1154 | minimum_refs += 2; | 1157 | minimum_refs += 2; |
1155 | } | 1158 | } |
1156 | br_write_unlock(vfsmount_lock); | 1159 | br_write_unlock(vfsmount_lock); |
@@ -1234,7 +1237,7 @@ void umount_tree(struct mount *mnt, int propagate, struct list_head *kill) | |||
1234 | list_del_init(&p->mnt.mnt_list); | 1237 | list_del_init(&p->mnt.mnt_list); |
1235 | __touch_mnt_namespace(p->mnt.mnt_ns); | 1238 | __touch_mnt_namespace(p->mnt.mnt_ns); |
1236 | p->mnt.mnt_ns = NULL; | 1239 | p->mnt.mnt_ns = NULL; |
1237 | __mnt_make_shortterm(&p->mnt); | 1240 | __mnt_make_shortterm(p); |
1238 | list_del_init(&p->mnt.mnt_child); | 1241 | list_del_init(&p->mnt.mnt_child); |
1239 | if (mnt_has_parent(p)) { | 1242 | if (mnt_has_parent(p)) { |
1240 | p->mnt_parent->mnt.mnt_ghosts++; | 1243 | p->mnt_parent->mnt.mnt_ghosts++; |
@@ -1273,7 +1276,7 @@ static int do_umount(struct mount *mnt, int flags) | |||
1273 | * all race cases, but it's a slowpath. | 1276 | * all race cases, but it's a slowpath. |
1274 | */ | 1277 | */ |
1275 | br_write_lock(vfsmount_lock); | 1278 | br_write_lock(vfsmount_lock); |
1276 | if (mnt_get_count(&mnt->mnt) != 2) { | 1279 | if (mnt_get_count(mnt) != 2) { |
1277 | br_write_unlock(vfsmount_lock); | 1280 | br_write_unlock(vfsmount_lock); |
1278 | return -EBUSY; | 1281 | return -EBUSY; |
1279 | } | 1282 | } |
@@ -1798,9 +1801,9 @@ static int change_mount_flags(struct vfsmount *mnt, int ms_flags) | |||
1798 | return 0; | 1801 | return 0; |
1799 | 1802 | ||
1800 | if (readonly_request) | 1803 | if (readonly_request) |
1801 | error = mnt_make_readonly(mnt); | 1804 | error = mnt_make_readonly(real_mount(mnt)); |
1802 | else | 1805 | else |
1803 | __mnt_unmake_readonly(mnt); | 1806 | __mnt_unmake_readonly(real_mount(mnt)); |
1804 | return error; | 1807 | return error; |
1805 | } | 1808 | } |
1806 | 1809 | ||
@@ -2034,7 +2037,7 @@ int finish_automount(struct vfsmount *m, struct path *path) | |||
2034 | /* The new mount record should have at least 2 refs to prevent it being | 2037 | /* The new mount record should have at least 2 refs to prevent it being |
2035 | * expired before we get a chance to add it | 2038 | * expired before we get a chance to add it |
2036 | */ | 2039 | */ |
2037 | BUG_ON(mnt_get_count(m) < 2); | 2040 | BUG_ON(mnt_get_count(real_mount(m)) < 2); |
2038 | 2041 | ||
2039 | if (m->mnt_sb == path->mnt->mnt_sb && | 2042 | if (m->mnt_sb == path->mnt->mnt_sb && |
2040 | m->mnt_root == path->dentry) { | 2043 | m->mnt_root == path->dentry) { |
@@ -2365,16 +2368,17 @@ static struct mnt_namespace *alloc_mnt_ns(void) | |||
2365 | 2368 | ||
2366 | void mnt_make_longterm(struct vfsmount *mnt) | 2369 | void mnt_make_longterm(struct vfsmount *mnt) |
2367 | { | 2370 | { |
2368 | __mnt_make_longterm(mnt); | 2371 | __mnt_make_longterm(real_mount(mnt)); |
2369 | } | 2372 | } |
2370 | 2373 | ||
2371 | void mnt_make_shortterm(struct vfsmount *mnt) | 2374 | void mnt_make_shortterm(struct vfsmount *m) |
2372 | { | 2375 | { |
2373 | #ifdef CONFIG_SMP | 2376 | #ifdef CONFIG_SMP |
2374 | if (atomic_add_unless(&mnt->mnt_longterm, -1, 1)) | 2377 | struct mount *mnt = real_mount(m); |
2378 | if (atomic_add_unless(&mnt->mnt.mnt_longterm, -1, 1)) | ||
2375 | return; | 2379 | return; |
2376 | br_write_lock(vfsmount_lock); | 2380 | br_write_lock(vfsmount_lock); |
2377 | atomic_dec(&mnt->mnt_longterm); | 2381 | atomic_dec(&mnt->mnt.mnt_longterm); |
2378 | br_write_unlock(vfsmount_lock); | 2382 | br_write_unlock(vfsmount_lock); |
2379 | #endif | 2383 | #endif |
2380 | } | 2384 | } |
@@ -2418,17 +2422,17 @@ static struct mnt_namespace *dup_mnt_ns(struct mnt_namespace *mnt_ns, | |||
2418 | q = new; | 2422 | q = new; |
2419 | while (p) { | 2423 | while (p) { |
2420 | q->mnt.mnt_ns = new_ns; | 2424 | q->mnt.mnt_ns = new_ns; |
2421 | __mnt_make_longterm(&q->mnt); | 2425 | __mnt_make_longterm(q); |
2422 | if (fs) { | 2426 | if (fs) { |
2423 | if (&p->mnt == fs->root.mnt) { | 2427 | if (&p->mnt == fs->root.mnt) { |
2424 | fs->root.mnt = mntget(&q->mnt); | 2428 | fs->root.mnt = mntget(&q->mnt); |
2425 | __mnt_make_longterm(&q->mnt); | 2429 | __mnt_make_longterm(q); |
2426 | mnt_make_shortterm(&p->mnt); | 2430 | mnt_make_shortterm(&p->mnt); |
2427 | rootmnt = &p->mnt; | 2431 | rootmnt = &p->mnt; |
2428 | } | 2432 | } |
2429 | if (&p->mnt == fs->pwd.mnt) { | 2433 | if (&p->mnt == fs->pwd.mnt) { |
2430 | fs->pwd.mnt = mntget(&q->mnt); | 2434 | fs->pwd.mnt = mntget(&q->mnt); |
2431 | __mnt_make_longterm(&q->mnt); | 2435 | __mnt_make_longterm(q); |
2432 | mnt_make_shortterm(&p->mnt); | 2436 | mnt_make_shortterm(&p->mnt); |
2433 | pwdmnt = &p->mnt; | 2437 | pwdmnt = &p->mnt; |
2434 | } | 2438 | } |
@@ -2474,7 +2478,7 @@ static struct mnt_namespace *create_mnt_ns(struct vfsmount *mnt) | |||
2474 | new_ns = alloc_mnt_ns(); | 2478 | new_ns = alloc_mnt_ns(); |
2475 | if (!IS_ERR(new_ns)) { | 2479 | if (!IS_ERR(new_ns)) { |
2476 | mnt->mnt_ns = new_ns; | 2480 | mnt->mnt_ns = new_ns; |
2477 | __mnt_make_longterm(mnt); | 2481 | __mnt_make_longterm(real_mount(mnt)); |
2478 | new_ns->root = mnt; | 2482 | new_ns->root = mnt; |
2479 | list_add(&new_ns->list, &new_ns->root->mnt_list); | 2483 | list_add(&new_ns->list, &new_ns->root->mnt_list); |
2480 | } else { | 2484 | } else { |