Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux
1
fork

Configure Feed

Select the types of activity you want to include in your feed.

xfs: support reserved blocks for the rt extent counter

The zoned space allocator will need reserved RT extents for garbage
collection and zeroing of partial blocks. Move the resblks related
fields into the freecounter array so that they can be used for all
counters.

Co-developed-by: Hans Holmberg <hans.holmberg@wdc.com>
Signed-off-by: Hans Holmberg <hans.holmberg@wdc.com>
Signed-off-by: Christoph Hellwig <hch@lst.de>
Reviewed-by: "Darrick J. Wong" <djwong@kernel.org>

+91 -62
+1 -1
fs/xfs/scrub/fscounters.c
··· 350 350 * The global incore space reservation is taken from the incore 351 351 * counters, so leave that out of the computation. 352 352 */ 353 - fsc->fdblocks -= mp->m_resblks_avail; 353 + fsc->fdblocks -= mp->m_free[XC_FREE_BLOCKS].res_avail; 354 354 355 355 /* 356 356 * Delayed allocation reservations are taken out of the incore counters
+14 -11
fs/xfs/xfs_fsops.c
··· 366 366 int 367 367 xfs_reserve_blocks( 368 368 struct xfs_mount *mp, 369 + enum xfs_free_counter ctr, 369 370 uint64_t request) 370 371 { 371 372 int64_t lcounter, delta; 372 373 int64_t fdblks_delta = 0; 373 374 int64_t free; 374 375 int error = 0; 376 + 377 + ASSERT(ctr < XC_FREE_NR); 375 378 376 379 /* 377 380 * With per-cpu counters, this becomes an interesting problem. we need ··· 394 391 * counters directly since we shouldn't have any problems unreserving 395 392 * space. 396 393 */ 397 - if (mp->m_resblks > request) { 398 - lcounter = mp->m_resblks_avail - request; 394 + if (mp->m_free[ctr].res_total > request) { 395 + lcounter = mp->m_free[ctr].res_avail - request; 399 396 if (lcounter > 0) { /* release unused blocks */ 400 397 fdblks_delta = lcounter; 401 - mp->m_resblks_avail -= lcounter; 398 + mp->m_free[ctr].res_avail -= lcounter; 402 399 } 403 - mp->m_resblks = request; 400 + mp->m_free[ctr].res_total = request; 404 401 if (fdblks_delta) { 405 402 spin_unlock(&mp->m_sb_lock); 406 - xfs_add_fdblocks(mp, fdblks_delta); 403 + xfs_add_freecounter(mp, ctr, fdblks_delta); 407 404 spin_lock(&mp->m_sb_lock); 408 405 } 409 406 ··· 422 419 * space to fill it because mod_fdblocks will refill an undersized 423 420 * reserve when it can. 424 421 */ 425 - free = xfs_sum_freecounter_raw(mp, XC_FREE_BLOCKS) - 426 - xfs_freecounter_unavailable(mp, XC_FREE_BLOCKS); 427 - delta = request - mp->m_resblks; 428 - mp->m_resblks = request; 422 + free = xfs_sum_freecounter_raw(mp, ctr) - 423 + xfs_freecounter_unavailable(mp, ctr); 424 + delta = request - mp->m_free[ctr].res_total; 425 + mp->m_free[ctr].res_total = request; 429 426 if (delta > 0 && free > 0) { 430 427 /* 431 428 * We'll either succeed in getting space from the free block ··· 439 436 */ 440 437 fdblks_delta = min(free, delta); 441 438 spin_unlock(&mp->m_sb_lock); 442 - error = xfs_dec_fdblocks(mp, fdblks_delta, 0); 439 + error = xfs_dec_freecounter(mp, ctr, fdblks_delta, 0); 443 440 if (!error) 444 - xfs_add_fdblocks(mp, fdblks_delta); 441 + xfs_add_freecounter(mp, ctr, fdblks_delta); 445 442 spin_lock(&mp->m_sb_lock); 446 443 } 447 444 out:
+2 -1
fs/xfs/xfs_fsops.h
··· 8 8 9 9 int xfs_growfs_data(struct xfs_mount *mp, struct xfs_growfs_data *in); 10 10 int xfs_growfs_log(struct xfs_mount *mp, struct xfs_growfs_log *in); 11 - int xfs_reserve_blocks(struct xfs_mount *mp, uint64_t request); 11 + int xfs_reserve_blocks(struct xfs_mount *mp, enum xfs_free_counter cnt, 12 + uint64_t request); 12 13 int xfs_fs_goingdown(struct xfs_mount *mp, uint32_t inflags); 13 14 14 15 int xfs_fs_reserve_ag_blocks(struct xfs_mount *mp);
+3 -3
fs/xfs/xfs_ioctl.c
··· 1131 1131 error = mnt_want_write_file(filp); 1132 1132 if (error) 1133 1133 return error; 1134 - error = xfs_reserve_blocks(mp, fsop.resblks); 1134 + error = xfs_reserve_blocks(mp, XC_FREE_BLOCKS, fsop.resblks); 1135 1135 mnt_drop_write_file(filp); 1136 1136 if (error) 1137 1137 return error; 1138 1138 } 1139 1139 1140 1140 spin_lock(&mp->m_sb_lock); 1141 - fsop.resblks = mp->m_resblks; 1142 - fsop.resblks_avail = mp->m_resblks_avail; 1141 + fsop.resblks = mp->m_free[XC_FREE_BLOCKS].res_total; 1142 + fsop.resblks_avail = mp->m_free[XC_FREE_BLOCKS].res_avail; 1143 1143 spin_unlock(&mp->m_sb_lock); 1144 1144 1145 1145 if (copy_to_user(arg, &fsop, sizeof(fsop)))
+40 -30
fs/xfs/xfs_mount.c
··· 461 461 return xfs_sync_sb(mp, false); 462 462 } 463 463 464 + static const char *const xfs_free_pool_name[] = { 465 + [XC_FREE_BLOCKS] = "free blocks", 466 + [XC_FREE_RTEXTENTS] = "free rt extents", 467 + }; 468 + 464 469 uint64_t 465 - xfs_default_resblks(xfs_mount_t *mp) 470 + xfs_default_resblks( 471 + struct xfs_mount *mp, 472 + enum xfs_free_counter ctr) 466 473 { 467 474 uint64_t resblks; 475 + 476 + if (ctr == XC_FREE_RTEXTENTS) 477 + return 0; 468 478 469 479 /* 470 480 * We default to 5% or 8192 fsbs of space reserved, whichever is ··· 688 678 uint quotamount = 0; 689 679 uint quotaflags = 0; 690 680 int error = 0; 681 + int i; 691 682 692 683 xfs_sb_mount_common(mp, sbp); 693 684 ··· 1057 1046 * privileged transactions. This is needed so that transaction 1058 1047 * space required for critical operations can dip into this pool 1059 1048 * when at ENOSPC. This is needed for operations like create with 1060 - * attr, unwritten extent conversion at ENOSPC, etc. Data allocations 1061 - * are not allowed to use this reserved space. 1049 + * attr, unwritten extent conversion at ENOSPC, garbage collection 1050 + * etc. Data allocations are not allowed to use this reserved space. 1062 1051 * 1063 1052 * This may drive us straight to ENOSPC on mount, but that implies 1064 1053 * we were already there on the last unmount. Warn if this occurs. 1065 1054 */ 1066 1055 if (!xfs_is_readonly(mp)) { 1067 - error = xfs_reserve_blocks(mp, xfs_default_resblks(mp)); 1068 - if (error) 1069 - xfs_warn(mp, 1070 - "Unable to allocate reserve blocks. Continuing without reserve pool."); 1056 + for (i = 0; i < XC_FREE_NR; i++) { 1057 + error = xfs_reserve_blocks(mp, i, 1058 + xfs_default_resblks(mp, i)); 1059 + if (error) 1060 + xfs_warn(mp, 1061 + "Unable to allocate reserve blocks. Continuing without reserve pool for %s.", 1062 + xfs_free_pool_name[i]); 1063 + } 1071 1064 1072 1065 /* Reserve AG blocks for future btree expansion. */ 1073 1066 error = xfs_fs_reserve_ag_blocks(mp); ··· 1188 1173 * we only every apply deltas to the superblock and hence the incore 1189 1174 * value does not matter.... 1190 1175 */ 1191 - error = xfs_reserve_blocks(mp, 0); 1176 + error = xfs_reserve_blocks(mp, XC_FREE_BLOCKS, 0); 1192 1177 if (error) 1193 1178 xfs_warn(mp, "Unable to free reserved block pool. " 1194 1179 "Freespace may not be correct on next mount."); ··· 1259 1244 enum xfs_free_counter ctr, 1260 1245 uint64_t delta) 1261 1246 { 1262 - bool has_resv_pool = (ctr == XC_FREE_BLOCKS); 1247 + struct xfs_freecounter *counter = &mp->m_free[ctr]; 1263 1248 uint64_t res_used; 1264 1249 1265 1250 /* 1266 1251 * If the reserve pool is depleted, put blocks back into it first. 1267 1252 * Most of the time the pool is full. 1268 1253 */ 1269 - if (!has_resv_pool || mp->m_resblks == mp->m_resblks_avail) { 1270 - percpu_counter_add(&mp->m_free[ctr].count, delta); 1254 + if (likely(counter->res_avail == counter->res_total)) { 1255 + percpu_counter_add(&counter->count, delta); 1271 1256 return; 1272 1257 } 1273 1258 1274 1259 spin_lock(&mp->m_sb_lock); 1275 - res_used = mp->m_resblks - mp->m_resblks_avail; 1260 + res_used = counter->res_total - counter->res_avail; 1276 1261 if (res_used > delta) { 1277 - mp->m_resblks_avail += delta; 1262 + counter->res_avail += delta; 1278 1263 } else { 1279 1264 delta -= res_used; 1280 - mp->m_resblks_avail = mp->m_resblks; 1281 - percpu_counter_add(&mp->m_free[ctr].count, delta); 1265 + counter->res_avail = counter->res_total; 1266 + percpu_counter_add(&counter->count, delta); 1282 1267 } 1283 1268 spin_unlock(&mp->m_sb_lock); 1284 1269 } ··· 1292 1277 uint64_t delta, 1293 1278 bool rsvd) 1294 1279 { 1295 - struct percpu_counter *counter = &mp->m_free[ctr].count; 1296 - uint64_t set_aside = 0; 1280 + struct xfs_freecounter *counter = &mp->m_free[ctr]; 1297 1281 s32 batch; 1298 - bool has_resv_pool; 1299 1282 1300 1283 ASSERT(ctr < XC_FREE_NR); 1301 - has_resv_pool = (ctr == XC_FREE_BLOCKS); 1302 - if (rsvd) 1303 - ASSERT(has_resv_pool); 1304 1284 1305 1285 /* 1306 1286 * Taking blocks away, need to be more accurate the closer we ··· 1305 1295 * then make everything serialise as we are real close to 1306 1296 * ENOSPC. 1307 1297 */ 1308 - if (__percpu_counter_compare(counter, 2 * XFS_FDBLOCKS_BATCH, 1298 + if (__percpu_counter_compare(&counter->count, 2 * XFS_FDBLOCKS_BATCH, 1309 1299 XFS_FDBLOCKS_BATCH) < 0) 1310 1300 batch = 1; 1311 1301 else ··· 1322 1312 * problems (i.e. transaction abort, pagecache discards, etc.) than 1323 1313 * slightly premature -ENOSPC. 1324 1314 */ 1325 - if (has_resv_pool) 1326 - set_aside = xfs_freecounter_unavailable(mp, ctr); 1327 - percpu_counter_add_batch(counter, -((int64_t)delta), batch); 1328 - if (__percpu_counter_compare(counter, set_aside, 1315 + percpu_counter_add_batch(&counter->count, -((int64_t)delta), batch); 1316 + if (__percpu_counter_compare(&counter->count, 1317 + xfs_freecounter_unavailable(mp, ctr), 1329 1318 XFS_FDBLOCKS_BATCH) < 0) { 1330 1319 /* 1331 1320 * Lock up the sb for dipping into reserves before releasing the 1332 1321 * space that took us to ENOSPC. 1333 1322 */ 1334 1323 spin_lock(&mp->m_sb_lock); 1335 - percpu_counter_add(counter, delta); 1324 + percpu_counter_add(&counter->count, delta); 1336 1325 if (!rsvd) 1337 1326 goto fdblocks_enospc; 1338 - if (delta > mp->m_resblks_avail) { 1339 - xfs_warn_once(mp, 1327 + if (delta > counter->res_avail) { 1328 + if (ctr == XC_FREE_BLOCKS) 1329 + xfs_warn_once(mp, 1340 1330 "Reserve blocks depleted! Consider increasing reserve pool size."); 1341 1331 goto fdblocks_enospc; 1342 1332 } 1343 - mp->m_resblks_avail -= delta; 1333 + counter->res_avail -= delta; 1344 1334 spin_unlock(&mp->m_sb_lock); 1345 1335 } 1346 1336
+11 -4
fs/xfs/xfs_mount.h
··· 108 108 struct xfs_freecounter { 109 109 /* free blocks for general use: */ 110 110 struct percpu_counter count; 111 + 112 + /* total reserved blocks: */ 113 + uint64_t res_total; 114 + 115 + /* available reserved blocks: */ 116 + uint64_t res_avail; 117 + 118 + /* reserved blks @ remount,ro: */ 119 + uint64_t res_saved; 111 120 }; 112 121 113 122 /* ··· 259 250 atomic64_t m_allocbt_blks; 260 251 261 252 struct xfs_groups m_groups[XG_TYPE_MAX]; 262 - uint64_t m_resblks; /* total reserved blocks */ 263 - uint64_t m_resblks_avail;/* available reserved blocks */ 264 - uint64_t m_resblks_save; /* reserved blks @ remount,ro */ 265 253 struct delayed_work m_reclaim_work; /* background inode reclaim */ 266 254 struct dentry *m_debugfs; /* debugfs parent */ 267 255 struct xfs_kobj m_kobj; ··· 644 638 } 645 639 646 640 extern void xfs_uuid_table_free(void); 647 - extern uint64_t xfs_default_resblks(xfs_mount_t *mp); 641 + uint64_t xfs_default_resblks(struct xfs_mount *mp, 642 + enum xfs_free_counter ctr); 648 643 extern int xfs_mountfs(xfs_mount_t *mp); 649 644 extern void xfs_unmountfs(xfs_mount_t *); 650 645
+20 -12
fs/xfs/xfs_super.c
··· 924 924 } 925 925 926 926 STATIC void 927 - xfs_save_resvblks(struct xfs_mount *mp) 927 + xfs_save_resvblks( 928 + struct xfs_mount *mp) 928 929 { 929 - mp->m_resblks_save = mp->m_resblks; 930 - xfs_reserve_blocks(mp, 0); 930 + enum xfs_free_counter i; 931 + 932 + for (i = 0; i < XC_FREE_NR; i++) { 933 + mp->m_free[i].res_saved = mp->m_free[i].res_total; 934 + xfs_reserve_blocks(mp, i, 0); 935 + } 931 936 } 932 937 933 938 STATIC void 934 - xfs_restore_resvblks(struct xfs_mount *mp) 939 + xfs_restore_resvblks( 940 + struct xfs_mount *mp) 935 941 { 936 - uint64_t resblks; 942 + uint64_t resblks; 943 + enum xfs_free_counter i; 937 944 938 - if (mp->m_resblks_save) { 939 - resblks = mp->m_resblks_save; 940 - mp->m_resblks_save = 0; 941 - } else 942 - resblks = xfs_default_resblks(mp); 943 - 944 - xfs_reserve_blocks(mp, resblks); 945 + for (i = 0; i < XC_FREE_NR; i++) { 946 + if (mp->m_free[i].res_saved) { 947 + resblks = mp->m_free[i].res_saved; 948 + mp->m_free[i].res_saved = 0; 949 + } else 950 + resblks = xfs_default_resblks(mp, i); 951 + xfs_reserve_blocks(mp, i, resblks); 952 + } 945 953 } 946 954 947 955 /*