|
|
c401cc |
From 6729ce720b3274d576524b14939017c8dc7a00bb Mon Sep 17 00:00:00 2001
|
|
|
c401cc |
Message-Id: <6729ce720b3274d576524b14939017c8dc7a00bb@dist-git>
|
|
|
c401cc |
From: Eric Blake <eblake@redhat.com>
|
|
|
c401cc |
Date: Wed, 26 Feb 2014 14:54:35 +0100
|
|
|
c401cc |
Subject: [PATCH] storage: always probe type with buffer
|
|
|
c401cc |
|
|
|
c401cc |
https://bugzilla.redhat.com/show_bug.cgi?id=1032370
|
|
|
c401cc |
|
|
|
c401cc |
This gets rid of another stat() per volume, as well as cutting
|
|
|
c401cc |
bytes read in half, when populating the volumes of a directory
|
|
|
c401cc |
pool during a pool refresh. Not to mention that it provides an
|
|
|
c401cc |
interface that can let gluster pools also probe file types.
|
|
|
c401cc |
|
|
|
c401cc |
* src/util/virstoragefile.h (virStorageFileProbeFormatFromFD):
|
|
|
c401cc |
Delete.
|
|
|
c401cc |
(virStorageFileProbeFormatFromBuf): New prototype.
|
|
|
c401cc |
(VIR_STORAGE_MAX_HEADER): New constant, based on...
|
|
|
c401cc |
* src/util/virstoragefile.c (STORAGE_MAX_HEAD): ...old name.
|
|
|
c401cc |
(vmdk4GetBackingStore, virStorageFileGetMetadataInternal)
|
|
|
c401cc |
(virStorageFileProbeFormat): Adjust clients.
|
|
|
c401cc |
(virStorageFileProbeFormatFromFD): Delete.
|
|
|
c401cc |
(virStorageFileProbeFormatFromBuf): Export.
|
|
|
c401cc |
* src/storage/storage_backend_fs.c (virStorageBackendProbeTarget):
|
|
|
c401cc |
Adjust client.
|
|
|
c401cc |
* src/libvirt_private.syms (virstoragefile.h): Adjust exports.
|
|
|
c401cc |
|
|
|
c401cc |
Signed-off-by: Eric Blake <eblake@redhat.com>
|
|
|
c401cc |
(cherry picked from commit 348b4e254bea98c83107887c0cf64c6572063d64)
|
|
|
c401cc |
Signed-off-by: Jiri Denemark <jdenemar@redhat.com>
|
|
|
c401cc |
---
|
|
|
c401cc |
src/libvirt_private.syms | 2 +-
|
|
|
c401cc |
src/storage/storage_backend_fs.c | 52 +++++++++++++++++---------
|
|
|
c401cc |
src/util/virstoragefile.c | 81 +++++++++++++---------------------------
|
|
|
c401cc |
src/util/virstoragefile.h | 12 +++++-
|
|
|
c401cc |
4 files changed, 71 insertions(+), 76 deletions(-)
|
|
|
c401cc |
|
|
|
c401cc |
diff --git a/src/libvirt_private.syms b/src/libvirt_private.syms
|
|
|
c401cc |
index 4d74d46..4d80130 100644
|
|
|
c401cc |
--- a/src/libvirt_private.syms
|
|
|
c401cc |
+++ b/src/libvirt_private.syms
|
|
|
c401cc |
@@ -1931,7 +1931,7 @@ virStorageFileIsClusterFS;
|
|
|
c401cc |
virStorageFileIsSharedFS;
|
|
|
c401cc |
virStorageFileIsSharedFSType;
|
|
|
c401cc |
virStorageFileProbeFormat;
|
|
|
c401cc |
-virStorageFileProbeFormatFromFD;
|
|
|
c401cc |
+virStorageFileProbeFormatFromBuf;
|
|
|
c401cc |
virStorageFileResize;
|
|
|
c401cc |
|
|
|
c401cc |
|
|
|
c401cc |
diff --git a/src/storage/storage_backend_fs.c b/src/storage/storage_backend_fs.c
|
|
|
c401cc |
index 5d68232..11bb39b 100644
|
|
|
c401cc |
--- a/src/storage/storage_backend_fs.c
|
|
|
c401cc |
+++ b/src/storage/storage_backend_fs.c
|
|
|
c401cc |
@@ -1,7 +1,7 @@
|
|
|
c401cc |
/*
|
|
|
c401cc |
* storage_backend_fs.c: storage backend for FS and directory handling
|
|
|
c401cc |
*
|
|
|
c401cc |
- * Copyright (C) 2007-2012 Red Hat, Inc.
|
|
|
c401cc |
+ * Copyright (C) 2007-2013 Red Hat, Inc.
|
|
|
c401cc |
* Copyright (C) 2007-2008 Daniel P. Berrange
|
|
|
c401cc |
*
|
|
|
c401cc |
* This library is free software; you can redistribute it and/or
|
|
|
c401cc |
@@ -71,6 +71,8 @@ virStorageBackendProbeTarget(virStorageVolTargetPtr target,
|
|
|
c401cc |
int ret = -1;
|
|
|
c401cc |
virStorageFileMetadata *meta = NULL;
|
|
|
c401cc |
struct stat sb;
|
|
|
c401cc |
+ char *header = NULL;
|
|
|
c401cc |
+ ssize_t len = VIR_STORAGE_MAX_HEADER;
|
|
|
c401cc |
|
|
|
c401cc |
*backingStore = NULL;
|
|
|
c401cc |
*backingStoreFormat = VIR_STORAGE_FILE_AUTO;
|
|
|
c401cc |
@@ -88,20 +90,33 @@ virStorageBackendProbeTarget(virStorageVolTargetPtr target,
|
|
|
c401cc |
goto error;
|
|
|
c401cc |
}
|
|
|
c401cc |
|
|
|
c401cc |
- if ((target->format = virStorageFileProbeFormatFromFD(target->path, fd)) < 0) {
|
|
|
c401cc |
- ret = -1;
|
|
|
c401cc |
- goto error;
|
|
|
c401cc |
- }
|
|
|
c401cc |
+ if (S_ISDIR(sb.st_mode)) {
|
|
|
c401cc |
+ target->format = VIR_STORAGE_FILE_DIR;
|
|
|
c401cc |
+ } else {
|
|
|
c401cc |
+ if ((len = virFileReadHeaderFD(fd, len, &header)) < 0) {
|
|
|
c401cc |
+ virReportSystemError(errno, _("cannot read header '%s'"),
|
|
|
c401cc |
+ target->path);
|
|
|
c401cc |
+ goto error;
|
|
|
c401cc |
+ }
|
|
|
c401cc |
|
|
|
c401cc |
- if (!(meta = virStorageFileGetMetadataFromFD(target->path, fd,
|
|
|
c401cc |
- target->format))) {
|
|
|
c401cc |
- ret = -1;
|
|
|
c401cc |
- goto error;
|
|
|
c401cc |
+ target->format = virStorageFileProbeFormatFromBuf(target->path,
|
|
|
c401cc |
+ header, len);
|
|
|
c401cc |
+ if (target->format < 0) {
|
|
|
c401cc |
+ ret = -1;
|
|
|
c401cc |
+ goto error;
|
|
|
c401cc |
+ }
|
|
|
c401cc |
+
|
|
|
c401cc |
+ if (!(meta = virStorageFileGetMetadataFromBuf(target->path,
|
|
|
c401cc |
+ header, len,
|
|
|
c401cc |
+ target->format))) {
|
|
|
c401cc |
+ ret = -1;
|
|
|
c401cc |
+ goto error;
|
|
|
c401cc |
+ }
|
|
|
c401cc |
}
|
|
|
c401cc |
|
|
|
c401cc |
VIR_FORCE_CLOSE(fd);
|
|
|
c401cc |
|
|
|
c401cc |
- if (meta->backingStore) {
|
|
|
c401cc |
+ if (meta && meta->backingStore) {
|
|
|
c401cc |
*backingStore = meta->backingStore;
|
|
|
c401cc |
meta->backingStore = NULL;
|
|
|
c401cc |
if (meta->backingStoreFormat == VIR_STORAGE_FILE_AUTO &&
|
|
|
c401cc |
@@ -126,10 +141,10 @@ virStorageBackendProbeTarget(virStorageVolTargetPtr target,
|
|
|
c401cc |
ret = 0;
|
|
|
c401cc |
}
|
|
|
c401cc |
|
|
|
c401cc |
- if (capacity && meta->capacity)
|
|
|
c401cc |
+ if (capacity && meta && meta->capacity)
|
|
|
c401cc |
*capacity = meta->capacity;
|
|
|
c401cc |
|
|
|
c401cc |
- if (encryption != NULL && meta->encrypted) {
|
|
|
c401cc |
+ if (encryption && meta && meta->encrypted) {
|
|
|
c401cc |
if (VIR_ALLOC(*encryption) < 0)
|
|
|
c401cc |
goto cleanup;
|
|
|
c401cc |
|
|
|
c401cc |
@@ -150,24 +165,25 @@ virStorageBackendProbeTarget(virStorageVolTargetPtr target,
|
|
|
c401cc |
}
|
|
|
c401cc |
|
|
|
c401cc |
virBitmapFree(target->features);
|
|
|
c401cc |
- target->features = meta->features;
|
|
|
c401cc |
- meta->features = NULL;
|
|
|
c401cc |
+ if (meta) {
|
|
|
c401cc |
+ target->features = meta->features;
|
|
|
c401cc |
+ meta->features = NULL;
|
|
|
c401cc |
+ }
|
|
|
c401cc |
|
|
|
c401cc |
- if (meta->compat) {
|
|
|
c401cc |
+ if (meta && meta->compat) {
|
|
|
c401cc |
VIR_FREE(target->compat);
|
|
|
c401cc |
target->compat = meta->compat;
|
|
|
c401cc |
meta->compat = NULL;
|
|
|
c401cc |
}
|
|
|
c401cc |
|
|
|
c401cc |
- virStorageFileFreeMetadata(meta);
|
|
|
c401cc |
-
|
|
|
c401cc |
- return ret;
|
|
|
c401cc |
+ goto cleanup;
|
|
|
c401cc |
|
|
|
c401cc |
error:
|
|
|
c401cc |
VIR_FORCE_CLOSE(fd);
|
|
|
c401cc |
|
|
|
c401cc |
cleanup:
|
|
|
c401cc |
virStorageFileFreeMetadata(meta);
|
|
|
c401cc |
+ VIR_FREE(header);
|
|
|
c401cc |
return ret;
|
|
|
c401cc |
|
|
|
c401cc |
}
|
|
|
c401cc |
diff --git a/src/util/virstoragefile.c b/src/util/virstoragefile.c
|
|
|
c401cc |
index 8b89db1..471287c 100644
|
|
|
c401cc |
--- a/src/util/virstoragefile.c
|
|
|
c401cc |
+++ b/src/util/virstoragefile.c
|
|
|
c401cc |
@@ -148,11 +148,6 @@ qedGetBackingStore(char **, int *, const char *, size_t);
|
|
|
c401cc |
#define QED_F_BACKING_FILE 0x01
|
|
|
c401cc |
#define QED_F_BACKING_FORMAT_NO_PROBE 0x04
|
|
|
c401cc |
|
|
|
c401cc |
-/* VMDK needs at least 20*512 B to find backing store,
|
|
|
c401cc |
- * ISO has 5 Byte magic on offset 32769,
|
|
|
c401cc |
- * other formats need less */
|
|
|
c401cc |
-#define STORAGE_MAX_HEAD 32769+5
|
|
|
c401cc |
-
|
|
|
c401cc |
|
|
|
c401cc |
static struct FileTypeInfo const fileTypeInfo[] = {
|
|
|
c401cc |
[VIR_STORAGE_FILE_NONE] = { 0, NULL, NULL, LV_LITTLE_ENDIAN,
|
|
|
c401cc |
@@ -442,7 +437,7 @@ vmdk4GetBackingStore(char **res,
|
|
|
c401cc |
size_t len;
|
|
|
c401cc |
int ret = BACKING_STORE_ERROR;
|
|
|
c401cc |
|
|
|
c401cc |
- if (VIR_ALLOC_N(desc, STORAGE_MAX_HEAD + 1) < 0)
|
|
|
c401cc |
+ if (VIR_ALLOC_N(desc, VIR_STORAGE_MAX_HEADER) < 0)
|
|
|
c401cc |
goto cleanup;
|
|
|
c401cc |
|
|
|
c401cc |
*res = NULL;
|
|
|
c401cc |
@@ -460,8 +455,8 @@ vmdk4GetBackingStore(char **res,
|
|
|
c401cc |
goto cleanup;
|
|
|
c401cc |
}
|
|
|
c401cc |
len = buf_size - 0x200;
|
|
|
c401cc |
- if (len > STORAGE_MAX_HEAD)
|
|
|
c401cc |
- len = STORAGE_MAX_HEAD;
|
|
|
c401cc |
+ if (len > VIR_STORAGE_MAX_HEADER)
|
|
|
c401cc |
+ len = VIR_STORAGE_MAX_HEADER;
|
|
|
c401cc |
memcpy(desc, buf + 0x200, len);
|
|
|
c401cc |
desc[len] = '\0';
|
|
|
c401cc |
start = strstr(desc, prefix);
|
|
|
c401cc |
@@ -677,7 +672,7 @@ virBackingStoreIsFile(const char *backing)
|
|
|
c401cc |
return true;
|
|
|
c401cc |
}
|
|
|
c401cc |
|
|
|
c401cc |
-static int
|
|
|
c401cc |
+int
|
|
|
c401cc |
virStorageFileProbeFormatFromBuf(const char *path,
|
|
|
c401cc |
char *buf,
|
|
|
c401cc |
size_t buflen)
|
|
|
c401cc |
@@ -685,7 +680,7 @@ virStorageFileProbeFormatFromBuf(const char *path,
|
|
|
c401cc |
int format = VIR_STORAGE_FILE_RAW;
|
|
|
c401cc |
size_t i;
|
|
|
c401cc |
int possibleFormat = VIR_STORAGE_FILE_RAW;
|
|
|
c401cc |
- VIR_DEBUG("path=%s", path);
|
|
|
c401cc |
+ VIR_DEBUG("path=%s, buf=%p, buflen=%zu", path, buf, buflen);
|
|
|
c401cc |
|
|
|
c401cc |
/* First check file magic */
|
|
|
c401cc |
for (i = 0; i < VIR_STORAGE_FILE_LAST; i++) {
|
|
|
c401cc |
@@ -877,36 +872,41 @@ cleanup:
|
|
|
c401cc |
|
|
|
c401cc |
|
|
|
c401cc |
/**
|
|
|
c401cc |
- * virStorageFileProbeFormatFromFD:
|
|
|
c401cc |
+ * virStorageFileProbeFormat:
|
|
|
c401cc |
*
|
|
|
c401cc |
- * Probe for the format of 'fd' (which is an open file descriptor
|
|
|
c401cc |
- * pointing to 'path'), returning the detected disk format.
|
|
|
c401cc |
+ * Probe for the format of 'path', returning the detected
|
|
|
c401cc |
+ * disk format.
|
|
|
c401cc |
*
|
|
|
c401cc |
* Callers are advised never to trust the returned 'format'
|
|
|
c401cc |
* unless it is listed as VIR_STORAGE_FILE_RAW, since a
|
|
|
c401cc |
- * malicious guest can turn a file into any other non-raw
|
|
|
c401cc |
+ * malicious guest can turn a raw file into any other non-raw
|
|
|
c401cc |
* format at will.
|
|
|
c401cc |
*
|
|
|
c401cc |
* Best option: Don't use this function
|
|
|
c401cc |
*/
|
|
|
c401cc |
int
|
|
|
c401cc |
-virStorageFileProbeFormatFromFD(const char *path, int fd)
|
|
|
c401cc |
+virStorageFileProbeFormat(const char *path, uid_t uid, gid_t gid)
|
|
|
c401cc |
{
|
|
|
c401cc |
- char *head = NULL;
|
|
|
c401cc |
- ssize_t len = STORAGE_MAX_HEAD;
|
|
|
c401cc |
+ int fd;
|
|
|
c401cc |
int ret = -1;
|
|
|
c401cc |
struct stat sb;
|
|
|
c401cc |
+ ssize_t len = VIR_STORAGE_MAX_HEADER;
|
|
|
c401cc |
+ char *header = NULL;
|
|
|
c401cc |
|
|
|
c401cc |
- if (fstat(fd, &sb) < 0) {
|
|
|
c401cc |
- virReportSystemError(errno,
|
|
|
c401cc |
- _("cannot stat file '%s'"),
|
|
|
c401cc |
- path);
|
|
|
c401cc |
+ if ((fd = virFileOpenAs(path, O_RDONLY, 0, uid, gid, 0)) < 0) {
|
|
|
c401cc |
+ virReportSystemError(-fd, _("Failed to open file '%s'"), path);
|
|
|
c401cc |
return -1;
|
|
|
c401cc |
}
|
|
|
c401cc |
|
|
|
c401cc |
+ if (fstat(fd, &sb) < 0) {
|
|
|
c401cc |
+ virReportSystemError(errno, _("cannot stat file '%s'"), path);
|
|
|
c401cc |
+ goto cleanup;
|
|
|
c401cc |
+ }
|
|
|
c401cc |
+
|
|
|
c401cc |
/* No header to probe for directories */
|
|
|
c401cc |
if (S_ISDIR(sb.st_mode)) {
|
|
|
c401cc |
- return VIR_STORAGE_FILE_DIR;
|
|
|
c401cc |
+ ret = VIR_STORAGE_FILE_DIR;
|
|
|
c401cc |
+ goto cleanup;
|
|
|
c401cc |
}
|
|
|
c401cc |
|
|
|
c401cc |
if (lseek(fd, 0, SEEK_SET) == (off_t)-1) {
|
|
|
c401cc |
@@ -914,44 +914,15 @@ virStorageFileProbeFormatFromFD(const char *path, int fd)
|
|
|
c401cc |
goto cleanup;
|
|
|
c401cc |
}
|
|
|
c401cc |
|
|
|
c401cc |
- if ((len = virFileReadHeaderFD(fd, len, (char **)&head)) < 0) {
|
|
|
c401cc |
+ if ((len = virFileReadHeaderFD(fd, len, &header)) < 0) {
|
|
|
c401cc |
virReportSystemError(errno, _("cannot read header '%s'"), path);
|
|
|
c401cc |
goto cleanup;
|
|
|
c401cc |
}
|
|
|
c401cc |
|
|
|
c401cc |
- ret = virStorageFileProbeFormatFromBuf(path, head, len);
|
|
|
c401cc |
+ ret = virStorageFileProbeFormatFromBuf(path, header, len);
|
|
|
c401cc |
|
|
|
c401cc |
cleanup:
|
|
|
c401cc |
- VIR_FREE(head);
|
|
|
c401cc |
- return ret;
|
|
|
c401cc |
-}
|
|
|
c401cc |
-
|
|
|
c401cc |
-
|
|
|
c401cc |
-/**
|
|
|
c401cc |
- * virStorageFileProbeFormat:
|
|
|
c401cc |
- *
|
|
|
c401cc |
- * Probe for the format of 'path', returning the detected
|
|
|
c401cc |
- * disk format.
|
|
|
c401cc |
- *
|
|
|
c401cc |
- * Callers are advised never to trust the returned 'format'
|
|
|
c401cc |
- * unless it is listed as VIR_STORAGE_FILE_RAW, since a
|
|
|
c401cc |
- * malicious guest can turn a raw file into any other non-raw
|
|
|
c401cc |
- * format at will.
|
|
|
c401cc |
- *
|
|
|
c401cc |
- * Best option: Don't use this function
|
|
|
c401cc |
- */
|
|
|
c401cc |
-int
|
|
|
c401cc |
-virStorageFileProbeFormat(const char *path, uid_t uid, gid_t gid)
|
|
|
c401cc |
-{
|
|
|
c401cc |
- int fd, ret;
|
|
|
c401cc |
-
|
|
|
c401cc |
- if ((fd = virFileOpenAs(path, O_RDONLY, 0, uid, gid, 0)) < 0) {
|
|
|
c401cc |
- virReportSystemError(-fd, _("Failed to open file '%s'"), path);
|
|
|
c401cc |
- return -1;
|
|
|
c401cc |
- }
|
|
|
c401cc |
-
|
|
|
c401cc |
- ret = virStorageFileProbeFormatFromFD(path, fd);
|
|
|
c401cc |
-
|
|
|
c401cc |
+ VIR_FREE(header);
|
|
|
c401cc |
VIR_FORCE_CLOSE(fd);
|
|
|
c401cc |
|
|
|
c401cc |
return ret;
|
|
|
c401cc |
@@ -998,7 +969,7 @@ virStorageFileGetMetadataFromFDInternal(const char *path,
|
|
|
c401cc |
int format)
|
|
|
c401cc |
{
|
|
|
c401cc |
char *buf = NULL;
|
|
|
c401cc |
- ssize_t len = STORAGE_MAX_HEAD;
|
|
|
c401cc |
+ ssize_t len = VIR_STORAGE_MAX_HEADER;
|
|
|
c401cc |
struct stat sb;
|
|
|
c401cc |
virStorageFileMetadataPtr ret = NULL;
|
|
|
c401cc |
|
|
|
c401cc |
diff --git a/src/util/virstoragefile.h b/src/util/virstoragefile.h
|
|
|
c401cc |
index 5fc8832..e1ac91b 100644
|
|
|
c401cc |
--- a/src/util/virstoragefile.h
|
|
|
c401cc |
+++ b/src/util/virstoragefile.h
|
|
|
c401cc |
@@ -27,6 +27,14 @@
|
|
|
c401cc |
# include "virbitmap.h"
|
|
|
c401cc |
# include "virutil.h"
|
|
|
c401cc |
|
|
|
c401cc |
+/* Minimum header size required to probe all known formats with
|
|
|
c401cc |
+ * virStorageFileProbeFormat, or obtain metadata from a known format.
|
|
|
c401cc |
+ * Rounded to multiple of 512 (ISO has a 5-byte magic at offset
|
|
|
c401cc |
+ * 32769). Some formats can be probed with fewer bytes. Although
|
|
|
c401cc |
+ * some formats theoretically permit metadata that can rely on offsets
|
|
|
c401cc |
+ * beyond this size, in practice that doesn't matter. */
|
|
|
c401cc |
+# define VIR_STORAGE_MAX_HEADER 0x8200
|
|
|
c401cc |
+
|
|
|
c401cc |
enum virStorageFileFormat {
|
|
|
c401cc |
VIR_STORAGE_FILE_AUTO_SAFE = -2,
|
|
|
c401cc |
VIR_STORAGE_FILE_AUTO = -1,
|
|
|
c401cc |
@@ -80,8 +88,8 @@ struct _virStorageFileMetadata {
|
|
|
c401cc |
# endif
|
|
|
c401cc |
|
|
|
c401cc |
int virStorageFileProbeFormat(const char *path, uid_t uid, gid_t gid);
|
|
|
c401cc |
-int virStorageFileProbeFormatFromFD(const char *path,
|
|
|
c401cc |
- int fd);
|
|
|
c401cc |
+int virStorageFileProbeFormatFromBuf(const char *path, char *buf,
|
|
|
c401cc |
+ size_t buflen);
|
|
|
c401cc |
|
|
|
c401cc |
virStorageFileMetadataPtr virStorageFileGetMetadata(const char *path,
|
|
|
c401cc |
int format,
|
|
|
c401cc |
--
|
|
|
c401cc |
1.9.0
|
|
|
c401cc |
|