-----Original Message-----
From: cardoe(a)cardoe.com [mailto:cardoe@cardoe.com] On Behalf Of Doug Goldstein
Sent: Wednesday, September 25, 2013 6:26 PM
To: Purcareata Bogdan-B43198
Cc: libvir-list
Subject: Re: [libvirt] [PATCH] LXC: Detect fs support. Mount only supported fs in
containers
On Wed, Sep 25, 2013 at 5:49 AM, Bogdan Purcareata
<bogdan.purcareata(a)freescale.com> wrote:
> Some filesystems - specifically securityfs - are not supported in
> all systems running libvirt containers. When starting a container,
> mount only the filesystems that are supported on the host. Detection
> of filesystem support is done at runtime.
Might be worth noting this behavior is since 6807238d87fd93dee30
>
> Signed-off-by: Bogdan Purcareata <bogdan.purcareata(a)freescale.com>
> ---
> src/lxc/lxc_container.c | 61 +++++++++++++++++++++++++++++++++++++++++++++++++
> 1 file changed, 61 insertions(+)
>
> diff --git a/src/lxc/lxc_container.c b/src/lxc/lxc_container.c
> index c60f5d8..eff9a24 100644
> --- a/src/lxc/lxc_container.c
> +++ b/src/lxc/lxc_container.c
> @@ -509,6 +509,61 @@ static int lxcContainerChildMountSort(const void *a, const void
*b)
> # define MS_SLAVE (1<<19)
> #endif
>
> +/*
> + * This function attempts to detect kernel support
> + * for a specific filesystem type. This is done by
> + * inspecting /proc/filesystems.
> + */
> +static int lxcCheckFSSupport(const char *fs_type)
> +{
> + FILE *fp = NULL;
> + int ret = -1;
So your error case here is -1, which is good which we typically use.
> + const char *fslist = "/proc/filesystems";
> + char *line = NULL;
> + const char *type;
> +
> + if (!fs_type)
> + return 1;
.... but here its 1. You appear to use 1 as the success case below so
this conflicts.
I want to consider this a success case as well - there shouldn't be a problem trying
to mount an entry with type=NULL. Since the filesystem type is NULL, the kernel should
support the mount. Is this judgement acceptable?
> +
> + VIR_DEBUG("Checking kernel support for %s", fs_type);
> +
> + VIR_DEBUG("Open %s", fslist);
Can we combine these two debugs?
Yes. Will do.
> + if (!(fp = fopen(fslist, "r"))) {
> + if (errno == ENOENT)
It seems like you had another line after this if check that went away
since the line below is not indented properly. Since we always want to
print the error message you probably want to drop this if check
Yes, copy/paste error. Will properly handle the error case.
> +
> + virReportSystemError(errno,
> + _("Unable to read %s"),
> + fslist);
> + goto cleanup;
> + }
> +
> + while (!feof(fp)) {
> + size_t n;
> + VIR_FREE(line);
> + if (getline(&line, &n, fp) <= 0) {
> + if (feof(fp))
> + break;
This could really be optimized with:
while (getline(&line, &n, fp) > 0) {
.....do work here....
}
if (ferror(fp)) {
.... handle error ...
}
And we wouldn't have to have nested error checking.
Thank you, will update.
> +
> + goto cleanup;
> + }
> +
> + type = strstr(line, fs_type);
So I dislike using strstr() here because it'll be a greedy match. e.g.
should you check for "fuse", it will also match "fuseblk" and
"fusectl". Or check for "nfs" and it'll match on
"nfs4".
After the strstr(), I can also do a strncmp(type, fs_type, strlen(fs_type)), and that will
make sure there is a complete match. Sorry I haven't thought of this caveat.
> + if (type) {
> + ret = 1;
So here's the success case that it was found and its set to 1.
> + goto cleanup;
> + }
> + }
> +
> + VIR_DEBUG("No kernel support for %s", fs_type);
> +
> + ret = 0;
> +
> +cleanup:
> + VIR_FREE(line);
> + VIR_FORCE_FCLOSE(fp);
> + return ret;
> +}
> +
> static int lxcContainerGetSubtree(const char *prefix,
> char ***mountsret,
> size_t *nmountsret)
> @@ -855,17 +910,23 @@ static int lxcContainerMountBasicFS(bool userns_enabled)
> for (i = 0; i < ARRAY_CARDINALITY(lxcBasicMounts); i++) {
> virLXCBasicMountInfo const *mnt = &lxcBasicMounts[i];
> const char *srcpath = NULL;
> + const char *dstpath = NULL;
>
> VIR_DEBUG("Processing %s -> %s",
> mnt->src, mnt->dst);
>
> srcpath = mnt->src;
> + dstpath = mnt->dst;
>
> /* Skip if mount doesn't exist in source */
> if ((srcpath[0] == '/') &&
> (access(srcpath, R_OK) < 0))
> continue;
>
> + if ((access(dstpath, R_OK) < 0) || /* mount is not present on host */
So I understand you are doing this for securityfs. But there's other
cases when the filesystem might not be mounted on the host but we want
to mount it in the container so I could see this check wrecking havoc
with that. I could also be wrong.
Initially, I thought of this as well. But there seems to be a problem with
virFileMakePath, since it is called either way, and it fails to make
/sys/kernel/securityfs. I also tried to make it by hand, without any luck:
root@p4080ds:/sys/kernel# mkdir securityfs
mkdir: cannot create directory 'securityfs': No such file or directory
So I assumed it is best to mount it only if it's already present. How do you think I
should handle this?
> + (!lxcCheckFSSupport(mnt->type))) /* no fs support in kernel */
> + continue;
> +
> #if WITH_SELINUX
> if (STREQ(mnt->src, SELINUX_MOUNT) &&
> (!is_selinux_enabled() || userns_enabled))
> --
> 1.7.11.7
>
>
> --
> libvir-list mailing list
> libvir-list(a)redhat.com
>
https://www.redhat.com/mailman/listinfo/libvir-list
Hopefully some of the comments above help. Thanks for fixing this
since I too had a kernel running without securityfs and hit this.
Thank you very much for your comments! Sorry for the delay, I missed the patch comments
when I initially read this mail.
Bogdan P.
--
Doug Goldstein