mirror of
https://gitlab.com/libvirt/libvirt.git
synced 2025-01-22 04:25:18 +00:00
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:
parent
7693c03973
commit
8077d64f96
@ -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,
|
||||
|
@ -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,
|
||||
|
@ -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;
|
||||
|
||||
|
@ -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;
|
||||
|
Loading…
x
Reference in New Issue
Block a user