On 12.02.21 09:58, Sascha Hauer wrote: > On Thu, Feb 11, 2021 at 06:11:39PM +0100, Ahmad Fatoum wrote: >> The VFS layer already increase the mount reference count for the mount >> point. This means e.g. following sequence is well-behaving: >> >> mkdir -p /mnt/disk0.0/media >> mount -o loop backing.squashfs /mnt/disk0.0/media >> umount /mnt/disk0.0 >> >> barebox will do the right thing and report >> >> umount: Device or resource busy >> >> However the reference count of the file where backing.squashfs comes >> from is not incremented on mount with the effect that following sequence >> crashes: >> >> mkdir -p /media >> mount -o loop /mnt/disk0.0/backing.squashfs /media >> umount /mnt/disk0.0 # should've returned EBUSY >> umount /media >> >> Fix this by touching the backing store's mount reference count when >> loop mounting and unmounting. >> >> Signed-off-by: Ahmad Fatoum <a.fatoum@xxxxxxxxxxxxxx> >> --- >> fs/fs.c | 38 +++++++++++++++++++++++++++++++++----- >> 1 file changed, 33 insertions(+), 5 deletions(-) >> >> diff --git a/fs/fs.c b/fs/fs.c >> index 00b8645fb0e9..10cc08fc93ab 100644 >> --- a/fs/fs.c >> +++ b/fs/fs.c >> @@ -89,7 +89,13 @@ static int init_fs(void) >> >> postcore_initcall(init_fs); >> >> +struct filename; >> + >> static struct fs_device_d *get_fsdevice_by_path(const char *path); >> +static int filename_lookup(int dfd, struct filename *name, unsigned flags, >> + struct path *path);; >> +static struct filename *getname(const char *filename); >> +static void path_put(const struct path *path); >> >> LIST_HEAD(fs_device_list); >> >> @@ -683,6 +689,8 @@ static void fs_remove(struct device_d *dev) >> struct fs_device_d *fsdev = dev_to_fs_device(dev); >> struct super_block *sb = &fsdev->sb; >> struct inode *inode, *tmp; >> + struct path path; >> + int ret; >> >> if (fsdev->dev.driver) { >> dev->driver->remove(dev); >> @@ -695,9 +703,17 @@ static void fs_remove(struct device_d *dev) >> if (fsdev->cdev) >> cdev_close(fsdev->cdev); >> >> - if (fsdev->loop && fsdev->cdev) >> + if (fsdev->loop && fsdev->cdev) { >> cdev_remove_loop(fsdev->cdev); >> >> + ret = filename_lookup(AT_FDCWD, getname(fsdev->backingstore), >> + LOOKUP_FOLLOW, &path); >> + if (!ret) { >> + mntput(path.mnt); >> + path_put(&path); >> + } >> + } >> + >> if (fsdev->vfsmount.mountpoint) >> fsdev->vfsmount.mountpoint->d_flags &= ~DCACHE_MOUNTED; >> >> @@ -767,17 +783,29 @@ static const char *detect_fs(const char *filename, const char *fsoptions) >> int fsdev_open_cdev(struct fs_device_d *fsdev) >> { >> unsigned long long offset = 0; >> + struct path path = {}; >> + int ret; >> >> parseopt_b(fsdev->options, "loop", &fsdev->loop); >> parseopt_llu_suffix(fsdev->options, "offset", &offset); >> - if (fsdev->loop) >> - fsdev->cdev = cdev_create_loop(fsdev->backingstore, O_RDWR, >> - offset); >> - else >> + if (fsdev->loop) { >> + ret = filename_lookup(AT_FDCWD, getname(fsdev->backingstore), >> + LOOKUP_FOLLOW, &path); >> + if (ret) >> + return ret; >> + >> + fsdev->cdev = cdev_create_loop(fsdev->backingstore, O_RDWR, offset); >> + } else { >> fsdev->cdev = cdev_open(fsdev->backingstore, O_RDWR); >> + } >> if (!fsdev->cdev) >> return -EINVAL; > > path_put() is missing in this error path. Thanks for catching. Just sent out v2. > > Sascha > > -- Pengutronix e.K. | | Steuerwalder Str. 21 | http://www.pengutronix.de/ | 31137 Hildesheim, Germany | Phone: +49-5121-206917-0 | Amtsgericht Hildesheim, HRA 2686 | Fax: +49-5121-206917-5555 | _______________________________________________ barebox mailing list barebox@xxxxxxxxxxxxxxxxxxx http://lists.infradead.org/mailman/listinfo/barebox