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.

zloop: forget write cache on force removal

Add a new options that causes zloop to truncate the zone files to the
write pointer value recorded at the last cache flush to simulate
unclean shutdowns.

Signed-off-by: Christoph Hellwig <hch@lst.de>
Reviewed-by: Bart Van Assche <bvanassche@acm.org>
Reviewed-by: Damien Le Moal <dlemoal@kernel.org>
Reviewed-by: Martin K. Petersen <martin.petersen@oracle.com>
Link: https://patch.msgid.link/20260323071156.2940772-3-hch@lst.de
Signed-off-by: Jens Axboe <axboe@kernel.dk>

authored by

Christoph Hellwig and committed by
Jens Axboe
829def1e eff8d165

+102
+5
Documentation/admin-guide/blockdev/zoned_loop.rst
··· 104 104 (extents), as when enabled, this can significantly reduce 105 105 the number of data extents needed to for a file data 106 106 mapping. 107 + discard_write_cache Discard all data that was not explicitly persisted using a 108 + flush operation when the device is removed by truncating 109 + each zone file to the size recorded during the last flush 110 + operation. This simulates power fail events where 111 + uncommitted data is lost. 107 112 =================== ========================================================= 108 113 109 114 3) Deleting a Zoned Device
+97
drivers/block/zloop.c
··· 17 17 #include <linux/mutex.h> 18 18 #include <linux/parser.h> 19 19 #include <linux/seq_file.h> 20 + #include <linux/xattr.h> 20 21 21 22 /* 22 23 * Options for adding (and removing) a device. ··· 35 34 ZLOOP_OPT_BUFFERED_IO = (1 << 8), 36 35 ZLOOP_OPT_ZONE_APPEND = (1 << 9), 37 36 ZLOOP_OPT_ORDERED_ZONE_APPEND = (1 << 10), 37 + ZLOOP_OPT_DISCARD_WRITE_CACHE = (1 << 11), 38 38 }; 39 39 40 40 static const match_table_t zloop_opt_tokens = { ··· 50 48 { ZLOOP_OPT_BUFFERED_IO, "buffered_io" }, 51 49 { ZLOOP_OPT_ZONE_APPEND, "zone_append=%u" }, 52 50 { ZLOOP_OPT_ORDERED_ZONE_APPEND, "ordered_zone_append" }, 51 + { ZLOOP_OPT_DISCARD_WRITE_CACHE, "discard_write_cache" }, 53 52 { ZLOOP_OPT_ERR, NULL } 54 53 }; 55 54 ··· 82 79 bool buffered_io; 83 80 bool zone_append; 84 81 bool ordered_zone_append; 82 + bool discard_write_cache; 85 83 }; 86 84 87 85 /* ··· 123 119 bool buffered_io; 124 120 bool zone_append; 125 121 bool ordered_zone_append; 122 + bool discard_write_cache; 126 123 127 124 const char *base_dir; 128 125 struct file *data_dir; ··· 555 550 zloop_put_cmd(cmd); 556 551 } 557 552 553 + static inline bool zloop_zone_is_active(struct zloop_zone *zone) 554 + { 555 + switch (zone->cond) { 556 + case BLK_ZONE_COND_EXP_OPEN: 557 + case BLK_ZONE_COND_IMP_OPEN: 558 + case BLK_ZONE_COND_CLOSED: 559 + return true; 560 + default: 561 + return false; 562 + } 563 + } 564 + 565 + static int zloop_record_safe_wps(struct zloop_device *zlo) 566 + { 567 + unsigned int i; 568 + int ret; 569 + 570 + for (i = 0; i < zlo->nr_zones; i++) { 571 + struct zloop_zone *zone = &zlo->zones[i]; 572 + struct file *file = zone->file; 573 + 574 + if (!zloop_zone_is_active(zone)) 575 + continue; 576 + ret = vfs_setxattr(file_mnt_idmap(file), file_dentry(file), 577 + "user.zloop.wp", &zone->wp, sizeof(zone->wp), 0); 578 + if (ret) { 579 + pr_err("%pg: failed to record write pointer (%d)\n", 580 + zlo->disk->part0, ret); 581 + return ret; 582 + } 583 + } 584 + 585 + return 0; 586 + } 587 + 558 588 /* 559 589 * Sync the entire FS containing the zone files instead of walking all files. 560 590 */ ··· 597 557 { 598 558 struct super_block *sb = file_inode(zlo->data_dir)->i_sb; 599 559 int ret; 560 + 561 + if (zlo->discard_write_cache) { 562 + ret = zloop_record_safe_wps(zlo); 563 + if (ret) 564 + return ret; 565 + } 600 566 601 567 down_read(&sb->s_umount); 602 568 ret = sync_filesystem(sb); ··· 1100 1054 zlo->zone_append = opts->zone_append; 1101 1055 if (zlo->zone_append) 1102 1056 zlo->ordered_zone_append = opts->ordered_zone_append; 1057 + zlo->discard_write_cache = opts->discard_write_cache; 1103 1058 1104 1059 zlo->workqueue = alloc_workqueue("zloop%d", WQ_UNBOUND | WQ_FREEZABLE, 1105 1060 opts->nr_queues * opts->queue_depth, zlo->id); ··· 1223 1176 return ret; 1224 1177 } 1225 1178 1179 + static void zloop_truncate(struct file *file, loff_t pos) 1180 + { 1181 + struct mnt_idmap *idmap = file_mnt_idmap(file); 1182 + struct dentry *dentry = file_dentry(file); 1183 + struct iattr newattrs; 1184 + 1185 + newattrs.ia_size = pos; 1186 + newattrs.ia_valid = ATTR_SIZE; 1187 + 1188 + inode_lock(dentry->d_inode); 1189 + notify_change(idmap, dentry, &newattrs, NULL); 1190 + inode_unlock(dentry->d_inode); 1191 + } 1192 + 1193 + static void zloop_forget_cache(struct zloop_device *zlo) 1194 + { 1195 + unsigned int i; 1196 + int ret; 1197 + 1198 + pr_info("%pg: discarding volatile write cache\n", zlo->disk->part0); 1199 + 1200 + for (i = 0; i < zlo->nr_zones; i++) { 1201 + struct zloop_zone *zone = &zlo->zones[i]; 1202 + struct file *file = zone->file; 1203 + sector_t old_wp; 1204 + 1205 + if (!zloop_zone_is_active(zone)) 1206 + continue; 1207 + 1208 + ret = vfs_getxattr(file_mnt_idmap(file), file_dentry(file), 1209 + "user.zloop.wp", &old_wp, sizeof(old_wp)); 1210 + if (ret == -ENODATA) { 1211 + old_wp = 0; 1212 + } else if (ret != sizeof(old_wp)) { 1213 + pr_err("%pg: failed to retrieve write pointer (%d)\n", 1214 + zlo->disk->part0, ret); 1215 + continue; 1216 + } 1217 + if (old_wp < zone->wp) 1218 + zloop_truncate(file, old_wp); 1219 + } 1220 + } 1221 + 1226 1222 static int zloop_ctl_remove(struct zloop_options *opts) 1227 1223 { 1228 1224 struct zloop_device *zlo; ··· 1300 1210 return ret; 1301 1211 1302 1212 del_gendisk(zlo->disk); 1213 + 1214 + if (zlo->discard_write_cache) 1215 + zloop_forget_cache(zlo); 1216 + 1303 1217 put_disk(zlo->disk); 1304 1218 1305 1219 pr_info("Removed device %d\n", opts->id); ··· 1454 1360 break; 1455 1361 case ZLOOP_OPT_ORDERED_ZONE_APPEND: 1456 1362 opts->ordered_zone_append = true; 1363 + break; 1364 + case ZLOOP_OPT_DISCARD_WRITE_CACHE: 1365 + opts->discard_write_cache = true; 1457 1366 break; 1458 1367 case ZLOOP_OPT_ERR: 1459 1368 default: