Commit eb518936 authored by Oleg Nesterov's avatar Oleg Nesterov Committed by Pavel Emelyanov

introduce --skip-mnt cli option

Which obviously can be used to "ignore" the mounts we do not want or
need to dump. The user should know what he does.

Note: this patch changes parse_mountinfo() to check should_skip_mount().
This is because imo we want to filter out the unwanted mounts asap, af
if they do not exist. This increases the chances the dumping will fail
if something else depends on this mount. Say, another mountpoint or an
opened file.

Perhaps it makes sense to teach should_skip_mount() to use fnmatch()
and/or look at the optional "(fs|mnt)=" prefix to skip by fsname too.

To me it would be better to force the user of this option to understand
what it does. Say, if "dump" fails because the child mount can't find
the skipped parent, he should add another --skip-mnt option or do not
dump. Otherwise, if we do this automagically the user can probably be
surpised, he might even miss the fact that we skip more than he asked.
Signed-off-by: 's avatarOleg Nesterov <oleg@redhat.com>
Signed-off-by: 's avatarPavel Emelyanov <xemul@parallels.com>
parent 9fee3dc8
......@@ -203,6 +203,7 @@ int main(int argc, char *argv[], char *envp[])
{ "cgroup-root", required_argument, 0, 1061},
{ "inherit-fd", required_argument, 0, 1062},
{ "feature", required_argument, 0, 1063},
{ "skip-mnt", required_argument, 0, 1064},
{ },
};
......@@ -416,6 +417,10 @@ int main(int argc, char *argv[], char *envp[])
if (check_add_feature(optarg) < 0)
return 1;
break;
case 1064:
if (!add_skip_mount(optarg))
return 1;
break;
case 'M':
{
char *aux;
......@@ -642,6 +647,7 @@ usage:
" change the root cgroup the controller will be\n"
" installed into. No controller means that root is the\n"
" default for all controllers not specified.\n"
" --skip-mnt PATH ignore this mountpoint when dumping the mount namespace.\n"
"\n"
"* Logging:\n"
" -o|--log-file FILE log file name\n"
......
......@@ -153,6 +153,7 @@ extern void mnt_entry_free(struct mount_info *mi);
struct vm_area_list;
extern bool add_skip_mount(const char *mountpoint);
extern struct mount_info *parse_mountinfo(pid_t pid, struct ns_id *nsid, bool for_dump);
extern int parse_pid_stat(pid_t pid, struct proc_pid_stat *s);
extern int parse_smaps(pid_t pid, struct vm_area_list *vma_area_list);
......
......@@ -1000,6 +1000,37 @@ err:
goto ret;
}
static LIST_HEAD(skip_mount_list);
struct str_node {
struct list_head node;
char string[];
};
bool add_skip_mount(const char *mountpoint)
{
struct str_node *skip = xmalloc(sizeof(struct str_node) +
strlen(mountpoint) + 1);
if (!skip)
return false;
strcpy(skip->string, mountpoint);
list_add(&skip->node, &skip_mount_list);
return true;
}
static bool should_skip_mount(const char *mountpoint)
{
struct str_node *pos;
list_for_each_entry(pos, &skip_mount_list, node) {
if (strcmp(mountpoint, pos->string) == 0)
return true;
}
return false;
}
struct mount_info *parse_mountinfo(pid_t pid, struct ns_id *nsid, bool for_dump)
{
struct mount_info *list = NULL;
......@@ -1029,6 +1060,18 @@ struct mount_info *parse_mountinfo(pid_t pid, struct ns_id *nsid, bool for_dump)
goto end;
}
/*
* Drop this mountpoint early, so that lookup_mnt_id/etc will
* fail loudly at "dump" stage if an opened file or another mnt
* depends on this one.
*/
if (for_dump && should_skip_mount(new->mountpoint + 1)) {
pr_info("\tskip %s @ %s\n", fsname, new->mountpoint);
mnt_entry_free(new);
new = NULL;
goto end;
}
pr_info("\ttype %s source %s mnt_id %d s_dev %#x %s @ %s flags %#x options %s\n",
fsname, new->source,
new->mnt_id, new->s_dev, new->root, new->mountpoint,
......
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