[libvirt] [PATCH v2] LXC: Detect fs support. Mount only supported filesystems

Gao feng gaofeng at cn.fujitsu.com
Mon Oct 7 03:52:26 UTC 2013


On 10/07/2013 11:44 AM, Gao feng wrote:
> On 10/04/2013 07:33 PM, Purcareata Bogdan-B43198 wrote:
> 
>>>> +/*
>>>> + * 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;
>>>> +    const char *fslist = "/proc/filesystems";
>>>> +    char *line = NULL;
>>>> +    char *type;
>>>> +    size_t n;
>>>> +
>>>> +    /* there should be no problem mounting an entry
>>>> +     * with NULL fs type, hence NULL fs types are
>>>> +     * supported */
>>>> +    if (!fs_type) {
>>>> +	ret = 1;
>>>> +	goto out;
>>>> +    }
>>>> +
>>>> +    VIR_DEBUG("Checking kernel support for %s in %s", fs_type, fslist);
>>>> +
>>>> +    if (!(fp = fopen(fslist, "r"))) {
>>>
>>> I don't know if we can open /proc/filesystems successfully here if container
>>> shares
>>> root directory with host, since the /proc filesystem has been unmounted in
>>> lxcContainerUnmountForSharedRoot.
>>
>> Right. I just noticed the search for "proc" fails, since /proc/filesystem requires procfs to be mounted. (Un)fortunately, my handling of lxcCheckFSSupport() bypassed this error, and mounted procfs anyways. I will update the code with a proper handle for the error code. I just don't see how I can handle all filesystem entries in an uniform manner, since each one is so special.
>>
>>>
> 
> So save the supported filesystem list before we unmount the proc filesystem, and in lxcCheckFSSupport
> use this list to check if the filesystem is supported by kernel.
> 
> btw it's better to return the error of fopen to user.
> 
>>>> +        virReportSystemError(errno,
>>>> +                             _("Unable to read %s"),
>>>> +                             fslist);
>>>> +        goto out;
>>>> +    }
>>>> +
>>>> +    while(getline(&line, &n, fp) > 0) {
>>>> +	type = strstr(line, fs_type);
>>>> +
>>>> +	if (!type)
>>>> +		continue;
>>>> +
>>>> +	if (!strncmp(type, fs_type, strlen(type))) {
>>>
>>> The strncmp() function compares the only first (at most) n bytes of s1 and s2.
>>> please use STREQ here.
>>
>> Thanks, I will update.
>>
>>>
>>>> +		ret = 1;
>>>> +		goto cleanup;
>>>> +	}
>>>> +    }
>>>> +
>>>> +    if (ferror(fp)) {
>>>> +	virReportSystemError(errno,
>>>> +                             _("Error reading line from %s"),
>>>> +                             fslist);
>>>> +        goto cleanup;
>>>> +    }
>>>> +
>>>> +    VIR_DEBUG("No kernel support for %s", fs_type);
>>>> +
>>>> +    ret = 0;
>>>> +
>>>
>>> You set ret to 0 here, so the return value 0 means this filesystem
>>> is unsupported by kernel, right? what the meaning of return value -1?
>>>
>>> you return -1 when ferror(fp) is true.
>>
>> So I thought it would be like this:
>> - -1 - error encountered
>> - 0 - no error, no kernel support for the filesystem
>> - 1 - no error, kernel support present
>>
>>>
>>>> +cleanup:
>>>> +    VIR_FREE(line);
>>>> +    VIR_FORCE_FCLOSE(fp);
>>>> +out:
>>>> +    return ret;
>>>> +}
>>>> +
>>>>  static int lxcContainerGetSubtree(const char *prefix,
>>>>                                    char ***mountsret,
>>>>                                    size_t *nmountsret)
>>>> @@ -789,17 +850,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 */
>>>> +	    (!lxcCheckFSSupport(mnt->type))) /* no fs support in kernel */
>>>> +		continue;
>>>> +
>>>
>>> The access is in the incorrect place, it should be called after we create mnt-
>>>> dst.
>>> so Move this check after virFileMakePath(mnt->dst).
>>
>> My specific problem was that mounting security failed even before reaching the actual mount syscall. 
>>
>> It failed when doing virFileMakePath("/sys/kernel/securityfs"), because /sys is previously mounted read only (I realized this just now).
>>
>> root at p4080ds:/sys/kernel# mkdir securityfs
>> mkdir: cannot create directory 'securityfs': No such file or directory
>>
> 
> I don't know how this occurred, since the directory securityfs is created when you mount sysfs.
> Actually virFileMakePath will not create securityfs directory since it already exists.
> 

So I think you can remove the check of access(dstpath, R_OK). if securityfs is supported,
virFileMakePath must be successful.

the reason fail to create directory securityfs is creating files is unsupported by sysfs.




More information about the libvir-list mailing list