Re: [PATCH v4] loop: Fix NULL pointer dereference in lo_rw_aio()
From: Tetsuo Handa
Date: Fri Jun 19 2026 - 10:35:07 EST
Sending this commit to linux.git will be the fastest way to identify who is issuing
I/O requests too late. Therefore, I want to get a conclusion on xfs/259 breakage.
Al, can you get the same result?
On 2026/06/13 20:00, Tetsuo Handa wrote:
> On 2026/06/10 2:50, Al Viro wrote:
>> Still breaks xfs/259, same as the version in next-20260605...
>
> I installed xfstests-dev and reproduced a "umount: /home/test: target is busy." problem which Al Viro is
> experiencing with https://git.kernel.org/pub/scm/linux/kernel/git/next/linux-next.git/commit/?h=next-20260608&id=fb1d5846e99c8aa4ce8da7e6ee7643b01da25b8c .
>
(...snipped...)
>
> I initially suspected that the cause of "target is busy" error is that fput() from
> __loop_clr_fd() does not wait for completion before "losetup -d" completes. But a
> debug printk() patch shown below indicated a tendency:
>
> (a) __loop_clr_fd() is called by "udev-worker" rather than "losetup" when this problem happens
>
> (b) propagate_mount_busy()!=0 when do_umount() fails with -EBUSY
>
> --------------------------------------------------------------------------------
> diff --git a/drivers/block/loop.c b/drivers/block/loop.c
> index c3b607a3ddc4..7408f314a1fa 100644
> --- a/drivers/block/loop.c
> +++ b/drivers/block/loop.c
> @@ -1763,6 +1763,8 @@ static void lo_release(struct gendisk *disk)
> mutex_unlock(&lo->lo_mutex);
>
> if (need_clear) {
> + printk("Flush: task=%s[%d] dev=loop%d state=%d\n",
> + current->comm, current->pid, lo->lo_number, lo->lo_state);
> /*
> * Temporarily release disk->open_mutex in order to flush pending I/O
> * requests before clearing the backing device.
> @@ -1813,6 +1815,8 @@ static void lo_release(struct gendisk *disk)
> mutex_lock(&lo->lo_disk->open_mutex);
> if (WARN_ON(data_race(READ_ONCE(lo->lo_state)) != Lo_rundown))
> return;
> + printk("Teardown: task=%s[%d] dev=loop%d state=%d\n",
> + current->comm, current->pid, lo->lo_number, lo->lo_state);
> __loop_clr_fd(lo);
> }
> }
> diff --git a/fs/namespace.c b/fs/namespace.c
> index 09ab7fc72f86..9710460fb449 100644
> --- a/fs/namespace.c
> +++ b/fs/namespace.c
> @@ -1893,6 +1893,8 @@ static int do_umount(struct mount *mnt, int flags)
> */
> lock_mount_hash();
> if (!list_empty(&mnt->mnt_mounts) || mnt_get_count(mnt) != 2) {
> + printk("%s: task=%s[%d] !list_empty(&mnt->mnt_mounts)=%d mnt_get_count(mnt)=%d\n", __func__,
> + current->comm, current->pid, !list_empty(&mnt->mnt_mounts), mnt_get_count(mnt));
> unlock_mount_hash();
> return -EBUSY;
> }
> @@ -1960,6 +1962,9 @@ static int do_umount(struct mount *mnt, int flags)
> if (!propagate_mount_busy(mnt, 2)) {
> umount_tree(mnt, UMOUNT_PROPAGATE|UMOUNT_SYNC);
> retval = 0;
> + } else {
> + printk("%s: task=%s[%d] propagate_mount_busy()!=0\n", __func__,
> + current->comm, current->pid);
> }
> }
> out:
> --------------------------------------------------------------------------------