NetBSD-Bugs archive

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index][Old Index]

kern/60286: zfs sparse zvol reports wrong volume size



>Number:         60286
>Category:       kern
>Synopsis:       zfs sparse zvol reports wrong volume size
>Confidential:   no
>Severity:       serious
>Priority:       medium
>Responsible:    kern-bug-people
>State:          open
>Class:          sw-bug
>Submitter-Id:   net
>Arrival-Date:   Fri May 22 15:15:00 +0000 2026
>Originator:     sergio lenzi
>Release:        10.1_STABLE
>Organization:
k1 sistemas
>Environment:
NetBSD desktop2.lenzicasa 10.1_STABLE NetBSD 10.1_STABLE (LZT_2048_USERS) #1: Fri May  1 15:07:14 -03 2026  NetBSD@lztdev.lenzicasa:/home/NetBSD/BUILD/10/amd64/OBJ/sys/arch/amd64/compile/GENERIC amd64
>Description:
# Fix zvol DIOCGWEDGEINFO reporting wrong disk size to userland (QEMU)
#     
# Bug: dkw_size in DIOCGWEDGEINFO is set from dg_secperunit, which counts
# sectors in dg_secsize units (typically 4096 bytes when spa_max_ashift=12).
# However, dkw_size is defined as "size of wedge in blocks" where blocks
# are DEV_BSIZE (512 bytes).  QEMU and other userland tools read dkw_size
# and multiply by 512 to get the device size in bytes, resulting in a
# device that appears 1/8th its actual size on pools with ashift=12.
#     
# Example: a 1TB zvol reports as 128GB, a 2TB zvol reports as 256GB.
#    
# Fix: convert dg_secperunit from dg_secsize sectors to DEV_BSIZE blocks
# by multiplying by (dg_secsize / DEV_BSIZE).
#    
# Tested on NetBSD 10.1_STABLE with QEMU 10.2.2 and ZFS pool ashift=1
>How-To-Repeat:
create a sparse zvol of 2TB buit qemu only sees 128G
>Fix:
# Fix zvol DIOCGWEDGEINFO reporting wrong disk size to userland (QEMU)
#
# Bug: dkw_size in DIOCGWEDGEINFO is set from dg_secperunit, which counts
# sectors in dg_secsize units (typically 4096 bytes when spa_max_ashift=12).
# However, dkw_size is defined as "size of wedge in blocks" where blocks
# are DEV_BSIZE (512 bytes).  QEMU and other userland tools read dkw_size
# and multiply by 512 to get the device size in bytes, resulting in a
# device that appears 1/8th its actual size on pools with ashift=12.
#
# Example: a 1TB zvol reports as 128GB, a 2TB zvol reports as 256GB.
#
# Fix: convert dg_secperunit from dg_secsize sectors to DEV_BSIZE blocks
# by multiplying by (dg_secsize / DEV_BSIZE).
#
# Tested on NetBSD 10.1_STABLE with QEMU 10.2.2 and ZFS pool ashift=12.

--- usr/src/external/cddl/osnet/dist/uts/common/fs/zfs/zvol.c.orig      2026-05-22 11:10:15.900492779 -0300
+++ usr/src/external/cddl/osnet/dist/uts/common/fs/zfs/zvol.c   2026-05-22 11:10:28.101264922 -0300
@@ -3621,7 +3621,13 @@
                strlcpy(dkw->dkw_parent, "ZFS", sizeof(dkw->dkw_parent));

                dkw->dkw_offset = 0;
-               dkw->dkw_size = dg->dg_secperunit;
+               /*
+                * dkw_size is in DEV_BSIZE (512) blocks, but dg_secperunit
+                * counts in dg_secsize blocks (which may be 4096 or larger
+                * depending on the pool's ashift).  Convert to DEV_BSIZE.
+                */
+               dkw->dkw_size = dg->dg_secperunit *
+                   (dg->dg_secsize / DEV_BSIZE);
                strcpy(dkw->dkw_ptype, DKW_PTYPE_FFS);

                break;
~




Home | Main Index | Thread Index | Old Index