return err;
}
-int finish_automount(struct vfsmount *m, const struct path *path)
+static int lock_mount_exact(const struct path *path,
+ struct pinned_mountpoint *mp)
{
struct dentry *dentry = path->dentry;
+ int err;
+
+ inode_lock(dentry->d_inode);
+ namespace_lock();
+ if (unlikely(cant_mount(dentry)))
+ err = -ENOENT;
+ else if (path_overmounted(path))
+ err = -EBUSY;
+ else
+ err = get_mountpoint(dentry, mp);
+ if (unlikely(err)) {
+ namespace_unlock();
+ inode_unlock(dentry->d_inode);
+ }
+ return err;
+}
+
+int finish_automount(struct vfsmount *m, const struct path *path)
+{
struct pinned_mountpoint mp = {};
struct mount *mnt;
int err;
* that overmounts our mountpoint to be means "quitely drop what we've
* got", not "try to mount it on top".
*/
- inode_lock(dentry->d_inode);
- namespace_lock();
- if (unlikely(cant_mount(dentry))) {
- err = -ENOENT;
- goto discard_locked;
- }
- if (path_overmounted(path)) {
- err = 0;
- goto discard_locked;
+ err = lock_mount_exact(path, &mp);
+ if (unlikely(err)) {
+ mntput(m);
+ return err == -EBUSY ? 0 : err;
}
- err = get_mountpoint(dentry, &mp);
- if (err)
- goto discard_locked;
-
err = do_add_mount(mnt, mp.mp, path,
path->mnt->mnt_flags | MNT_SHRINKABLE);
unlock_mount(&mp);
goto discard;
return 0;
-discard_locked:
- namespace_unlock();
- inode_unlock(dentry->d_inode);
discard:
mntput(m);
return err;