|
|
c401cc |
From fd7349166af834cd954fed04091611f91e312a25 Mon Sep 17 00:00:00 2001
|
|
|
c401cc |
Message-Id: <fd7349166af834cd954fed04091611f91e312a25@dist-git>
|
|
|
c401cc |
From: Eric Blake <eblake@redhat.com>
|
|
|
c401cc |
Date: Wed, 26 Feb 2014 14:54:34 +0100
|
|
|
c401cc |
Subject: [PATCH] storage: refactor backing chain division of labor
|
|
|
c401cc |
|
|
|
c401cc |
https://bugzilla.redhat.com/show_bug.cgi?id=1032370
|
|
|
c401cc |
|
|
|
c401cc |
Future patches will want to learn metadata about a file using
|
|
|
c401cc |
a buffer that was already parsed in order to probe the file's
|
|
|
c401cc |
format. Rather than reopening and re-reading the file, it makes
|
|
|
c401cc |
sense to separate getting file contents from actually parsing
|
|
|
c401cc |
those contents.
|
|
|
c401cc |
|
|
|
c401cc |
* src/util/virstoragefile.c (virStorageFileGetMetadataFromBuf)
|
|
|
c401cc |
(virStorageFileGetMetadataFromFDInternal): New functions.
|
|
|
c401cc |
(virStorageFileGetMetadataInternal): Hoist fstat() and read() into
|
|
|
c401cc |
callers.
|
|
|
c401cc |
(virStorageFileGetMetadataFromFD)
|
|
|
c401cc |
(virStorageFileGetMetadataRecurse): Rework clients.
|
|
|
c401cc |
* src/util/virstoragefile.h (virStorageFileGetMetadataFromBuf):
|
|
|
c401cc |
New prototype.
|
|
|
c401cc |
* src/libvirt_private.syms (virstoragefile.h): Export it.
|
|
|
c401cc |
|
|
|
c401cc |
Signed-off-by: Eric Blake <eblake@redhat.com>
|
|
|
c401cc |
(cherry picked from commit 3ead2e7dedab7d9380496798ef0201be2b0047b5)
|
|
|
c401cc |
Signed-off-by: Jiri Denemark <jdenemar@redhat.com>
|
|
|
c401cc |
---
|
|
|
c401cc |
src/libvirt_private.syms | 1 +
|
|
|
c401cc |
src/util/virstoragefile.c | 118 +++++++++++++++++++++++++++++++++-------------
|
|
|
c401cc |
src/util/virstoragefile.h | 4 ++
|
|
|
c401cc |
3 files changed, 91 insertions(+), 32 deletions(-)
|
|
|
c401cc |
|
|
|
c401cc |
diff --git a/src/libvirt_private.syms b/src/libvirt_private.syms
|
|
|
c401cc |
index e239aba..4d74d46 100644
|
|
|
c401cc |
--- a/src/libvirt_private.syms
|
|
|
c401cc |
+++ b/src/libvirt_private.syms
|
|
|
c401cc |
@@ -1924,6 +1924,7 @@ virStorageFileFormatTypeToString;
|
|
|
c401cc |
virStorageFileFreeMetadata;
|
|
|
c401cc |
virStorageFileGetLVMKey;
|
|
|
c401cc |
virStorageFileGetMetadata;
|
|
|
c401cc |
+virStorageFileGetMetadataFromBuf;
|
|
|
c401cc |
virStorageFileGetMetadataFromFD;
|
|
|
c401cc |
virStorageFileGetSCSIKey;
|
|
|
c401cc |
virStorageFileIsClusterFS;
|
|
|
c401cc |
diff --git a/src/util/virstoragefile.c b/src/util/virstoragefile.c
|
|
|
c401cc |
index bb27461..8b89db1 100644
|
|
|
c401cc |
--- a/src/util/virstoragefile.c
|
|
|
c401cc |
+++ b/src/util/virstoragefile.c
|
|
|
c401cc |
@@ -752,47 +752,26 @@ qcow2GetFeatures(virBitmapPtr *features,
|
|
|
c401cc |
}
|
|
|
c401cc |
|
|
|
c401cc |
|
|
|
c401cc |
-/* Given a file descriptor FD open on PATH, and optionally opened from
|
|
|
c401cc |
- * a given DIRECTORY, return metadata about that file, assuming it has
|
|
|
c401cc |
- * the given FORMAT. */
|
|
|
c401cc |
+/* Given a header in BUF with length LEN, as parsed from the file
|
|
|
c401cc |
+ * located at PATH, and optionally opened from a given DIRECTORY,
|
|
|
c401cc |
+ * return metadata about that file, assuming it has the given
|
|
|
c401cc |
+ * FORMAT. */
|
|
|
c401cc |
static virStorageFileMetadataPtr
|
|
|
c401cc |
virStorageFileGetMetadataInternal(const char *path,
|
|
|
c401cc |
- int fd,
|
|
|
c401cc |
+ char *buf,
|
|
|
c401cc |
+ size_t len,
|
|
|
c401cc |
const char *directory,
|
|
|
c401cc |
int format)
|
|
|
c401cc |
{
|
|
|
c401cc |
virStorageFileMetadata *meta = NULL;
|
|
|
c401cc |
- char *buf = NULL;
|
|
|
c401cc |
- ssize_t len = STORAGE_MAX_HEAD;
|
|
|
c401cc |
virStorageFileMetadata *ret = NULL;
|
|
|
c401cc |
- struct stat sb;
|
|
|
c401cc |
|
|
|
c401cc |
- VIR_DEBUG("path=%s, fd=%d, format=%d", path, fd, format);
|
|
|
c401cc |
+ VIR_DEBUG("path=%s, buf=%p, len=%zu, directory=%s, format=%d",
|
|
|
c401cc |
+ path, buf, len, NULLSTR(directory), format);
|
|
|
c401cc |
|
|
|
c401cc |
if (VIR_ALLOC(meta) < 0)
|
|
|
c401cc |
return NULL;
|
|
|
c401cc |
|
|
|
c401cc |
- if (fstat(fd, &sb) < 0) {
|
|
|
c401cc |
- virReportSystemError(errno,
|
|
|
c401cc |
- _("cannot stat file '%s'"),
|
|
|
c401cc |
- path);
|
|
|
c401cc |
- goto cleanup;
|
|
|
c401cc |
- }
|
|
|
c401cc |
-
|
|
|
c401cc |
- /* No header to probe for directories, but also no backing file */
|
|
|
c401cc |
- if (S_ISDIR(sb.st_mode))
|
|
|
c401cc |
- return meta;
|
|
|
c401cc |
-
|
|
|
c401cc |
- if (lseek(fd, 0, SEEK_SET) == (off_t)-1) {
|
|
|
c401cc |
- virReportSystemError(errno, _("cannot seek to start of '%s'"), path);
|
|
|
c401cc |
- goto cleanup;
|
|
|
c401cc |
- }
|
|
|
c401cc |
-
|
|
|
c401cc |
- if ((len = virFileReadHeaderFD(fd, len, (char **)&buf)) < 0) {
|
|
|
c401cc |
- virReportSystemError(errno, _("cannot read header '%s'"), path);
|
|
|
c401cc |
- goto cleanup;
|
|
|
c401cc |
- }
|
|
|
c401cc |
-
|
|
|
c401cc |
if (format == VIR_STORAGE_FILE_AUTO)
|
|
|
c401cc |
format = virStorageFileProbeFormatFromBuf(path, buf, len);
|
|
|
c401cc |
|
|
|
c401cc |
@@ -893,7 +872,6 @@ done:
|
|
|
c401cc |
|
|
|
c401cc |
cleanup:
|
|
|
c401cc |
virStorageFileFreeMetadata(meta);
|
|
|
c401cc |
- VIR_FREE(buf);
|
|
|
c401cc |
return ret;
|
|
|
c401cc |
}
|
|
|
c401cc |
|
|
|
c401cc |
@@ -979,6 +957,81 @@ virStorageFileProbeFormat(const char *path, uid_t uid, gid_t gid)
|
|
|
c401cc |
return ret;
|
|
|
c401cc |
}
|
|
|
c401cc |
|
|
|
c401cc |
+
|
|
|
c401cc |
+/**
|
|
|
c401cc |
+ * virStorageFileGetMetadataFromBuf:
|
|
|
c401cc |
+ * @path: name of file, for error messages
|
|
|
c401cc |
+ * @buf: header bytes from @path
|
|
|
c401cc |
+ * @len: length of @buf
|
|
|
c401cc |
+ * @format: expected image format
|
|
|
c401cc |
+ *
|
|
|
c401cc |
+ * Extract metadata about the storage volume with the specified
|
|
|
c401cc |
+ * image format. If image format is VIR_STORAGE_FILE_AUTO, it
|
|
|
c401cc |
+ * will probe to automatically identify the format. Does not recurse.
|
|
|
c401cc |
+ *
|
|
|
c401cc |
+ * Callers are advised never to use VIR_STORAGE_FILE_AUTO as a
|
|
|
c401cc |
+ * format, since a malicious guest can turn a raw file into any
|
|
|
c401cc |
+ * other non-raw format at will.
|
|
|
c401cc |
+ *
|
|
|
c401cc |
+ * If the returned meta.backingStoreFormat is VIR_STORAGE_FILE_AUTO
|
|
|
c401cc |
+ * it indicates the image didn't specify an explicit format for its
|
|
|
c401cc |
+ * backing store. Callers are advised against probing for the
|
|
|
c401cc |
+ * backing store format in this case.
|
|
|
c401cc |
+ *
|
|
|
c401cc |
+ * Caller MUST free the result after use via virStorageFileFreeMetadata.
|
|
|
c401cc |
+ */
|
|
|
c401cc |
+virStorageFileMetadataPtr
|
|
|
c401cc |
+virStorageFileGetMetadataFromBuf(const char *path,
|
|
|
c401cc |
+ char *buf,
|
|
|
c401cc |
+ size_t len,
|
|
|
c401cc |
+ int format)
|
|
|
c401cc |
+{
|
|
|
c401cc |
+ return virStorageFileGetMetadataInternal(path, buf, len, NULL, format);
|
|
|
c401cc |
+}
|
|
|
c401cc |
+
|
|
|
c401cc |
+
|
|
|
c401cc |
+/* Internal version that also supports a containing directory name. */
|
|
|
c401cc |
+static virStorageFileMetadataPtr
|
|
|
c401cc |
+virStorageFileGetMetadataFromFDInternal(const char *path,
|
|
|
c401cc |
+ int fd,
|
|
|
c401cc |
+ const char *directory,
|
|
|
c401cc |
+ int format)
|
|
|
c401cc |
+{
|
|
|
c401cc |
+ char *buf = NULL;
|
|
|
c401cc |
+ ssize_t len = STORAGE_MAX_HEAD;
|
|
|
c401cc |
+ struct stat sb;
|
|
|
c401cc |
+ virStorageFileMetadataPtr ret = NULL;
|
|
|
c401cc |
+
|
|
|
c401cc |
+ if (fstat(fd, &sb) < 0) {
|
|
|
c401cc |
+ virReportSystemError(errno,
|
|
|
c401cc |
+ _("cannot stat file '%s'"),
|
|
|
c401cc |
+ path);
|
|
|
c401cc |
+ return NULL;
|
|
|
c401cc |
+ }
|
|
|
c401cc |
+
|
|
|
c401cc |
+ /* No header to probe for directories, but also no backing file */
|
|
|
c401cc |
+ if (S_ISDIR(sb.st_mode)) {
|
|
|
c401cc |
+ ignore_value(VIR_ALLOC(ret));
|
|
|
c401cc |
+ goto cleanup;
|
|
|
c401cc |
+ }
|
|
|
c401cc |
+
|
|
|
c401cc |
+ if (lseek(fd, 0, SEEK_SET) == (off_t)-1) {
|
|
|
c401cc |
+ virReportSystemError(errno, _("cannot seek to start of '%s'"), path);
|
|
|
c401cc |
+ goto cleanup;
|
|
|
c401cc |
+ }
|
|
|
c401cc |
+
|
|
|
c401cc |
+ if ((len = virFileReadHeaderFD(fd, len, &buf)) < 0) {
|
|
|
c401cc |
+ virReportSystemError(errno, _("cannot read header '%s'"), path);
|
|
|
c401cc |
+ goto cleanup;
|
|
|
c401cc |
+ }
|
|
|
c401cc |
+
|
|
|
c401cc |
+ ret = virStorageFileGetMetadataInternal(path, buf, len, directory, format);
|
|
|
c401cc |
+cleanup:
|
|
|
c401cc |
+ VIR_FREE(buf);
|
|
|
c401cc |
+ return ret;
|
|
|
c401cc |
+}
|
|
|
c401cc |
+
|
|
|
c401cc |
+
|
|
|
c401cc |
/**
|
|
|
c401cc |
* virStorageFileGetMetadataFromFD:
|
|
|
c401cc |
*
|
|
|
c401cc |
@@ -1002,9 +1055,10 @@ virStorageFileGetMetadataFromFD(const char *path,
|
|
|
c401cc |
int fd,
|
|
|
c401cc |
int format)
|
|
|
c401cc |
{
|
|
|
c401cc |
- return virStorageFileGetMetadataInternal(path, fd, NULL, format);
|
|
|
c401cc |
+ return virStorageFileGetMetadataFromFDInternal(path, fd, NULL, format);
|
|
|
c401cc |
}
|
|
|
c401cc |
|
|
|
c401cc |
+
|
|
|
c401cc |
/* Recursive workhorse for virStorageFileGetMetadata. */
|
|
|
c401cc |
static virStorageFileMetadataPtr
|
|
|
c401cc |
virStorageFileGetMetadataRecurse(const char *path, const char *directory,
|
|
|
c401cc |
@@ -1031,7 +1085,7 @@ virStorageFileGetMetadataRecurse(const char *path, const char *directory,
|
|
|
c401cc |
return NULL;
|
|
|
c401cc |
}
|
|
|
c401cc |
|
|
|
c401cc |
- ret = virStorageFileGetMetadataInternal(path, fd, directory, format);
|
|
|
c401cc |
+ ret = virStorageFileGetMetadataFromFDInternal(path, fd, directory, format);
|
|
|
c401cc |
|
|
|
c401cc |
if (VIR_CLOSE(fd) < 0)
|
|
|
c401cc |
VIR_WARN("could not close file %s", path);
|
|
|
c401cc |
diff --git a/src/util/virstoragefile.h b/src/util/virstoragefile.h
|
|
|
c401cc |
index 1f89839..5fc8832 100644
|
|
|
c401cc |
--- a/src/util/virstoragefile.h
|
|
|
c401cc |
+++ b/src/util/virstoragefile.h
|
|
|
c401cc |
@@ -90,6 +90,10 @@ virStorageFileMetadataPtr virStorageFileGetMetadata(const char *path,
|
|
|
c401cc |
virStorageFileMetadataPtr virStorageFileGetMetadataFromFD(const char *path,
|
|
|
c401cc |
int fd,
|
|
|
c401cc |
int format);
|
|
|
c401cc |
+virStorageFileMetadataPtr virStorageFileGetMetadataFromBuf(const char *path,
|
|
|
c401cc |
+ char *buf,
|
|
|
c401cc |
+ size_t len,
|
|
|
c401cc |
+ int format);
|
|
|
c401cc |
int virStorageFileChainGetBroken(virStorageFileMetadataPtr chain,
|
|
|
c401cc |
char **broken_file);
|
|
|
c401cc |
|
|
|
c401cc |
--
|
|
|
c401cc |
1.9.0
|
|
|
c401cc |
|