Infinite Loop when automounting device mounted elsewhere

Sascha Hauer s.hauer at pengutronix.de
Fri Nov 27 03:48:17 EST 2020


On Wed, Nov 25, 2020 at 10:33:45AM +0100, Ahmad Fatoum wrote:
> Hello,
> 
> I just ran into this issue:
> 
>   $ mkdir /boot
>   $ mount /dev/mmc2.0 /boot
>   $ ls /mnt/mmc2.0/
>   mounted /dev/mmc2.0 on /boot
>   mounted /dev/mmc2.0 on /boot
>   mounted /dev/mmc2.0 on /boot
>   [ Ad infinitum ]
> 
> This is more readily reproducible with barebox platforms where a separate
> boot partition is default-mounted as /boot. In that case, accessing the
> partition's corresponding /mnt entry will hang.
> 
> The hang can be traced back to fs/fs.c:follow_managed():
> 
>   while (managed = path->dentry->d_flags,
>   	managed &= DCACHE_MANAGED_DENTRY,
>   	managed != 0) {
> 	if (managed & DCACHE_MOUNTED) {
>   		struct vfsmount *mounted = lookup_mnt(path);
>   
>   		if (mounted) {
>   			dput(path->dentry);
>   			if (need_mntput)
>   				mntput(path->mnt);
>   			path->mnt = mounted;
>   			path->dentry = dget(mounted->mnt_root);
>   			need_mntput = true;
>   			continue;
>   		}
>   	}
>   
>   	/* Handle an automount point */
>   	if (managed & DCACHE_NEED_AUTOMOUNT) {
>   		ret = follow_automount(path, nd, &need_mntput);
>   		if (ret < 0)
>   			break;
>   		continue;
>   	}
>   
> 	/* We didn't change the current path point */
>   	break;
>   }
> 
> 
> The code attempts the follow_automount, which would succeed here,
> but it doesn't actually mount the current mount point, so we never
> enter the first if clause that would change path->dentry and lead
> us out of the loop.
> 
> I am unsure at what layer this should be fixed. Any suggestions?

This goes down to the command "mount mmc2.0" being executed. The mount
command then does a cdev_mount_default() which does this:

	/*
	 * If this cdev is already mounted somewhere use this path
	 * instead of mounting it again to avoid corruption on the
	 * filesystem. Note this ignores eventual fsoptions though.
	 */
	path = cdev_get_mount_path(cdev);
	if (path)
		return path;

The mount command is happy then and returns successfully. I think the
mount command should return an error when the cdev is mounted already
but the path it's mounted to is not the default path for that cdev.

Another option would be to implement bind mounts and do a bind mount
to the default path.

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 |



More information about the barebox mailing list