Resolves:
https://bugzilla.redhat.com/show_bug.cgi?id=977706
v1, v2 by Ján Tomko
https://www.redhat.com/archives/libvir-list/2013-July/msg00639.html
To get volume file fd in the fist place. The purpose of doing so
is to ensure the async deletion of volume doesn't make impact on
the following operation for the volume till we recheck the existence
of volume file later.
If we don't get its fd firstly, it is diffcult to differentiate
the non-existent file error caused by system or being deleted
asynchronous.
---
src/storage/storage_backend.c | 49 +++++++++++++++++-----------------------
src/storage/storage_backend_fs.c | 6 +++++
2 files changed, 27 insertions(+), 28 deletions(-)
diff --git a/src/storage/storage_backend.c b/src/storage/storage_backend.c
index 8d5880e..aa1635a 100644
--- a/src/storage/storage_backend.c
+++ b/src/storage/storage_backend.c
@@ -1093,29 +1093,13 @@ virStorageBackendVolOpenCheckMode(const char *path, unsigned int
flags)
int fd, mode = 0;
struct stat sb;
char *base = last_component(path);
-
- if (lstat(path, &sb) < 0) {
- virReportSystemError(errno,
- _("cannot stat file '%s'"),
- path);
- return -1;
- }
-
- if (S_ISFIFO(sb.st_mode)) {
- VIR_WARN("ignoring FIFO '%s'", path);
- return -2;
- } else if (S_ISSOCK(sb.st_mode)) {
- VIR_WARN("ignoring socket '%s'", path);
- return -2;
- }
+ int ret = -1;
if ((fd = open(path, O_RDONLY|O_NONBLOCK|O_NOCTTY)) < 0) {
- if ((errno == ENOENT || errno == ELOOP) &&
- S_ISLNK(sb.st_mode)) {
- VIR_WARN("ignoring dangling symlink '%s'", path);
+ if (errno == ENOENT) {
+ VIR_WARN("volume '%s' does not exist", path);
return -2;
}
-
virReportSystemError(errno,
_("cannot open volume '%s'"),
path);
@@ -1126,8 +1110,7 @@ virStorageBackendVolOpenCheckMode(const char *path, unsigned int
flags)
virReportSystemError(errno,
_("cannot stat file '%s'"),
path);
- VIR_FORCE_CLOSE(fd);
- return -1;
+ goto error;
}
if (S_ISREG(sb.st_mode))
@@ -1141,26 +1124,36 @@ virStorageBackendVolOpenCheckMode(const char *path, unsigned int
flags)
if (STREQ(base, ".") ||
STREQ(base, "..")) {
- VIR_FORCE_CLOSE(fd);
VIR_INFO("Skipping special dir '%s'", base);
- return -2;
+ goto skipfile;
}
+ } else if (S_ISFIFO(sb.st_mode)) {
+ VIR_WARN("ignoring FIFO '%s'", path);
+ goto skipfile;
+ } else if (S_ISSOCK(sb.st_mode)) {
+ VIR_WARN("ignoring socket '%s'", path);
+ goto skipfile;
}
if (!(mode & flags)) {
- VIR_FORCE_CLOSE(fd);
- VIR_INFO("Skipping volume '%s'", path);
-
if (mode & VIR_STORAGE_VOL_OPEN_ERROR) {
virReportError(VIR_ERR_INTERNAL_ERROR,
_("unexpected storage mode for '%s'"),
path);
- return -1;
+ goto error;
}
- return -2;
+ VIR_INFO("Skipping volume '%s'", path);
+ goto skipfile;
}
return fd;
+
+skipfile:
+ ret = -2;
+
+error:
+ VIR_FORCE_CLOSE(fd);
+ return ret;
}
int virStorageBackendVolOpen(const char *path)
diff --git a/src/storage/storage_backend_fs.c b/src/storage/storage_backend_fs.c
index d305b06..d0276fc 100644
--- a/src/storage/storage_backend_fs.c
+++ b/src/storage/storage_backend_fs.c
@@ -889,6 +889,12 @@ virStorageBackendFileSystemRefresh(virConnectPtr conn
ATTRIBUTE_UNUSED,
}
}
+ /* Recheck the existence of volume again */
+ if (access(vol->target.path, F_OK) < 0) {
+ virStorageVolDefFree(vol);
+ vol = NULL;
+ continue;
+ }
if (VIR_REALLOC_N(pool->volumes.objs,
pool->volumes.count+1) < 0)
--
1.8.3.1