
In modern Linux environments — especially those running SAP HANA — storage I/O performance is a critical bottleneck. A single disk simply cannot deliver the throughput that enterprise workloads demand. Striped LVM (Logical Volume Manager) solves this by distributing data across multiple physical disks in parallel, multiplying effective throughput without requiring specialized hardware.
This blog is aimed at Linux system administrators and SAP Basis engineers who need to build, manage, and safely extend striped LVM volumes. We cover the complete lifecycle — from creating the first striped LV, to extending it online using two different real-world scenarios, to understanding how XFS filesystem geometry must stay aligned with LVM stripe parameters throughout.
Why does this matter? For SAP HANA, I/O latency directly impacts query response time. A misconfigured or misaligned stripe layout leads to suboptimal I/O — and once XFS is formatted, its stripe geometry is permanent and cannot be corrected without recreating the filesystem. Getting it right from the start, and keeping it correct through every extension, is the goal of this guide.
All commands in this blog were executed live on SAP HANA test host hana1 running SUSE Linux Enterprise Server — including the mistakes, errors, and their resolutions.
It includes the following topics:
- What Is LVM Striping and Why Does It Matter
- Environment Used in This Walkthrough
- Building a Striped LV From Scratch
- How XFS and LVM Work Together
- Extending the LV — Scenario A: Resize Existing Disks (pvresize)
- Extending the LV — Scenario B: Add New Disks (vgextend)
- Scenario Comparison
- Errors Encountered and Lessons Learned
- Best Practices Summary
- Quick Reference Command Sheet
What Is LVM Striping and Why Does It Matter
Contents
- 1 What Is LVM Striping and Why Does It Matter
- 2 Environment Used in This Walkthrough
- 3 Building a Striped LV From Scratch
- 4 How XFS and LVM Work Together
- 5 Extending the LV — Scenario A: Resize Existing Disks (pvresize)
- 6 Extending the LV — Scenario B: Add New Disks (vgextend)
- 7 Scenario Comparison
- 8 Errors Encountered and Lessons Learned
- 9 Best Practices Summary
- 9.0.1 Always verify free space before extending
- 9.0.2 Use +100%FREE not 100%FREE
- 9.0.3 Match -i to the count of new free PVs, not total PVs in VG
- 9.0.4 Keep -I consistent throughout the LV lifecycle
- 9.0.5 Resize all stripe member PVs equally in Scenario A
- 9.0.6 Always run xfs_growfs after lvextend
- 9.0.7 Verify with lvdisplay -m after every extension
- 10 Quick Reference Command Sheet
- 11 Summary
- 12 Get Help and Stay Connected
When you write data to a single disk, you are limited by that one disk’s throughput. No matter how fast your CPU or how much RAM you have, the I/O ceiling is one spindle or one SSD.
Application
↓
Single disk ← bottleneck
Striping splits your data across multiple physical disks in fixed-size chunks called stripe units. Each chunk goes to a different disk, and all disks write simultaneously.
Application writes 256K
↓
LVM Striped LV (-i 4, -I 64K)
↓
Split into 4 × 64K chunks
↓
sdd → 64K | sde → 64K | sdf → 64K | sdg → 64K
(all four disks write simultaneously)
With 4 disks you get up to 4× the throughput of a single disk. For SAP HANA, where I/O latency directly impacts query performance, this is not optional — it is a design requirement.
Key Terminology
| Term | What It Means |
|---|---|
| PV (Physical Volume) | A raw disk or partition initialized for LVM |
| VG (Volume Group) | A pool combining one or more PVs |
| LV (Logical Volume) | A virtual disk carved out of a VG |
| PE (Physical Extent) | Fixed-size allocation unit on a PV (default 4 MiB) |
| LE (Logical Extent) | Corresponding unit on the LV — maps to PEs |
| Stripe unit (-I) | Size of each chunk written to one disk |
| Stripe count (-i) | Number of disks in the stripe set |
| sunit | XFS term for stripe unit, expressed in 4K filesystem blocks |
| swidth | XFS term for total stripe width = sunit × stripe count |
Environment Used in This Walkthrough
All commands in this blog were executed live on SAP HANA test host hana1. The starting disk layout was as follows:
sdd 100G } sde 100G } Four free disks — used to build the test striped LV sdf 100G } (later resized to 200G each for Scenario A) sdg 100G }
Building a Striped LV From Scratch
Step 1 — Initialize Disks as Physical Volumes
The first step is to initialize all four disks as LVM Physical Volumes. pvcreate writes LVM metadata to the start of each disk and marks it available for use in a Volume Group.
pvcreate /dev/sdd /dev/sde /dev/sdf /dev/sdg
Expected output:
Physical volume "/dev/sdd" successfully created.
Physical volume "/dev/sde" successfully created.
Physical volume "/dev/sdf" successfully created.
Physical volume "/dev/sdg" successfully created.
Step 2 — Create a Volume Group
Combine all four PVs into a single Volume Group. This pools their capacity into one logical storage container.
vgcreate test_stripe_vg /dev/sdd /dev/sde /dev/sdf /dev/sdg
Expected output:
Volume group "test_stripe_vg" successfully created
Step 3 — Create the Striped Logical Volume
Create a striped LV using all available space in the VG, with 4 stripes and a 64 KiB stripe unit:
lvcreate -n test_stripe_lv -l 100%FREE -i 4 -I 64 test_stripe_vg
| Flag | Value | Meaning |
|---|---|---|
-n |
test_stripe_lv |
Name of the LV |
-l |
100%FREE |
Use all available space in the VG |
-i |
4 |
Stripe across 4 disks |
-I |
64 |
Each stripe chunk is 64 KiB |
Step 4 — Verify the Stripe Layout
Always verify the segment map immediately after creation to confirm stripe count, stripe size, and equal PE distribution across all member PVs:
lvdisplay -m /dev/test_stripe_vg/test_stripe_lv
Expected output:
LV Size 399.98 GiB
Segments 1
Type striped
Stripes 4
Stripe size 64.00 KiB
Stripe 0: /dev/sdd PE 0 to 25598
Stripe 1: /dev/sde PE 0 to 25598
Stripe 2: /dev/sdf PE 0 to 25598
Stripe 3: /dev/sdg PE 0 to 25598
1 segment, 4 stripes, equal PE distribution — this is a healthy striped LV. Also confirm at the kernel device-mapper level:
dmsetup table
test_stripe_vg-test_stripe_lv:
0 838828032 striped 4 128 8:48 2048 8:64 2048 8:80 2048 8:96 2048
striped 4 128 confirms 4 disks with 128 sectors (64K) per stripe — exactly as specified.
Step 5 — Format With XFS (Stripe-Aware)
This is the most critical step that most guides omit. You must pass the stripe geometry to mkfs.xfs explicitly so XFS can align its internal structures to the LVM stripe layout. These values are written into the XFS superblock and are permanent.
mkfs.xfs -f -d su=64k,sw=4 /dev/test_stripe_vg/test_stripe_lv
| Flag | Value | Meaning |
|---|---|---|
su |
64k |
Stripe unit — must match -I 64 from lvcreate |
sw |
4 |
Stripe width count — must match -i 4 from lvcreate |
XFS converts and stores these in its superblock as block counts:
sunit = 64K ÷ 4K (bsize) = 16 blocks
swidth = 16 × 4 stripes = 64 blocks
Step 6 — Mount and Verify Alignment
mount /dev/test_stripe_vg/test_stripe_lv /mnt
xfs_info /mnt
Confirm the alignment values in the output:
data = bsize=4096 blocks=104853248
= sunit=16 swidth=64 blks
sunit=16 (64K) and swidth=64 (256K = 4 × 64K) confirm that XFS is now stripe-aware and will align all I/O to the LVM stripe geometry.
df -hT /mnt
/dev/mapper/test_stripe_vg-test_stripe_lv xfs 400G 441M 400G 1% /mnt
How XFS and LVM Work Together
Understanding the relationship between XFS geometry and LVM stripe layout is essential for maintaining performance through any future extension.
The I/O Flow
Application writes 256K of data
↓
XFS aligns write to sunit (64K) boundary
XFS sends full swidth (256K) chunk when possible
↓
LVM receives 256K
LVM splits into 4 × 64K pieces
↓
sdd ← 64K | sde ← 64K | sdf ← 64K | sdg ← 64K
all four disks write in parallel
Why Alignment Matters
If XFS sends an unaligned write that crosses a 64K stripe boundary, LVM must access two stripes instead of one — doubling the disk operations for a single logical write:
UNALIGNED (bad):
|--- 64K stripe ---|--- 64K stripe ---|
|-- 24K write --|
crosses boundary → 2 disk operations
ALIGNED (good):
|--- 64K stripe ---|--- 64K stripe ---|
|-- 24K write --|
stays within one stripe → 1 disk operation
Where sunit and swidth Come From
lvcreate -I 64 → stripe unit = 64K
mkfs.xfs bsize → default 4K
sunit = stripe unit ÷ bsize = 64K ÷ 4K = 16 blocks
swidth = sunit × stripe count = 16 × 4 = 64 blocks
The rule: -I controls sunit. -i controls swidth. Neither can be changed after mkfs without recreating the filesystem.
Extending the LV — Scenario A: Resize Existing Disks (pvresize)
This is the recommended approach. Each underlying disk is expanded at the hypervisor or SAN layer, and LVM is then informed of the new size using pvresize. The stripe geometry and segment layout are preserved perfectly — the LV remains a single uniform segment.
When to use: When your storage infrastructure supports online disk resize (VMware, Azure, AWS, SAN LUNs).
Pre-Resize State
Each disk was resized from 100G to 200G at the hypervisor. LVM is not yet aware of the change:
pvs
PV PSize PFree
/dev/sdd 100.00g 0
/dev/sde 100.00g 0
/dev/sdf 100.00g 0
/dev/sdg 100.00g 0
Step 1 — Scan New Disk Sizes Into LVM
Run pvresize on each member PV. This is an online operation — no unmount required.
pvresize /dev/sdd
pvresize /dev/sde
pvresize /dev/sdf
pvresize /dev/sdg
Expected output per disk:
Physical volume "/dev/sdd" changed
1 physical volume(s) resized or updated / 0 not resized
Verify the new free space:
pvs
PV PSize PFree
/dev/sdd 200.00g 100.00g
/dev/sde 200.00g 100.00g
/dev/sdf 200.00g 100.00g
/dev/sdg 200.00g 100.00g
VFree = 399.98 GiB across the VG — ready to extend.
Step 2 — Extend the LV
Important: Always use -l +100%FREE with the + prefix. Without +, LVM sets an absolute target size equal to the current VG free space — which may equal or be less than the current LV size, resulting in no growth or an error.
lvextend -l +100%FREE -i 4 -I 64 /dev/test_stripe_vg/test_stripe_lv
Size of logical volume changed from 399.98 GiB to 799.98 GiB.
Logical volume test_stripe_vg/test_stripe_lv successfully resized.
Step 3 — Grow the XFS Filesystem Online
xfs_growfs /mnt
data blocks changed from 104,853,248 to 209,711,104
XFS now uses the full 800G. No format, no downtime, no data loss.
Verify the Result
lvdisplay -m /dev/test_stripe_vg/test_stripe_lv
LV Size 799.98 GiB
Segments 1 ← still one segment
Stripes 4 ← still 4-stripe throughout
Stripe size 64.00 KiB ← unchanged
Stripe 0: /dev/sdd PE 0 to 51198
Stripe 1: /dev/sde PE 0 to 51198
Stripe 2: /dev/sdf PE 0 to 51198
Stripe 3: /dev/sdg PE 0 to 51198
xfs_info /mnt
sunit=16 swidth=64 blks ← geometry unchanged and correct
Single segment. Uniform stripe geometry. XFS alignment intact. This is the ideal outcome.
Extending the LV — Scenario B: Add New Disks (vgextend)
This approach adds brand new disks to the VG and uses them to extend the LV. It introduces additional segments to the LV, which has important implications for XFS alignment if not handled carefully.
When to use: Only when resizing existing disks at the infrastructure layer is not possible.
Step 1 — Initialize and Add New Disks
pvcreate /dev/sdh /dev/sdi
vgextend test_stripe_vg /dev/sdh /dev/sdi
Volume group "test_stripe_vg" successfully extended
VFree is now ~400G from the two new disks.
Step 2 — Extend the LV (Common Mistake)
The most common error here is using -i equal to the total PV count in the VG (6) rather than the count of PVs that actually have free space (2):
# WRONG — using total PV count
lvextend -i 6 -I 64 -l +100%FREE /dev/test_stripe_vg/test_stripe_lv
Rounding size (307194 extents) down to stripe boundary...
Size of logical volume UNCHANGED from 799.98 GiB.
LVM needs 6 PVs with free extents simultaneously to build a 6-stripe segment. Only sdh and sdi have free space. Rounding down to a 6-stripe boundary with 2 free PVs yields zero usable extents — LVM silently does nothing.
The correct approach is to set -i equal to the number of new PVs being added:
# CORRECT — -i matches the 2 new PVs
lvextend -i 2 -I 64 -l +100%FREE /dev/test_stripe_vg/test_stripe_lv
Size of logical volume changed from 799.98 GiB to 1.17 TiB.
Logical volume successfully resized.
The XFS Alignment Problem
After extension with -i 2, the LV now has two segments with different effective stripe widths:
lvdisplay -m /dev/test_stripe_vg/test_stripe_lv
Segment 1 (LE 0 to 204795):
Stripes 4
Stripe size 64.00 KiB ← swidth = 4 × 64K = 256K
Segment 2 (LE 204796 to 307193):
Stripes 2
Stripe size 64.00 KiB ← swidth = 2 × 64K = 128K
XFS was formatted with swidth=64 (4-stripe). xfs_growfs adds blocks to cover the new space, but cannot change swidth. I/O that lands in Segment 2 is misaligned relative to XFS expectations — throughput in that region is suboptimal.
How to Avoid This in Scenario B
Always add new disks in multiples of the original stripe count. If the LV was created with -i 4, add 4 new disks and extend with -i 4:
pvcreate /dev/sdh /dev/sdi /dev/sdj /dev/sdk
vgextend test_stripe_vg /dev/sdh /dev/sdi /dev/sdj /dev/sdk
lvextend -i 4 -I 64 -l +100%FREE /dev/test_stripe_vg/test_stripe_lv
xfs_growfs /mnt
Result: both segments are 4-stripe / 64K — identical geometry and consistent XFS alignment throughout.
Scenario Comparison
| Criterion | Scenario A (pvresize) | Scenario B (vgextend) |
|---|---|---|
| LV segment count | 1 (uniform) | 2 (split) |
| Stripe uniformity | 4-stripe throughout | Mixed if -i mismatched |
| XFS alignment | Always preserved | Risk of mismatch |
| Performance | Uniform across entire LV | Variable if segments differ |
| Online operation | Yes | Yes |
| Downtime required | None | None |
| Complexity | Low | Medium |
| Recommended | Yes | Only if pvresize not possible |
Errors Encountered and Lessons Learned
These are real mistakes made during the live session on hana1. Each is a trap that is easy to fall into.
Error 1 — Missing + Prefix in -l 100%FREE
lvextend -l 100%FREE /dev/test_stripe_vg/test_stripe_lv
New size (102396 extents) not larger than existing size (102400 extents).
Without +, LVM interprets the value as an absolute target size equal to current VG free space. If that target is smaller than the existing LV, nothing grows. Always use -l +100%FREE.
Error 2 — Wrong -i Count When Adding New Disks
lvextend -i 6 -I 64 -l +100%FREE /dev/test_stripe_vg/test_stripe_lv
Size of logical volume UNCHANGED.
Only 2 PVs had free space. -i 6 demanded 6. LVM rounded down to zero and did nothing — no error message. The -i flag must always equal the number of PVs that currently have free extents, not the total PV count in the VG.
Best Practices Summary
-
Always verify free space before extending
pvs # confirm PFree on all member PVs vgs # confirm VFree in the VG -
Use +100%FREE not 100%FREE
lvextend -l +100%FREE ... # ✓ adds space on top of current size lvextend -l 100%FREE ... # ✗ sets absolute target — dangerous -
Match -i to the count of new free PVs, not total PVs in VG
# Adding 2 new disks → use -i 2 lvextend -i 2 -I 64 -l +100%FREE /dev/VG/LV # Adding 4 new disks → use -i 4 lvextend -i 4 -I 64 -l +100%FREE /dev/VG/LV -
Keep -I consistent throughout the LV lifecycle
The stripe unit must never change. Use the same
-I 64on everylvextendthat was used atlvcreate. -
Resize all stripe member PVs equally in Scenario A
LVM stripes equally across all member PVs. If only 3 of 4 disks are resized, the extra space on the larger PVs is stranded at the boundary and cannot be used without
pvmove. -
Always run xfs_growfs after lvextend
lvextend ... && xfs_growfs /mountpoint -
Verify with lvdisplay -m after every extension
Confirm segment count, stripe count, and stripe size match expectations. A single segment with uniform stripe count is the healthy state.
Quick Reference Command Sheet
Build a Striped LV
pvcreate /dev/sdd /dev/sde /dev/sdf /dev/sdg
vgcreate my_vg /dev/sdd /dev/sde /dev/sdf /dev/sdg
lvcreate -n my_lv -l 100%FREE -i 4 -I 64 my_vg
mkfs.xfs -f -d su=64k,sw=4 /dev/my_vg/my_lv
mount /dev/my_vg/my_lv /mnt
Extend — Scenario A (pvresize)
pvresize /dev/sdd && pvresize /dev/sde && pvresize /dev/sdf && pvresize /dev/sdg
pvs && vgs
lvextend -l +100%FREE -i 4 -I 64 /dev/my_vg/my_lv
xfs_growfs /mnt
Extend — Scenario B (vgextend)
pvcreate /dev/sdh /dev/sdi /dev/sdj /dev/sdk
vgextend my_vg /dev/sdh /dev/sdi /dev/sdj /dev/sdk
vgs
lvextend -l +100%FREE -i 4 -I 64 /dev/my_vg/my_lv
xfs_growfs /mnt
Verify Everything
lvdisplay -m /dev/my_vg/my_lv # segment map and stripe layout
lvs -a -o +devices,stripes,stripesize # stripe summary per LV
dmsetup table # kernel device-mapper confirmation
xfs_info /mnt # confirm sunit and swidth
df -hT /mnt # filesystem size
pvs && vgs # PV and VG health
Summary
In this blog, we have explored the complete lifecycle of a striped LVM volume on Linux — from initial creation through two distinct online extension scenarios — with all commands executed and verified live on a real SAP HANA host. We have seen how XFS stripe geometry is set permanently at format time, why it must stay consistent with LVM stripe parameters through every extension, and what happens when it does not.
The key takeaways: prefer Scenario A (pvresize) wherever your infrastructure allows it — it preserves a single uniform segment and requires no special handling. If adding new disks, always match the new -i value to the count of new PVs, and add them in multiples of the original stripe count to preserve XFS alignment. And never skip xfs_growfs after any lvextend.
Get Help and Stay Connected
If you have questions about LVM striping, XFS alignment, or storage configuration for SAP HANA on SUSE Linux, reach out through the SUSE Community Forums or contact your SUSE support team. Our engineers are available to help you design and validate storage layouts that meet SAP performance requirements.
Stay updated with the latest Linux storage best practices, SAP integration guides, and SUSE technical content by following the SUSE Blog and joining our community of Linux and SAP professionals.
(Visited 1 times, 1 visits today)





