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

Pull btrfs fixes from David Sterba:

- detect possible file name hash collision earlier so it does not lead
to transaction abort

- handle b-tree leaf overflows when snapshotting a subvolume with set
received UUID, leading to transaction abort

- in zoned mode, reorder relocation block group initialization after
the transaction kthread start

- fix orphan cleanup state tracking of subvolume, this could lead to
invalid dentries under some conditions

- add locking around updates of dynamic reclain state update

- in subpage mode, add missing RCU unlock when trying to releae extent
buffer

- remap tree fixes:
- add missing description strings for the newly added remap tree
- properly update search key when iterating backrefs

* tag 'for-7.0-rc3-tag' of git://git.kernel.org/pub/scm/linux/kernel/git/kdave/linux:
btrfs: remove duplicated definition of btrfs_printk_in_rcu()
btrfs: remove unnecessary transaction abort in the received subvol ioctl
btrfs: abort transaction on failure to update root in the received subvol ioctl
btrfs: fix transaction abort on set received ioctl due to item overflow
btrfs: fix transaction abort when snapshotting received subvolumes
btrfs: fix transaction abort on file creation due to name hash collision
btrfs: read key again after incrementing slot in move_existing_remaps()
btrfs: add missing RCU unlock in error path in try_release_subpage_extent_buffer()
btrfs: set BTRFS_ROOT_ORPHAN_CLEANUP during subvol create
btrfs: zoned: move btrfs_zoned_reserve_data_reloc_bg() after kthread start
btrfs: hold space_info->lock when clearing periodic reclaim ready
btrfs: print-tree: add remap tree definitions

+126 -9
+6 -1
fs/btrfs/disk-io.c
··· 3594 3594 } 3595 3595 } 3596 3596 3597 - btrfs_zoned_reserve_data_reloc_bg(fs_info); 3598 3597 btrfs_free_zone_cache(fs_info); 3599 3598 3600 3599 btrfs_check_active_zone_reservation(fs_info); ··· 3620 3621 ret = PTR_ERR(fs_info->transaction_kthread); 3621 3622 goto fail_cleaner; 3622 3623 } 3624 + 3625 + /* 3626 + * Starts a transaction, must be called after the transaction kthread 3627 + * is initialized. 3628 + */ 3629 + btrfs_zoned_reserve_data_reloc_bg(fs_info); 3623 3630 3624 3631 ret = btrfs_read_qgroup_config(fs_info); 3625 3632 if (ret)
+1
fs/btrfs/extent_io.c
··· 4507 4507 */ 4508 4508 if (!test_and_clear_bit(EXTENT_BUFFER_TREE_REF, &eb->bflags)) { 4509 4509 spin_unlock(&eb->refs_lock); 4510 + rcu_read_lock(); 4510 4511 break; 4511 4512 } 4512 4513
+19
fs/btrfs/inode.c
··· 6612 6612 int ret; 6613 6613 bool xa_reserved = false; 6614 6614 6615 + if (!args->orphan && !args->subvol) { 6616 + /* 6617 + * Before anything else, check if we can add the name to the 6618 + * parent directory. We want to avoid a dir item overflow in 6619 + * case we have an existing dir item due to existing name 6620 + * hash collisions. We do this check here before we call 6621 + * btrfs_add_link() down below so that we can avoid a 6622 + * transaction abort (which could be exploited by malicious 6623 + * users). 6624 + * 6625 + * For subvolumes we already do this in btrfs_mksubvol(). 6626 + */ 6627 + ret = btrfs_check_dir_item_collision(BTRFS_I(dir)->root, 6628 + btrfs_ino(BTRFS_I(dir)), 6629 + name); 6630 + if (ret < 0) 6631 + return ret; 6632 + } 6633 + 6615 6634 path = btrfs_alloc_path(); 6616 6635 if (!path) 6617 6636 return -ENOMEM;
+28 -4
fs/btrfs/ioctl.c
··· 672 672 goto out; 673 673 } 674 674 675 + /* 676 + * Subvolumes have orphans cleaned on first dentry lookup. A new 677 + * subvolume cannot have any orphans, so we should set the bit before we 678 + * add the subvolume dentry to the dentry cache, so that it is in the 679 + * same state as a subvolume after first lookup. 680 + */ 681 + set_bit(BTRFS_ROOT_ORPHAN_CLEANUP, &new_root->state); 675 682 d_instantiate_new(dentry, new_inode_args.inode); 676 683 new_inode_args.inode = NULL; 677 684 ··· 3859 3852 goto out; 3860 3853 } 3861 3854 3855 + received_uuid_changed = memcmp(root_item->received_uuid, sa->uuid, 3856 + BTRFS_UUID_SIZE); 3857 + 3858 + /* 3859 + * Before we attempt to add the new received uuid, check if we have room 3860 + * for it in case there's already an item. If the size of the existing 3861 + * item plus this root's ID (u64) exceeds the maximum item size, we can 3862 + * return here without the need to abort a transaction. If we don't do 3863 + * this check, the btrfs_uuid_tree_add() call below would fail with 3864 + * -EOVERFLOW and result in a transaction abort. Malicious users could 3865 + * exploit this to turn the fs into RO mode. 3866 + */ 3867 + if (received_uuid_changed && !btrfs_is_empty_uuid(sa->uuid)) { 3868 + ret = btrfs_uuid_tree_check_overflow(fs_info, sa->uuid, 3869 + BTRFS_UUID_KEY_RECEIVED_SUBVOL); 3870 + if (ret < 0) 3871 + goto out; 3872 + } 3873 + 3862 3874 /* 3863 3875 * 1 - root item 3864 3876 * 2 - uuid items (received uuid + subvol uuid) ··· 3893 3867 sa->rtime.sec = ct.tv_sec; 3894 3868 sa->rtime.nsec = ct.tv_nsec; 3895 3869 3896 - received_uuid_changed = memcmp(root_item->received_uuid, sa->uuid, 3897 - BTRFS_UUID_SIZE); 3898 3870 if (received_uuid_changed && 3899 3871 !btrfs_is_empty_uuid(root_item->received_uuid)) { 3900 3872 ret = btrfs_uuid_tree_remove(trans, root_item->received_uuid, 3901 3873 BTRFS_UUID_KEY_RECEIVED_SUBVOL, 3902 3874 btrfs_root_id(root)); 3903 3875 if (unlikely(ret && ret != -ENOENT)) { 3904 - btrfs_abort_transaction(trans, ret); 3905 3876 btrfs_end_transaction(trans); 3906 3877 goto out; 3907 3878 } ··· 3913 3890 3914 3891 ret = btrfs_update_root(trans, fs_info->tree_root, 3915 3892 &root->root_key, &root->root_item); 3916 - if (ret < 0) { 3893 + if (unlikely(ret < 0)) { 3894 + btrfs_abort_transaction(trans, ret); 3917 3895 btrfs_end_transaction(trans); 3918 3896 goto out; 3919 3897 }
-3
fs/btrfs/messages.h
··· 31 31 #define btrfs_printk_in_rcu(fs_info, level, fmt, args...) \ 32 32 btrfs_no_printk(fs_info, fmt, ##args) 33 33 34 - #define btrfs_printk_in_rcu(fs_info, level, fmt, args...) \ 35 - btrfs_no_printk(fs_info, fmt, ##args) 36 - 37 34 #define btrfs_printk_rl_in_rcu(fs_info, level, fmt, args...) \ 38 35 btrfs_no_printk(fs_info, fmt, ##args) 39 36
+10
fs/btrfs/print-tree.c
··· 38 38 { BTRFS_BLOCK_GROUP_TREE_OBJECTID, "BLOCK_GROUP_TREE" }, 39 39 { BTRFS_DATA_RELOC_TREE_OBJECTID, "DATA_RELOC_TREE" }, 40 40 { BTRFS_RAID_STRIPE_TREE_OBJECTID, "RAID_STRIPE_TREE" }, 41 + { BTRFS_REMAP_TREE_OBJECTID, "REMAP_TREE" }, 41 42 }; 42 43 43 44 const char *btrfs_root_name(const struct btrfs_key *key, char *buf) ··· 416 415 [BTRFS_UUID_KEY_SUBVOL] = "UUID_KEY_SUBVOL", 417 416 [BTRFS_UUID_KEY_RECEIVED_SUBVOL] = "UUID_KEY_RECEIVED_SUBVOL", 418 417 [BTRFS_RAID_STRIPE_KEY] = "RAID_STRIPE", 418 + [BTRFS_IDENTITY_REMAP_KEY] = "IDENTITY_REMAP", 419 + [BTRFS_REMAP_KEY] = "REMAP", 420 + [BTRFS_REMAP_BACKREF_KEY] = "REMAP_BACKREF", 419 421 }; 420 422 421 423 if (key->type == 0 && key->objectid == BTRFS_FREE_SPACE_OBJECTID) ··· 439 435 struct btrfs_extent_data_ref *dref; 440 436 struct btrfs_shared_data_ref *sref; 441 437 struct btrfs_dev_extent *dev_extent; 438 + struct btrfs_remap_item *remap; 442 439 struct btrfs_key key; 443 440 444 441 if (!l) ··· 573 568 case BTRFS_RAID_STRIPE_KEY: 574 569 print_raid_stripe_key(l, btrfs_item_size(l, i), 575 570 btrfs_item_ptr(l, i, struct btrfs_stripe_extent)); 571 + break; 572 + case BTRFS_REMAP_KEY: 573 + case BTRFS_REMAP_BACKREF_KEY: 574 + remap = btrfs_item_ptr(l, i, struct btrfs_remap_item); 575 + pr_info("\t\taddress %llu\n", btrfs_remap_address(l, remap)); 576 576 break; 577 577 } 578 578 }
+2
fs/btrfs/relocation.c
··· 4399 4399 4400 4400 leaf = path->nodes[0]; 4401 4401 } 4402 + 4403 + btrfs_item_key_to_cpu(leaf, &key, path->slots[0]); 4402 4404 } 4403 4405 4404 4406 remap = btrfs_item_ptr(leaf, path->slots[0], struct btrfs_remap_item);
+4 -1
fs/btrfs/space-info.c
··· 2194 2194 if (!btrfs_should_periodic_reclaim(space_info)) 2195 2195 continue; 2196 2196 for (raid = 0; raid < BTRFS_NR_RAID_TYPES; raid++) { 2197 - if (do_reclaim_sweep(space_info, raid)) 2197 + if (do_reclaim_sweep(space_info, raid)) { 2198 + spin_lock(&space_info->lock); 2198 2199 btrfs_set_periodic_reclaim_ready(space_info, false); 2200 + spin_unlock(&space_info->lock); 2201 + } 2199 2202 } 2200 2203 } 2201 2204 }
+16
fs/btrfs/transaction.c
··· 1905 1905 ret = btrfs_uuid_tree_add(trans, new_root_item->received_uuid, 1906 1906 BTRFS_UUID_KEY_RECEIVED_SUBVOL, 1907 1907 objectid); 1908 + /* 1909 + * We are creating of lot of snapshots of the same root that was 1910 + * received (has a received UUID) and reached a leaf's limit for 1911 + * an item. We can safely ignore this and avoid a transaction 1912 + * abort. A deletion of this snapshot will still work since we 1913 + * ignore if an item with a BTRFS_UUID_KEY_RECEIVED_SUBVOL key 1914 + * is missing (see btrfs_delete_subvolume()). Send/receive will 1915 + * work too since it peeks the first root id from the existing 1916 + * item (it could peek any), and in case it's missing it 1917 + * falls back to search by BTRFS_UUID_KEY_SUBVOL keys. 1918 + * Creation of a snapshot does not require CAP_SYS_ADMIN, so 1919 + * we don't want users triggering transaction aborts, either 1920 + * intentionally or not. 1921 + */ 1922 + if (ret == -EOVERFLOW) 1923 + ret = 0; 1908 1924 if (unlikely(ret && ret != -EEXIST)) { 1909 1925 btrfs_abort_transaction(trans, ret); 1910 1926 goto fail;
+38
fs/btrfs/uuid-tree.c
··· 199 199 return 0; 200 200 } 201 201 202 + /* 203 + * Check if we can add one root ID to a UUID key. 204 + * If the key does not yet exists, we can, otherwise only if extended item does 205 + * not exceeds the maximum item size permitted by the leaf size. 206 + * 207 + * Returns 0 on success, negative value on error. 208 + */ 209 + int btrfs_uuid_tree_check_overflow(struct btrfs_fs_info *fs_info, 210 + const u8 *uuid, u8 type) 211 + { 212 + BTRFS_PATH_AUTO_FREE(path); 213 + int ret; 214 + u32 item_size; 215 + struct btrfs_key key; 216 + 217 + if (WARN_ON_ONCE(!fs_info->uuid_root)) 218 + return -EINVAL; 219 + 220 + path = btrfs_alloc_path(); 221 + if (!path) 222 + return -ENOMEM; 223 + 224 + btrfs_uuid_to_key(uuid, type, &key); 225 + ret = btrfs_search_slot(NULL, fs_info->uuid_root, &key, path, 0, 0); 226 + if (ret < 0) 227 + return ret; 228 + if (ret > 0) 229 + return 0; 230 + 231 + item_size = btrfs_item_size(path->nodes[0], path->slots[0]); 232 + 233 + if (sizeof(struct btrfs_item) + item_size + sizeof(u64) > 234 + BTRFS_LEAF_DATA_SIZE(fs_info)) 235 + return -EOVERFLOW; 236 + 237 + return 0; 238 + } 239 + 202 240 static int btrfs_uuid_iter_rem(struct btrfs_root *uuid_root, u8 *uuid, u8 type, 203 241 u64 subid) 204 242 {
+2
fs/btrfs/uuid-tree.h
··· 12 12 u64 subid); 13 13 int btrfs_uuid_tree_remove(struct btrfs_trans_handle *trans, const u8 *uuid, u8 type, 14 14 u64 subid); 15 + int btrfs_uuid_tree_check_overflow(struct btrfs_fs_info *fs_info, 16 + const u8 *uuid, u8 type); 15 17 int btrfs_uuid_tree_iterate(struct btrfs_fs_info *fs_info); 16 18 int btrfs_create_uuid_tree(struct btrfs_fs_info *fs_info); 17 19 int btrfs_uuid_scan_kthread(void *data);