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
This commit is contained in:
Cole Robinson 2011-05-26 14:05:32 -04:00
parent 7693c03973
commit 8077d64f96
4 changed files with 82 additions and 13 deletions

View File

@ -36,6 +36,7 @@
#include <sys/stat.h> #include <sys/stat.h>
#include <sys/param.h> #include <sys/param.h>
#include <dirent.h> #include <dirent.h>
#include "dirname.h"
#ifdef __linux__ #ifdef __linux__
# include <sys/ioctl.h> # include <sys/ioctl.h>
# include <linux/fs.h> # include <linux/fs.h>
@ -994,6 +995,7 @@ virStorageBackendVolOpenCheckMode(const char *path, unsigned int flags)
{ {
int fd, mode = 0; int fd, mode = 0;
struct stat sb; struct stat sb;
char *base = last_component(path);
if ((fd = open(path, O_RDONLY|O_NONBLOCK|O_NOCTTY)) < 0) { if ((fd = open(path, O_RDONLY|O_NONBLOCK|O_NOCTTY)) < 0) {
if ((errno == ENOENT || errno == ELOOP) && if ((errno == ENOENT || errno == ELOOP) &&
@ -1022,9 +1024,20 @@ virStorageBackendVolOpenCheckMode(const char *path, unsigned int flags)
mode = VIR_STORAGE_VOL_OPEN_CHAR; mode = VIR_STORAGE_VOL_OPEN_CHAR;
else if (S_ISBLK(sb.st_mode)) else if (S_ISBLK(sb.st_mode))
mode = VIR_STORAGE_VOL_OPEN_BLOCK; 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)) { if (!(mode & flags)) {
VIR_FORCE_CLOSE(fd); VIR_FORCE_CLOSE(fd);
VIR_INFO("Skipping volume '%s'", path);
if (mode & VIR_STORAGE_VOL_OPEN_ERROR) { if (mode & VIR_STORAGE_VOL_OPEN_ERROR) {
virStorageReportError(VIR_ERR_INTERNAL_ERROR, virStorageReportError(VIR_ERR_INTERNAL_ERROR,
@ -1047,11 +1060,13 @@ int virStorageBackendVolOpen(const char *path)
int int
virStorageBackendUpdateVolTargetInfo(virStorageVolTargetPtr target, virStorageBackendUpdateVolTargetInfo(virStorageVolTargetPtr target,
unsigned long long *allocation, unsigned long long *allocation,
unsigned long long *capacity) unsigned long long *capacity,
unsigned int openflags)
{ {
int ret, fd; int ret, fd;
if ((ret = virStorageBackendVolOpen(target->path)) < 0) if ((ret = virStorageBackendVolOpenCheckMode(target->path,
openflags)) < 0)
return ret; return ret;
fd = ret; fd = ret;
@ -1066,24 +1081,34 @@ virStorageBackendUpdateVolTargetInfo(virStorageVolTargetPtr target,
} }
int int
virStorageBackendUpdateVolInfo(virStorageVolDefPtr vol, virStorageBackendUpdateVolInfoFlags(virStorageVolDefPtr vol,
int withCapacity) int withCapacity,
unsigned int openflags)
{ {
int ret; int ret;
if ((ret = virStorageBackendUpdateVolTargetInfo(&vol->target, if ((ret = virStorageBackendUpdateVolTargetInfo(&vol->target,
&vol->allocation, &vol->allocation,
withCapacity ? &vol->capacity : NULL)) < 0) withCapacity ? &vol->capacity : NULL,
openflags)) < 0)
return ret; return ret;
if (vol->backingStore.path && if (vol->backingStore.path &&
(ret = virStorageBackendUpdateVolTargetInfo(&vol->backingStore, (ret = virStorageBackendUpdateVolTargetInfo(&vol->backingStore,
NULL, NULL)) < 0) NULL, NULL,
VIR_STORAGE_VOL_OPEN_DEFAULT)) < 0)
return ret; return ret;
return 0; return 0;
} }
int virStorageBackendUpdateVolInfo(virStorageVolDefPtr vol,
int withCapacity)
{
return virStorageBackendUpdateVolInfoFlags(vol, withCapacity,
VIR_STORAGE_VOL_OPEN_DEFAULT);
}
/* /*
* virStorageBackendUpdateVolTargetInfoFD: * virStorageBackendUpdateVolTargetInfoFD:
* @conn: connection to report errors on * @conn: connection to report errors on
@ -1125,6 +1150,11 @@ virStorageBackendUpdateVolTargetInfoFD(virStorageVolTargetPtr target,
*/ */
if (capacity) if (capacity)
*capacity = sb.st_size; *capacity = sb.st_size;
} else if (S_ISDIR(sb.st_mode)) {
*allocation = 0;
if (capacity)
*capacity = 0;
} else { } else {
off_t end; off_t end;
/* XXX this is POSIX compliant, but doesn't work for CHAR files, /* XXX this is POSIX compliant, but doesn't work for CHAR files,

View File

@ -93,6 +93,7 @@ enum {
VIR_STORAGE_VOL_OPEN_REG = 1 << 1, /* regular files okay */ VIR_STORAGE_VOL_OPEN_REG = 1 << 1, /* regular files okay */
VIR_STORAGE_VOL_OPEN_BLOCK = 1 << 2, /* block 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_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 |\ # define VIR_STORAGE_VOL_OPEN_DEFAULT (VIR_STORAGE_VOL_OPEN_ERROR |\
@ -107,9 +108,13 @@ ATTRIBUTE_NONNULL(1);
int virStorageBackendUpdateVolInfo(virStorageVolDefPtr vol, int virStorageBackendUpdateVolInfo(virStorageVolDefPtr vol,
int withCapacity); int withCapacity);
int virStorageBackendUpdateVolInfoFlags(virStorageVolDefPtr vol,
int withCapacity,
unsigned int openflags);
int virStorageBackendUpdateVolTargetInfo(virStorageVolTargetPtr target, int virStorageBackendUpdateVolTargetInfo(virStorageVolTargetPtr target,
unsigned long long *allocation, unsigned long long *allocation,
unsigned long long *capacity); unsigned long long *capacity,
unsigned int openflags);
int virStorageBackendUpdateVolTargetInfoFD(virStorageVolTargetPtr target, int virStorageBackendUpdateVolTargetInfoFD(virStorageVolTargetPtr target,
int fd, int fd,
unsigned long long *allocation, unsigned long long *allocation,

View File

@ -48,6 +48,11 @@
#define VIR_FROM_THIS VIR_FROM_STORAGE #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) static int ATTRIBUTE_NONNULL(2) ATTRIBUTE_NONNULL(3)
virStorageBackendProbeTarget(virStorageVolTargetPtr target, virStorageBackendProbeTarget(virStorageVolTargetPtr target,
char **backingStore, char **backingStore,
@ -65,7 +70,7 @@ virStorageBackendProbeTarget(virStorageVolTargetPtr target,
*encryption = NULL; *encryption = NULL;
if ((ret = virStorageBackendVolOpenCheckMode(target->path, 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 */ return ret; /* Take care to propagate ret, it is not always -1 */
fd = ret; fd = ret;
@ -676,8 +681,8 @@ virStorageBackendFileSystemRefresh(virConnectPtr conn ATTRIBUTE_UNUSED,
vol->backingStore.format = backingStoreFormat; vol->backingStore.format = backingStoreFormat;
if (virStorageBackendUpdateVolTargetInfo(&vol->backingStore, if (virStorageBackendUpdateVolTargetInfo(&vol->backingStore,
NULL, NULL, NULL,
NULL) < 0) { VIR_STORAGE_VOL_OPEN_DEFAULT) < 0) {
/* The backing file is currently unavailable, the capacity, /* The backing file is currently unavailable, the capacity,
* allocation, owner, group and mode are unknown. Just log the * allocation, owner, group and mode are unknown. Just log the
* error an continue. * error an continue.
@ -941,7 +946,8 @@ virStorageBackendFileSystemVolRefresh(virConnectPtr conn,
int ret; int ret;
/* Refresh allocation / permissions info in case its changed */ /* 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) if (ret < 0)
return ret; return ret;

View File

@ -24,6 +24,7 @@
#include <config.h> #include <config.h>
#include "storage_file.h" #include "storage_file.h"
#include <sys/stat.h>
#include <unistd.h> #include <unistd.h>
#include <fcntl.h> #include <fcntl.h>
#ifdef __linux__ #ifdef __linux__
@ -736,6 +737,19 @@ virStorageFileProbeFormatFromFD(const char *path, int fd)
unsigned char *head; unsigned char *head;
ssize_t len = STORAGE_MAX_HEAD; ssize_t len = STORAGE_MAX_HEAD;
int ret = -1; 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) { if (VIR_ALLOC_N(head, len) < 0) {
virReportOOMError(); virReportOOMError();
@ -812,9 +826,10 @@ virStorageFileGetMetadataFromFD(const char *path,
int format, int format,
virStorageFileMetadata *meta) virStorageFileMetadata *meta)
{ {
unsigned char *head; unsigned char *head = NULL;
ssize_t len = STORAGE_MAX_HEAD; ssize_t len = STORAGE_MAX_HEAD;
int ret = -1; int ret = -1;
struct stat sb;
if (VIR_ALLOC_N(head, len) < 0) { if (VIR_ALLOC_N(head, len) < 0) {
virReportOOMError(); virReportOOMError();
@ -823,6 +838,19 @@ virStorageFileGetMetadataFromFD(const char *path,
memset(meta, 0, sizeof (*meta)); 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) { if (lseek(fd, 0, SEEK_SET) == (off_t)-1) {
virReportSystemError(errno, _("cannot seek to start of '%s'"), path); virReportSystemError(errno, _("cannot seek to start of '%s'"), path);
goto cleanup; goto cleanup;