int lvm_snapshot(const char *orig, const char *path, uint64_t size) { int ret; char *pathdup, *lv; char sz[24]; char cmd_output[MAXPATHLEN]; struct lvcreate_args cmd_args = {0}; ret = snprintf(sz, 24, "%" PRIu64 "b", size); if (ret < 0 || ret >= 24) { ERROR("Failed to create string"); return -1; } pathdup = strdup(path); if (!pathdup) { ERROR("Failed to duplicate string \"%s\"", path); return -1; } lv = strrchr(pathdup, '/'); if (!lv) { ERROR("Failed to detect \"/\" in string \"%s\"", pathdup); free(pathdup); return -1; } *lv = '\0'; lv++; TRACE("Parsed logical volume \"%s\"", lv); /* Check if the original logical volume is backed by a thinpool, in * which case we cannot specify a size that's different from the * original size. */ ret = lvm_is_thin_volume(orig); if (ret < 0) { free(pathdup); return -1; } else if (ret) { cmd_args.thinpool = orig; } cmd_args.lv = lv; cmd_args.source_lv = orig; cmd_args.size = sz; TRACE("Creating new lvm snapshot \"%s\" of \"%s\" with size \"%s\"", lv, orig, sz); ret = run_command(cmd_output, sizeof(cmd_output), lvm_snapshot_exec_wrapper, (void *)&cmd_args); if (ret < 0) { ERROR("Failed to create logical volume \"%s\": %s", orig, cmd_output); free(pathdup); return -1; } free(pathdup); return 0; }
int lvm_snapshot(const char *orig, const char *path, uint64_t size) { int ret, pid; char sz[24], *pathdup, *lv; if ((pid = fork()) < 0) { SYSERROR("failed fork"); return -1; } if (pid > 0) return wait_for_pid(pid); // specify bytes to lvcreate ret = snprintf(sz, 24, "%"PRIu64"b", size); if (ret < 0 || ret >= 24) exit(EXIT_FAILURE); pathdup = strdup(path); if (!pathdup) exit(EXIT_FAILURE); lv = strrchr(pathdup, '/'); if (!lv) { free(pathdup); exit(EXIT_FAILURE); } *lv = '\0'; lv++; // check if the original lv is backed by a thin pool, in which case we // cannot specify a size that's different from the original size. ret = lvm_is_thin_volume(orig); if (ret == -1) { free(pathdup); return -1; } if (!ret) { ret = execlp("lvcreate", "lvcreate", "-s", "-L", sz, "-n", lv, orig, (char *)NULL); } else { ret = execlp("lvcreate", "lvcreate", "-s", "-n", lv, orig, (char *)NULL); } free(pathdup); exit(EXIT_FAILURE); }