"virGetDeviceID" could be used across the sources, but it doesn't
relate with this series, and could be done later.
* src/util/util.h: (Declare virGetDeviceID, and
vir{Get,Set}DeviceUnprivSGIO)
* src/util/util.c: (Implement virGetDeviceID and
vir{Get,Set}DeviceUnprivSGIO)
* src/libvirt_private.syms: Export private symbols of upper helpers
---
src/libvirt_private.syms | 3 +
src/util/util.c | 140 ++++++++++++++++++++++++++++++++++++++++++++++
src/util/util.h | 11 ++++
3 files changed, 154 insertions(+), 0 deletions(-)
diff --git a/src/libvirt_private.syms b/src/libvirt_private.syms
index 9288ad3..f1e1631 100644
--- a/src/libvirt_private.syms
+++ b/src/libvirt_private.syms
@@ -1281,6 +1281,8 @@ virFileWaitForDevices;
virFileWriteStr;
virFindFileInPath;
virFormatIntDecimal;
+virGetDeviceID;
+virGetDeviceUnprivSGIO;
virGetGroupID;
virGetGroupName;
virGetHostname;
@@ -1299,6 +1301,7 @@ virPipeReadUntilEOF;
virScaleInteger;
virSetBlocking;
virSetCloseExec;
+virSetDeviceUnprivSGIO;
virSetInherit;
virSetNonBlock;
virSetUIDGID;
diff --git a/src/util/util.c b/src/util/util.c
index 05e7ca7..baca182 100644
--- a/src/util/util.c
+++ b/src/util/util.c
@@ -3129,3 +3129,143 @@ virStrIsPrint(const char *str)
return true;
}
+
+#if defined(major) && defined(minor)
+int
+virGetDeviceID(const char *path, int *major, int *minor)
+{
+ struct stat sb;
+ char *canonical_path = NULL;
+
+ if (virFileResolveLink(path, &canonical_path) < 0)
+ 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;
+ }
+
+ if (major)
+ *major = major(sb.st_rdev);
+ if (minor)
+ *minor = minor(sb.st_rdev);
+
+ VIR_FREE(canonical_path);
+ return 0;
+}
+#else
+int
+virGetDeviceID(const char *path ATRRIBUTE_UNUSED,
+ int *major ATRRIBUTE_UNUSED,
+ int *minor ATRRIBUTE_UNUSED)
+{
+
+ return -ENOSYS;
+}
+#endif
+
+#define SYSFS_DEV_BLOCK_PATH "/sys/dev/block"
+
+static char *
+virGetUnprivSGIOSysfsPath(const char *path,
+ const char *sysfs_dir)
+{
+ int major, minor;
+ char *sysfs_path = NULL;
+ int rc;
+
+ if ((rc = virGetDeviceID(path, &major, &minor)) < 0) {
+ virReportSystemError(-rc,
+ _("Unable to get device ID '%s'"),
+ path);
+ return NULL;
+ }
+
+ if (virAsprintf(&sysfs_path, "%s/%d:%d/queue/unpriv_sgio",
+ sysfs_dir ? sysfs_dir : SYSFS_DEV_BLOCK_PATH,
+ major, minor) < 0) {
+ virReportOOMError();
+ return NULL;
+ }
+
+ return sysfs_path;
+}
+
+int
+virSetDeviceUnprivSGIO(const char *path,
+ const char *sysfs_dir,
+ int unpriv_sgio)
+{
+ char *sysfs_path = NULL;
+ char *val = NULL;
+ int ret = -1;
+ int rc;
+
+ if (!(sysfs_path = virGetUnprivSGIOSysfsPath(path, sysfs_dir)))
+ 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,
+ const char *sysfs_dir,
+ int *unpriv_sgio)
+{
+ char *sysfs_path = NULL;
+ char *buf = NULL;
+ char *tmp = NULL;
+ int ret = -1;
+
+ if (!(sysfs_path = virGetUnprivSGIOSysfsPath(path, sysfs_dir)))
+ 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 (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 6d5dd03..79c88a8 100644
--- a/src/util/util.h
+++ b/src/util/util.h
@@ -281,4 +281,15 @@ bool virIsDevMapperDevice(const char *dev_name)
ATTRIBUTE_NONNULL(1);
bool virValidateWWN(const char *wwn);
bool virStrIsPrint(const char *str);
+
+int virGetDeviceID(const char *path,
+ int *major,
+ int *minor);
+int virSetDeviceUnprivSGIO(const char *path,
+ const char *sysfs_dir,
+ int unpriv_sgio);
+int virGetDeviceUnprivSGIO(const char *path,
+ const char *sysfs_dir,
+ int *unpriv_sgio);
+
#endif /* __VIR_UTIL_H__ */
--
1.7.7.6