PVMOVE(8)

πŸ’– pvmove(8) β€” System Manager's Manual πŸ’–

okay bestie, welcome to pvmove, section 8 of the manual, and she is that girl. let's get into it πŸ’…


✨ NAME ✨

pvmove β€” Move extents from one physical volume to another πŸ¦‹


✨ SYNOPSIS ✨

pvmove position_args
       [ option_args ]
       [ position_args ]

🌸 DESCRIPTION 🌸

so what does pvmove actually do? she moves the allocated physical extents (PEs) sitting on a source PV over to one or more destination PVs. iconic behavior honestly. and if you want, you can also name a source LV β€” in which case only the extents that LV is using get moved, and they land on free (or explicitly specified) extents on the destination PV. no destination PV given? then the normal allocation rules for the VG just do their thing. periodt.

now, real talk: if pvmove gets interrupted for any reason (machine crashed, etc. 😭 β€” it happens), just run pvmove again with no PV arguments to restart whatever operations were in progress from the last checkpoint. or, alternatively, use the abort option any time you want to abort the operation. where your LVs end up after an abort depends on whether the atomic option was used, so keep that in mind bestie.

πŸ‘€ also: more than one pvmove can run concurrently, but only if they're moving data from different source PVs. extra pvmoves will ignore any LVs already in the process of being changed, so some data might not get moved. no cap.

πŸ¦‹ USAGE πŸ¦‹

Move PV extents.

pvmove PV
       [ -A|--autobackup y|n ]
       [ -n|--name String ]
       [ --alloc contiguous|cling|cling_by_tags|normal|anywhere|inherit
       ]
       [ --atomic ]
       [ --noudevsync ]
       [ --reportformat basic|json|json_std ]
       [ COMMON_OPTIONS ]
       [ PV ... ]

β€”

Continue or abort existing pvmove operations.

pvmove
       [ COMMON_OPTIONS ]

β€”

Common options for command:

[ -b|--background ]
[ -i|--interval [+]Number ]
[ --abort ]

Common options for lvm:

[ -d|--debug ... ]
[ -h|--help ]
[ -q|--quiet ... ]
[ -t|--test ]
[ -v|--verbose ... ]
[ -y|--yes ]
[ --commandprofile String ]
[ --config String ]
[ --devices PV ]
[ --devicesfile String ]
[ --driverloaded y|n ]
[ --journal String ]
[ --lockopt String ]
[ --longhelp ]
[ --nohints ]
[ --nolocking ]
[ --profile String ]
[ --version ]

πŸ‘‘ OPTIONS πŸ‘‘

  • --abort β€” Aborts whatever pvmove operations are currently in progress. If the pvmove was started with the --atomic option, then literally all LVs will stay put on the source PV. Otherwise it's a split: segments that already got moved stay on the destination PV, and segments that didn't move stay on the source PV. messy but that's the deal 🫢
  • --alloc contiguous|cling|cling_by_tags|normal|anywhere|inherit β€” decides the allocation policy when a command needs to grab Physical Extents (PEs) out of the VG. every VG and every LV has an allocation policy, and you can change it with vgchange/lvchange, or just override it right here on the command line. so: normal applies the common-sense rules, like not putting parallel stripes on the same PV. inherit hands the VG policy down to an LV. contiguous requires the new PEs to be placed adjacent to existing PEs. cling places new PEs on the same PV as existing PEs in the same stripe of the LV. and if there are enough PEs for an allocation but normal won't use them, anywhere will β€” even if it tanks performance, e.g. by putting two stripes on the same PV πŸ’€ also, optional positional PV args on the command line can limit which PVs the command will use for allocation. see lvm(8) for more on allocation.
  • --atomic β€” makes a pvmove operation atomic, meaning every affected LV gets moved to the destination PV, or none of them do if the operation is aborted. all or nothing, main character energy πŸ‘‘
  • -A|--autobackup y|n β€” says whether metadata should get backed up automatically after a change. turning this on is strongly advised! see vgcfgbackup(8) for more.
  • -b|--background β€” if the operation needs polling, this makes the command return before the operation is complete, and the polling happens in the background. go do your thing, bestie ✨
  • --commandprofile String β€” the command profile to use for command configuration. see lvm.conf(5) for more about profiles.
  • --config String β€” config settings for the command. these override lvm.conf(5) settings. the String arg uses the same format as lvm.conf(5), or you can use the section/field syntax. see lvm.conf(5) for more about config.
  • -d|--debug ... β€” sets the debug level. repeat it 1 to 6 times to crank up the detail of messages going to the log file and/or syslog (if configured). πŸ”₯
  • --devices PV β€” restricts which devices are visible and accessible to the command. devices not listed will look like they're missing. can be repeated, or accepts a comma-separated list of devices. this overrides the devices file.
  • --devicesfile String β€” a file listing the devices LVM should use. it has to exist in /etc/lvm/devices/ and it's managed with the lvmdevices(8) command. this overrides the lvm.conf(5) devices/devicesfile and devices/use_devicesfile settings.
  • --driverloaded y|n β€” if set to no, the command won't even try to use device-mapper. for testing and debugging 🧚
  • -h|--help β€” display help text.
  • -i|--interval [+]Number β€” reports progress at regular intervals. with a + prefix, the first check is delayed by the given number of seconds, which lets background operations start before polling begins. cute, considerate, we love her πŸ’–
  • --journal String β€” records information in the systemd journal. this is in addition to whatever the lvm.conf log/journal setting already enables. command: record information about the command. output: record the default command output. debug: record full command debugging.
  • --lockopt String β€” used to pass options for special cases to lvmlockd. see lvmlockd(8) for more.
  • --longhelp β€” display long help text.
  • -n|--name String β€” move only the extents belonging to the named LV. targeted. focused. πŸ’…
  • --nohints β€” don't use the hints file to locate devices for PVs. a command may read more devices to find PVs when hints aren't used. the command will still do standard hint file invalidation where appropriate, so don't worry.
  • --nolocking β€” disables locking. use with caution, because concurrent commands may produce incorrect results 😭
  • --noudevsync β€” disables udev synchronization. the process won't wait for notification from udev; it'll just keep going regardless of any possible udev processing happening in the background. only use this if udev isn't running, or has rules that ignore the devices LVM creates.
  • --profile String β€” an alias for --commandprofile or --metadataprofile, depending on the command.
  • -q|--quiet ... β€” suppresses output and log messages. overrides --debug and --verbose. repeat it once to also suppress any prompts with answer no.
  • --reportformat basic|json|json_std β€” overrides the current output format for reports, which is defined globally by the report/output_format setting in lvm.conf(5). basic is the original format with columns and rows β€” and if there's more than one report per command, each report gets prefixed with the report name for identification. json produces report output in JSON format. json_std produces report output in JSON format that's more compliant with the JSON standard. see lvmreport(7) for more.
  • -t|--test β€” run in test mode. commands will not update metadata. this works by disabling all metadata writing but still returning success to the calling function. heads up bestie: this may lead to unusual error messages in multi-stage operations if a tool relies on reading back metadata it believes has changed but hasn't πŸ™ˆ
  • -v|--verbose ... β€” sets the verbose level. repeat it 1 to 4 times to increase the detail of messages sent to stdout and stderr.
  • --version β€” display version information.
  • -y|--yes β€” don't prompt for confirmation interactively, just always assume the answer is yes. use with extreme caution ⚠️ (for automatic no, see -qq.)

πŸ“ VARIABLES πŸ“

  • PV β€” Physical Volume name, a device path under /dev. for commands managing physical extents, a PV positional arg generally accepts a suffix indicating a range (or multiple ranges) of physical extents (PEs). when the first PE is omitted, it defaults to the start of the device, and when the last PE is omitted it defaults to the end.

Start and end range (inclusive): PV[:PE-PE] ...

Start and length range (counting from 0): PV[:PE+PE] ...

  • String β€” see the option description for information about the string content.
  • Size[UNIT] β€” Size is an input number that accepts an optional unit. input units are always treated as base two values, regardless of capitalization β€” e.g. k and K both mean 1024. the default input unit is specified by letter, followed by |UNIT. UNIT represents other possible input units: b|B is bytes, s|S is sectors of 512 bytes, k|K is KiB, m|M is MiB, g|G is GiB, t|T is TiB, p|P is PiB, e|E is EiB. (this should not be confused with the output control --units, where capital letters mean multiples of 1000.)

🌈 ENVIRONMENT VARIABLES 🌈

see lvm(8) for information about environment variables used by lvm. for example, LVM_VG_NAME can generally be substituted for a required VG parameter πŸ’œ

πŸŽ€ NOTES πŸŽ€

okay bestie, buckle up, here's literally how pvmove does its lil dance πŸ’ƒ:

  1. a temporary 'pvmove' LV gets created to store all the deets of every data movement that's required.
  2. every LV in the VG gets searched for contiguous data that needs moving, based on whatever you put on the command line. for each piece of data found, a new segment is added to the end of the pvmove LV. that segment is literally a temporary mirror, copying the data from the original location to a freshly allocated location. the original LV gets updated to use that new temporary mirror segment in the pvmove LV instead of touching the data directly. ✨
  3. the VG metadata gets updated on disk.
  4. the first segment of the pvmove LV is activated and starts mirroring the first part of the data. only one segment is mirrored at once because honestly that's usually more efficient. πŸ’…
  5. a daemon repeatedly checks progress at the specified time interval. the moment it detects the first temporary mirror is in sync, it breaks that mirror so only the new location for that data gets used, and writes a checkpoint into the VG metadata on disk. then it activates the mirror for the next segment of the pvmove LV. πŸ”₯
  6. when there are no more segments left to be mirrored, the temporary LV is removed and the VG metadata gets updated so the LVs reflect the new data locations. slay, done.
note that this new procedure cannot support the original LVM1 type of on-disk metadata. metadata can be converted using vgconvert(8). ⚠️

by default, pvmove will mirror an entire LV segment at once. if the process gets interrupted (like, say, by a system crash or power failure 😭) before the segment is fully mirrored, the entire segment must be mirrored again when pvmove is restarted. for very large segments, this can result in significant rework, which is giving pain. the allocation/pvmove_max_segment_size_mb setting in lvm.conf(5) can be used to limit the maximum size of data mirrored in a single operation. when set to a non-zero value, pvmove will split large segments into smaller chunks of the specified size (in MiB), mirror each chunk, and update metadata between chunks. this ensures that at most one chunk needs to be re-mirrored after an interruption. for example, setting this to 10240 will limit each mirroring operation to 10 GiB. the default value of 0 means no limit β€” entire segments are mirrored at once.

if the --atomic option is used, a slightly different approach is used for the move. again, a temporary 'pvmove' LV is created to store the details of all the data movements required. this temporary LV contains all the segments of the various LVs that need to be moved. however, in this case, an identical LV is allocated that contains the same number of segments and a mirror is created to copy the contents from the first temporary LV to the second one. after a complete copy is made, the temporary LVs are removed, leaving behind the segments on the destination PV. if an abort is issued during the move, all LVs being moved will remain on the source PV. 🫢

pvmove is not allowed on RAID logical volumes that have integrity enabled. see lvmraid(7).


🌸 EXAMPLES 🌸

move all physical extents that are used by simple LVs on the specified PV to free physical extents elsewhere in the VG:

pvmove /dev/sdb1

use a specific destination PV when moving physical extents:

pvmove /dev/sdb1 /dev/sdc1

move extents belonging to a single LV:

pvmove -n lvol1 /dev/sdb1 /dev/sdc1

rather than moving the contents of an entire device, it's possible to move a range of physical extents β€” for example numbers 1000 to 1999 inclusive on the specified PV:

pvmove /dev/sdb1:1000-1999

a range of physical extents to move can be specified as start+length. for example, 1000+1000 specifies 1000 extents starting from PE 1000. (counting starts from 0, so this refers to the 1001st to the 2000th PE inclusive.) :

pvmove /dev/sdb1:1000+1000

move a range of physical extents to a specific PV (which must have sufficient free extents):

pvmove /dev/sdb1:1000-1999 /dev/sdc1

move a range of physical extents to specific new extents on a new PV:

pvmove /dev/sdb1:1000-1999 /dev/sdc1:0-999

if the source and destination are on the same disk, the anywhere allocation policy is needed:

pvmove --alloc anywhere /dev/sdb1:1000-1999 /dev/sdb1:0-999

the part of a specific LV present within a range of physical extents can also be picked out and moved:

pvmove -n lvol1 /dev/sdb1:1000-1999 /dev/sdc1

πŸ‘‘ SEE ALSO πŸ‘‘

lvm(8), lvm.conf(5), lvmconfig(8), lvmdevices(8),

pvchange(8), pvck(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), vgimportclone(8), vgimportdevices(8), vgmerge(8), vgmknodes(8), vgreduce(8), vgremove(8), vgrename(8), vgs(8), vgscan(8), vgsplit(8),

lvcreate(8), lvchange(8), lvconvert(8), lvdisplay(8), lvextend(8), lvreduce(8), lvremove(8), lvrename(8), lvresize(8), lvs(8), lvscan(8),

lvm-fullreport(8), lvm-lvpoll(8), blkdeactivate(8), lvmdump(8),

dmeventd(8), lvmpolld(8), lvmlockd(8), lvmlockctl(8), lvmdbusd(8), fsadm(8),

lvmsystemid(7), lvmreport(7), lvmcache(7), lvmraid(7), lvmthin(7), lvmvdo(7), lvmautoactivation(7)


that's the whole page bestie, you ate it up fr fr πŸ’– this lil manual was brought to you by Red Hat, Inc., it's LVM TOOLS 2.03.44(2) from 2026-10-27, and you found it under PVMOVE(8). go move some extents, you main character πŸ¦‹πŸ’…βœ¨

πŸ“¦ where this page comes from