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.9-rc1-tag' of git://git.kernel.org/pub/scm/linux/kernel/git/kdave/linux

Pull btrfs fixes from David Sterba:

- fix race when reading extent buffer and 'uptodate' status is missed
by one thread (introduced in 6.5)

- do additional validation of devices using major:minor numbers

- zoned mode fixes:
- use zone-aware super block access during scrub
- fix use-after-free during device replace (found by KASAN)
- also delete zones that are 100% unusable to reclaim space

- extent unpinning fixes:
- fix extent map leak after error handling
- print correct range in error message

- error code and message updates

* tag 'for-6.9-rc1-tag' of git://git.kernel.org/pub/scm/linux/kernel/git/kdave/linux:
btrfs: fix race in read_extent_buffer_pages()
btrfs: return accurate error code on open failure in open_fs_devices()
btrfs: zoned: don't skip block groups with 100% zone unusable
btrfs: use btrfs_warn() to log message at btrfs_add_extent_mapping()
btrfs: fix message not properly printing interval when adding extent map
btrfs: fix warning messages not printing interval at unpin_extent_range()
btrfs: fix extent map leak in unexpected scenario at unpin_extent_cache()
btrfs: validate device maj:min during open
btrfs: zoned: fix use-after-free in do_zone_finish()
btrfs: zoned: use zone aware sb location for scrub

+63 -22
+2 -1
fs/btrfs/block-group.c
··· 1559 1559 * needing to allocate extents from the block group. 1560 1560 */ 1561 1561 used = btrfs_space_info_used(space_info, true); 1562 - if (space_info->total_bytes - block_group->length < used) { 1562 + if (space_info->total_bytes - block_group->length < used && 1563 + block_group->zone_unusable < block_group->length) { 1563 1564 /* 1564 1565 * Add a reference for the list, compensate for the ref 1565 1566 * drop under the "next" label for the
+13
fs/btrfs/extent_io.c
··· 4333 4333 if (test_and_set_bit(EXTENT_BUFFER_READING, &eb->bflags)) 4334 4334 goto done; 4335 4335 4336 + /* 4337 + * Between the initial test_bit(EXTENT_BUFFER_UPTODATE) and the above 4338 + * test_and_set_bit(EXTENT_BUFFER_READING), someone else could have 4339 + * started and finished reading the same eb. In this case, UPTODATE 4340 + * will now be set, and we shouldn't read it in again. 4341 + */ 4342 + if (unlikely(test_bit(EXTENT_BUFFER_UPTODATE, &eb->bflags))) { 4343 + clear_bit(EXTENT_BUFFER_READING, &eb->bflags); 4344 + smp_mb__after_atomic(); 4345 + wake_up_bit(&eb->bflags, EXTENT_BUFFER_READING); 4346 + return 0; 4347 + } 4348 + 4336 4349 clear_bit(EXTENT_BUFFER_READ_ERR, &eb->bflags); 4337 4350 eb->read_mirror = 0; 4338 4351 check_buffer_tree_ref(eb);
+8 -8
fs/btrfs/extent_map.c
··· 309 309 btrfs_warn(fs_info, 310 310 "no extent map found for inode %llu (root %lld) when unpinning extent range [%llu, %llu), generation %llu", 311 311 btrfs_ino(inode), btrfs_root_id(inode->root), 312 - start, len, gen); 312 + start, start + len, gen); 313 313 ret = -ENOENT; 314 314 goto out; 315 315 } ··· 318 318 btrfs_warn(fs_info, 319 319 "found extent map for inode %llu (root %lld) with unexpected start offset %llu when unpinning extent range [%llu, %llu), generation %llu", 320 320 btrfs_ino(inode), btrfs_root_id(inode->root), 321 - em->start, start, len, gen); 321 + em->start, start, start + len, gen); 322 322 ret = -EUCLEAN; 323 323 goto out; 324 324 } ··· 340 340 em->mod_len = em->len; 341 341 } 342 342 343 - free_extent_map(em); 344 343 out: 345 344 write_unlock(&tree->lock); 345 + free_extent_map(em); 346 346 return ret; 347 347 348 348 } ··· 629 629 */ 630 630 ret = merge_extent_mapping(em_tree, existing, 631 631 em, start); 632 - if (ret) { 632 + if (WARN_ON(ret)) { 633 633 free_extent_map(em); 634 634 *em_in = NULL; 635 - WARN_ONCE(ret, 636 - "extent map merge error existing [%llu, %llu) with em [%llu, %llu) start %llu\n", 637 - existing->start, existing->len, 638 - orig_start, orig_len, start); 635 + btrfs_warn(fs_info, 636 + "extent map merge error existing [%llu, %llu) with em [%llu, %llu) start %llu", 637 + existing->start, extent_map_end(existing), 638 + orig_start, orig_start + orig_len, start); 639 639 } 640 640 free_extent_map(existing); 641 641 }
+11 -1
fs/btrfs/scrub.c
··· 2812 2812 gen = btrfs_get_last_trans_committed(fs_info); 2813 2813 2814 2814 for (i = 0; i < BTRFS_SUPER_MIRROR_MAX; i++) { 2815 - bytenr = btrfs_sb_offset(i); 2815 + ret = btrfs_sb_log_location(scrub_dev, i, 0, &bytenr); 2816 + if (ret == -ENOENT) 2817 + break; 2818 + 2819 + if (ret) { 2820 + spin_lock(&sctx->stat_lock); 2821 + sctx->stat.super_errors++; 2822 + spin_unlock(&sctx->stat_lock); 2823 + continue; 2824 + } 2825 + 2816 2826 if (bytenr + BTRFS_SUPER_INFO_SIZE > 2817 2827 scrub_dev->commit_total_bytes) 2818 2828 break;
+22 -5
fs/btrfs/volumes.c
··· 692 692 device->bdev = file_bdev(bdev_file); 693 693 clear_bit(BTRFS_DEV_STATE_IN_FS_METADATA, &device->dev_state); 694 694 695 + if (device->devt != device->bdev->bd_dev) { 696 + btrfs_warn(NULL, 697 + "device %s maj:min changed from %d:%d to %d:%d", 698 + device->name->str, MAJOR(device->devt), 699 + MINOR(device->devt), MAJOR(device->bdev->bd_dev), 700 + MINOR(device->bdev->bd_dev)); 701 + 702 + device->devt = device->bdev->bd_dev; 703 + } 704 + 695 705 fs_devices->open_devices++; 696 706 if (test_bit(BTRFS_DEV_STATE_WRITEABLE, &device->dev_state) && 697 707 device->devid != BTRFS_DEV_REPLACE_DEVID) { ··· 1184 1174 struct btrfs_device *device; 1185 1175 struct btrfs_device *latest_dev = NULL; 1186 1176 struct btrfs_device *tmp_device; 1177 + int ret = 0; 1187 1178 1188 1179 list_for_each_entry_safe(device, tmp_device, &fs_devices->devices, 1189 1180 dev_list) { 1190 - int ret; 1181 + int ret2; 1191 1182 1192 - ret = btrfs_open_one_device(fs_devices, device, flags, holder); 1193 - if (ret == 0 && 1183 + ret2 = btrfs_open_one_device(fs_devices, device, flags, holder); 1184 + if (ret2 == 0 && 1194 1185 (!latest_dev || device->generation > latest_dev->generation)) { 1195 1186 latest_dev = device; 1196 - } else if (ret == -ENODATA) { 1187 + } else if (ret2 == -ENODATA) { 1197 1188 fs_devices->num_devices--; 1198 1189 list_del(&device->dev_list); 1199 1190 btrfs_free_device(device); 1200 1191 } 1192 + if (ret == 0 && ret2 != 0) 1193 + ret = ret2; 1201 1194 } 1202 - if (fs_devices->open_devices == 0) 1195 + 1196 + if (fs_devices->open_devices == 0) { 1197 + if (ret) 1198 + return ret; 1203 1199 return -EINVAL; 1200 + } 1204 1201 1205 1202 fs_devices->opened = 1; 1206 1203 fs_devices->latest_dev = latest_dev;
+7 -7
fs/btrfs/zoned.c
··· 1574 1574 if (!map) 1575 1575 return -EINVAL; 1576 1576 1577 - cache->physical_map = btrfs_clone_chunk_map(map, GFP_NOFS); 1578 - if (!cache->physical_map) { 1579 - ret = -ENOMEM; 1580 - goto out; 1581 - } 1577 + cache->physical_map = map; 1582 1578 1583 1579 zone_info = kcalloc(map->num_stripes, sizeof(*zone_info), GFP_NOFS); 1584 1580 if (!zone_info) { ··· 1686 1690 } 1687 1691 bitmap_free(active); 1688 1692 kfree(zone_info); 1689 - btrfs_free_chunk_map(map); 1690 1693 1691 1694 return ret; 1692 1695 } ··· 2170 2175 struct btrfs_chunk_map *map; 2171 2176 const bool is_metadata = (block_group->flags & 2172 2177 (BTRFS_BLOCK_GROUP_METADATA | BTRFS_BLOCK_GROUP_SYSTEM)); 2178 + struct btrfs_dev_replace *dev_replace = &fs_info->dev_replace; 2173 2179 int ret = 0; 2174 2180 int i; 2175 2181 ··· 2246 2250 btrfs_clear_data_reloc_bg(block_group); 2247 2251 spin_unlock(&block_group->lock); 2248 2252 2253 + down_read(&dev_replace->rwsem); 2249 2254 map = block_group->physical_map; 2250 2255 for (i = 0; i < map->num_stripes; i++) { 2251 2256 struct btrfs_device *device = map->stripes[i].dev; ··· 2263 2266 zinfo->zone_size >> SECTOR_SHIFT); 2264 2267 memalloc_nofs_restore(nofs_flags); 2265 2268 2266 - if (ret) 2269 + if (ret) { 2270 + up_read(&dev_replace->rwsem); 2267 2271 return ret; 2272 + } 2268 2273 2269 2274 if (!(block_group->flags & BTRFS_BLOCK_GROUP_DATA)) 2270 2275 zinfo->reserved_active_zones++; 2271 2276 btrfs_dev_clear_active_zone(device, physical); 2272 2277 } 2278 + up_read(&dev_replace->rwsem); 2273 2279 2274 2280 if (!fully_written) 2275 2281 btrfs_dec_block_group_ro(block_group);