diff options
Diffstat (limited to 'fs/namespace.c')
-rw-r--r-- | fs/namespace.c | 225 |
1 files changed, 129 insertions, 96 deletions
diff --git a/fs/namespace.c b/fs/namespace.c index 1b3f2ac59c5e..a66feed7311d 100644 --- a/fs/namespace.c +++ b/fs/namespace.c | |||
@@ -183,7 +183,7 @@ static inline void mnt_dec_count(struct vfsmount *mnt) | |||
183 | unsigned int mnt_get_count(struct vfsmount *mnt) | 183 | unsigned int mnt_get_count(struct vfsmount *mnt) |
184 | { | 184 | { |
185 | #ifdef CONFIG_SMP | 185 | #ifdef CONFIG_SMP |
186 | unsigned int count = atomic_read(&mnt->mnt_longrefs); | 186 | unsigned int count = 0; |
187 | int cpu; | 187 | int cpu; |
188 | 188 | ||
189 | for_each_possible_cpu(cpu) { | 189 | for_each_possible_cpu(cpu) { |
@@ -217,7 +217,7 @@ struct vfsmount *alloc_vfsmnt(const char *name) | |||
217 | if (!mnt->mnt_pcp) | 217 | if (!mnt->mnt_pcp) |
218 | goto out_free_devname; | 218 | goto out_free_devname; |
219 | 219 | ||
220 | atomic_set(&mnt->mnt_longrefs, 1); | 220 | this_cpu_add(mnt->mnt_pcp->mnt_count, 1); |
221 | #else | 221 | #else |
222 | mnt->mnt_count = 1; | 222 | mnt->mnt_count = 1; |
223 | mnt->mnt_writers = 0; | 223 | mnt->mnt_writers = 0; |
@@ -611,6 +611,21 @@ static void attach_mnt(struct vfsmount *mnt, struct path *path) | |||
611 | list_add_tail(&mnt->mnt_child, &path->mnt->mnt_mounts); | 611 | list_add_tail(&mnt->mnt_child, &path->mnt->mnt_mounts); |
612 | } | 612 | } |
613 | 613 | ||
614 | static inline void __mnt_make_longterm(struct vfsmount *mnt) | ||
615 | { | ||
616 | #ifdef CONFIG_SMP | ||
617 | atomic_inc(&mnt->mnt_longterm); | ||
618 | #endif | ||
619 | } | ||
620 | |||
621 | /* needs vfsmount lock for write */ | ||
622 | static inline void __mnt_make_shortterm(struct vfsmount *mnt) | ||
623 | { | ||
624 | #ifdef CONFIG_SMP | ||
625 | atomic_dec(&mnt->mnt_longterm); | ||
626 | #endif | ||
627 | } | ||
628 | |||
614 | /* | 629 | /* |
615 | * vfsmount lock must be held for write | 630 | * vfsmount lock must be held for write |
616 | */ | 631 | */ |
@@ -624,8 +639,11 @@ static void commit_tree(struct vfsmount *mnt) | |||
624 | BUG_ON(parent == mnt); | 639 | BUG_ON(parent == mnt); |
625 | 640 | ||
626 | list_add_tail(&head, &mnt->mnt_list); | 641 | list_add_tail(&head, &mnt->mnt_list); |
627 | list_for_each_entry(m, &head, mnt_list) | 642 | list_for_each_entry(m, &head, mnt_list) { |
628 | m->mnt_ns = n; | 643 | m->mnt_ns = n; |
644 | __mnt_make_longterm(m); | ||
645 | } | ||
646 | |||
629 | list_splice(&head, n->list.prev); | 647 | list_splice(&head, n->list.prev); |
630 | 648 | ||
631 | list_add_tail(&mnt->mnt_hash, mount_hashtable + | 649 | list_add_tail(&mnt->mnt_hash, mount_hashtable + |
@@ -734,51 +752,30 @@ static inline void mntfree(struct vfsmount *mnt) | |||
734 | deactivate_super(sb); | 752 | deactivate_super(sb); |
735 | } | 753 | } |
736 | 754 | ||
737 | #ifdef CONFIG_SMP | 755 | static void mntput_no_expire(struct vfsmount *mnt) |
738 | static inline void __mntput(struct vfsmount *mnt, int longrefs) | ||
739 | { | 756 | { |
740 | if (!longrefs) { | ||
741 | put_again: | 757 | put_again: |
742 | br_read_lock(vfsmount_lock); | 758 | #ifdef CONFIG_SMP |
743 | if (likely(atomic_read(&mnt->mnt_longrefs))) { | 759 | br_read_lock(vfsmount_lock); |
744 | mnt_dec_count(mnt); | 760 | if (likely(atomic_read(&mnt->mnt_longterm))) { |
745 | br_read_unlock(vfsmount_lock); | 761 | mnt_dec_count(mnt); |
746 | return; | ||
747 | } | ||
748 | br_read_unlock(vfsmount_lock); | 762 | br_read_unlock(vfsmount_lock); |
749 | } else { | 763 | return; |
750 | BUG_ON(!atomic_read(&mnt->mnt_longrefs)); | ||
751 | if (atomic_add_unless(&mnt->mnt_longrefs, -1, 1)) | ||
752 | return; | ||
753 | } | 764 | } |
765 | br_read_unlock(vfsmount_lock); | ||
754 | 766 | ||
755 | br_write_lock(vfsmount_lock); | 767 | br_write_lock(vfsmount_lock); |
756 | if (!longrefs) | 768 | mnt_dec_count(mnt); |
757 | mnt_dec_count(mnt); | ||
758 | else | ||
759 | atomic_dec(&mnt->mnt_longrefs); | ||
760 | if (mnt_get_count(mnt)) { | 769 | if (mnt_get_count(mnt)) { |
761 | br_write_unlock(vfsmount_lock); | 770 | br_write_unlock(vfsmount_lock); |
762 | return; | 771 | return; |
763 | } | 772 | } |
764 | if (unlikely(mnt->mnt_pinned)) { | ||
765 | mnt_add_count(mnt, mnt->mnt_pinned + 1); | ||
766 | mnt->mnt_pinned = 0; | ||
767 | br_write_unlock(vfsmount_lock); | ||
768 | acct_auto_close_mnt(mnt); | ||
769 | goto put_again; | ||
770 | } | ||
771 | br_write_unlock(vfsmount_lock); | ||
772 | mntfree(mnt); | ||
773 | } | ||
774 | #else | 773 | #else |
775 | static inline void __mntput(struct vfsmount *mnt, int longrefs) | ||
776 | { | ||
777 | put_again: | ||
778 | mnt_dec_count(mnt); | 774 | mnt_dec_count(mnt); |
779 | if (likely(mnt_get_count(mnt))) | 775 | if (likely(mnt_get_count(mnt))) |
780 | return; | 776 | return; |
781 | br_write_lock(vfsmount_lock); | 777 | br_write_lock(vfsmount_lock); |
778 | #endif | ||
782 | if (unlikely(mnt->mnt_pinned)) { | 779 | if (unlikely(mnt->mnt_pinned)) { |
783 | mnt_add_count(mnt, mnt->mnt_pinned + 1); | 780 | mnt_add_count(mnt, mnt->mnt_pinned + 1); |
784 | mnt->mnt_pinned = 0; | 781 | mnt->mnt_pinned = 0; |
@@ -789,12 +786,6 @@ put_again: | |||
789 | br_write_unlock(vfsmount_lock); | 786 | br_write_unlock(vfsmount_lock); |
790 | mntfree(mnt); | 787 | mntfree(mnt); |
791 | } | 788 | } |
792 | #endif | ||
793 | |||
794 | static void mntput_no_expire(struct vfsmount *mnt) | ||
795 | { | ||
796 | __mntput(mnt, 0); | ||
797 | } | ||
798 | 789 | ||
799 | void mntput(struct vfsmount *mnt) | 790 | void mntput(struct vfsmount *mnt) |
800 | { | 791 | { |
@@ -802,7 +793,7 @@ void mntput(struct vfsmount *mnt) | |||
802 | /* avoid cacheline pingpong, hope gcc doesn't get "smart" */ | 793 | /* avoid cacheline pingpong, hope gcc doesn't get "smart" */ |
803 | if (unlikely(mnt->mnt_expiry_mark)) | 794 | if (unlikely(mnt->mnt_expiry_mark)) |
804 | mnt->mnt_expiry_mark = 0; | 795 | mnt->mnt_expiry_mark = 0; |
805 | __mntput(mnt, 0); | 796 | mntput_no_expire(mnt); |
806 | } | 797 | } |
807 | } | 798 | } |
808 | EXPORT_SYMBOL(mntput); | 799 | EXPORT_SYMBOL(mntput); |
@@ -815,33 +806,6 @@ struct vfsmount *mntget(struct vfsmount *mnt) | |||
815 | } | 806 | } |
816 | EXPORT_SYMBOL(mntget); | 807 | EXPORT_SYMBOL(mntget); |
817 | 808 | ||
818 | void mntput_long(struct vfsmount *mnt) | ||
819 | { | ||
820 | #ifdef CONFIG_SMP | ||
821 | if (mnt) { | ||
822 | /* avoid cacheline pingpong, hope gcc doesn't get "smart" */ | ||
823 | if (unlikely(mnt->mnt_expiry_mark)) | ||
824 | mnt->mnt_expiry_mark = 0; | ||
825 | __mntput(mnt, 1); | ||
826 | } | ||
827 | #else | ||
828 | mntput(mnt); | ||
829 | #endif | ||
830 | } | ||
831 | EXPORT_SYMBOL(mntput_long); | ||
832 | |||
833 | struct vfsmount *mntget_long(struct vfsmount *mnt) | ||
834 | { | ||
835 | #ifdef CONFIG_SMP | ||
836 | if (mnt) | ||
837 | atomic_inc(&mnt->mnt_longrefs); | ||
838 | return mnt; | ||
839 | #else | ||
840 | return mntget(mnt); | ||
841 | #endif | ||
842 | } | ||
843 | EXPORT_SYMBOL(mntget_long); | ||
844 | |||
845 | void mnt_pin(struct vfsmount *mnt) | 809 | void mnt_pin(struct vfsmount *mnt) |
846 | { | 810 | { |
847 | br_write_lock(vfsmount_lock); | 811 | br_write_lock(vfsmount_lock); |
@@ -1216,7 +1180,7 @@ void release_mounts(struct list_head *head) | |||
1216 | dput(dentry); | 1180 | dput(dentry); |
1217 | mntput(m); | 1181 | mntput(m); |
1218 | } | 1182 | } |
1219 | mntput_long(mnt); | 1183 | mntput(mnt); |
1220 | } | 1184 | } |
1221 | } | 1185 | } |
1222 | 1186 | ||
@@ -1226,19 +1190,21 @@ void release_mounts(struct list_head *head) | |||
1226 | */ | 1190 | */ |
1227 | void umount_tree(struct vfsmount *mnt, int propagate, struct list_head *kill) | 1191 | void umount_tree(struct vfsmount *mnt, int propagate, struct list_head *kill) |
1228 | { | 1192 | { |
1193 | LIST_HEAD(tmp_list); | ||
1229 | struct vfsmount *p; | 1194 | struct vfsmount *p; |
1230 | 1195 | ||
1231 | for (p = mnt; p; p = next_mnt(p, mnt)) | 1196 | for (p = mnt; p; p = next_mnt(p, mnt)) |
1232 | list_move(&p->mnt_hash, kill); | 1197 | list_move(&p->mnt_hash, &tmp_list); |
1233 | 1198 | ||
1234 | if (propagate) | 1199 | if (propagate) |
1235 | propagate_umount(kill); | 1200 | propagate_umount(&tmp_list); |
1236 | 1201 | ||
1237 | list_for_each_entry(p, kill, mnt_hash) { | 1202 | list_for_each_entry(p, &tmp_list, mnt_hash) { |
1238 | list_del_init(&p->mnt_expire); | 1203 | list_del_init(&p->mnt_expire); |
1239 | list_del_init(&p->mnt_list); | 1204 | list_del_init(&p->mnt_list); |
1240 | __touch_mnt_namespace(p->mnt_ns); | 1205 | __touch_mnt_namespace(p->mnt_ns); |
1241 | p->mnt_ns = NULL; | 1206 | p->mnt_ns = NULL; |
1207 | __mnt_make_shortterm(p); | ||
1242 | list_del_init(&p->mnt_child); | 1208 | list_del_init(&p->mnt_child); |
1243 | if (p->mnt_parent != p) { | 1209 | if (p->mnt_parent != p) { |
1244 | p->mnt_parent->mnt_ghosts++; | 1210 | p->mnt_parent->mnt_ghosts++; |
@@ -1246,6 +1212,7 @@ void umount_tree(struct vfsmount *mnt, int propagate, struct list_head *kill) | |||
1246 | } | 1212 | } |
1247 | change_mnt_propagation(p, MS_PRIVATE); | 1213 | change_mnt_propagation(p, MS_PRIVATE); |
1248 | } | 1214 | } |
1215 | list_splice(&tmp_list, kill); | ||
1249 | } | 1216 | } |
1250 | 1217 | ||
1251 | static void shrink_submounts(struct vfsmount *mnt, struct list_head *umounts); | 1218 | static void shrink_submounts(struct vfsmount *mnt, struct list_head *umounts); |
@@ -1277,7 +1244,7 @@ static int do_umount(struct vfsmount *mnt, int flags) | |||
1277 | */ | 1244 | */ |
1278 | br_write_lock(vfsmount_lock); | 1245 | br_write_lock(vfsmount_lock); |
1279 | if (mnt_get_count(mnt) != 2) { | 1246 | if (mnt_get_count(mnt) != 2) { |
1280 | br_write_lock(vfsmount_lock); | 1247 | br_write_unlock(vfsmount_lock); |
1281 | return -EBUSY; | 1248 | return -EBUSY; |
1282 | } | 1249 | } |
1283 | br_write_unlock(vfsmount_lock); | 1250 | br_write_unlock(vfsmount_lock); |
@@ -1848,9 +1815,10 @@ static int do_move_mount(struct path *path, char *old_name) | |||
1848 | return err; | 1815 | return err; |
1849 | 1816 | ||
1850 | down_write(&namespace_sem); | 1817 | down_write(&namespace_sem); |
1851 | while (d_mountpoint(path->dentry) && | 1818 | err = follow_down(path, true); |
1852 | follow_down(path)) | 1819 | if (err < 0) |
1853 | ; | 1820 | goto out; |
1821 | |||
1854 | err = -EINVAL; | 1822 | err = -EINVAL; |
1855 | if (!check_mnt(path->mnt) || !check_mnt(old_path.mnt)) | 1823 | if (!check_mnt(path->mnt) || !check_mnt(old_path.mnt)) |
1856 | goto out; | 1824 | goto out; |
@@ -1908,6 +1876,8 @@ out: | |||
1908 | return err; | 1876 | return err; |
1909 | } | 1877 | } |
1910 | 1878 | ||
1879 | static int do_add_mount(struct vfsmount *, struct path *, int); | ||
1880 | |||
1911 | /* | 1881 | /* |
1912 | * create a new mount for userspace and request it to be added into the | 1882 | * create a new mount for userspace and request it to be added into the |
1913 | * namespace's tree | 1883 | * namespace's tree |
@@ -1916,6 +1886,7 @@ static int do_new_mount(struct path *path, char *type, int flags, | |||
1916 | int mnt_flags, char *name, void *data) | 1886 | int mnt_flags, char *name, void *data) |
1917 | { | 1887 | { |
1918 | struct vfsmount *mnt; | 1888 | struct vfsmount *mnt; |
1889 | int err; | ||
1919 | 1890 | ||
1920 | if (!type) | 1891 | if (!type) |
1921 | return -EINVAL; | 1892 | return -EINVAL; |
@@ -1928,15 +1899,47 @@ static int do_new_mount(struct path *path, char *type, int flags, | |||
1928 | if (IS_ERR(mnt)) | 1899 | if (IS_ERR(mnt)) |
1929 | return PTR_ERR(mnt); | 1900 | return PTR_ERR(mnt); |
1930 | 1901 | ||
1931 | return do_add_mount(mnt, path, mnt_flags, NULL); | 1902 | err = do_add_mount(mnt, path, mnt_flags); |
1903 | if (err) | ||
1904 | mntput(mnt); | ||
1905 | return err; | ||
1906 | } | ||
1907 | |||
1908 | int finish_automount(struct vfsmount *m, struct path *path) | ||
1909 | { | ||
1910 | int err; | ||
1911 | /* The new mount record should have at least 2 refs to prevent it being | ||
1912 | * expired before we get a chance to add it | ||
1913 | */ | ||
1914 | BUG_ON(mnt_get_count(m) < 2); | ||
1915 | |||
1916 | if (m->mnt_sb == path->mnt->mnt_sb && | ||
1917 | m->mnt_root == path->dentry) { | ||
1918 | err = -ELOOP; | ||
1919 | goto fail; | ||
1920 | } | ||
1921 | |||
1922 | err = do_add_mount(m, path, path->mnt->mnt_flags | MNT_SHRINKABLE); | ||
1923 | if (!err) | ||
1924 | return 0; | ||
1925 | fail: | ||
1926 | /* remove m from any expiration list it may be on */ | ||
1927 | if (!list_empty(&m->mnt_expire)) { | ||
1928 | down_write(&namespace_sem); | ||
1929 | br_write_lock(vfsmount_lock); | ||
1930 | list_del_init(&m->mnt_expire); | ||
1931 | br_write_unlock(vfsmount_lock); | ||
1932 | up_write(&namespace_sem); | ||
1933 | } | ||
1934 | mntput(m); | ||
1935 | mntput(m); | ||
1936 | return err; | ||
1932 | } | 1937 | } |
1933 | 1938 | ||
1934 | /* | 1939 | /* |
1935 | * add a mount into a namespace's mount tree | 1940 | * add a mount into a namespace's mount tree |
1936 | * - provide the option of adding the new mount to an expiration list | ||
1937 | */ | 1941 | */ |
1938 | int do_add_mount(struct vfsmount *newmnt, struct path *path, | 1942 | static int do_add_mount(struct vfsmount *newmnt, struct path *path, int mnt_flags) |
1939 | int mnt_flags, struct list_head *fslist) | ||
1940 | { | 1943 | { |
1941 | int err; | 1944 | int err; |
1942 | 1945 | ||
@@ -1944,9 +1947,10 @@ int do_add_mount(struct vfsmount *newmnt, struct path *path, | |||
1944 | 1947 | ||
1945 | down_write(&namespace_sem); | 1948 | down_write(&namespace_sem); |
1946 | /* Something was mounted here while we slept */ | 1949 | /* Something was mounted here while we slept */ |
1947 | while (d_mountpoint(path->dentry) && | 1950 | err = follow_down(path, true); |
1948 | follow_down(path)) | 1951 | if (err < 0) |
1949 | ; | 1952 | goto unlock; |
1953 | |||
1950 | err = -EINVAL; | 1954 | err = -EINVAL; |
1951 | if (!(mnt_flags & MNT_SHRINKABLE) && !check_mnt(path->mnt)) | 1955 | if (!(mnt_flags & MNT_SHRINKABLE) && !check_mnt(path->mnt)) |
1952 | goto unlock; | 1956 | goto unlock; |
@@ -1962,22 +1966,29 @@ int do_add_mount(struct vfsmount *newmnt, struct path *path, | |||
1962 | goto unlock; | 1966 | goto unlock; |
1963 | 1967 | ||
1964 | newmnt->mnt_flags = mnt_flags; | 1968 | newmnt->mnt_flags = mnt_flags; |
1965 | if ((err = graft_tree(newmnt, path))) | 1969 | err = graft_tree(newmnt, path); |
1966 | goto unlock; | ||
1967 | |||
1968 | if (fslist) /* add to the specified expiration list */ | ||
1969 | list_add_tail(&newmnt->mnt_expire, fslist); | ||
1970 | |||
1971 | up_write(&namespace_sem); | ||
1972 | return 0; | ||
1973 | 1970 | ||
1974 | unlock: | 1971 | unlock: |
1975 | up_write(&namespace_sem); | 1972 | up_write(&namespace_sem); |
1976 | mntput_long(newmnt); | ||
1977 | return err; | 1973 | return err; |
1978 | } | 1974 | } |
1979 | 1975 | ||
1980 | EXPORT_SYMBOL_GPL(do_add_mount); | 1976 | /** |
1977 | * mnt_set_expiry - Put a mount on an expiration list | ||
1978 | * @mnt: The mount to list. | ||
1979 | * @expiry_list: The list to add the mount to. | ||
1980 | */ | ||
1981 | void mnt_set_expiry(struct vfsmount *mnt, struct list_head *expiry_list) | ||
1982 | { | ||
1983 | down_write(&namespace_sem); | ||
1984 | br_write_lock(vfsmount_lock); | ||
1985 | |||
1986 | list_add_tail(&mnt->mnt_expire, expiry_list); | ||
1987 | |||
1988 | br_write_unlock(vfsmount_lock); | ||
1989 | up_write(&namespace_sem); | ||
1990 | } | ||
1991 | EXPORT_SYMBOL(mnt_set_expiry); | ||
1981 | 1992 | ||
1982 | /* | 1993 | /* |
1983 | * process a list of expirable mountpoints with the intent of discarding any | 1994 | * process a list of expirable mountpoints with the intent of discarding any |
@@ -2266,6 +2277,22 @@ static struct mnt_namespace *alloc_mnt_ns(void) | |||
2266 | return new_ns; | 2277 | return new_ns; |
2267 | } | 2278 | } |
2268 | 2279 | ||
2280 | void mnt_make_longterm(struct vfsmount *mnt) | ||
2281 | { | ||
2282 | __mnt_make_longterm(mnt); | ||
2283 | } | ||
2284 | |||
2285 | void mnt_make_shortterm(struct vfsmount *mnt) | ||
2286 | { | ||
2287 | #ifdef CONFIG_SMP | ||
2288 | if (atomic_add_unless(&mnt->mnt_longterm, -1, 1)) | ||
2289 | return; | ||
2290 | br_write_lock(vfsmount_lock); | ||
2291 | atomic_dec(&mnt->mnt_longterm); | ||
2292 | br_write_unlock(vfsmount_lock); | ||
2293 | #endif | ||
2294 | } | ||
2295 | |||
2269 | /* | 2296 | /* |
2270 | * Allocate a new namespace structure and populate it with contents | 2297 | * Allocate a new namespace structure and populate it with contents |
2271 | * copied from the namespace of the passed in task structure. | 2298 | * copied from the namespace of the passed in task structure. |
@@ -2303,14 +2330,19 @@ static struct mnt_namespace *dup_mnt_ns(struct mnt_namespace *mnt_ns, | |||
2303 | q = new_ns->root; | 2330 | q = new_ns->root; |
2304 | while (p) { | 2331 | while (p) { |
2305 | q->mnt_ns = new_ns; | 2332 | q->mnt_ns = new_ns; |
2333 | __mnt_make_longterm(q); | ||
2306 | if (fs) { | 2334 | if (fs) { |
2307 | if (p == fs->root.mnt) { | 2335 | if (p == fs->root.mnt) { |
2336 | fs->root.mnt = mntget(q); | ||
2337 | __mnt_make_longterm(q); | ||
2338 | mnt_make_shortterm(p); | ||
2308 | rootmnt = p; | 2339 | rootmnt = p; |
2309 | fs->root.mnt = mntget_long(q); | ||
2310 | } | 2340 | } |
2311 | if (p == fs->pwd.mnt) { | 2341 | if (p == fs->pwd.mnt) { |
2342 | fs->pwd.mnt = mntget(q); | ||
2343 | __mnt_make_longterm(q); | ||
2344 | mnt_make_shortterm(p); | ||
2312 | pwdmnt = p; | 2345 | pwdmnt = p; |
2313 | fs->pwd.mnt = mntget_long(q); | ||
2314 | } | 2346 | } |
2315 | } | 2347 | } |
2316 | p = next_mnt(p, mnt_ns->root); | 2348 | p = next_mnt(p, mnt_ns->root); |
@@ -2319,9 +2351,9 @@ static struct mnt_namespace *dup_mnt_ns(struct mnt_namespace *mnt_ns, | |||
2319 | up_write(&namespace_sem); | 2351 | up_write(&namespace_sem); |
2320 | 2352 | ||
2321 | if (rootmnt) | 2353 | if (rootmnt) |
2322 | mntput_long(rootmnt); | 2354 | mntput(rootmnt); |
2323 | if (pwdmnt) | 2355 | if (pwdmnt) |
2324 | mntput_long(pwdmnt); | 2356 | mntput(pwdmnt); |
2325 | 2357 | ||
2326 | return new_ns; | 2358 | return new_ns; |
2327 | } | 2359 | } |
@@ -2354,6 +2386,7 @@ struct mnt_namespace *create_mnt_ns(struct vfsmount *mnt) | |||
2354 | new_ns = alloc_mnt_ns(); | 2386 | new_ns = alloc_mnt_ns(); |
2355 | if (!IS_ERR(new_ns)) { | 2387 | if (!IS_ERR(new_ns)) { |
2356 | mnt->mnt_ns = new_ns; | 2388 | mnt->mnt_ns = new_ns; |
2389 | __mnt_make_longterm(mnt); | ||
2357 | new_ns->root = mnt; | 2390 | new_ns->root = mnt; |
2358 | list_add(&new_ns->list, &new_ns->root->mnt_list); | 2391 | list_add(&new_ns->list, &new_ns->root->mnt_list); |
2359 | } | 2392 | } |