[libvirt] [PATCH 3/5] virfile: Introduce virFileMajMinToName

Michal Privoznik mprivozn at redhat.com
Mon Mar 26 10:13:14 UTC 2018


On 03/26/2018 11:58 AM, Peter Krempa wrote:
> On Mon, Mar 26, 2018 at 07:16:44 +0200, Michal Privoznik wrote:
>> This function can be used to translate MAJ:MIN device pair into
>> /dev/blah name.
>>
>> Signed-off-by: Michal Privoznik <mprivozn at redhat.com>
>> ---
>>  src/libvirt_private.syms |  1 +
>>  src/util/virfile.c       | 53 ++++++++++++++++++++++++++++++++++++++++++++++++
>>  src/util/virfile.h       |  3 +++
>>  3 files changed, 57 insertions(+)
>>
>> diff --git a/src/util/virfile.c b/src/util/virfile.c
>> index f89e4bd823..62620862a1 100644
>> --- a/src/util/virfile.c
>> +++ b/src/util/virfile.c
>> @@ -68,6 +68,12 @@
>>  # include <libdevmapper.h>
>>  #endif
>>  
>> +#ifdef MAJOR_IN_MKDEV
>> +# include <sys/mkdev.h>
>> +#elif MAJOR_IN_SYSMACROS
>> +# include <sys/sysmacros.h>
>> +#endif
>> +
>>  #include "configmake.h"
>>  #include "intprops.h"
>>  #include "viralloc.h"
>> @@ -4317,3 +4323,50 @@ virFileGetMPathTargets(const char *path ATTRIBUTE_UNUSED,
>>      return -1;
>>  }
>>  #endif /* ! WITH_DEVMAPPER */
>> +
>> +
>> +/**
>> + * virFileMajMinToName:
>> + * @device: device (rdev) to translate
>> + * @name: returned name
> 
> I'd prefer if you supply the device identifiers already separated. That
> means that the function in the previous patch should preferrably already
> split them so that we don't need to do it here.

Okay.

> 
>> + *
>> + * For given MAJ:MIN pair (stored in one integer like in st_rdev)
>> + * fetch device name, e.g. 8:0 is translated to "/dev/sda".
>> + * Caller is responsible for freeing @name when no longer needed.
> 
> There is no info on how to treat errors.
> 
>> + *
>> + * Returns 0 on success, -1 otherwise.
> 
> Why isn't the path returned directly?

No reason. It's just that I'm used to functions returning an integer. I
can change it.

> 
>> + */
>> +int
>> +virFileMajMinToName(unsigned long long device,
>> +                    char **name)
>> +{
>> +    struct stat sb;
>> +    char *sysfsPath = NULL;
>> +    char *link = NULL;
>> +    int ret = -1;
>> +
>> +    *name = NULL;
>> +    if (virAsprintf(&sysfsPath, "/sys/dev/block/%u:%u",
>> +                    major(device), minor(device)) < 0)
> 
> So the libdevmapper code is using a similar path to figure out the sysfs
> path, but only for devicemapper devices since it accesses
> /sys/dev/block/%u:%u/dm/name.
> 
> I've also found that '/dev/block/' has the information you might need.
> 
> Is there any particular reason to use sysfs? I'm not really persuaded
> that the directory name in sysfs is good enough so if you can provide
> where you've inspired yourself it will be beneficial.

Okay, I'll switch to /dev/block/... Looks like I took too much
inspiration from other projects O:-)

> 
> Additionally virAsprintf reports libvirt errors but this function does
> not. 
> 
>> +        goto cleanup;
>> +
>> +    if (lstat(sysfsPath, &sb) < 0)
>> +        goto cleanup;
>> +
>> +    if (!S_ISLNK(sb.st_mode)) {
>> +        errno = ENXIO;
>> +        goto cleanup;
>> +    }
>> +
>> +    if (virFileReadLink(sysfsPath, &link) < 0)
>> +        goto cleanup;
>> +
>> +    if (virAsprintf(name, "/dev/%s", last_component(link)) < 0)
>> +        goto cleanup;
> 
> So this is the fishy path. I'd prefer /dev/block since the path already
> points to something in the /dev/ filesystem and isn't conjured up from
> something that looks the same.
> 

Ah, good point. So if I do plain:

virAsprintf(&path, "/dev/block/%u:%u", major(), minor())

I immediately get the correct symlink with both namespace and cgroup
codes know how to deal with. Cool, so this patch might be dropped.

Michal




More information about the libvir-list mailing list