[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]

[libvirt] [PATCH v4] 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

v3:
    Use gnulib last_component

v4:
    Use gnulib "dirname.h", not system <dirname.h>
    Don't skip lost+found

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..d269e4c 100644
--- a/src/storage/storage_backend.c
+++ b/src/storage/storage_backend.c
@@ -36,6 +36,7 @@
 #include <sys/stat.h>
 #include <sys/param.h>
 #include <dirent.h>
+#include "dirname.h"
 #ifdef __linux__
 # include <sys/ioctl.h>
 # include <linux/fs.h>
@@ -994,6 +995,7 @@ virStorageBackendVolOpenCheckMode(const char *path, unsigned int flags)
 {
     int fd, mode = 0;
     struct stat sb;
+    char *base = last_component(path);
 
     if ((fd = open(path, O_RDONLY|O_NONBLOCK|O_NOCTTY)) < 0) {
         if ((errno == ENOENT || errno == ELOOP) &&
@@ -1022,9 +1024,20 @@ 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, "..")) {
+            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


[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]