[libvirt] [PATCH 07/15] util: Prepare helpers for unpriv_sgio setting

Osier Yang jyang at redhat.com
Wed Dec 5 08:20:41 UTC 2012


"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: (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          |  145 ++++++++++++++++++++++++++++++++++++++++++++++
 src/util/util.h          |    7 ++
 3 files changed, 156 insertions(+), 0 deletions(-)

diff --git a/src/libvirt_private.syms b/src/libvirt_private.syms
index df54f1e..78e4a5c 100644
--- a/src/libvirt_private.syms
+++ b/src/libvirt_private.syms
@@ -1271,6 +1271,9 @@ virFileWaitForDevices;
 virFileWriteStr;
 virFindFileInPath;
 virFormatIntDecimal;
+virGetDeviceMajor;
+virGetDeviceMinor;
+virGetDeviceUnprivSGIO;
 virGetGroupID;
 virGetGroupName;
 virGetHostname;
@@ -1289,6 +1292,7 @@ virPipeReadUntilEOF;
 virScaleInteger;
 virSetBlocking;
 virSetCloseExec;
+virSetDeviceUnprivSGIO;
 virSetInherit;
 virSetNonBlock;
 virSetUIDGID;
diff --git a/src/util/util.c b/src/util/util.c
index 2fd0f2c..4dab6ac 100644
--- a/src/util/util.c
+++ b/src/util/util.c
@@ -3113,3 +3113,148 @@ virValidateWWN(const char *wwn) {
 
     return true;
 }
+
+#if defined(major) && defined(minor)
+int
+virGetDeviceMajor(const char *path)
+{
+    struct stat sb;
+
+    if (stat(path, &sb) < 0)
+        return -errno;
+
+    if (!S_ISBLK(sb.st_mode))
+        return -EINVAL;
+
+    return major(sb.st_rdev);
+}
+
+int
+virGetDeviceMinor(const char *path)
+{
+    struct stat sb;
+
+    if (stat(path, &sb) < 0)
+        return -errno;
+
+    if (!S_ISBLK(sb.st_mode))
+        return -EINVAL;
+
+    return minor(sb.st_rdev);
+}
+#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;
+
+    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;
+    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;
+    }
+
+    ret = 0;
+cleanup:
+    VIR_FREE(sysfs_path);
+    VIR_FREE(buf);
+    return ret;
+}
diff --git a/src/util/util.h b/src/util/util.h
index 4316ab1..41146c1 100644
--- a/src/util/util.h
+++ b/src/util/util.h
@@ -280,4 +280,11 @@ bool virIsDevMapperDevice(const char *dev_name) ATTRIBUTE_NONNULL(1);
 
 bool virValidateWWN(const char *wwn);
 
+int virGetDeviceMajor(const char *path);
+int virGetDeviceMinor(const char *path);
+int virSetDeviceUnprivSGIO(const char *path,
+                           int unpriv_sgio);
+int virGetDeviceUnprivSGIO(const char *path,
+                           int *unpriv_sgio);
+
 #endif /* __VIR_UTIL_H__ */
-- 
1.7.7.6




More information about the libvir-list mailing list