NetBSD-Bugs archive

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

Re: kern/60286: zfs sparse zvol reports wrong volume size



The following reply was made to PR kern/60286; it has been noted by GNATS.

From: mlelstv%serpens.de@localhost (Michael van Elst)
To: gnats-bugs%netbsd.org@localhost
Cc: 
Subject: Re: kern/60286: zfs sparse zvol reports wrong volume size
Date: Fri, 22 May 2026 21:56:25 -0000 (UTC)

 gnats-admin%NetBSD.org@localhost ("nervoso%k1.com.br@localhost via gnats") writes:
 
 ># 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).
 
 DIOCGWEDGEINFO uses the sector size as units for dkw_offset
 and dkw_size. You need to query the sector size of the wedge
 parent device to get information in bytes.
 
 
 Have a look at what the dk driver does. Internally it
 stores the data that you can read as dkw_offset/dkw_size
 as sc_offset/sc_size (dkwedge_size reads the value with locking).
 
         p_offset = sc->sc_offset << sc->sc_parent->dk_blkshift;
         p_size = dkwedge_size(sc) << sc->sc_parent->dk_blkshift;
 
 -> the data is transformed into DEV_BSIZE coordinates by adjusting
    them with dk_blkshift of the parent device. dk_blkshift is how
    many bits you need to shift left to get to DEV_BSIZE units, a
    disk with 4k sectors would have a dk_blkshift value of 12-9 = 3.
 
         /* Make sure it's in-range. */
         if (bounds_check_with_mediasize(bp, DEV_BSIZE, p_size) <= 0)
                 goto done;
 
 -> Now the DEV_BSIZE units are validated
 
         /* Translate it to the parent's raw LBA. */
         bp->b_rawblkno = bp->b_blkno + p_offset;
 
 -> And the actual block inside the wedge is addressed.
 
 
 >  QEMU and other userland tools read dkw_size
 
 There are surely programs that do things incorrectly. And
 yes, I just looked at qemu, it's also doing things wrong
 by multipling dkw_size with a constant 512.
 
 A zvol of 1G returns:
 
 #zfs list
 NAME         USED  AVAIL  REFER  MOUNTPOINT
 tank        3.45T  10.6T  2.16T  /tank
 tank/myvol  1.03G  10.6T    56K  -
 
 #dkctl /dev/zvol/rdsk/tank/myvol getwedgeinfo
 tank/myvol at ZFS: 
 tank/myvol: 262144 blocks at 0, type: ffs
 
 #dkctl /dev/zvol/rdsk/tank/myvol getgeometry
 /dev/zvol/rdsk/tank/myvol: 1073741824 bytes in 262144 blocks of 4096 bytes
 



Home | Main Index | Thread Index | Old Index