Skip to content

Commit 6632068

Browse files
author
Al Viro
committed
copy_tree(): don't link the mounts via mnt_list
The only place that really needs to be adjusted is commit_tree() - there we need to iterate through the copy and we might as well use next_mnt() for that. However, in case when our tree has been slid under something already mounted (propagation to a mountpoint that already has something mounted on it or a 'beneath' move_mount) we need to take care not to walk into the overmounting tree. Signed-off-by: Al Viro <viro@zeniv.linux.org.uk>
1 parent dd5a4e1 commit 6632068

File tree

3 files changed

+27
-39
lines changed

3 files changed

+27
-39
lines changed

fs/mount.h

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -193,7 +193,7 @@ static inline bool mnt_ns_empty(const struct mnt_namespace *ns)
193193
return RB_EMPTY_ROOT(&ns->mounts);
194194
}
195195

196-
static inline void move_from_ns(struct mount *mnt, struct list_head *dt_list)
196+
static inline void move_from_ns(struct mount *mnt)
197197
{
198198
struct mnt_namespace *ns = mnt->mnt_ns;
199199
WARN_ON(!mnt_ns_attached(mnt));
@@ -203,7 +203,6 @@ static inline void move_from_ns(struct mount *mnt, struct list_head *dt_list)
203203
ns->mnt_first_node = rb_next(&mnt->mnt_node);
204204
rb_erase(&mnt->mnt_node, &ns->mounts);
205205
RB_CLEAR_NODE(&mnt->mnt_node);
206-
list_add_tail(&mnt->mnt_list, dt_list);
207206
}
208207

209208
bool has_locked_children(struct mount *mnt, struct dentry *dentry);

fs/namespace.c

Lines changed: 24 additions & 36 deletions
Original file line numberDiff line numberDiff line change
@@ -1161,34 +1161,6 @@ static void mnt_add_to_ns(struct mnt_namespace *ns, struct mount *mnt)
11611161
mnt_notify_add(mnt);
11621162
}
11631163

1164-
/*
1165-
* vfsmount lock must be held for write
1166-
*/
1167-
static void commit_tree(struct mount *mnt)
1168-
{
1169-
struct mount *parent = mnt->mnt_parent;
1170-
struct mount *m;
1171-
LIST_HEAD(head);
1172-
struct mnt_namespace *n = parent->mnt_ns;
1173-
1174-
BUG_ON(parent == mnt);
1175-
1176-
if (!mnt_ns_attached(mnt)) {
1177-
list_add_tail(&head, &mnt->mnt_list);
1178-
while (!list_empty(&head)) {
1179-
m = list_first_entry(&head, typeof(*m), mnt_list);
1180-
list_del(&m->mnt_list);
1181-
1182-
mnt_add_to_ns(n, m);
1183-
}
1184-
n->nr_mounts += n->pending_mounts;
1185-
n->pending_mounts = 0;
1186-
}
1187-
1188-
make_visible(mnt);
1189-
touch_mnt_namespace(n);
1190-
}
1191-
11921164
static struct mount *next_mnt(struct mount *p, struct mount *root)
11931165
{
11941166
struct list_head *next = p->mnt_mounts.next;
@@ -1215,6 +1187,27 @@ static struct mount *skip_mnt_tree(struct mount *p)
12151187
return p;
12161188
}
12171189

1190+
/*
1191+
* vfsmount lock must be held for write
1192+
*/
1193+
static void commit_tree(struct mount *mnt)
1194+
{
1195+
struct mnt_namespace *n = mnt->mnt_parent->mnt_ns;
1196+
1197+
if (!mnt_ns_attached(mnt)) {
1198+
for (struct mount *m = mnt; m; m = next_mnt(m, mnt))
1199+
if (unlikely(mnt_ns_attached(m)))
1200+
m = skip_mnt_tree(m);
1201+
else
1202+
mnt_add_to_ns(n, m);
1203+
n->nr_mounts += n->pending_mounts;
1204+
n->pending_mounts = 0;
1205+
}
1206+
1207+
make_visible(mnt);
1208+
touch_mnt_namespace(n);
1209+
}
1210+
12181211
/**
12191212
* vfs_create_mount - Create a mount for a configured superblock
12201213
* @fc: The configuration context with the superblock attached
@@ -1831,9 +1824,8 @@ static void umount_tree(struct mount *mnt, enum umount_tree_flags how)
18311824
for (p = mnt; p; p = next_mnt(p, mnt)) {
18321825
p->mnt.mnt_flags |= MNT_UMOUNT;
18331826
if (mnt_ns_attached(p))
1834-
move_from_ns(p, &tmp_list);
1835-
else
1836-
list_move(&p->mnt_list, &tmp_list);
1827+
move_from_ns(p);
1828+
list_add_tail(&p->mnt_list, &tmp_list);
18371829
}
18381830

18391831
/* Hide the mounts from mnt_mounts */
@@ -2270,7 +2262,6 @@ struct mount *copy_tree(struct mount *src_root, struct dentry *dentry,
22702262
list_add(&dst_mnt->mnt_expire,
22712263
&src_mnt->mnt_expire);
22722264
}
2273-
list_add_tail(&dst_mnt->mnt_list, &res->mnt_list);
22742265
attach_mnt(dst_mnt, dst_parent, src_parent->mnt_mp);
22752266
unlock_mount_hash();
22762267
}
@@ -2686,12 +2677,9 @@ static int attach_recursive_mnt(struct mount *source_mnt,
26862677
list_del_init(&source_mnt->mnt_expire);
26872678
} else {
26882679
if (source_mnt->mnt_ns) {
2689-
LIST_HEAD(head);
2690-
26912680
/* move from anon - the caller will destroy */
26922681
for (p = source_mnt; p; p = next_mnt(p, source_mnt))
2693-
move_from_ns(p, &head);
2694-
list_del_init(&head);
2682+
move_from_ns(p);
26952683
}
26962684
}
26972685

fs/pnode.c

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -449,7 +449,8 @@ static void umount_one(struct mount *m, struct list_head *to_umount)
449449
{
450450
m->mnt.mnt_flags |= MNT_UMOUNT;
451451
list_del_init(&m->mnt_child);
452-
move_from_ns(m, to_umount);
452+
move_from_ns(m);
453+
list_add_tail(&m->mnt_list, to_umount);
453454
}
454455

455456
static void remove_from_candidate_list(struct mount *m)

0 commit comments

Comments
 (0)