Commit ac838719 authored by Ian Kent's avatar Ian Kent Committed by Al Viro

autofs4 - fix device ioctl mount lookup

When reconnecting to automounts at startup an autofs ioctl is used
to find the device and inode of existing mounts so they can be used
to open a file descriptor of possibly covered mounts.

At this time the the caller might not yet "own" the mount so it can
trigger calling ->d_automount(). This causes automount to hang when
trying to reconnect to direct or offset mount types.

Consequently kern_path() can't be used but kern_path_mountpoint() can be.
Signed-off-by: default avatarIan Kent <raven@themaw.net>
Cc: Jeff Layton <jlayton@redhat.com>
Cc: Al Viro <viro@ZenIV.linux.org.uk>
Signed-off-by: default avatarAl Viro <viro@zeniv.linux.org.uk>
parent 2d864651
...@@ -183,13 +183,14 @@ static int autofs_dev_ioctl_protosubver(struct file *fp, ...@@ -183,13 +183,14 @@ static int autofs_dev_ioctl_protosubver(struct file *fp,
return 0; return 0;
} }
/* Find the topmost mount satisfying test() */
static int find_autofs_mount(const char *pathname, static int find_autofs_mount(const char *pathname,
struct path *res, struct path *res,
int test(struct path *path, void *data), int test(struct path *path, void *data),
void *data) void *data)
{ {
struct path path; struct path path;
int err = kern_path(pathname, 0, &path); int err = kern_path_mountpoint(AT_FDCWD, pathname, &path, 0);
if (err) if (err)
return err; return err;
err = -ENOENT; err = -ENOENT;
...@@ -197,10 +198,9 @@ static int find_autofs_mount(const char *pathname, ...@@ -197,10 +198,9 @@ static int find_autofs_mount(const char *pathname,
if (path.dentry->d_sb->s_magic == AUTOFS_SUPER_MAGIC) { if (path.dentry->d_sb->s_magic == AUTOFS_SUPER_MAGIC) {
if (test(&path, data)) { if (test(&path, data)) {
path_get(&path); path_get(&path);
if (!err) /* already found some */
path_put(res);
*res = path; *res = path;
err = 0; err = 0;
break;
} }
} }
if (!follow_up(&path)) if (!follow_up(&path))
...@@ -486,12 +486,11 @@ static int autofs_dev_ioctl_askumount(struct file *fp, ...@@ -486,12 +486,11 @@ static int autofs_dev_ioctl_askumount(struct file *fp,
* mount if there is one or 0 if it isn't a mountpoint. * mount if there is one or 0 if it isn't a mountpoint.
* *
* If we aren't supplied with a file descriptor then we * If we aren't supplied with a file descriptor then we
* lookup the nameidata of the path and check if it is the * lookup the path and check if it is the root of a mount.
* root of a mount. If a type is given we are looking for * If a type is given we are looking for a particular autofs
* a particular autofs mount and if we don't find a match * mount and if we don't find a match we return fail. If the
* we return fail. If the located nameidata path is the * located path is the root of a mount we return 1 along with
* root of a mount we return 1 along with the super magic * the super magic of the mount or 0 otherwise.
* of the mount or 0 otherwise.
* *
* In both cases the the device number (as returned by * In both cases the the device number (as returned by
* new_encode_dev()) is also returned. * new_encode_dev()) is also returned.
...@@ -519,9 +518,11 @@ static int autofs_dev_ioctl_ismountpoint(struct file *fp, ...@@ -519,9 +518,11 @@ static int autofs_dev_ioctl_ismountpoint(struct file *fp,
if (!fp || param->ioctlfd == -1) { if (!fp || param->ioctlfd == -1) {
if (autofs_type_any(type)) if (autofs_type_any(type))
err = kern_path(name, LOOKUP_FOLLOW, &path); err = kern_path_mountpoint(AT_FDCWD,
name, &path, LOOKUP_FOLLOW);
else else
err = find_autofs_mount(name, &path, test_by_type, &type); err = find_autofs_mount(name, &path,
test_by_type, &type);
if (err) if (err)
goto out; goto out;
devid = new_encode_dev(path.dentry->d_sb->s_dev); devid = new_encode_dev(path.dentry->d_sb->s_dev);
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment