diff --git a/WHATS_NEW b/WHATS_NEW index 4d5fe2fa5..e0765039f 100644 --- a/WHATS_NEW +++ b/WHATS_NEW @@ -1,5 +1,6 @@ Version 2.00.17 - ============================= + fsadm support for fsck and resizing - needs testing. Add read-only GFS pool support. Add lvm2create_initrd script from http://poochiereds.net/svn/lvm2/ Fix rounding of large diplayed sizes. diff --git a/configure b/configure index 3b6502b64..0a9780649 100755 --- a/configure +++ b/configure @@ -309,7 +309,7 @@ ac_includes_default="\ #endif" ac_default_prefix=/usr -ac_subst_vars='SHELL PATH_SEPARATOR PACKAGE_NAME PACKAGE_TARNAME PACKAGE_VERSION PACKAGE_STRING PACKAGE_BUGREPORT exec_prefix prefix program_transform_name bindir sbindir libexecdir datadir sysconfdir sharedstatedir localstatedir libdir includedir oldincludedir infodir mandir build_alias host_alias target_alias DEFS ECHO_C ECHO_N ECHO_T LIBS AWK CC CFLAGS LDFLAGS CPPFLAGS ac_ct_CC EXEEXT OBJEXT INSTALL_PROGRAM INSTALL_SCRIPT INSTALL_DATA LN_S SET_MAKE RANLIB ac_ct_RANLIB CPP EGREP build build_cpu build_vendor build_os host host_cpu host_vendor host_os target target_cpu target_vendor target_os MSGFMT JOBS STATIC_LINK LVM1 POOL SNAPSHOTS MIRRORS OWNER GROUP CLDFLAGS CLDWHOLEARCHIVE CLDNOWHOLEARCHIVE LD_DEPS LD_FLAGS SOFLAG LVM_VERSION LVM1_FALLBACK DEBUG DEVMAPPER HAVE_LIBDL HAVE_SELINUX CMDLIB LOCALEDIR CONFDIR STATICDIR INTL_PACKAGE INTL LIBOBJS LTLIBOBJS' +ac_subst_vars='SHELL PATH_SEPARATOR PACKAGE_NAME PACKAGE_TARNAME PACKAGE_VERSION PACKAGE_STRING PACKAGE_BUGREPORT exec_prefix prefix program_transform_name bindir sbindir libexecdir datadir sysconfdir sharedstatedir localstatedir libdir includedir oldincludedir infodir mandir build_alias host_alias target_alias DEFS ECHO_C ECHO_N ECHO_T LIBS AWK CC CFLAGS LDFLAGS CPPFLAGS ac_ct_CC EXEEXT OBJEXT INSTALL_PROGRAM INSTALL_SCRIPT INSTALL_DATA LN_S SET_MAKE RANLIB ac_ct_RANLIB CPP EGREP build build_cpu build_vendor build_os host host_cpu host_vendor host_os target target_cpu target_vendor target_os MSGFMT JOBS STATIC_LINK LVM1 POOL SNAPSHOTS MIRRORS OWNER GROUP CLDFLAGS CLDWHOLEARCHIVE CLDNOWHOLEARCHIVE LD_DEPS LD_FLAGS SOFLAG LVM_VERSION LVM1_FALLBACK DEBUG DEVMAPPER HAVE_LIBDL HAVE_SELINUX CMDLIB LOCALEDIR CONFDIR STATICDIR INTL_PACKAGE INTL FSADM LIBOBJS LTLIBOBJS' ac_subst_files='' # Initialize some variables set by options. @@ -3898,7 +3898,8 @@ case "$host_os" in LD_FLAGS="-Wl,--export-dynamic" SOFLAG="-shared" DEVMAPPER=yes - ODIRECT=yes ;; + ODIRECT=yes + FSADM=yes ;; darwin*) CFLAGS="-no-cpp-precomp -fno-common" CLDFLAGS= @@ -3908,7 +3909,8 @@ case "$host_os" in LD_FLAGS= SOFLAG="-dynamiclib" DEVMAPPER=no - ODIRECT=no ;; + ODIRECT=no + FSADM=no ;; esac @@ -5195,7 +5197,8 @@ fi - ac_config_files="$ac_config_files Makefile make.tmpl doc/Makefile include/Makefile lib/Makefile lib/format1/Makefile lib/format_pool/Makefile lib/mirror/Makefile lib/snapshot/Makefile man/Makefile po/Makefile tools/Makefile tools/version.h test/mm/Makefile test/device/Makefile test/format1/Makefile test/regex/Makefile test/filters/Makefile" + + ac_config_files="$ac_config_files Makefile make.tmpl doc/Makefile include/Makefile lib/Makefile lib/format1/Makefile lib/format_pool/Makefile lib/mirror/Makefile lib/snapshot/Makefile man/Makefile po/Makefile tools/Makefile tools/version.h tools/fsadm/Makefile test/mm/Makefile test/device/Makefile test/format1/Makefile test/regex/Makefile test/filters/Makefile" cat >confcache <<\_ACEOF # This file is a shell script that caches the results of configure # tests run on this system so they can be shared between configure @@ -5759,6 +5762,7 @@ do "po/Makefile" ) CONFIG_FILES="$CONFIG_FILES po/Makefile" ;; "tools/Makefile" ) CONFIG_FILES="$CONFIG_FILES tools/Makefile" ;; "tools/version.h" ) CONFIG_FILES="$CONFIG_FILES tools/version.h" ;; + "tools/fsadm/Makefile" ) CONFIG_FILES="$CONFIG_FILES tools/fsadm/Makefile" ;; "test/mm/Makefile" ) CONFIG_FILES="$CONFIG_FILES test/mm/Makefile" ;; "test/device/Makefile" ) CONFIG_FILES="$CONFIG_FILES test/device/Makefile" ;; "test/format1/Makefile" ) CONFIG_FILES="$CONFIG_FILES test/format1/Makefile" ;; @@ -5903,6 +5907,7 @@ s,@CONFDIR@,$CONFDIR,;t t s,@STATICDIR@,$STATICDIR,;t t s,@INTL_PACKAGE@,$INTL_PACKAGE,;t t s,@INTL@,$INTL,;t t +s,@FSADM@,$FSADM,;t t s,@LIBOBJS@,$LIBOBJS,;t t s,@LTLIBOBJS@,$LTLIBOBJS,;t t CEOF diff --git a/configure.in b/configure.in index 888484849..faaa631f3 100644 --- a/configure.in +++ b/configure.in @@ -58,7 +58,8 @@ case "$host_os" in LD_FLAGS="-Wl,--export-dynamic" SOFLAG="-shared" DEVMAPPER=yes - ODIRECT=yes ;; + ODIRECT=yes + FSADM=yes ;; darwin*) CFLAGS="-no-cpp-precomp -fno-common" CLDFLAGS= @@ -68,7 +69,8 @@ case "$host_os" in LD_FLAGS= SOFLAG="-dynamiclib" DEVMAPPER=no - ODIRECT=no ;; + ODIRECT=no + FSADM=no ;; esac dnl -- prefix is /usr by default, the exec_prefix default is setup later @@ -370,6 +372,7 @@ AC_SUBST(CONFDIR) AC_SUBST(STATICDIR) AC_SUBST(INTL_PACKAGE) AC_SUBST(INTL) +AC_SUBST(FSADM) dnl First and last lines should not contain files to generate in order to dnl keep utility scripts running properly @@ -387,6 +390,7 @@ man/Makefile \ po/Makefile \ tools/Makefile \ tools/version.h \ +tools/fsadm/Makefile \ test/mm/Makefile \ test/device/Makefile \ test/format1/Makefile \ diff --git a/tools/Makefile.in b/tools/Makefile.in index 864bb316c..1f43f6368 100644 --- a/tools/Makefile.in +++ b/tools/Makefile.in @@ -16,6 +16,10 @@ srcdir = @srcdir@ top_srcdir = @top_srcdir@ VPATH = @srcdir@ +ifeq ("@FSADM@", "yes") + SUBDIRS += fsadm +endif + SOURCES =\ archiver.c \ dumpconfig.c \ @@ -84,7 +88,7 @@ ifeq ("@DEVMAPPER@", "yes") LVMLIBS += -ldevmapper endif -include ../make.tmpl +include $(top_srcdir)/make.tmpl lvm: $(OBJECTS) lvm.o $(top_srcdir)/lib/liblvm.a $(CC) -o $@ $(OBJECTS) lvm.o $(LD_FLAGS) $(LVMLIBS) $(LIBS) -rdynamic diff --git a/tools/args.h b/tools/args.h index 2e77c519f..41eedf8d1 100644 --- a/tools/args.h +++ b/tools/args.h @@ -96,6 +96,7 @@ arg(maxphysicalvolumes_ARG, 'p', "maxphysicalvolumes", int_arg) arg(partial_ARG, 'P', "partial", NULL) arg(physicalvolume_ARG, 'P', "physicalvolume", NULL) arg(readahead_ARG, 'r', "readahead", int_arg) +arg(resizefs_ARG, 'r', "resizefs", NULL) arg(reset_ARG, 'R', "reset", NULL) arg(physicalextentsize_ARG, 's', "physicalextentsize", size_mb_arg) arg(separator_ARG, 's', "separator", string_arg) diff --git a/tools/commands.h b/tools/commands.h index 823626468..980034207 100644 --- a/tools/commands.h +++ b/tools/commands.h @@ -169,14 +169,16 @@ xx(lvextend, "\t[-i|--stripes Stripes [-I|--stripesize StripeSize]]\n" "\t{-l|--extents [+]LogicalExtentsNumber |\n" "\t -L|--size [+]LogicalVolumeSize[kKmMgGtT]}\n" + "\t[-n|--nofsck]\n" + "\t[-r|--resizefs]\n" "\t[-t|--test]\n" "\t[--type VolumeType]\n" "\t[-v|--verbose]\n" "\t[--version]" "\n" "\tLogicalVolume[Path] [ PhysicalVolumePath... ]\n", - alloc_ARG, autobackup_ARG, extents_ARG, size_ARG, stripes_ARG, - stripesize_ARG, test_ARG, type_ARG) + alloc_ARG, autobackup_ARG, extents_ARG, nofsck_ARG, resizefs_ARG, + size_ARG, stripes_ARG, stripesize_ARG, test_ARG, type_ARG) xx(lvmchange, "With the device mapper, this is obsolete and does nothing.", @@ -230,12 +232,14 @@ xx(lvreduce, "\t[-h|--help]\n" "\t{-l|--extents [-]LogicalExtentsNumber |\n" "\t -L|--size [-]LogicalVolumeSize[kKmMgGtT]}\n" + "\t[-n|--nofsck]\n" + "\t[-r|--resizefs]\n" "\t[-t|--test]\n" "\t[-v|--verbose]\n" "\t[--version]" "\n" "\tLogicalVolume[Path]\n", - autobackup_ARG, force_ARG, extents_ARG, + autobackup_ARG, force_ARG, extents_ARG, nofsck_ARG, resizefs_ARG, size_ARG, test_ARG, yes_ARG) xx(lvremove, @@ -276,14 +280,16 @@ xx(lvresize, "\t[-i|--stripes Stripes [-I|--stripesize StripeSize]]\n" "\t{-l|--extents [+|-]LogicalExtentsNumber |\n" "\t -L|--size [+|-]LogicalVolumeSize[kKmMgGtT]}\n" + "\t[-n|--nofsck]\n" + "\t[-r|--resizefs]\n" "\t[-t|--test]\n" "\t[--type VolumeType]\n" "\t[-v|--verbose]\n" "\t[--version]" "\n" "\tLogicalVolume[Path] [ PhysicalVolumePath... ]\n", - alloc_ARG, autobackup_ARG, extents_ARG, size_ARG, stripes_ARG, - stripesize_ARG, test_ARG, type_ARG) + alloc_ARG, autobackup_ARG, extents_ARG, nofsck_ARG, resizefs_ARG, + size_ARG, stripes_ARG, stripesize_ARG, test_ARG, type_ARG) xx(lvs, "Display information about logical volumes", diff --git a/tools/lvresize.c b/tools/lvresize.c index bbff62ed1..7760fc6f0 100644 --- a/tools/lvresize.c +++ b/tools/lvresize.c @@ -15,6 +15,8 @@ #include "tools.h" +#define SIZE_BUF 128 + struct lvresize_params { const char *vg_name; const char *lv_name; @@ -35,6 +37,9 @@ struct lvresize_params { LV_EXTEND = 2 } resize; + int resizefs; + int nofsck; + int argc; char **argv; }; @@ -80,6 +85,9 @@ static int _read_params(struct cmd_context *cmd, int argc, char **argv, return 0; } + lp->resizefs = arg_count(cmd, resizefs_ARG) ? 1 : 0; + lp->nofsck = arg_count(cmd, nofsck_ARG) ? 1 : 0; + if (!argc) { log_error("Please provide the logical volume name"); return 0; @@ -121,6 +129,8 @@ static int _lvresize(struct cmd_context *cmd, struct lvresize_params *lp) uint32_t seg_extents; uint32_t sz, str; struct list *pvh = NULL; + char size_buf[SIZE_BUF]; + char lv_path[PATH_MAX]; if (!(vg = vg_read(cmd, lp->vg_name, &consistent))) { log_error("Volume group %s doesn't exist", lp->vg_name); @@ -340,7 +350,13 @@ static int _lvresize(struct cmd_context *cmd, struct lvresize_params *lp) if (lp->resize == LV_REDUCE) { if (lp->argc) log_print("Ignoring PVs on command line when reducing"); + } else if (!(pvh = lp->argc ? create_pv_list(cmd->mem, vg, lp->argc, + lp->argv) : &vg->pvs)) { + stack; + return ECMD_FAILED; + } + if (lp->resize == LV_REDUCE || lp->resizefs) { memset(&info, 0, sizeof(info)); if (!lv_info(lv, &info) && driver_version(NULL, 0)) { @@ -348,7 +364,13 @@ static int _lvresize(struct cmd_context *cmd, struct lvresize_params *lp) return ECMD_FAILED; } - if (info.exists) { + if (lp->resizefs && !info.exists) { + log_error("Logical volume %s must be activated " + "before resizing filesystem", lp->lv_name); + return ECMD_FAILED; + } + + if (info.exists && !lp->resizefs && (lp->resize == LV_REDUCE)) { log_print("WARNING: Reducing active%s logical volume " "to %s", info.open_count ? " and open" : "", display_size(cmd, (uint64_t) lp->extents * @@ -357,50 +379,71 @@ static int _lvresize(struct cmd_context *cmd, struct lvresize_params *lp) log_print("THIS MAY DESTROY YOUR DATA " "(filesystem etc.)"); + + if (!arg_count(cmd, force_ARG)) { + if (yes_no_prompt("Do you really want to " + "reduce %s? [y/n]: ", + lp->lv_name) == 'n') { + log_print("Logical volume %s NOT " + "reduced", lp->lv_name); + return ECMD_FAILED; + } + } + } + } + + if (lp->resizefs) { + if (lvm_snprintf(lv_path, PATH_MAX, "%s%s/%s", cmd->dev_dir, + lp->vg_name, lp->lv_name) < 0) { + log_error("Couldn't create LV path for %s", + lp->lv_name); + return ECMD_FAILED; } - if (!arg_count(cmd, force_ARG)) { - if (yes_no_prompt("Do you really want to reduce %s?" - " [y/n]: ", lp->lv_name) == 'n') { - log_print("Logical volume %s NOT reduced", - lp->lv_name); + if (lvm_snprintf(size_buf, SIZE_BUF, "%" PRIu64, + (uint64_t) lp->extents * vg->extent_size / 2) + < 0) { + log_error("Couldn't generate new LV size string"); + return ECMD_FAILED; + } + + if (!lp->nofsck) { + if (!exec_cmd("fsadm", "check", lv_path, NULL)) { + stack; return ECMD_FAILED; } } - if (!archive(vg)) { - stack; - return ECMD_FAILED; + if (lp->resize == LV_REDUCE) { + if (!exec_cmd("fsadm", "resize", lv_path, size_buf)) { + stack; + return ECMD_FAILED; + } } - - if (!lv_reduce(vg->fid, lv, lv->le_count - lp->extents)) - return ECMD_FAILED; } - if (lp->resize == LV_EXTEND) { - if (!(pvh = lp->argc ? create_pv_list(cmd->mem, vg, lp->argc, - lp->argv) : &vg->pvs)) { + if (!archive(vg)) { + stack; + return ECMD_FAILED; + } + + log_print("%sing logical volume %s to %s", + (lp->resize == LV_REDUCE) ? "Reduc" : "Extend", + lp->lv_name, + display_size(cmd, (uint64_t) lp->extents * vg->extent_size, + SIZE_SHORT)); + + if (lp->resize == LV_REDUCE) { + if (!lv_reduce(vg->fid, lv, lv->le_count - lp->extents)) { stack; return ECMD_FAILED; } - - if (!archive(vg)) { - stack; - return ECMD_FAILED; - } - - log_print("Extending logical volume %s to %s", lp->lv_name, - display_size(cmd, (uint64_t) - lp->extents * vg->extent_size, - SIZE_SHORT)); - - if (!lv_extend(vg->fid, lv, lp->segtype, lp->stripes, + } else if (!lv_extend(vg->fid, lv, lp->segtype, lp->stripes, lp->stripe_size, 0u, lp->extents - lv->le_count, NULL, 0u, 0u, pvh, alloc)) { - stack; - return ECMD_FAILED; - } + stack; + return ECMD_FAILED; } /* store vg on disk(s) */ @@ -436,6 +479,13 @@ static int _lvresize(struct cmd_context *cmd, struct lvresize_params *lp) log_print("Logical volume %s successfully resized", lp->lv_name); + if (lp->resizefs && (lp->resize == LV_EXTEND)) { + if (!exec_cmd("fsadm", "resize", lv_path, size_buf)) { + stack; + return ECMD_FAILED; + } + } + return ECMD_PROCESSED; } diff --git a/tools/toollib.c b/tools/toollib.c index 1032e2af9..67b17e75b 100644 --- a/tools/toollib.c +++ b/tools/toollib.c @@ -16,6 +16,7 @@ #include "tools.h" #include +#include int process_each_lv_in_vg(struct cmd_context *cmd, struct volume_group *vg, struct list *arg_lvnames, struct list *tags, @@ -121,7 +122,7 @@ int process_each_lv(struct cmd_context *cmd, int argc, char **argv, int consistent; struct list *slh, *tags_arg; - struct list *vgnames; /* VGs to process */ + struct list *vgnames; /* VGs to process */ struct str_list *sll; struct volume_group *vg; struct list tags, lvnames; @@ -221,8 +222,7 @@ int process_each_lv(struct cmd_context *cmd, int argc, char **argv, log_error("vg/lv string alloc failed"); return ECMD_FAILED; } - if (!str_list_add(cmd->mem, &arg_lvnames, - vglv)) { + if (!str_list_add(cmd->mem, &arg_lvnames, vglv)) { log_error("strlist allocation failed"); return ECMD_FAILED; } @@ -883,3 +883,44 @@ struct list *clone_pv_list(struct pool *mem, struct list *pvsl) return r; } + +int exec_cmd(const char *command, const char *fscmd, const char *lv_path, + const char *size) +{ + pid_t pid; + int status; + + log_verbose("Executing: %s %s %s %s", command, fscmd, lv_path, size); + + if ((pid = fork()) == -1) { + log_error("fork failed: %s", strerror(errno)); + return 0; + } + + if (!pid) { + /* Child */ + /* FIXME Use execve directly */ + execlp(command, command, fscmd, lv_path, size, NULL); + log_sys_error("execlp", command); + exit(errno); + } + + /* Parent */ + if (wait4(pid, &status, 0, NULL) != pid) { + log_error("wait4 child process %u failed: %s", pid, + strerror(errno)); + return 0; + } + + if (!WIFEXITED(status)) { + log_error("Child %u exited abnormally", pid); + return 0; + } + + if (WEXITSTATUS(status)) { + log_error("%s failed: %u", command, WEXITSTATUS(status)); + return 0; + } + + return 1; +} diff --git a/tools/toollib.h b/tools/toollib.h index 077c5d350..78a01e8e9 100644 --- a/tools/toollib.h +++ b/tools/toollib.h @@ -79,4 +79,7 @@ struct list *create_pv_list(struct pool *mem, struct list *clone_pv_list(struct pool *mem, struct list *pvs); +int exec_cmd(const char *command, const char *fscmd, const char *lv_path, + const char *size); + #endif