* [linux-lvm] pvresize patch pending
@ 2005-10-28 16:59 Zac Slade
2005-10-28 17:01 ` Alasdair G Kergon
0 siblings, 1 reply; 12+ messages in thread
From: Zac Slade @ 2005-10-28 16:59 UTC (permalink / raw)
To: linux-lvm
A friend and I have been working on a patch to provide pvresize to the lvm2
distribution. We have a working version now and are looking for some code
review/testing. Currently it only supports growing a pv and it only supports
growing it to the actual size of the device that backs the pv.
Is this the right venue to distribute this patch or is there another way that it
should be disseminated?
Thank you,
Zac Slade
krakrjak@volumehost.com
-------------------------------------------------
This mail sent through IMP: http://horde.org/imp/
^ permalink raw reply [flat|nested] 12+ messages in thread
* Re: [linux-lvm] pvresize patch pending
2005-10-28 16:59 [linux-lvm] pvresize patch pending Zac Slade
@ 2005-10-28 17:01 ` Alasdair G Kergon
2005-10-28 17:17 ` Zac Slade
0 siblings, 1 reply; 12+ messages in thread
From: Alasdair G Kergon @ 2005-10-28 17:01 UTC (permalink / raw)
To: LVM general discussion and development
On Fri, Oct 28, 2005 at 11:59:56AM -0500, Zac Slade wrote:
> Is this the right venue to distribute this patch
Yes!
Alasdair
--
agk@redhat.com
^ permalink raw reply [flat|nested] 12+ messages in thread
* Re: [linux-lvm] pvresize patch pending
2005-10-28 17:01 ` Alasdair G Kergon
@ 2005-10-28 17:17 ` Zac Slade
2005-10-28 17:55 ` Zac Slade
0 siblings, 1 reply; 12+ messages in thread
From: Zac Slade @ 2005-10-28 17:17 UTC (permalink / raw)
To: LVM general discussion and development
Quoting Alasdair G Kergon <agk@redhat.com>:
> On Fri, Oct 28, 2005 at 11:59:56AM -0500, Zac Slade wrote:
> > Is this the right venue to distribute this patch
>
> Yes!
Well alright. Attached is a unified diff I validated that it merges
successfully against LVM2.2.01.13.tar.gz and LVM2.2.01.14.tar.gz. Those files I
obtained through gentoo's portage system. I also checked out the cvs and the
patch does apply successfully. To integrate the patch just enter the
distribution directory where the LVM2 sources are and execute, patch -p1 <
path-to.patch.
For testing we used an lv that was mounted on a loopback device. The only
option that pvresize will take is a pv pathname.
Here's your patch!
Zac Slade
krakrjak@volumehost.com
-------------------------------------------------
This mail sent through IMP: http://horde.org/imp/
^ permalink raw reply [flat|nested] 12+ messages in thread
* Re: [linux-lvm] pvresize patch pending
2005-10-28 17:17 ` Zac Slade
@ 2005-10-28 17:55 ` Zac Slade
2005-10-28 19:27 ` Alasdair G Kergon
0 siblings, 1 reply; 12+ messages in thread
From: Zac Slade @ 2005-10-28 17:55 UTC (permalink / raw)
To: LVM general discussion and development
Quoting Alasdair G Kergon <agk@redhat.com>:
> On Fri, Oct 28, 2005 at 12:17:54PM -0500, Zac Slade wrote:
> > Well alright. Attached is a unified diff I validated that it merges
>
> Not attached:-)
>
Opps. See previous in thread for patching:
diff -uNdr LVM2.2.01.13/lib/format_text/format-text.c
LVM2.2.01.13.patched/lib/format_text/format-text.c
--- LVM2.2.01.13/lib/format_text/format-text.c 2005-10-28 06:54:22.000000000 -0500
+++ LVM2.2.01.13.patched/lib/format_text/format-text.c 2005-10-28
06:55:13.000000000 -0500
@@ -1059,7 +1059,7 @@
/* FIXME Test mode don't update cache? */
if (!(info = lvmcache_add(fmt->labeller, (char *) &pv->id, pv->dev,
- ORPHAN, NULL))) {
+ pv->vg_name, NULL))) {
stack;
return 0;
}
diff -uNdr LVM2.2.01.13/tools/Makefile.in LVM2.2.01.13.patched/tools/Makefile.in
--- LVM2.2.01.13/tools/Makefile.in 2005-06-06 12:12:07.000000000 -0500
+++ LVM2.2.01.13.patched/tools/Makefile.in 2005-10-28 05:21:40.000000000 -0500
@@ -39,6 +39,7 @@
polldaemon.c \
pvchange.c \
pvcreate.c \
+ pvresize.c \
pvdisplay.c \
pvmove.c \
pvremove.c \
diff -uNdr LVM2.2.01.13/tools/commands.h LVM2.2.01.13.patched/tools/commands.h
--- LVM2.2.01.13/tools/commands.h 2005-06-06 12:12:07.000000000 -0500
+++ LVM2.2.01.13.patched/tools/commands.h 2005-10-28 05:19:40.000000000 -0500
@@ -486,8 +487,9 @@
force_ARG, test_ARG, yes_ARG)
xx(pvresize,
- "Resize a physical volume in use by a volume group",
- "Not implemented. Use pvcreate options.",
+ "Resize (grow only) a physical volume",
+ "pvresize " "\n"
+ "\tPhysicalVolume\n",
/***
"pvresize "
"[-A|--autobackup {y|n}] "
Files LVM2.2.01.13/tools/lvm.o and LVM2.2.01.13.patched/tools/lvm.o differ
diff -uNdr LVM2.2.01.13/tools/pvresize.c LVM2.2.01.13.patched/tools/pvresize.c
--- LVM2.2.01.13/tools/pvresize.c 1969-12-31 18:00:00.000000000 -0600
+++ LVM2.2.01.13.patched/tools/pvresize.c 2005-10-28 06:49:09.000000000 -0500
@@ -0,0 +1,149 @@
+/* pvresize
+ * Currently this code only supports growing a pv
+ * And you can only resize it to the actual size
+ * of the PhysicalVolume.
+ *
+ * The tricky part is making it smaller.
+ *
+ * Code is copyright 2005:
+ * Boyd Smith <bss03@volumehost.com>
+ * Zac Slade <krakrjak@volumehost.com>
+ *
+ */
+
+#include "tools.h"
+
+static int _pvresize_single(struct cmd_context *cmd, struct physical_volume *pv,
+ void *handle)
+{
+ struct volume_group *vg = NULL;
+ struct pv_list *pvl;
+ const char *pv_name = dev_name(pv->dev);
+ char uuid[64];
+
+ if (*pv->vg_name != '\0') {
+ log_verbose("Finding volume group of physical volume \"%s\"",
+ pv_name);
+
+ if (!lock_vol(cmd, pv->vg_name, LCK_VG_WRITE)) {
+ log_error("Can't get lock for %s", pv->vg_name);
+ return ECMD_FAILED;
+ }
+
+ if (!(vg = vg_read(cmd, pv->vg_name, NULL))) {
+ unlock_vg(cmd, pv->vg_name);
+ log_error("Unable to find volume group of \"%s\"",
+ pv_name);
+ return ECMD_FAILED;
+ }
+
+ if (vg->status & EXPORTED_VG) {
+ unlock_vg(cmd, pv->vg_name);
+ log_error("Volume group \"%s\" is exported", vg->name);
+ return ECMD_FAILED;
+ }
+
+ if (!(vg->status & LVM_WRITE)) {
+ unlock_vg(cmd, pv->vg_name);
+ log_error("Volume group \"%s\" is read-only", vg->name);
+ return ECMD_FAILED;
+ }
+
+ if (!(pvl = find_pv_in_vg(vg, pv_name))) {
+ unlock_vg(cmd, pv->vg_name);
+ log_error
+ ("Unable to find \"%s\" in volume group \"%s\"",
+ pv_name, vg->name);
+ return ECMD_FAILED;
+ }
+ if (arg_count(cmd, uuid_ARG) && lvs_in_vg_activated(vg)) {
+ unlock_vg(cmd, pv->vg_name);
+ log_error("Volume group containing %s has active "
+ "logical volumes", pv_name);
+ return ECMD_FAILED;
+ }
+ pv = pvl->pv;
+ if (!archive(vg))
+ return ECMD_FAILED;
+ } else {
+ if (!lock_vol(cmd, ORPHAN, LCK_VG_WRITE)) {
+ log_error("Can't get lock for orphans");
+ return ECMD_FAILED;
+ }
+ }
+ uint64_t size =0;
+ struct device *dev;
+
+ if (!(dev = dev_cache_get(pv_name, cmd->filter))) {
+ log_error("%s: Couldn't find device. Check your filters?",
+ pv_name);
+ goto error;
+ }
+
+ if (!dev_get_size(pv->dev, &size)) {
+ log_error("%s: Couldn't get size.", dev_name(pv->dev));
+ goto error;
+ }
+
+ if (size < pv->size) {
+ log_error("Trying to shrink pv %s to %lu bytes.", dev_name(pv->dev), size);
+ goto error;
+ } else if (size == pv->size) {
+ log_error("Trying to extend pv %s to the same size.", dev_name(pv->dev));
+ goto error;
+ }
+
+ pv->size = size;
+ /* No mda or label changes */
+ if (!(pv->fmt->ops->pv_write(pv->fmt, pv, NULL, -1))) {
+ log_error("Failed to write physical volume \"%s\"", pv_name);
+ goto error;
+ }
+
+ log_verbose("Updating physical volume \"%s\"", pv_name);
+ if (*pv->vg_name != '\0') {
+ if (!vg_write(vg) || !vg_commit(vg)) {
+ unlock_vg(cmd, pv->vg_name);
+ log_error("Failed to store physical volume \"%s\" in "
+ "volume group \"%s\"", pv_name, vg->name);
+ return 0;
+ }
+ backup(vg);
+ unlock_vg(cmd, pv->vg_name);
+ } else {
+ if (!(pv_write(cmd, pv, NULL, INT64_C(-1)))) {
+ unlock_vg(cmd, ORPHAN);
+ log_error("Failed to store physical volume \"%s\"",
+ pv_name);
+ return 0;
+ }
+ unlock_vg(cmd, ORPHAN);
+ }
+
+ log_print("Physical volume \"%s\" changed", pv_name);
+ return ECMD_PROCESSED;
+error:
+ unlock_vg(cmd, pv->vg_name);
+ return ECMD_FAILED;
+}
+
+int pvresize(struct cmd_context *cmd, int argc, char **argv)
+{
+ char *pv_name;
+ struct physical_volume *pv;
+ int done;
+ if (argc != 1) {
+ log_error("Currently limited to only One physical volume");
+ return EINVALID_CMD_LINE;
+ }
+ log_verbose("Using physical volume on command line");
+ pv_name = argv[0];
+ /* FIXME Read VG instead - pv_read will fail */
+ if (!(pv = pv_read(cmd, pv_name, NULL, NULL, 1))) {
+ log_error("Failed to read physical volume %s", pv_name);
+ }
+ done = _pvresize_single(cmd, pv, NULL);
+ return (done == 1) ? ECMD_PROCESSED : ECMD_FAILED;
+}
+
+
diff -uNdr LVM2.2.01.13/tools/stub.h LVM2.2.01.13.patched/tools/stub.h
--- LVM2.2.01.13/tools/stub.h 2004-03-30 13:35:43.000000000 -0600
+++ LVM2.2.01.13.patched/tools/stub.h 2005-10-28 05:31:40.000000000 -0500
@@ -19,7 +19,7 @@
/*int e2fsadm(struct cmd_context *cmd, int argc, char **argv) unimplemented*/
int lvmsadc(struct cmd_context *cmd, int argc, char **argv) unimplemented
int lvmsar(struct cmd_context *cmd, int argc, char **argv) unimplemented
-int pvresize(struct cmd_context *cmd, int argc, char **argv) unimplemented
+/*int pvresize(struct cmd_context *cmd, int argc, char **argv) unimplemented*/
int pvdata(struct cmd_context *cmd, int argc, char **argv) {
log_error("There's no 'pvdata' command in LVM2.");
Zac Slade
krakrjak@volumehost.com
-------------------------------------------------
This mail sent through IMP: http://horde.org/imp/
^ permalink raw reply [flat|nested] 12+ messages in thread
* Re: [linux-lvm] pvresize patch pending
2005-10-28 17:55 ` Zac Slade
@ 2005-10-28 19:27 ` Alasdair G Kergon
2005-10-28 20:14 ` Zak Kipling
0 siblings, 1 reply; 12+ messages in thread
From: Alasdair G Kergon @ 2005-10-28 19:27 UTC (permalink / raw)
To: LVM general discussion and development
On Fri, Oct 28, 2005 at 12:55:52PM -0500, Zac Slade wrote:
> + pv->size = size;
If the PV belongs to a VG (the only case that matters - pvcreate
is quite adequate otherwise), after the pv_write (equivalent
to 'pvcreate'), more fields need updating I think - see
add_pv_to_vg() - incl. the various extent counters and
the segment lists.
[If you only allow 'pvresize' with format_text this might be easier -
compatibility with LVM1 size calculations and restrictions is always
tricky and needs careful testing - is it really worth the effort?]
> + log_error("Currently limited to only One physical volume");
Try process_each_pv(), which also handles the locking for you.
For shrinking, you need to ensure that all the extents that are
about to be removed are unallocated - if they aren't, then the
metadata should be considered corrupt and it's best to refuse to change it.
[Separate recovery options needed.]
Alasdair
--
agk@redhat.com
^ permalink raw reply [flat|nested] 12+ messages in thread
* Re: [linux-lvm] pvresize patch pending
2005-10-28 19:27 ` Alasdair G Kergon
@ 2005-10-28 20:14 ` Zak Kipling
2005-10-28 21:21 ` Alasdair G Kergon
2005-10-31 2:42 ` Alasdair G Kergon
0 siblings, 2 replies; 12+ messages in thread
From: Zak Kipling @ 2005-10-28 20:14 UTC (permalink / raw)
To: LVM general discussion and development
[-- Attachment #1: Type: text/plain, Size: 1488 bytes --]
Alasdair G Kergon wrote:
> If the PV belongs to a VG (the only case that matters - pvcreate
> is quite adequate otherwise), after the pv_write (equivalent
> to 'pvcreate'), more fields need updating I think - see
> add_pv_to_vg() - incl. the various extent counters and
> the segment lists.
Indeed. I've recently been working on an implementation myself
(primarily because I wanted to grow a live PV on my own system), which
I've attached in its current (somewhat rough, but seemingly working)
state as a patch against CVS HEAD.
In addition to updating pv->size it also adjusts pv->pe_count,
pe->segments, vg->extent_count and vg->free_count.
In the shrinking case, it checks that the removed extents are free
(though ideally it would relocate them elsewhere in the VG, like pvmove.
There is no requirement for LVs to be deactivated, as the actual LVs
don't get touched during the operation.
I've tested it (both growing and shrinking) on loop devices containing
small LVM systems, and successfully used it to grow the PV housing a
running system (including the root filesystem).
The main issues I'm not sure about are:
* Support for metadata formats other than format_text.
* Support for more than one mda on a PV (I think it will currently
clobber ones at the end of the PV, since it assumes all space after
pe_start is available for extents).
I hadn't planned on posting it quite yet, but since the discussion has
started it might be useful.
--
Zak Kipling.
[-- Attachment #2: lvm2-pvresize.diff --]
[-- Type: text/x-patch, Size: 14708 bytes --]
Index: lib/metadata/pv_alloc.h
===================================================================
RCS file: /cvs/lvm2/LVM2/lib/metadata/pv_alloc.h,v
retrieving revision 1.5
diff -b -u -r1.5 pv_alloc.h
--- lib/metadata/pv_alloc.h 16 Oct 2005 23:03:58 -0000 1.5
+++ lib/metadata/pv_alloc.h 28 Oct 2005 20:04:49 -0000
@@ -25,4 +25,8 @@
int check_pv_segments(struct volume_group *vg);
void merge_pv_segments(struct pv_segment *peg1, struct pv_segment *peg2);
+/* This code is experimental. Do NOT complain if it trashes your LVM system */
+int pv_resize(struct physical_volume *pv, struct volume_group *vg,
+ uint32_t new_pe_count);
+
#endif
Index: lib/metadata/pv_manip.c
===================================================================
RCS file: /cvs/lvm2/LVM2/lib/metadata/pv_manip.c,v
retrieving revision 1.8
diff -b -u -r1.8 pv_manip.c
--- lib/metadata/pv_manip.c 16 Oct 2005 23:03:58 -0000 1.8
+++ lib/metadata/pv_manip.c 28 Oct 2005 20:04:50 -0000
@@ -301,3 +301,107 @@
return ret;
}
+
+
+/*
+ * Resize a PV, adding or removing segments as needed.
+ * Update the volume group if supplied.
+ * New size must fit within pv->size
+ *
+ * This code is experimental. Do NOT complain if it trashes your LVM system
+ */
+int pv_resize(struct physical_volume *pv,
+ struct volume_group *vg,
+ uint32_t new_pe_count)
+{
+ struct pv_segment *peg, *tmp_peg;
+ uint32_t old_pe_count = pv->pe_count;
+
+ if (new_pe_count < old_pe_count) {
+ if (new_pe_count < pv->pe_alloc_count) {
+ log_error("%s: cannot resize to %" PRIu32 " extents "
+ "as %" PRIu32 " are allocated.",
+ dev_name(pv->dev), new_pe_count,
+ pv->pe_alloc_count);
+ return 0;
+ }
+
+ log_verbose("Reducing physical volume %s to %" PRIu32
+ " extents.", dev_name(pv->dev), new_pe_count);
+
+ if (!pv_split_segment(pv, new_pe_count)) return 0;
+
+ list_iterate_items_safe(peg, tmp_peg, &pv->segments) {
+ if (peg->pe + peg->len > new_pe_count) {
+ if (peg->lvseg) {
+ log_error("%s: cannot resize to %"PRIu32
+ " extents as later ones are "
+ "allocated.",
+ dev_name(pv->dev),
+ new_pe_count);
+ return 0;
+ }
+ else {
+ assert (peg->pe >= new_pe_count);
+ list_del(&peg->list);
+ }
+ }
+ }
+ }
+ else if (new_pe_count > old_pe_count) {
+ if (pv->size / pv->pe_size < new_pe_count) {
+ log_error("%s: cannot resize to %" PRIu32 " extents as there "
+ "is only space for %" PRIu64 ".", dev_name(pv->dev),
+ new_pe_count, pv->size / pv->pe_size);
+ }
+
+ log_verbose("Extending physical volume %s to %" PRIu32
+ " extents.", dev_name(pv->dev), new_pe_count);
+
+ peg = _alloc_pv_segment(pv->fmt->cmd->mem, pv,
+ old_pe_count,
+ new_pe_count - old_pe_count,
+ NULL, 0);
+ list_add(&pv->segments, &peg->list);
+
+ pv->pe_count = new_pe_count;
+ }
+ else {
+ log_verbose("No change to size of physical volume %s.",
+ dev_name(pv->dev));
+ return 1;
+ }
+
+ pv->pe_count = new_pe_count;
+
+ if (vg) {
+ if (strcmp(pv->vg_name, vg->name)) {
+ log_error("pv_resize internal error: given wrong "
+ "volume group %s.", vg->name);
+ return 0;
+ }
+
+ log_verbose("Changing extent count of volume group %s to "
+ "match", vg->name);
+
+ if (new_pe_count < old_pe_count) {
+ assert(vg->extent_count >= old_pe_count);
+ assert(vg->free_count >= old_pe_count - new_pe_count);
+ vg->extent_count -= (old_pe_count - new_pe_count);
+ vg->free_count -= (old_pe_count - new_pe_count);
+ }
+ else if (new_pe_count > old_pe_count) {
+ vg->extent_count += (new_pe_count - old_pe_count);
+ vg->free_count += (new_pe_count - old_pe_count);
+ }
+ }
+ else {
+ if (*pv->vg_name) {
+ log_error("pv_resize internal error: need volume group "
+ "%s.", pv->vg_name);
+ return 0;
+ }
+ }
+
+ return 1;
+}
Index: man/Makefile.in
===================================================================
RCS file: /cvs/lvm2/LVM2/man/Makefile.in,v
retrieving revision 1.14
diff -b -u -r1.14 Makefile.in
--- man/Makefile.in 9 Dec 2004 16:57:37 -0000 1.14
+++ man/Makefile.in 28 Oct 2005 20:04:50 -0000
@@ -19,10 +19,10 @@
MAN5=lvm.conf.5
MAN8=lvchange.8 lvcreate.8 lvdisplay.8 lvextend.8 lvm.8 lvmchange.8 \
lvmdiskscan.8 lvreduce.8 lvremove.8 lvrename.8 lvresize.8 lvs.8 \
- lvscan.8 pvchange.8 pvcreate.8 pvdisplay.8 pvmove.8 pvremove.8 pvs.8 \
- pvscan.8 vgcfgbackup.8 vgcfgrestore.8 vgchange.8 vgck.8 vgcreate.8 \
- vgconvert.8 vgdisplay.8 vgexport.8 vgextend.8 vgimport.8 \
- vgmerge.8 vgmknodes.8 vgreduce.8 vgremove.8 vgrename.8 \
+ lvscan.8 pvchange.8 pvcreate.8 pvdisplay.8 pvmove.8 pvremove.8 \
+ pvresize.8 pvs.8 pvscan.8 vgcfgbackup.8 vgcfgrestore.8 vgchange.8 \
+ vgck.8 vgcreate.8 vgconvert.8 vgdisplay.8 vgexport.8 vgextend.8 \
+ vgimport.8 vgmerge.8 vgmknodes.8 vgreduce.8 vgremove.8 vgrename.8 \
vgs.8 vgscan.8 vgsplit.8
MAN8CLUSTER=clvmd.8
MAN5DIR=${mandir}/man5
Index: man/pvresize.8
===================================================================
RCS file: man/pvresize.8
diff -N man/pvresize.8
--- /dev/null 1 Jan 1970 00:00:00 -0000
+++ man/pvresize.8 28 Oct 2005 20:04:50 -0000
@@ -0,0 +1,53 @@
+.TH PVCREATE 8 "LVM TOOLS" "Sistina Software UK" \" -*- nroff -*-
+.SH NAME
+pvresize \- resize a disk or partition in use by LVM
+.SH SYNOPSIS
+.B pvresize
+.RB [ \-d | \-\-debug ]
+.RB [ \-h | \-\-help ]
+.RB [ \-t | \-\-test ]
+.RB [ \-v | \-\-verbose ]
+.RB [ \-\-setphysicalvolumesize size ]
+.IR PhysicalVolume " [" PhysicalVolume ...]
+.SH DESCRIPTION
+.B pvresize
+resizes
+.I PhysicalVolume
+which may already be in a volume group and have active logical volumes
+allocated on it.
+.SH STATUS
+.B pvresize
+is currently EXPERIMENTAL. Make sure you have a backup and do NOT complain if
+it trashes your LVM system.
+.SH OPTIONS
+See \fBlvm\fP(8) for common options.
+.TP
+.BR \-\-setphysicalvolumesize " size"
+Overrides the automatically-detected size of the PV. Use with care, or
+prior to reducing the physical size of the device.
+.SH EXAMPLES
+Expand the PV on /dev/sda1 after enlarging the partition with fdisk:
+.sp
+.B pvresize /dev/sda1
+.sp
+Shrink the PV on /dev/sda1 prior to shrinking the partition with fdisk
+(ensure that the PV size is appropriate for your intended new partition
+size):
+.sp
+.B pvresize --setphysicalvolumesize 40G /dev/sda1
+.sp
+.SH RESTRICTIONS
+.B pvresize
+will refuse to shrink
+.I PhysicalVolume
+if it has allocated extents after where its new end would be. In the future,
+it should relocate these elsewhere in the volume group if there is sufficient
+free space, like
+.B pvmove
+does.
+.sp
+.B pvresize
+probably won't currently work correctly on LVM1 volumes, or PVs with extra
+metadata areas.
+.SH SEE ALSO
+.BR lvm "(8), " pvmove "(8), " lvresize "(8), " fdisk "(8)"
Index: tools/Makefile.in
===================================================================
RCS file: /cvs/lvm2/LVM2/tools/Makefile.in,v
retrieving revision 1.68
diff -b -u -r1.68 Makefile.in
--- tools/Makefile.in 6 Jun 2005 17:12:07 -0000 1.68
+++ tools/Makefile.in 28 Oct 2005 20:04:50 -0000
@@ -42,6 +42,7 @@
pvdisplay.c \
pvmove.c \
pvremove.c \
+ pvresize.c \
pvscan.c \
reporter.c \
segtypes.c \
Index: tools/commands.h
===================================================================
RCS file: /cvs/lvm2/LVM2/tools/commands.h,v
retrieving revision 1.75
diff -b -u -r1.75 commands.h
--- tools/commands.h 17 Oct 2005 16:41:38 -0000 1.75
+++ tools/commands.h 28 Oct 2005 20:04:52 -0000
@@ -373,6 +373,22 @@
all_ARG, allocatable_ARG, allocation_ARG, autobackup_ARG, deltag_ARG,
addtag_ARG, test_ARG, uuid_ARG)
+xx(pvresize,
+ "Resize physical volume(s) in use by LVM [EXPERIMENTAL]",
+ "pvresize " "\n"
+ "\t[-d|--debug]" "\n"
+ "\t[-h|-?|--help] " "\n"
+ "\t[--setphysicalvolumesize PhysicalVolumeSize[kKmMgGtT]" "\n"
+ "\t[-t|--test] " "\n"
+ "\t[-v|--verbose] " "\n"
+ "\t[--version] " "\n"
+ "\tPhysicalVolume [PhysicalVolume...]\n"
+ "\t\n"
+ "\tpvresize is EXPERIMENTAL -- ensure you have a backup and\n"
+ "\tdo NOT complain if it trashes your LVM system!\n",
+
+ test_ARG, physicalvolumesize_ARG)
+
xx(pvcreate,
"Initialize physical volume(s) for use by LVM",
"pvcreate " "\n"
Index: tools/pvresize.c
===================================================================
RCS file: tools/pvresize.c
diff -N tools/pvresize.c
--- /dev/null 1 Jan 1970 00:00:00 -0000
+++ tools/pvresize.c 28 Oct 2005 20:04:52 -0000
@@ -0,0 +1,212 @@
+/*
+ * Copyright (C) 2001-2004 Sistina Software, Inc. All rights reserved.
+ * Copyright (C) 2004 Red Hat, Inc. All rights reserved.
+ * Copyright (C) 2005 Zak Kipling. All rights reserved.
+ *
+ * This file is part of LVM2.
+ *
+ * This copyrighted material is made available to anyone wishing to use,
+ * modify, copy, or redistribute it subject to the terms and conditions
+ * of the GNU General Public License v.2.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+
+#include "tools.h"
+#include "pv_alloc.h"
+
+/* This code is experimental. Do NOT complain if it trashes your LVM system */
+
+/* FIXME Locking. PVs in VG. */
+
+static int _pvresize_single(struct cmd_context *cmd,
+ struct physical_volume *pv)
+{
+ struct volume_group *vg = NULL;
+ struct pv_list *pvl;
+ struct list mdas;
+ uint64_t sector;
+
+ const char *pv_name = dev_name(pv->dev);
+
+ int consistent = 1;
+ uint64_t size = 0;
+ uint32_t old_pe_count = 0, new_pe_count = 0;
+
+ list_init(&mdas);
+
+ if (arg_sign_value(cmd, physicalvolumesize_ARG, 0) == SIGN_MINUS) {
+ log_error("Physical volume size may not be negative");
+ return 0;
+ }
+ size = arg_uint64_value(cmd, physicalvolumesize_ARG, UINT64_C(0)) * 2;
+
+ /* If in a VG, must change using volume group. */
+ if (*pv->vg_name) {
+ log_verbose("Finding volume group of physical volume \"%s\"",
+ pv_name);
+
+ if (!lock_vol(cmd, pv->vg_name, LCK_VG_WRITE)) {
+ log_error("Can't get lock for %s", pv->vg_name);
+ return 0;
+ }
+
+ if (!(vg = vg_read(cmd, pv->vg_name, &consistent))) {
+ unlock_vg(cmd, pv->vg_name);
+ log_error("Unable to find volume group of \"%s\"",
+ pv_name);
+ return 0;
+ }
+
+ if (vg->status & EXPORTED_VG) {
+ unlock_vg(cmd, pv->vg_name);
+ log_error("Volume group \"%s\" is exported", vg->name);
+ return 0;
+ }
+
+ if (!(vg->status & LVM_WRITE)) {
+ unlock_vg(cmd, pv->vg_name);
+ log_error("Volume group \"%s\" is read-only", vg->name);
+ return 0;
+ }
+
+ if (!(pvl = find_pv_in_vg(vg, pv_name))) {
+ unlock_vg(cmd, pv->vg_name);
+ log_error
+ ("Unable to find \"%s\" in volume group \"%s\"",
+ pv_name, vg->name);
+ return 0;
+ }
+ pv = pvl->pv;
+ if (!archive(vg))
+ return 0;
+ } else {
+ if (!lock_vol(cmd, ORPHAN, LCK_VG_WRITE)) {
+ log_error("Can't get lock for orphans");
+ return 0;
+ }
+
+ if (!(pv = pv_read(cmd, pv_name, &mdas, §or, 1))) {
+ unlock_vg(cmd, ORPHAN);
+ log_error("Unable to read PV \"%s\"", pv_name);
+ return 0;
+ }
+
+ }
+
+ /* change size of PV */
+ if (!dev_get_size(pv->dev, &pv->size)) {
+ log_error("%s: Couldn't get size.", pv_name);
+ return 0;
+ }
+
+ if (size) {
+ if (size > pv->size)
+ log_print("WARNING: %s: Overriding real size. "
+ "You could lose data.", pv_name);
+ log_verbose("%s: Pretending size is %" PRIu64 " sectors.",
+ pv_name, size);
+ pv->size = size;
+ }
+
+ if (pv->size < PV_MIN_SIZE) {
+ log_error("%s: Size must exceed minimum of %ld sectors.",
+ pv_name, PV_MIN_SIZE);
+ return 0;
+ }
+
+ if (pv->size < pv->pe_start) {
+ log_error("%s: Size must exceed physical extent start of "
+ "%" PRIu64 " sectors.", pv_name, pv->pe_start);
+ return 0;
+ }
+
+ pv->size -= pv->pe_start;
+
+ log_verbose("Resizing volume \"%s\" to %" PRIu64 " sectors.",
+ pv_name, pv->size);
+
+ if (pv->pe_size) {
+ new_pe_count = (pv->size - pv->pe_start) / vg->extent_size;
+
+ log_verbose("That makes %" PRIu32 " extents of %" PRIu32
+ " sectors each.", new_pe_count, pv->pe_size);
+
+ if (new_pe_count < pv->pe_count) {
+ if (!new_pe_count) {
+ log_error("%s: Size must leave space for at "
+ "least one physical extent of "
+ "%" PRIu32 " sectors.", pv_name,
+ pv->pe_size);
+ return 0;
+ }
+ }
+
+ old_pe_count = pv->pe_count;
+ if (!pv_resize(pv, vg, new_pe_count)) return 0;
+ }
+
+ log_verbose("Updating physical volume \"%s\"", pv_name);
+ if (*pv->vg_name) {
+ if (!vg_write(vg) || !vg_commit(vg)) {
+ unlock_vg(cmd, pv->vg_name);
+ log_error("Failed to store physical volume \"%s\" in "
+ "volume group \"%s\"", pv_name, vg->name);
+ return 0;
+ }
+ backup(vg);
+ unlock_vg(cmd, pv->vg_name);
+ } else {
+ if (!(pv_write(cmd, pv, NULL, INT64_C(-1)))) {
+ unlock_vg(cmd, ORPHAN);
+ log_error("Failed to store physical volume \"%s\"",
+ pv_name);
+ return 0;
+ }
+ unlock_vg(cmd, ORPHAN);
+ }
+
+ log_print("Physical volume \"%s\" changed", pv_name);
+
+ return 1;
+}
+
+int pvresize(struct cmd_context *cmd, int argc, char **argv)
+{
+ int opt = 0;
+ int done = 0;
+ int total = 0;
+
+ struct physical_volume *pv;
+ char *pv_name;
+
+ struct list mdas;
+
+ list_init(&mdas);
+
+ if (!argc) {
+ log_error("Please give a physical volume path");
+ return EINVALID_CMD_LINE;
+ }
+
+ for (; opt < argc; opt++) {
+ pv_name = argv[opt];
+ /* FIXME Read VG instead - pv_read will fail */
+ if (!(pv = pv_read(cmd, pv_name, &mdas, NULL, 1))) {
+ log_error("Failed to read physical volume %s",
+ pv_name);
+ continue;
+ }
+ total++;
+ done += _pvresize_single(cmd, pv);
+ }
+
+ log_print("%d physical volume%s changed / %d physical volume%s "
+ "not changed",
+ done, done == 1 ? "" : "s",
+ total - done, (total - done) == 1 ? "" : "s");
+
+ return (total == done) ? ECMD_PROCESSED : ECMD_FAILED;
+}
Index: tools/stub.h
===================================================================
RCS file: /cvs/lvm2/LVM2/tools/stub.h,v
retrieving revision 1.43
diff -b -u -r1.43 stub.h
--- tools/stub.h 30 Mar 2004 19:35:43 -0000 1.43
+++ tools/stub.h 28 Oct 2005 20:04:52 -0000
@@ -19,7 +19,6 @@
/*int e2fsadm(struct cmd_context *cmd, int argc, char **argv) unimplemented*/
int lvmsadc(struct cmd_context *cmd, int argc, char **argv) unimplemented
int lvmsar(struct cmd_context *cmd, int argc, char **argv) unimplemented
-int pvresize(struct cmd_context *cmd, int argc, char **argv) unimplemented
int pvdata(struct cmd_context *cmd, int argc, char **argv) {
log_error("There's no 'pvdata' command in LVM2.");
^ permalink raw reply [flat|nested] 12+ messages in thread
* Re: [linux-lvm] pvresize patch pending
2005-10-28 20:14 ` Zak Kipling
@ 2005-10-28 21:21 ` Alasdair G Kergon
2005-10-29 0:37 ` Zac Slade
2005-10-31 2:42 ` Alasdair G Kergon
1 sibling, 1 reply; 12+ messages in thread
From: Alasdair G Kergon @ 2005-10-28 21:21 UTC (permalink / raw)
To: LVM general discussion and development
On Fri, Oct 28, 2005 at 09:14:43PM +0100, Zak Kipling wrote:
> Indeed. I've recently been working on an implementation myself
> (primarily because I wanted to grow a live PV on my own system), which
> I've attached in its current (somewhat rough, but seemingly working)
> state as a patch against CVS HEAD.
Unless I've missed something while skimming through, I think the code
still needs a preceding 'pvcreate --restorefile' equivalent to ensure
the size of the device is set correctly in the label (for PVs in a VG).
(But since the 'Reinstate full PV size when removing from VG.' fix,
perhaps a code audit would show that we can safely override that label
field with the one taken from the VG and allow it to remain wrong on disk.)
https://www.redhat.com/archives/linux-lvm/2005-July/msg00033.html
https://www.redhat.com/archives/linux-lvm/2005-July/msg00029.html
pvs -o +dev_size
Apart from that and the process_each_pv() simplification, it
looks pretty good!
> * Support for metadata formats other than format_text.
Let's just exclude them with a FMT_RESIZE_PV feature flag.
> * Support for more than one mda on a PV (I think it will currently
> clobber ones at the end of the PV, since it assumes all space after
> pe_start is available for extents).
Check the number of mdas on the PV and refuse to proceed if it exceeds 1.
We need to write separate new tools to add/remove/manipulate mdas.
Alasdair
--
agk@redhat.com
^ permalink raw reply [flat|nested] 12+ messages in thread
* Re: [linux-lvm] pvresize patch pending
2005-10-28 21:21 ` Alasdair G Kergon
@ 2005-10-29 0:37 ` Zac Slade
2005-10-29 1:02 ` Alasdair G Kergon
0 siblings, 1 reply; 12+ messages in thread
From: Zac Slade @ 2005-10-29 0:37 UTC (permalink / raw)
To: LVM general discussion and development
Quoting Alasdair G Kergon <agk@redhat.com>:
> On Fri, Oct 28, 2005 at 09:14:43PM +0100, Zak Kipling wrote:
> > Indeed. I've recently been working on an implementation myself
> > (primarily because I wanted to grow a live PV on my own system), which
> > I've attached in its current (somewhat rough, but seemingly working)
> > state as a patch against CVS HEAD.
>
> Unless I've missed something while skimming through, I think the code
> still needs a preceding 'pvcreate --restorefile' equivalent to ensure
> the size of the device is set correctly in the label (for PVs in a VG).
> (But since the 'Reinstate full PV size when removing from VG.' fix,
> perhaps a code audit would show that we can safely override that label
> field with the one taken from the VG and allow it to remain wrong on disk.)
I'm going to work on integrating his patch with ours and see if we can't make it
more cohesive.
> https://www.redhat.com/archives/linux-lvm/2005-July/msg00033.html
> https://www.redhat.com/archives/linux-lvm/2005-July/msg00029.html
> pvs -o +dev_size
I think that to get this part write might take a fundemental shift in the way
pv_write() and _pv_write() behave. What would be nice is to make pv_write()
distinguish between a pv_create calling it and a pv_resize. Then have _pv_write
only write the pv mda to the disk. By doing this _pv_write becomes generic and
allows for further extension. Also then we can probably implement atomicity for
pv updates (though updating a pv was not initially engineered into lvm it can
become very handy).
> Apart from that and the process_each_pv() simplification, it
> looks pretty good!
Actually there is no need to use process_each_pv(). I don't think that it's
necessary or even wise to support resizing more than one pv at a time. Instead
it should act less like pvcreate and more like lvextend. That way supporting
--setphysicalvolumesize makes sense.
> > * Support for metadata formats other than format_text.
>
> Let's just exclude them with a FMT_RESIZE_PV feature flag.
Well it would be nice to support format_pool I'm not sure what the win for
supporting format1 is.... What would be required architecurally to support
alternative formats?
> > * Support for more than one mda on a PV (I think it will currently
> > clobber ones at the end of the PV, since it assumes all space after
> > pe_start is available for extents).
>
> Check the number of mdas on the PV and refuse to proceed if it exceeds 1.
> We need to write separate new tools to add/remove/manipulate mdas.
Can't we just borrow the code from pvcreate to manipulate the metadatacopies?
This shouldn't be the end of the world to get working while the infrastructure
gets put into place to support it more gracefully.
Zac Slade
krakrjak@volumehost.com
-------------------------------------------------
This mail sent through IMP: http://horde.org/imp/
^ permalink raw reply [flat|nested] 12+ messages in thread
* Re: [linux-lvm] pvresize patch pending
2005-10-29 0:37 ` Zac Slade
@ 2005-10-29 1:02 ` Alasdair G Kergon
2005-10-29 20:08 ` Alasdair G Kergon
2005-11-04 1:53 ` Zac Slade
0 siblings, 2 replies; 12+ messages in thread
From: Alasdair G Kergon @ 2005-10-29 1:02 UTC (permalink / raw)
To: LVM general discussion and development
On Fri, Oct 28, 2005 at 07:37:27PM -0500, Zac Slade wrote:
> I think that to get this part write might take a fundemental shift in the way
> pv_write() and _pv_write() behave. What would be nice is to make pv_write()
> distinguish between a pv_create calling it and a pv_resize. Then have _pv_write
> only write the pv mda to the disk. By doing this _pv_write becomes generic and
> allows for further extension. Also then we can probably implement atomicity for
> pv updates (though updating a pv was not initially engineered into lvm it can
> become very handy).
I'm reluctant to extend pv_write - long term I want to get rid of it
(and pv_read also) as PV operations are always awkward and getting in the way.
Everything should be done with (new-style) VGs and LVs.
pvcreate is also superfluous - I want to absorb it into vgcreate/vgextend etc.
So every labelled volume will always belong to a VG - with enhanced
vgsplit/vgmerge & allocation facilities.
CVS now lets you create PVs on LVs - another step towards eliminating
PVs.
> Actually there is no need to use process_each_pv
If you don't use it, you have to duplicate the logic in it as you have
already done - incompletely (e.g. tag support is missing).
> necessary or even wise to support resizing more than one pv at a time.
If ppl want to do that, why stop them?
> Can't we just borrow the code from pvcreate to manipulate the metadatacopies?
Not yet. That problem needs solving as part of a general mda-manipulating
feature. No point in doing it first for a rarely-used case.
Alasdair
--
agk@redhat.com
^ permalink raw reply [flat|nested] 12+ messages in thread
* Re: [linux-lvm] pvresize patch pending
2005-10-29 1:02 ` Alasdair G Kergon
@ 2005-10-29 20:08 ` Alasdair G Kergon
2005-11-04 1:53 ` Zac Slade
1 sibling, 0 replies; 12+ messages in thread
From: Alasdair G Kergon @ 2005-10-29 20:08 UTC (permalink / raw)
To: LVM general discussion and development
Are any of you are interested in working on something else in
a related area of the code?
New tool:
lvimport - Bring an existing filesystem on a partition under LVM control
e.g. you have an ext3 filesystem on /dev/hda3 and you want to turn it
into an LV without moving it.
Requires an existing VG with at least one pre-existing mda.
(could be from metadata/dirs of course)
Involves (equivalent of) running pvcreate -Zn --metadatacopies 0
on the partition,
probably with --labelsector 1 (may depend on fs),
changing pe_start to 0,
getting the last sector used by the filesystem (add a new helper
function to fsadm to give this info based on filesystem type?),
vgchange --physicalextentsize if necessary so that the entire
filesystem is enclosed by PEs,
adding the new PV to the VG,
creating an LV enclosing the filesystem.
Now the PV label is within the new LV - but stored in a sector
that the filesystem doesn't use.
There might be a case for reducing the size of the filesystem
slightly before doing this if it's close to the end of the
partition, so that the pe size isn't too small.
[The number of PEs is 32-bits, so tiny PEs put constraints
on the VG size - need to make sure the code detects problems here,
or consider implications of switching to 64 bits.]
Ensure none of the tools can leave you with a VG with no mdas
(eg split off the new PV with vgsplit)
Require filesystem to be unmounted first.
Alasdair
--
agk@redhat.com
^ permalink raw reply [flat|nested] 12+ messages in thread
* Re: [linux-lvm] pvresize patch pending
2005-10-28 20:14 ` Zak Kipling
2005-10-28 21:21 ` Alasdair G Kergon
@ 2005-10-31 2:42 ` Alasdair G Kergon
1 sibling, 0 replies; 12+ messages in thread
From: Alasdair G Kergon @ 2005-10-31 2:42 UTC (permalink / raw)
To: LVM general discussion and development
On Fri, Oct 28, 2005 at 09:14:43PM +0100, Zak Kipling wrote:
> Indeed. I've recently been working on an implementation myself
> (primarily because I wanted to grow a live PV on my own system), which
> I've attached in its current (somewhat rough, but seemingly working)
> state as a patch against CVS HEAD.
I've merged this into CVS - we can finish testing it there alongside
the other development going on at the moment.
Alasdair
--
agk@redhat.com
^ permalink raw reply [flat|nested] 12+ messages in thread
* Re: [linux-lvm] pvresize patch pending
2005-10-29 1:02 ` Alasdair G Kergon
2005-10-29 20:08 ` Alasdair G Kergon
@ 2005-11-04 1:53 ` Zac Slade
1 sibling, 0 replies; 12+ messages in thread
From: Zac Slade @ 2005-11-04 1:53 UTC (permalink / raw)
To: LVM general discussion and development
Quoting Alasdair G Kergon <agk@redhat.com>:
> On Fri, Oct 28, 2005 at 07:37:27PM -0500, Zac Slade wrote:
> > I think that to get this part write might take a fundemental shift in the
> way
> > pv_write() and _pv_write() behave. What would be nice is to make
> pv_write()
> > distinguish between a pv_create calling it and a pv_resize. Then have
> _pv_write
> > only write the pv mda to the disk. By doing this _pv_write becomes generic
> and
> > allows for further extension. Also then we can probably implement
> atomicity for
> > pv updates (though updating a pv was not initially engineered into lvm it
> can
> > become very handy).
>
> I'm reluctant to extend pv_write - long term I want to get rid of it
> (and pv_read also) as PV operations are always awkward and getting in the
> way.
> Everything should be done with (new-style) VGs and LVs.
>
> pvcreate is also superfluous - I want to absorb it into vgcreate/vgextend
> etc.
> So every labelled volume will always belong to a VG - with enhanced
> vgsplit/vgmerge & allocation facilities.
> CVS now lets you create PVs on LVs - another step towards eliminating
> PVs.
So instead of using pv_read and pv_write (except for backward compatibility)
this functionality should then be migrated into vgcreate? Okay, I can see that.
Doing away with the pv* methods will subtract some abstraction. However with
this fundamental shift how do you reconcile the pv/vg structures? Just do away
with the notion of pvs all together or instead have them, but they only exists
as an internal structure not visible to the user?
I'm still learning the codebase and I'm not sure there is an obvious way to
start this. I'm assuming that you don't want pvcreate reinvented inside
vgcreate, but instead have vgcreate do something new to abstract the underlying
devices by only utilizing a vg structure not having seperate pv structures.
This code may already exist. A few hints in the right direction would be nice.
I'll keep poking around.
Zac Slade
krakrjak@volumehost.com
-------------------------------------------------
This mail sent through IMP: http://horde.org/imp/
^ permalink raw reply [flat|nested] 12+ messages in thread
end of thread, other threads:[~2005-11-04 1:53 UTC | newest]
Thread overview: 12+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2005-10-28 16:59 [linux-lvm] pvresize patch pending Zac Slade
2005-10-28 17:01 ` Alasdair G Kergon
2005-10-28 17:17 ` Zac Slade
2005-10-28 17:55 ` Zac Slade
2005-10-28 19:27 ` Alasdair G Kergon
2005-10-28 20:14 ` Zak Kipling
2005-10-28 21:21 ` Alasdair G Kergon
2005-10-29 0:37 ` Zac Slade
2005-10-29 1:02 ` Alasdair G Kergon
2005-10-29 20:08 ` Alasdair G Kergon
2005-11-04 1:53 ` Zac Slade
2005-10-31 2:42 ` Alasdair G Kergon
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).