On 17.02.2016 14:40, Olga Krishtal wrote: > To update information about ploop volumes inside the a single pool we need > to be sure that it is the ploop directory and not some other directory. > Ploop volume directory obligatory contains root.hds - image file and disk > descriptor - DiskDescriptor.xml. If path to a volume is a path to some > directory, we check the existance of this files. > > The capacity of a ploop volume is obtained via offset > in the header file: > https://openvz.org/Ploop/format > > Signed-off-by: Olga Krishtal <okrishtal@xxxxxxxxxxxxx> > --- > src/storage/storage_backend.c | 92 ++++++++++++++++++++++++++--------- > src/storage/storage_backend.h | 2 +- > src/storage/storage_backend_fs.c | 6 ++- > src/storage/storage_backend_logical.c | 2 +- > src/util/virstoragefile.c | 9 +++- > 5 files changed, 84 insertions(+), 27 deletions(-) > > diff --git a/src/storage/storage_backend.c b/src/storage/storage_backend.c > index 60e6bd0..0e3c99c 100644 > --- a/src/storage/storage_backend.c > +++ b/src/storage/storage_backend.c > @@ -1587,6 +1587,25 @@ virStorageBackendDetectBlockVolFormatFD(virStorageSourcePtr target, > return 0; > } > > +static bool virStorageBackendIsPloopDir(char *path) > +{ > + char *file = NULL; > + bool ret = false; > + > + if (virAsprintf(&file, "%s/%s", path, "root.hds") < 0) > + return ret; let's stick with "%s/root.hds" in all places. > + if (!virFileExists(file)) > + goto cleanup; > + VIR_FREE(file); > + if (virAsprintf(&file, "%s/%s", path, "DiskDescriptor.xml") < 0) > + goto cleanup; > + if (!virFileExists(file)) > + goto cleanup; > + ret = true; > + cleanup: > + VIR_FREE(file); > + return ret; > +} > > /* > * Allows caller to silently ignore files with improper mode > @@ -1595,29 +1614,35 @@ virStorageBackendDetectBlockVolFormatFD(virStorageSourcePtr target, > * return -2 if file mode is unexpected or the volume is a dangling > * symbolic link. > */ > + > +#define FAILED_STAT(path, ret) { \ > + if (errno == ENOENT) { \ > + if (noerror) { \ > + VIR_WARN("ignoring missing file '%s'", path);\ > + ret = -2; \ > + } \ > + virReportError(VIR_ERR_NO_STORAGE_VOL, \ > + _("no storage vol with matching path '%s'"), path); \ > + ret = -1; \ > + } \ > + virReportSystemError(errno, \ > + _("cannot stat file '%s'"), path);\ > + ret = -1;\ > +} There is no need to introduce macros here. Function is enought. > + > int > -virStorageBackendVolOpen(const char *path, struct stat *sb, > +virStorageBackendVolOpen(virStorageSourcePtr target, struct stat *sb, > unsigned int flags) > { > - int fd, mode = 0; > - char *base = last_component(path); > + int fd, mode = 0, ret = 0; > + char *base = last_component(target->path); > bool noerror = (flags & VIR_STORAGE_VOL_OPEN_NOERROR); > + char *path = target->path; > + char *ploop_path = NULL; > > if (lstat(path, sb) < 0) { > - if (errno == ENOENT) { > - if (noerror) { > - VIR_WARN("ignoring missing file '%s'", path); > - return -2; > - } > - virReportError(VIR_ERR_NO_STORAGE_VOL, > - _("no storage vol with matching path '%s'"), > - path); > - return -1; > - } > - virReportSystemError(errno, > - _("cannot stat file '%s'"), > - path); > - return -1; > + FAILED_STAT(path, ret); > + return ret; > } > > if (S_ISFIFO(sb->st_mode)) { > @@ -1636,6 +1661,18 @@ virStorageBackendVolOpen(const char *path, struct stat *sb, > virReportError(VIR_ERR_INTERNAL_ERROR, > _("Volume path '%s' is a socket"), path); > return -1; > + } else if (S_ISDIR(sb->st_mode)) { > + if (virStorageBackendIsPloopDir(path)) { > + if (virAsprintf(&ploop_path, "%s/%s", target->path, "root.hds") < 0) > + return -1; > + path = ploop_path; > + target->format = VIR_STORAGE_FILE_PLOOP; > + if (lstat(path, sb) < 0) { > + FAILED_STAT(path, ret); > + VIR_FREE(ploop_path); > + return ret; > + } > + } > } > > /* O_NONBLOCK should only matter during open() for fifos and > @@ -1732,6 +1769,7 @@ virStorageBackendVolOpen(const char *path, struct stat *sb, > return -1; > } > > + VIR_FREE(ploop_path); we don't have cleanup label in this function and a lot of returns above this freeing thus we have memory leaks. I think instead of changing all returns in this function we could leave it as it is and pass good path here from outside. To check is this a ploop or not we can just call virFileExist for hds file (i mean not using stat call as i'm not sure is it heavier than access or not and current code seems to optimize stat calls). > return fd; > } > > @@ -1759,8 +1797,10 @@ virStorageBackendUpdateVolTargetInfo(virStorageSourcePtr target, > virStorageSourcePtr meta = NULL; > char *buf = NULL; > ssize_t len = VIR_STORAGE_MAX_HEADER; > + char *path = NULL; > + char *target_path = target->path; > > - if ((ret = virStorageBackendVolOpen(target->path, &sb, openflags)) < 0) > + if ((ret = virStorageBackendVolOpen(target, &sb, openflags)) < -1) > goto cleanup; > fd = ret; > > @@ -1775,7 +1815,7 @@ virStorageBackendUpdateVolTargetInfo(virStorageSourcePtr target, > } > > if (lseek(fd, 0, SEEK_SET) == (off_t)-1) { > - virReportSystemError(errno, _("cannot seek to start of '%s'"), target->path); > + virReportSystemError(errno, _("cannot seek to start of '%s'"), target_path); > ret = -1; > goto cleanup; > } > @@ -1783,18 +1823,23 @@ virStorageBackendUpdateVolTargetInfo(virStorageSourcePtr target, > if ((len = virFileReadHeaderFD(fd, len, &buf)) < 0) { > if (readflags & VIR_STORAGE_VOL_READ_NOERROR) { > VIR_WARN("ignoring failed header read for '%s'", > - target->path); > + target_path); > ret = -2; > } else { > virReportSystemError(errno, > _("cannot read header '%s'"), > - target->path); > + target_path); > ret = -1; > } > goto cleanup; > } > > - if (!(meta = virStorageFileGetMetadataFromBuf(target->path, buf, len, target->format, > + if (target->format == VIR_STORAGE_FILE_PLOOP) { > + if (virAsprintf(&path, "%s/%s", target->path, "root.hds") < 0) > + return -1; > + target_path = path; > + } > + if (!(meta = virStorageFileGetMetadataFromBuf(target_path, buf, len, target->format, > NULL))) { do we need path to actual hds here? and all the changes above from target->path to target_path > ret = -1; > goto cleanup; > @@ -1814,6 +1859,7 @@ virStorageBackendUpdateVolTargetInfo(virStorageSourcePtr target, > virStorageSourceFree(meta); > VIR_FORCE_CLOSE(fd); > VIR_FREE(buf); > + VIR_FREE(path); > return ret; > } > > @@ -2076,6 +2122,8 @@ virStorageBackendVolUploadLocal(virConnectPtr conn ATTRIBUTE_UNUSED, > ret = virFDStreamOpenBlockDevice(stream, target_path, > offset, len, O_WRONLY); > if (ret < 0) { > + virReportError(VIR_ERR_INTERNAL_ERROR, "%s", _("error " > + "occured during the upload of ploop volume")); must be in correspondent patch > goto cleanup; > } > > diff --git a/src/storage/storage_backend.h b/src/storage/storage_backend.h > index 65e91dc..de48012 100644 > --- a/src/storage/storage_backend.h > +++ b/src/storage/storage_backend.h > @@ -203,7 +203,7 @@ enum { > # define VIR_STORAGE_VOL_OPEN_DEFAULT (VIR_STORAGE_VOL_OPEN_REG |\ > VIR_STORAGE_VOL_OPEN_BLOCK) > > -int virStorageBackendVolOpen(const char *path, struct stat *sb, > +int virStorageBackendVolOpen(virStorageSourcePtr target, struct stat *sb, > unsigned int flags) > ATTRIBUTE_RETURN_CHECK > ATTRIBUTE_NONNULL(1) ATTRIBUTE_NONNULL(2); > diff --git a/src/storage/storage_backend_fs.c b/src/storage/storage_backend_fs.c > index abb6e47..f978b6e 100644 > --- a/src/storage/storage_backend_fs.c > +++ b/src/storage/storage_backend_fs.c > @@ -75,7 +75,7 @@ virStorageBackendProbeTarget(virStorageSourcePtr target, > if (encryption) > *encryption = NULL; > > - if ((rc = virStorageBackendVolOpen(target->path, &sb, > + if ((rc = virStorageBackendVolOpen(target, &sb, > VIR_STORAGE_VOL_FS_PROBE_FLAGS)) < 0) > return rc; /* Take care to propagate rc, it is not always -1 */ > fd = rc; > @@ -83,6 +83,10 @@ virStorageBackendProbeTarget(virStorageSourcePtr target, > if (virStorageBackendUpdateVolTargetInfoFD(target, fd, &sb) < 0) > goto cleanup; > > + if (target->format == VIR_STORAGE_FILE_PLOOP) { > + ret = 0; > + goto cleanup; > + } looks like if we return here we don't update capacity properly. > if (S_ISDIR(sb.st_mode)) { > target->format = VIR_STORAGE_FILE_DIR; > ret = 0; > diff --git a/src/storage/storage_backend_logical.c b/src/storage/storage_backend_logical.c > index ba26223..aaace5b 100644 > --- a/src/storage/storage_backend_logical.c > +++ b/src/storage/storage_backend_logical.c > @@ -955,7 +955,7 @@ virStorageBackendLogicalCreateVol(virConnectPtr conn, > virCommandFree(cmd); > cmd = NULL; > > - if ((fd = virStorageBackendVolOpen(vol->target.path, &sb, > + if ((fd = virStorageBackendVolOpen(&vol->target, &sb, > VIR_STORAGE_VOL_OPEN_DEFAULT)) < 0) > goto error; > > diff --git a/src/util/virstoragefile.c b/src/util/virstoragefile.c > index 101070f..5184310 100644 > --- a/src/util/virstoragefile.c > +++ b/src/util/virstoragefile.c > @@ -184,6 +184,10 @@ qedGetBackingStore(char **, int *, const char *, size_t); > #define QED_F_BACKING_FILE 0x01 > #define QED_F_BACKING_FORMAT_NO_PROBE 0x04 > > +/* Location of ploop image size in the header file * > + * https://openvz.org/Ploop/format */ > +#define PLOOP_IMAGE_SIZE_OFFSET 36 > +#define PLOOP_SIZE_MULTIPLIER 512 > > static struct FileTypeInfo const fileTypeInfo[] = { > [VIR_STORAGE_FILE_NONE] = { 0, NULL, NULL, LV_LITTLE_ENDIAN, > @@ -236,8 +240,9 @@ static struct FileTypeInfo const fileTypeInfo[] = { > -1, {0}, 0, 0, 0, 0, NULL, NULL }, > [VIR_STORAGE_FILE_VHD] = { 0, NULL, NULL, LV_LITTLE_ENDIAN, > -1, {0}, 0, 0, 0, 0, NULL, NULL }, > - [VIR_STORAGE_FILE_PLOOP] = { 0, NULL, NULL, LV_LITTLE_ENDIAN, > - -1, {0}, 0, 0, 0, 0, NULL, NULL }, > + [VIR_STORAGE_FILE_PLOOP] = { 0, "WithoutFreSpaceExt", NULL, LV_LITTLE_ENDIAN, > + -1, {0}, PLOOP_IMAGE_SIZE_OFFSET, 0, > + PLOOP_SIZE_MULTIPLIER, 0, NULL, NULL }, > > /* All formats with a backing store probe below here */ > [VIR_STORAGE_FILE_COW] = { > -- libvir-list mailing list libvir-list@xxxxxxxxxx https://www.redhat.com/mailman/listinfo/libvir-list