"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 4ec19a0..e500ea9 100644
--- a/src/libvirt_private.syms
+++ b/src/libvirt_private.syms
@@ -1283,6 +1283,8 @@ virFileWaitForDevices;
virFileWriteStr;
virFindFileInPath;
virFormatIntDecimal;
+virGetDeviceID;
+virGetDeviceUnprivSGIO;
virGetGroupID;
virGetGroupName;
virGetHostname;
@@ -1301,6 +1303,7 @@ virPipeReadUntilEOF;
virScaleInteger;
virSetBlocking;
virSetCloseExec;
+virSetDeviceUnprivSGIO;
virSetInherit;
virSetNonBlock;
virSetUIDGID;
diff --git a/src/util/util.c b/src/util/util.c
index 05e7ca7..06c7e33 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 *maj, int *min)
+{
+ 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 (maj)
+ *maj = major(sb.st_rdev);
+ if (min)
+ *min = minor(sb.st_rdev);
+
+ VIR_FREE(canonical_path);
+ return 0;
+}
+#else
+int
+virGetDeviceID(const char *path ATRRIBUTE_UNUSED,
+ int *maj ATRRIBUTE_UNUSED,
+ int *min ATRRIBUTE_UNUSED)
+{
+
+ return -ENOSYS;
+}
+#endif
+
+#define SYSFS_DEV_BLOCK_PATH "/sys/dev/block"
+
+static char *
+virGetUnprivSGIOSysfsPath(const char *path,
+ const char *sysfs_dir)
+{
+ int maj, min;
+ char *sysfs_path = NULL;
+ int rc;
+
+ if ((rc = virGetDeviceID(path, &maj, &min)) < 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,
+ maj, min) < 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..71003f7 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 *maj,
+ int *min);
+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