[libvirt] [PATCH]: Rework xenLinuxDomainDeviceID to support more devices

Jim Meyering jim at meyering.net
Tue Aug 5 13:08:57 UTC 2008


Chris Lalancette <clalance at redhat.com> wrote:
...
> test suite.  As far as the error reporting goes, I won't argue that my patch
> gives slightly less information.  However, that being said, I have to believe
> that the most likely use of block statistics is something like:
>
> virsh dumpxml <dom>
> ...see what devices are listed there
> virsh domblkstats <dom> <device>
>
> In which case the slightly less verbose error reporting won't matter a whole lot.

Hi Chris,

...
> Index: src/stats_linux.c
> ===================================================================
...
> +static int
> +disk_re_match(const char *regex, const char *path, int *part)
> +{
> +    regex_t myreg;
> +    int err;
> +    int retval;
> +    regmatch_t pmatch[2];
> +
> +    retval = 0;
> +
> +    err = regcomp(&myreg, regex, REG_EXTENDED);
> +    if (err != 0)
> +        return 0;
> +
> +    err = regexec(&myreg, path, 2, pmatch, 0);
> +
> +    if (err == 0) {
> +        /* OK, we have a match; see if we have a partition */
> +        *part = 0;
> +        if (pmatch[1].rm_so != -1) {
> +            if (virStrToLong_i(path + pmatch[1].rm_so, NULL, 10, part) < 0)
> +                retval = 0;
> +            else
> +                retval = 1;
> +        }
> +        else
> +            retval = 1;
> +    }

How about dropping both "else" blocks and initializing "retval=1" above:

       if (err == 0) {
           /* OK, we have a match; see if we have a partition */
           *part = 0;
           retval = 1;
           if (pmatch[1].rm_so != -1) {
               if (virStrToLong_i(path + pmatch[1].rm_so, NULL, 10, part) < 0)
                   retval = 0;
           }
       }

You could even reduce the retval-setting part to a single statement:

    if (err == 0) {
        /* OK, we have a match; see if we have a partition */
        *part = 0;
        retval = (pmatch[1].rm_so == -1
                  || virStrToLong_i(path + pmatch[1].rm_so,
                                    NULL, 10, part) == 0);
    }

>  int
>  xenLinuxDomainDeviceID(virConnectPtr conn, int domid, const char *path)
>  {
> -    int disk, part = 0;
> -
> -    /* Strip leading path if any */
> -    if (strlen(path) > 5 &&
> -        STRPREFIX(path, "/dev/"))
> -        path += 5;
> +    int major, minor;
> +    int part;
> +    int retval;
> +    char *mod_path;
> +
> +    int scsi_majors[] = { SCSI_DISK0_MAJOR, SCSI_DISK1_MAJOR,

I know you just moved these, but they can be const:

       int const scsi_majors[] = {...

...
> +    int ide_majors[] = { IDE0_MAJOR, IDE1_MAJOR, IDE2_MAJOR, IDE3_MAJOR,

       int const ide_majors[] = { ...

...
> +    if (strlen(path) > 5 && STRPREFIX(path, "/dev/"))

Maybe use ">= 5", so that this code will preserve /dev/,
rather than turn it into "/dev//dev/" ?

> +        retval = asprintf(&mod_path, "%s", path);
> +    else
> +        retval = asprintf(&mod_path, "/dev/%s", path);
...
> +    if (disk_re_match("/dev/sd[a-z]([1-9]|1[0-5])?$", mod_path, &part)) {
> +        major = scsi_majors[(mod_path[7] - 'a') / 16];
> +        minor = ((mod_path[7] - 'a') % 16) * 16 + part;
> +        retval = major * 256 + minor;
> +    }
> +    else if (disk_re_match("/dev/sd[a-h][a-z]([1-9]|1[0-5])?$",
> +                           mod_path, &part) ||
> +             disk_re_match("/dev/sdi[a-v]([1-9]|1[0-5])?$",
> +                           mod_path, &part)) {
> +        major = scsi_majors[((mod_path[7] - 'a' + 1) * 26 + (mod_path[8] - 'a')) / 16];
> +        minor = (((mod_path[7] - 'a' + 1) * 26 + (mod_path[8] - 'a')) % 16)
> +            * 16 + part;
> +        retval = major * 256 + minor;
> +    }
> +    else if (disk_re_match("/dev/hd[a-t]([1-9]|[1-5][0-9]|6[0-3])?$",
> +                           mod_path, &part)) {
> +        major = ide_majors[(mod_path[7] - 'a') / 2];
> +        minor = ((mod_path[7] - 'a') % 2) * 64 + part;
> +        retval = major * 256 + minor;
>      }
> +    else if (disk_re_match("/dev/xvd[a-p]([1-9]|1[0-5])?$", mod_path, &part))
> +        retval = (202 << 8) + ((mod_path[8] - 'a') << 4) + part;
> +    else if (disk_re_match("/dev/xvd[q-z]([1-9]|1[0-5])?$", mod_path, &part))
> +        retval = (1 << 28) + ((mod_path[8] - 'a') << 8) + part;
> +    else if (disk_re_match("/dev/xvd[a-i][a-z]([1-9]|1[0-5])?$",
> +                           mod_path, &part))
> +        retval = (1 << 28) + (((mod_path[8] - 'a' + 1) * 26 + (mod_path[9] - 'a')) << 8) + part;

To retain the diagnostic Dan mentioned, you should be able to
insert something like this just before the final "else":

    else if (disk_re_match("/dev/sd[a-z]([0-9])+$", mod_path, &part)) {

> +    else
> +        statsErrorFunc (conn, VIR_ERR_INVALID_ARG, __FUNCTION__,
> +                        "unsupported path, use xvdN, hdN, or sdN", domid);




More information about the libvir-list mailing list