/* * path must be '/dev/$vg/$lv', $vg must be an existing VG, and $lv must not * yet exist. This function will attempt to create /dev/$vg/$lv of size * $size. If thinpool is specified, we'll check for it's existence and if * it's * a valid thin pool, and if so, we'll create the requested lv from that * thin * pool. */ static int do_lvm_create(const char *path, uint64_t size, const char *thinpool) { int ret, pid, len; char sz[24], *pathdup, *vg, *lv, *tp = NULL; 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) exit(EXIT_FAILURE); *lv = '\0'; lv++; vg = strrchr(pathdup, '/'); if (!vg) exit(EXIT_FAILURE); vg++; if (thinpool) { len = strlen(pathdup) + strlen(thinpool) + 2; tp = alloca(len); ret = snprintf(tp, len, "%s/%s", pathdup, thinpool); if (ret < 0 || ret >= len) exit(EXIT_FAILURE); ret = lvm_is_thin_pool(tp); INFO("got %d for thin pool at path: %s", ret, tp); if (ret < 0) exit(EXIT_FAILURE); if (!ret) tp = NULL; } if (!tp) execlp("lvcreate", "lvcreate", "-L", sz, vg, "-n", lv, (char *)NULL); else execlp("lvcreate", "lvcreate", "--thinpool", tp, "-V", sz, vg, "-n", lv, (char *)NULL); SYSERROR("execlp"); exit(EXIT_FAILURE); }
/* The path must be "/dev/<vg>/<lv>". The volume group <vg> must be an existing * volume group, and the logical volume <lv> must not yet exist. * This function will attempt to create "/dev/<vg>/<lv> of size <size>. If * thinpool is specified, we'll check for it's existence and if it's a valid * thin pool, and if so, we'll create the requested logical volume from that * thin pool. */ static int do_lvm_create(const char *path, uint64_t size, const char *thinpool) { int len, ret; char *pathdup, *vg, *lv; char cmd_output[MAXPATHLEN]; char sz[24]; char *tp = NULL; struct lvcreate_args cmd_args = {0}; ret = snprintf(sz, 24, "%" PRIu64 "b", size); if (ret < 0 || ret >= 24) { ERROR("Failed to create string: %d", ret); 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); vg = strrchr(pathdup, '/'); if (!vg) { ERROR("Failed to detect \"/\" in string \"%s\"", pathdup); free(pathdup); return -1; } vg++; TRACE("Parsed volume group \"%s\"", vg); if (thinpool) { len = strlen(pathdup) + strlen(thinpool) + 2; tp = alloca(len); ret = snprintf(tp, len, "%s/%s", pathdup, thinpool); if (ret < 0 || ret >= len) { ERROR("Failed to create string: %d", ret); free(pathdup); return -1; } ret = lvm_is_thin_pool(tp); TRACE("got %d for thin pool at path: %s", ret, tp); if (ret < 0) { ERROR("Failed to detect whether \"%s\" is a thinpool", tp); free(pathdup); return -1; } else if (!ret) { TRACE("Detected that \"%s\" is not a thinpool", tp); tp = NULL; } else { TRACE("Detected \"%s\" is a thinpool", tp); } } cmd_args.thinpool = tp; cmd_args.vg = vg; cmd_args.lv = lv; cmd_args.size = sz; TRACE("Creating new lvm storage volume \"%s\" on volume group \"%s\" " "of size \"%s\"", lv, vg, sz); ret = run_command(cmd_output, sizeof(cmd_output), lvm_create_exec_wrapper, (void *)&cmd_args); if (ret < 0) { ERROR("Failed to create logical volume \"%s\": %s", lv, cmd_output); free(pathdup); return -1; } TRACE("Created new lvm storage volume \"%s\" on volume group \"%s\" " "of size \"%s\"", lv, vg, sz); free(pathdup); return ret; }