mirror of
https://mirrors.bfsu.edu.cn/git/linux.git
synced 2024-11-11 04:18:39 +08:00
fix old umount_tree() breakage
Expiry-related code calls umount_tree() several times with the same list to collect vfsmounts to. Which is fine, except that umount_tree() implicitly assumed that the list would be empty on each call - it moves the victims over there and then iterates through the list kicking them out. It's *almost* idempotent, so everything nearly worked. However, mnt->ghosts handling (and thus expirability checks) had been broken - that part was not idempotent... The fix is trivial - use local temporary list, splice it to the the collector list when we are through. Signed-off-by: Al Viro <viro@zeniv.linux.org.uk>
This commit is contained in:
parent
b650c858c2
commit
7b8a53fd81
@ -1226,15 +1226,16 @@ void release_mounts(struct list_head *head)
|
||||
*/
|
||||
void umount_tree(struct vfsmount *mnt, int propagate, struct list_head *kill)
|
||||
{
|
||||
LIST_HEAD(tmp_list);
|
||||
struct vfsmount *p;
|
||||
|
||||
for (p = mnt; p; p = next_mnt(p, mnt))
|
||||
list_move(&p->mnt_hash, kill);
|
||||
list_move(&p->mnt_hash, &tmp_list);
|
||||
|
||||
if (propagate)
|
||||
propagate_umount(kill);
|
||||
propagate_umount(&tmp_list);
|
||||
|
||||
list_for_each_entry(p, kill, mnt_hash) {
|
||||
list_for_each_entry(p, &tmp_list, mnt_hash) {
|
||||
list_del_init(&p->mnt_expire);
|
||||
list_del_init(&p->mnt_list);
|
||||
__touch_mnt_namespace(p->mnt_ns);
|
||||
@ -1246,6 +1247,7 @@ void umount_tree(struct vfsmount *mnt, int propagate, struct list_head *kill)
|
||||
}
|
||||
change_mnt_propagation(p, MS_PRIVATE);
|
||||
}
|
||||
list_splice(&tmp_list, kill);
|
||||
}
|
||||
|
||||
static void shrink_submounts(struct vfsmount *mnt, struct list_head *umounts);
|
||||
|
Loading…
Reference in New Issue
Block a user