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.

Merge tag 'for-6.12-rc2-tag' of git://git.kernel.org/pub/scm/linux/kernel/git/kdave/linux

Pull btrfs fixes from David Sterba:

- update fstrim loop and add more cancellation points, fix reported
delayed or blocked suspend if there's a huge chunk queued

- fix error handling in recent qgroup xarray conversion

- in zoned mode, fix warning printing device path without RCU
protection

- again fix invalid extent xarray state (6252690f7e1b), lost due to
refactoring

* tag 'for-6.12-rc2-tag' of git://git.kernel.org/pub/scm/linux/kernel/git/kdave/linux:
btrfs: fix clear_dirty and writeback ordering in submit_one_sector()
btrfs: zoned: fix missing RCU locking in error message when loading zone info
btrfs: fix missing error handling when adding delayed ref with qgroups enabled
btrfs: add cancellation points to trim loops
btrfs: split remaining space to discard in chunks

+76 -24
+33 -9
fs/btrfs/delayed-ref.c
··· 840 840 * helper function to actually insert a head node into the rbtree. 841 841 * this does all the dirty work in terms of maintaining the correct 842 842 * overall modification count. 843 + * 844 + * Returns an error pointer in case of an error. 843 845 */ 844 846 static noinline struct btrfs_delayed_ref_head * 845 847 add_delayed_ref_head(struct btrfs_trans_handle *trans, ··· 864 862 if (ret) { 865 863 /* Clean up if insertion fails or item exists. */ 866 864 xa_release(&delayed_refs->dirty_extents, qrecord->bytenr); 865 + /* Caller responsible for freeing qrecord on error. */ 866 + if (ret < 0) 867 + return ERR_PTR(ret); 867 868 kfree(qrecord); 868 869 } else { 869 870 qrecord_inserted = true; ··· 1005 1000 struct btrfs_fs_info *fs_info = trans->fs_info; 1006 1001 struct btrfs_delayed_ref_node *node; 1007 1002 struct btrfs_delayed_ref_head *head_ref; 1003 + struct btrfs_delayed_ref_head *new_head_ref; 1008 1004 struct btrfs_delayed_ref_root *delayed_refs; 1009 1005 struct btrfs_qgroup_extent_record *record = NULL; 1010 1006 bool qrecord_inserted; 1011 1007 int action = generic_ref->action; 1012 1008 bool merged; 1009 + int ret; 1013 1010 1014 1011 node = kmem_cache_alloc(btrfs_delayed_ref_node_cachep, GFP_NOFS); 1015 1012 if (!node) 1016 1013 return -ENOMEM; 1017 1014 1018 1015 head_ref = kmem_cache_alloc(btrfs_delayed_ref_head_cachep, GFP_NOFS); 1019 - if (!head_ref) 1016 + if (!head_ref) { 1017 + ret = -ENOMEM; 1020 1018 goto free_node; 1019 + } 1021 1020 1022 1021 if (btrfs_qgroup_full_accounting(fs_info) && !generic_ref->skip_qgroup) { 1023 1022 record = kzalloc(sizeof(*record), GFP_NOFS); 1024 - if (!record) 1023 + if (!record) { 1024 + ret = -ENOMEM; 1025 1025 goto free_head_ref; 1026 + } 1026 1027 if (xa_reserve(&trans->transaction->delayed_refs.dirty_extents, 1027 - generic_ref->bytenr, GFP_NOFS)) 1028 + generic_ref->bytenr, GFP_NOFS)) { 1029 + ret = -ENOMEM; 1028 1030 goto free_record; 1031 + } 1029 1032 } 1030 1033 1031 1034 init_delayed_ref_common(fs_info, node, generic_ref); ··· 1047 1034 * insert both the head node and the new ref without dropping 1048 1035 * the spin lock 1049 1036 */ 1050 - head_ref = add_delayed_ref_head(trans, head_ref, record, 1051 - action, &qrecord_inserted); 1037 + new_head_ref = add_delayed_ref_head(trans, head_ref, record, 1038 + action, &qrecord_inserted); 1039 + if (IS_ERR(new_head_ref)) { 1040 + spin_unlock(&delayed_refs->lock); 1041 + ret = PTR_ERR(new_head_ref); 1042 + goto free_record; 1043 + } 1044 + head_ref = new_head_ref; 1052 1045 1053 1046 merged = insert_delayed_ref(trans, head_ref, node); 1054 1047 spin_unlock(&delayed_refs->lock); ··· 1082 1063 kmem_cache_free(btrfs_delayed_ref_head_cachep, head_ref); 1083 1064 free_node: 1084 1065 kmem_cache_free(btrfs_delayed_ref_node_cachep, node); 1085 - return -ENOMEM; 1066 + return ret; 1086 1067 } 1087 1068 1088 1069 /* ··· 1113 1094 struct btrfs_delayed_extent_op *extent_op) 1114 1095 { 1115 1096 struct btrfs_delayed_ref_head *head_ref; 1097 + struct btrfs_delayed_ref_head *head_ref_ret; 1116 1098 struct btrfs_delayed_ref_root *delayed_refs; 1117 1099 struct btrfs_ref generic_ref = { 1118 1100 .type = BTRFS_REF_METADATA, ··· 1133 1113 delayed_refs = &trans->transaction->delayed_refs; 1134 1114 spin_lock(&delayed_refs->lock); 1135 1115 1136 - add_delayed_ref_head(trans, head_ref, NULL, BTRFS_UPDATE_DELAYED_HEAD, 1137 - NULL); 1138 - 1116 + head_ref_ret = add_delayed_ref_head(trans, head_ref, NULL, 1117 + BTRFS_UPDATE_DELAYED_HEAD, NULL); 1139 1118 spin_unlock(&delayed_refs->lock); 1119 + 1120 + if (IS_ERR(head_ref_ret)) { 1121 + kmem_cache_free(btrfs_delayed_ref_head_cachep, head_ref); 1122 + return PTR_ERR(head_ref_ret); 1123 + } 1140 1124 1141 1125 /* 1142 1126 * Need to update the delayed_refs_rsv with any changes we may have
+21 -5
fs/btrfs/extent-tree.c
··· 1300 1300 bytes_left = end - start; 1301 1301 } 1302 1302 1303 - if (bytes_left) { 1303 + while (bytes_left) { 1304 + u64 bytes_to_discard = min(BTRFS_MAX_DISCARD_CHUNK_SIZE, bytes_left); 1305 + 1304 1306 ret = blkdev_issue_discard(bdev, start >> SECTOR_SHIFT, 1305 - bytes_left >> SECTOR_SHIFT, 1307 + bytes_to_discard >> SECTOR_SHIFT, 1306 1308 GFP_NOFS); 1307 - if (!ret) 1308 - *discarded_bytes += bytes_left; 1309 + 1310 + if (ret) { 1311 + if (ret != -EOPNOTSUPP) 1312 + break; 1313 + continue; 1314 + } 1315 + 1316 + start += bytes_to_discard; 1317 + bytes_left -= bytes_to_discard; 1318 + *discarded_bytes += bytes_to_discard; 1319 + 1320 + if (btrfs_trim_interrupted()) { 1321 + ret = -ERESTARTSYS; 1322 + break; 1323 + } 1309 1324 } 1325 + 1310 1326 return ret; 1311 1327 } 1312 1328 ··· 6475 6459 start += len; 6476 6460 *trimmed += bytes; 6477 6461 6478 - if (fatal_signal_pending(current)) { 6462 + if (btrfs_trim_interrupted()) { 6479 6463 ret = -ERESTARTSYS; 6480 6464 break; 6481 6465 }
+7 -7
fs/btrfs/extent_io.c
··· 1306 1306 free_extent_map(em); 1307 1307 em = NULL; 1308 1308 1309 + /* 1310 + * Although the PageDirty bit is cleared before entering this 1311 + * function, subpage dirty bit is not cleared. 1312 + * So clear subpage dirty bit here so next time we won't submit 1313 + * a folio for a range already written to disk. 1314 + */ 1315 + btrfs_folio_clear_dirty(fs_info, folio, filepos, sectorsize); 1309 1316 btrfs_set_range_writeback(inode, filepos, filepos + sectorsize - 1); 1310 1317 /* 1311 1318 * Above call should set the whole folio with writeback flag, even ··· 1322 1315 */ 1323 1316 ASSERT(folio_test_writeback(folio)); 1324 1317 1325 - /* 1326 - * Although the PageDirty bit is cleared before entering this 1327 - * function, subpage dirty bit is not cleared. 1328 - * So clear subpage dirty bit here so next time we won't submit 1329 - * folio for range already written to disk. 1330 - */ 1331 - btrfs_folio_clear_dirty(fs_info, folio, filepos, sectorsize); 1332 1318 submit_extent_folio(bio_ctrl, disk_bytenr, folio, 1333 1319 sectorsize, filepos - folio_pos(folio)); 1334 1320 return 0;
+2 -2
fs/btrfs/free-space-cache.c
··· 3809 3809 if (async && *total_trimmed) 3810 3810 break; 3811 3811 3812 - if (fatal_signal_pending(current)) { 3812 + if (btrfs_trim_interrupted()) { 3813 3813 ret = -ERESTARTSYS; 3814 3814 break; 3815 3815 } ··· 4000 4000 } 4001 4001 block_group->discard_cursor = start; 4002 4002 4003 - if (fatal_signal_pending(current)) { 4003 + if (btrfs_trim_interrupted()) { 4004 4004 if (start != offset) 4005 4005 reset_trimming_bitmap(ctl, offset); 4006 4006 ret = -ERESTARTSYS;
+6
fs/btrfs/free-space-cache.h
··· 10 10 #include <linux/list.h> 11 11 #include <linux/spinlock.h> 12 12 #include <linux/mutex.h> 13 + #include <linux/freezer.h> 13 14 #include "fs.h" 14 15 15 16 struct inode; ··· 55 54 struct btrfs_free_space *info) 56 55 { 57 56 return (info->trim_state == BTRFS_TRIM_STATE_TRIMMING); 57 + } 58 + 59 + static inline bool btrfs_trim_interrupted(void) 60 + { 61 + return fatal_signal_pending(current) || freezing(current); 58 62 } 59 63 60 64 /*
+6
fs/btrfs/volumes.h
··· 30 30 31 31 #define BTRFS_MAX_DATA_CHUNK_SIZE (10ULL * SZ_1G) 32 32 33 + /* 34 + * Arbitratry maximum size of one discard request to limit potentially long time 35 + * spent in blkdev_issue_discard(). 36 + */ 37 + #define BTRFS_MAX_DISCARD_CHUNK_SIZE (SZ_1G) 38 + 33 39 extern struct mutex uuid_mutex; 34 40 35 41 #define BTRFS_STRIPE_LEN SZ_64K
+1 -1
fs/btrfs/zoned.c
··· 1340 1340 switch (zone.cond) { 1341 1341 case BLK_ZONE_COND_OFFLINE: 1342 1342 case BLK_ZONE_COND_READONLY: 1343 - btrfs_err(fs_info, 1343 + btrfs_err_in_rcu(fs_info, 1344 1344 "zoned: offline/readonly zone %llu on device %s (devid %llu)", 1345 1345 (info->physical >> device->zone_info->zone_size_shift), 1346 1346 rcu_str_deref(device->name), device->devid);