On Fri, Dec 14, 2012 at 03:05:36 +0800, Osier Yang wrote: > "virGetDevice{Major,Minor}" could be used across the sources, > but it doesn't relate with this series, and could be done later. > > * src/util/util.h: (Declare virGetDevice{Major,Minor}, and > vir{Get,Set}DeviceUnprivSGIO) > * src/util/util.c: (New internal helper virCanonicalizeDiskPath to > canonicalize the disk path; Implement > virGetDevice{Major,Minor} and > vir{Get,Set}DeviceUnprivSGIO) > * src/libvirt_private.syms: Export private symbols of upper helpers > --- > src/libvirt_private.syms | 4 + > src/util/util.c | 180 ++++++++++++++++++++++++++++++++++++++++++++++ > src/util/util.h | 8 ++ > 3 files changed, 192 insertions(+), 0 deletions(-) ... > diff --git a/src/util/util.c b/src/util/util.c > index 05e7ca7..8c6d43c 100644 > --- a/src/util/util.c > +++ b/src/util/util.c > @@ -3129,3 +3129,183 @@ virStrIsPrint(const char *str) > > return true; > } > + > +static char * > +virCanonicalizeDiskPath(const char *path) > +{ > + char *canonical_path = NULL; > + > + if (STRPREFIX(path, "/dev/disk/by-path") || > + STRPREFIX(path, "/dev/disk/by-uuid") || > + STRPREFIX(path, "/dev/disk/by-id")) { > + if (virFileResolveLink(path, &canonical_path) < 0) > + return NULL; > + } else { > + canonical_path = strdup(path); > + } > + > + return canonical_path; > +} There's no reason to restrict virFileResolveLink only to disk paths that start with /dev/disk/by-*. Symlinks to devices can be anywhere; just call it unconditionally. > + > +#if defined(major) && defined(minor) > +int > +virGetDeviceMajor(const char *path) > +{ > + struct stat sb; > + char *canonical_path = NULL; > + > + if (!(canonical_path = virCanonicalizeDiskPath(path))) > + return -errno; > + > + if (stat(canonical_path, &sb) < 0) { > + VIR_FREE(canonical_path); > + return -errno; > + } > + > + if (!S_ISBLK(sb.st_mode)) { > + VIR_FREE(canonical_path); > + return -EINVAL; > + } > + > + VIR_FREE(canonical_path); > + return major(sb.st_rdev); > +} > + > +int > +virGetDeviceMinor(const char *path) > +{ > + struct stat sb; > + char *canonical_path = NULL; > + > + if (!(canonical_path = virCanonicalizeDiskPath(path))) > + return -errno; > + > + if (stat(canonical_path, &sb) < 0) { > + VIR_FREE(canonical_path); > + return -errno; > + } > + > + if (!S_ISBLK(sb.st_mode)) { > + VIR_FREE(canonical_path); > + return -EINVAL; > + } > + > + VIR_FREE(canonical_path); > + return minor(sb.st_rdev); > +} Oh, this is horrible. Why did you create two functions for getting major and minor numbers? Creating int virGetDeviceID(const char *path, int *major, int *minor) that would extract both at one go (since you want to get both of them anyway and if not, you can allow NULL to be passed for either) seems to be a better approach. And while at it, you can just remove the virCanonicalizeDiskPath helper and call virFileResolveLink directly in virGetDeviceID. > +#else > +int > +virGetDeviceMajor(const char *path) > +{ > + return -ENOSYS; > +} > + > +int > +virGetDeviceMinor(const char *path) > +{ > + return -ENOSYS; > +} > +#endif > + > +static char * > +virGetUnprivSGIOSysfsPath(const char *path) > +{ > + int major, minor; > + char *sysfs_path = NULL; > + > + if ((major = virGetDeviceMajor(path)) < 0) { > + virReportSystemError(-major, > + _("Unable to get major number of device '%s'"), > + path); > + return NULL; > + } > + > + if ((minor = virGetDeviceMinor(path)) < 0) { > + virReportSystemError(-minor, > + _("Unable to get minor number of device '%s'"), > + path); > + return NULL; > + } > + > + if (virAsprintf(&sysfs_path, "/sys/dev/block/%d:%d/queue/unpriv_sgio", > + major, minor) < 0) { > + virReportOOMError(); > + return NULL; > + } > + > + return sysfs_path; > +} > + > +int > +virSetDeviceUnprivSGIO(const char *path, > + int unpriv_sgio) > +{ > + char *sysfs_path = NULL; > + char *val = NULL; > + int ret = -1; > + int rc = -1; Nit: no need to initalize rc. > + > + if (!(sysfs_path = virGetUnprivSGIOSysfsPath(path))) > + return -1; > + > + if (!virFileExists(sysfs_path)) { > + virReportError(VIR_ERR_OPERATION_INVALID, "%s", > + _("unpriv_sgio is not supported by this kernel")); > + goto cleanup; > + } > + > + if (virAsprintf(&val, "%d", unpriv_sgio) < 0) { > + virReportOOMError(); > + goto cleanup; > + } > + > + if ((rc = virFileWriteStr(sysfs_path, val, 0)) < 0) { > + virReportSystemError(-rc, _("failed to set %s"), sysfs_path); > + goto cleanup; > + } > + > + ret = 0; > +cleanup: > + VIR_FREE(sysfs_path); > + VIR_FREE(val); > + return ret; > +} > + > +int > +virGetDeviceUnprivSGIO(const char *path, > + int *unpriv_sgio) > +{ > + char *sysfs_path = NULL; > + char *buf = NULL; > + char *tmp = NULL; Nit: sysfs_path and tmp do not really need be initialized. > + int ret = -1; > + int rc = -1; > + > + if (!(sysfs_path = virGetUnprivSGIOSysfsPath(path))) > + return -1; > + > + if (!virFileExists(sysfs_path)) { > + virReportError(VIR_ERR_OPERATION_INVALID, "%s", > + _("unpriv_sgio is not supported by this kernel")); > + goto cleanup; > + } > + > + if (virFileReadAll(sysfs_path, 1024, &buf) < 0) > + goto cleanup; > + > + if ((tmp = strchr(buf, '\n'))) > + *tmp = '\0'; > + > + if ((rc = virStrToLong_i(buf, NULL, 10, > + unpriv_sgio)) < 0) { > + virReportError(VIR_ERR_INTERNAL_ERROR, > + _("failed to parse value of %s"), sysfs_path); > + goto cleanup; > + } rc is completely useless in this function. > + ret = 0; > +cleanup: > + VIR_FREE(sysfs_path); > + VIR_FREE(buf); > + return ret; > +} Jirka -- libvir-list mailing list libvir-list@xxxxxxxxxx https://www.redhat.com/mailman/listinfo/libvir-list