Skip to content

Commit 9f7a0e5

Browse files
committed
spa_min_alloc should be GCD, not min
Since spa_min_alloc may not be a power of 2, unlike ashifts, in the case of DRAID, we should not select the minimal value among several vdevs. Rounding to a multiple of it is unlikely to work for other vdevs. Instead, using the greatest common divisor produces smaller yet more reasonable results. Signed-off-by: Ameer Hamza <[email protected]>
1 parent ca960ce commit 9f7a0e5

File tree

4 files changed

+50
-9
lines changed

4 files changed

+50
-9
lines changed

include/sys/spa_impl.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -250,6 +250,7 @@ struct spa {
250250
uint64_t spa_min_ashift; /* of vdevs in normal class */
251251
uint64_t spa_max_ashift; /* of vdevs in normal class */
252252
uint64_t spa_min_alloc; /* of vdevs in normal class */
253+
uint64_t spa_gcd_alloc; /* of vdevs in normal class */
253254
uint64_t spa_config_guid; /* config pool guid */
254255
uint64_t spa_load_guid; /* spa_load initialized guid */
255256
uint64_t spa_last_synced_guid; /* last synced guid */

module/zfs/spa_misc.c

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -772,6 +772,7 @@ spa_add(const char *name, nvlist_t *config, const char *altroot)
772772
spa->spa_min_ashift = INT_MAX;
773773
spa->spa_max_ashift = 0;
774774
spa->spa_min_alloc = INT_MAX;
775+
spa->spa_gcd_alloc = INT_MAX;
775776

776777
/* Reset cached value */
777778
spa->spa_dedup_dspace = ~0ULL;

module/zfs/vdev.c

Lines changed: 32 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1393,6 +1393,36 @@ vdev_remove_parent(vdev_t *cvd)
13931393
vdev_free(mvd);
13941394
}
13951395

1396+
/*
1397+
* Choose GCD for spa_gcd_alloc.
1398+
*/
1399+
static uint64_t
1400+
vdev_gcd(uint64_t a, uint64_t b)
1401+
{
1402+
while (b != 0) {
1403+
uint64_t t = b;
1404+
b = a % b;
1405+
a = t;
1406+
}
1407+
return (a);
1408+
}
1409+
1410+
/*
1411+
* Set spa_min_alloc and spa_gcd_alloc.
1412+
*/
1413+
static void
1414+
vdev_spa_set_alloc(spa_t *spa, uint64_t min_alloc)
1415+
{
1416+
if (min_alloc < spa->spa_min_alloc)
1417+
spa->spa_min_alloc = min_alloc;
1418+
if (spa->spa_gcd_alloc == INT_MAX) {
1419+
spa->spa_gcd_alloc = min_alloc;
1420+
} else {
1421+
spa->spa_gcd_alloc = vdev_gcd(min_alloc,
1422+
spa->spa_gcd_alloc);
1423+
}
1424+
}
1425+
13961426
void
13971427
vdev_metaslab_group_create(vdev_t *vd)
13981428
{
@@ -1445,8 +1475,7 @@ vdev_metaslab_group_create(vdev_t *vd)
14451475
spa->spa_min_ashift = vd->vdev_ashift;
14461476

14471477
uint64_t min_alloc = vdev_get_min_alloc(vd);
1448-
if (min_alloc < spa->spa_min_alloc)
1449-
spa->spa_min_alloc = min_alloc;
1478+
vdev_spa_set_alloc(spa, min_alloc);
14501479
}
14511480
}
14521481
}
@@ -2207,8 +2236,7 @@ vdev_open(vdev_t *vd)
22072236
if (vd->vdev_top == vd && vd->vdev_ashift != 0 &&
22082237
vd->vdev_islog == 0 && vd->vdev_aux == NULL) {
22092238
uint64_t min_alloc = vdev_get_min_alloc(vd);
2210-
if (min_alloc < spa->spa_min_alloc)
2211-
spa->spa_min_alloc = min_alloc;
2239+
vdev_spa_set_alloc(spa, min_alloc);
22122240
}
22132241

22142242
/*

module/zfs/zio.c

Lines changed: 16 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1596,6 +1596,17 @@ zio_shrink(zio_t *zio, uint64_t size)
15961596
}
15971597
}
15981598

1599+
/*
1600+
* Get allocation size.
1601+
*/
1602+
static uint64_t
1603+
zio_roundup_alloc_size(spa_t *spa, uint64_t size)
1604+
{
1605+
if (size > spa->spa_min_alloc)
1606+
return (roundup(size, spa->spa_gcd_alloc));
1607+
return (spa->spa_min_alloc);
1608+
}
1609+
15991610
/*
16001611
* ==========================================================================
16011612
* Prepare to read and write logical blocks
@@ -1802,9 +1813,9 @@ zio_write_compress(zio_t *zio)
18021813
* in that we charge for the padding used to fill out
18031814
* the last sector.
18041815
*/
1805-
ASSERT3U(spa->spa_min_alloc, >=, SPA_MINBLOCKSHIFT);
1806-
size_t rounded = (size_t)roundup(psize,
1807-
spa->spa_min_alloc);
1816+
ASSERT3U(spa->spa_gcd_alloc, >=, SPA_MINBLOCKSIZE);
1817+
size_t rounded = (size_t)zio_roundup_alloc_size(spa,
1818+
psize);
18081819
if (rounded >= lsize) {
18091820
compress = ZIO_COMPRESS_OFF;
18101821
zio_buf_free(cbuf, lsize);
@@ -1847,8 +1858,8 @@ zio_write_compress(zio_t *zio)
18471858
* take this codepath because it will change the on-disk block
18481859
* and decryption will fail.
18491860
*/
1850-
size_t rounded = MIN((size_t)roundup(psize,
1851-
spa->spa_min_alloc), lsize);
1861+
size_t rounded = MIN((size_t)zio_roundup_alloc_size(spa, psize),
1862+
lsize);
18521863

18531864
if (rounded != psize) {
18541865
abd_t *cdata = abd_alloc_linear(rounded, B_TRUE);

0 commit comments

Comments
 (0)