[libvirt] [PATCH v2] storage: List directory volumes for dir/fs/netfs pools

Since directories can be used for <filesystem> passthrough, they are basically storage volumes. v2: Skip ., .., lost+found dirs Signed-off-by: Cole Robinson <crobinso@redhat.com> --- src/storage/storage_backend.c | 44 +++++++++++++++++++++++++++++++------ src/storage/storage_backend.h | 7 +++++- src/storage/storage_backend_fs.c | 14 ++++++++--- src/util/storage_file.c | 30 +++++++++++++++++++++++++- 4 files changed, 82 insertions(+), 13 deletions(-) diff --git a/src/storage/storage_backend.c b/src/storage/storage_backend.c index 02e455f..77095f2 100644 --- a/src/storage/storage_backend.c +++ b/src/storage/storage_backend.c @@ -994,6 +994,7 @@ virStorageBackendVolOpenCheckMode(const char *path, unsigned int flags) { int fd, mode = 0; struct stat sb; + char *base = basename(path); if ((fd = open(path, O_RDONLY|O_NONBLOCK|O_NOCTTY)) < 0) { if ((errno == ENOENT || errno == ELOOP) && @@ -1022,9 +1023,21 @@ virStorageBackendVolOpenCheckMode(const char *path, unsigned int flags) mode = VIR_STORAGE_VOL_OPEN_CHAR; else if (S_ISBLK(sb.st_mode)) mode = VIR_STORAGE_VOL_OPEN_BLOCK; + else if (S_ISDIR(sb.st_mode)) { + mode = VIR_STORAGE_VOL_OPEN_DIR; + + if (STREQ(base, ".") || + STREQ(base, "..") || + STREQ(base, "lost+found")) { + VIR_FORCE_CLOSE(fd); + VIR_INFO("Skipping special dir '%s'", base); + return -2; + } + } if (!(mode & flags)) { VIR_FORCE_CLOSE(fd); + VIR_INFO("Skipping volume '%s'", path); if (mode & VIR_STORAGE_VOL_OPEN_ERROR) { virStorageReportError(VIR_ERR_INTERNAL_ERROR, @@ -1047,11 +1060,13 @@ int virStorageBackendVolOpen(const char *path) int virStorageBackendUpdateVolTargetInfo(virStorageVolTargetPtr target, unsigned long long *allocation, - unsigned long long *capacity) + unsigned long long *capacity, + unsigned int openflags) { int ret, fd; - if ((ret = virStorageBackendVolOpen(target->path)) < 0) + if ((ret = virStorageBackendVolOpenCheckMode(target->path, + openflags)) < 0) return ret; fd = ret; @@ -1066,24 +1081,34 @@ virStorageBackendUpdateVolTargetInfo(virStorageVolTargetPtr target, } int -virStorageBackendUpdateVolInfo(virStorageVolDefPtr vol, - int withCapacity) +virStorageBackendUpdateVolInfoFlags(virStorageVolDefPtr vol, + int withCapacity, + unsigned int openflags) { int ret; if ((ret = virStorageBackendUpdateVolTargetInfo(&vol->target, - &vol->allocation, - withCapacity ? &vol->capacity : NULL)) < 0) + &vol->allocation, + withCapacity ? &vol->capacity : NULL, + openflags)) < 0) return ret; if (vol->backingStore.path && (ret = virStorageBackendUpdateVolTargetInfo(&vol->backingStore, - NULL, NULL)) < 0) + NULL, NULL, + VIR_STORAGE_VOL_OPEN_DEFAULT)) < 0) return ret; return 0; } +int virStorageBackendUpdateVolInfo(virStorageVolDefPtr vol, + int withCapacity) +{ + return virStorageBackendUpdateVolInfoFlags(vol, withCapacity, + VIR_STORAGE_VOL_OPEN_DEFAULT); +} + /* * virStorageBackendUpdateVolTargetInfoFD: * @conn: connection to report errors on @@ -1125,6 +1150,11 @@ virStorageBackendUpdateVolTargetInfoFD(virStorageVolTargetPtr target, */ if (capacity) *capacity = sb.st_size; + } else if (S_ISDIR(sb.st_mode)) { + *allocation = 0; + if (capacity) + *capacity = 0; + } else { off_t end; /* XXX this is POSIX compliant, but doesn't work for CHAR files, diff --git a/src/storage/storage_backend.h b/src/storage/storage_backend.h index fcfbed0..67ac32c 100644 --- a/src/storage/storage_backend.h +++ b/src/storage/storage_backend.h @@ -93,6 +93,7 @@ enum { VIR_STORAGE_VOL_OPEN_REG = 1 << 1, /* regular files okay */ VIR_STORAGE_VOL_OPEN_BLOCK = 1 << 2, /* block files okay */ VIR_STORAGE_VOL_OPEN_CHAR = 1 << 3, /* char files okay */ + VIR_STORAGE_VOL_OPEN_DIR = 1 << 4, /* directories okay */ }; # define VIR_STORAGE_VOL_OPEN_DEFAULT (VIR_STORAGE_VOL_OPEN_ERROR |\ @@ -107,9 +108,13 @@ ATTRIBUTE_NONNULL(1); int virStorageBackendUpdateVolInfo(virStorageVolDefPtr vol, int withCapacity); +int virStorageBackendUpdateVolInfoFlags(virStorageVolDefPtr vol, + int withCapacity, + unsigned int openflags); int virStorageBackendUpdateVolTargetInfo(virStorageVolTargetPtr target, unsigned long long *allocation, - unsigned long long *capacity); + unsigned long long *capacity, + unsigned int openflags); int virStorageBackendUpdateVolTargetInfoFD(virStorageVolTargetPtr target, int fd, unsigned long long *allocation, diff --git a/src/storage/storage_backend_fs.c b/src/storage/storage_backend_fs.c index b8d4d63..3f4d978 100644 --- a/src/storage/storage_backend_fs.c +++ b/src/storage/storage_backend_fs.c @@ -48,6 +48,11 @@ #define VIR_FROM_THIS VIR_FROM_STORAGE +#define VIR_STORAGE_VOL_FS_OPEN_FLAGS (VIR_STORAGE_VOL_OPEN_DEFAULT |\ + VIR_STORAGE_VOL_OPEN_DIR) +#define VIR_STORAGE_VOL_FS_REFRESH_FLAGS (VIR_STORAGE_VOL_FS_OPEN_FLAGS &\ + ~VIR_STORAGE_VOL_OPEN_ERROR) + static int ATTRIBUTE_NONNULL(2) ATTRIBUTE_NONNULL(3) virStorageBackendProbeTarget(virStorageVolTargetPtr target, char **backingStore, @@ -65,7 +70,7 @@ virStorageBackendProbeTarget(virStorageVolTargetPtr target, *encryption = NULL; if ((ret = virStorageBackendVolOpenCheckMode(target->path, - (VIR_STORAGE_VOL_OPEN_DEFAULT & ~VIR_STORAGE_VOL_OPEN_ERROR))) < 0) + VIR_STORAGE_VOL_FS_REFRESH_FLAGS)) < 0) return ret; /* Take care to propagate ret, it is not always -1 */ fd = ret; @@ -676,8 +681,8 @@ virStorageBackendFileSystemRefresh(virConnectPtr conn ATTRIBUTE_UNUSED, vol->backingStore.format = backingStoreFormat; if (virStorageBackendUpdateVolTargetInfo(&vol->backingStore, - NULL, - NULL) < 0) { + NULL, NULL, + VIR_STORAGE_VOL_OPEN_DEFAULT) < 0) { /* The backing file is currently unavailable, the capacity, * allocation, owner, group and mode are unknown. Just log the * error an continue. @@ -941,7 +946,8 @@ virStorageBackendFileSystemVolRefresh(virConnectPtr conn, int ret; /* Refresh allocation / permissions info in case its changed */ - ret = virStorageBackendUpdateVolInfo(vol, 0); + ret = virStorageBackendUpdateVolInfoFlags(vol, 0, + VIR_STORAGE_VOL_FS_OPEN_FLAGS); if (ret < 0) return ret; diff --git a/src/util/storage_file.c b/src/util/storage_file.c index ede79fa..8dbd933 100644 --- a/src/util/storage_file.c +++ b/src/util/storage_file.c @@ -24,6 +24,7 @@ #include <config.h> #include "storage_file.h" +#include <sys/stat.h> #include <unistd.h> #include <fcntl.h> #ifdef __linux__ @@ -736,6 +737,19 @@ virStorageFileProbeFormatFromFD(const char *path, int fd) unsigned char *head; ssize_t len = STORAGE_MAX_HEAD; int ret = -1; + struct stat sb; + + if (fstat(fd, &sb) < 0) { + virReportSystemError(errno, + _("cannot stat file '%s'"), + path); + return -1; + } + + /* No header to probe for directories */ + if (S_ISDIR(sb.st_mode)) { + return VIR_STORAGE_FILE_DIR; + } if (VIR_ALLOC_N(head, len) < 0) { virReportOOMError(); @@ -812,9 +826,10 @@ virStorageFileGetMetadataFromFD(const char *path, int format, virStorageFileMetadata *meta) { - unsigned char *head; + unsigned char *head = NULL; ssize_t len = STORAGE_MAX_HEAD; int ret = -1; + struct stat sb; if (VIR_ALLOC_N(head, len) < 0) { virReportOOMError(); @@ -823,6 +838,19 @@ virStorageFileGetMetadataFromFD(const char *path, memset(meta, 0, sizeof (*meta)); + if (fstat(fd, &sb) < 0) { + virReportSystemError(errno, + _("cannot stat file '%s'"), + path); + return -1; + } + + /* No header to probe for directories */ + if (S_ISDIR(sb.st_mode)) { + ret = 0; + goto cleanup; + } + if (lseek(fd, 0, SEEK_SET) == (off_t)-1) { virReportSystemError(errno, _("cannot seek to start of '%s'"), path); goto cleanup; -- 1.7.4.4

On 05/26/2011 01:34 PM, Cole Robinson wrote:
Since directories can be used for <filesystem> passthrough, they are basically storage volumes.
v2: Skip ., .., lost+found dirs
Signed-off-by: Cole Robinson <crobinso@redhat.com> --- src/storage/storage_backend.c | 44 +++++++++++++++++++++++++++++++------ src/storage/storage_backend.h | 7 +++++- src/storage/storage_backend_fs.c | 14 ++++++++--- src/util/storage_file.c | 30 +++++++++++++++++++++++++- 4 files changed, 82 insertions(+), 13 deletions(-)
Almost there.
diff --git a/src/storage/storage_backend.c b/src/storage/storage_backend.c index 02e455f..77095f2 100644 --- a/src/storage/storage_backend.c +++ b/src/storage/storage_backend.c @@ -994,6 +994,7 @@ virStorageBackendVolOpenCheckMode(const char *path, unsigned int flags) { int fd, mode = 0; struct stat sb; + char *base = basename(path);
basename() is not portable (some, but not all, implementations modify the string in place, and it is not required to be threadsafe). Instead, use "dirname.h" from gnulib (we already have it imported) and the function base_name() (which malloc's the result) or last_component() (which returns a pointer into the middle of path).
+ else if (S_ISDIR(sb.st_mode)) { + mode = VIR_STORAGE_VOL_OPEN_DIR; + + if (STREQ(base, ".") || + STREQ(base, "..") || + STREQ(base, "lost+found")) {
Given your usage, I think last_component() is the better fit. ACK with that fixed. -- Eric Blake eblake@redhat.com +1-801-349-2682 Libvirt virtualization library http://libvirt.org
participants (2)
-
Cole Robinson
-
Eric Blake