findmnt: don't rely on st_dev for --target

The overlay filesystem does not provide usable st_dev (in traditional
UNIX way). It's necessary to search in /proc/self/mountinfo to detect
which path element is mountpoint.

$ findmnt --target /mnt/merged/dir-a/foo
TARGET      SOURCE  FSTYPE  OPTIONS
/mnt/merged overlay overlay rw,relatime,lowerdir=/mnt/low,upperdir=/mnt/high/data,workdir=/mnt/high/work

Signed-off-by: Karel Zak <kzak@redhat.com>
This commit is contained in:
Karel Zak 2015-03-10 12:51:44 +01:00
parent 7d3a07d87f
commit cd41b385a0
3 changed files with 20 additions and 10 deletions

View File

@ -960,6 +960,10 @@ int mnt_open_uniq_filename(const char *filename, char **name)
* This function finds the mountpoint that a given path resides in. @path
* should be canonicalized. The returned pointer should be freed by the caller.
*
* WARNING: the function compares st_dev of the @path elements. This traditional
* way maybe be insufficient on filesystems like Linux "overlay". See also
* mnt_table_find_target().
*
* Returns: allocated string with the target of the mounted device or NULL on error
*/
char *mnt_get_mountpoint(const char *path)

View File

@ -185,8 +185,12 @@ Search in
.IR /etc/fstab .
The output is in the list format (see \fB--list\fR).
.TP
.BR \-T , " \-\-target \fIdir\fP"
Explicitly define the mount target (mountpoint directory).
.BR \-T , " \-\-target \fIpath\fP"
Explicitly define the mount target (mountpoint directory). If the \fIpath\fR
is not a mountpoint file or directory than
.B findmnt
checks \fIpath\fR elements in reverse order for get the mountpoint (this feature is
supported only if search in kernel files and unsupported for \fB\-\-fstab\fP).
.TP
.BR \-t , " \-\-types \fIlist\fP"
Limit the set of printed filesystems. More than one type may be

View File

@ -259,10 +259,12 @@ static void set_source_match(const char *data)
set_match(COL_SOURCE, data);
}
static void enable_extra_target_match(void)
/* @tb has to be from kernel (so no fstab or so)! */
static void enable_extra_target_match(struct libmnt_table *tb)
{
char *cn = NULL, *mnt = NULL;
const char *tgt = NULL;
char *cn = NULL;
const char *tgt = NULL, *mnt = NULL;
struct libmnt_fs *fs;
/*
* Check if match pattern is mountpoint, if not use the
@ -276,11 +278,11 @@ static void enable_extra_target_match(void)
return;
}
mnt = mnt_get_mountpoint(tgt);
fs = mnt_table_find_mountpoint(tb, tgt, MNT_ITER_BACKWARD);
if (fs)
mnt = mnt_fs_get_target(fs);
if (mnt && strcmp(mnt, tgt) != 0)
set_match(COL_TARGET, mnt); /* replace the current setting */
else
free(mnt);
set_match(COL_TARGET, xstrdup(mnt)); /* replace the current setting */
if (!cache)
free(cn);
@ -1606,7 +1608,7 @@ int main(int argc, char *argv[])
* try it again with extra functionality for target
* match
*/
enable_extra_target_match();
enable_extra_target_match(tb);
rc = add_matching_lines(tb, table, direction);
}
}