We've been seeing errors on our build servers related to failing to inherit inode properties. This is because we do not pre-reserve space for them, instead trying to reserve space with NO_FLUSH at inheritance time. NO_FLUSH can transiently fail, but we'll still complain. It's just an extra credit, so simply add that to the places that call btrfs_new_inode and call it good enough.
Signed-off-by: Josef Bacik <jo...@toxicpanda.com> --- fs/btrfs/inode.c | 78 ++++++++++++++++++++++---------------------------------- fs/btrfs/ioctl.c | 27 ++++++++++++-------- 2 files changed, 46 insertions(+), 59 deletions(-) diff --git a/fs/btrfs/inode.c b/fs/btrfs/inode.c index 6126de9b8b9c..0da4a9d6d9fe 100644 --- a/fs/btrfs/inode.c +++ b/fs/btrfs/inode.c @@ -59,6 +59,14 @@ struct btrfs_dio_data { int overwrite; }; +/* + * 2 for inode item and ref + * 2 for dir items + * 1 for xattr if selinux is on + * 1 for inherited properties + */ +#define BTRFS_NEW_INODE_ITEMS 6 + static const struct inode_operations btrfs_dir_inode_operations; static const struct inode_operations btrfs_symlink_inode_operations; static const struct inode_operations btrfs_dir_ro_inode_operations; @@ -6479,12 +6487,7 @@ static int btrfs_mknod(struct inode *dir, struct dentry *dentry, u64 objectid; u64 index = 0; - /* - * 2 for inode item and ref - * 2 for dir items - * 1 for xattr if selinux is on - */ - trans = btrfs_start_transaction(root, 5); + trans = btrfs_start_transaction(root, BTRFS_NEW_INODE_ITEMS); if (IS_ERR(trans)) return PTR_ERR(trans); @@ -6543,12 +6546,7 @@ static int btrfs_create(struct inode *dir, struct dentry *dentry, u64 objectid; u64 index = 0; - /* - * 2 for inode item and ref - * 2 for dir items - * 1 for xattr if selinux is on - */ - trans = btrfs_start_transaction(root, 5); + trans = btrfs_start_transaction(root, BTRFS_NEW_INODE_ITEMS); if (IS_ERR(trans)) return PTR_ERR(trans); @@ -6695,12 +6693,7 @@ static int btrfs_mkdir(struct inode *dir, struct dentry *dentry, umode_t mode) u64 objectid = 0; u64 index = 0; - /* - * 2 items for inode and ref - * 2 items for dir items - * 1 for xattr if selinux is on - */ - trans = btrfs_start_transaction(root, 5); + trans = btrfs_start_transaction(root, BTRFS_NEW_INODE_ITEMS); if (IS_ERR(trans)) return PTR_ERR(trans); @@ -9428,14 +9421,11 @@ static int btrfs_rename_exchange(struct inode *old_dir, down_read(&fs_info->subvol_sem); /* - * We want to reserve the absolute worst case amount of items. So if - * both inodes are subvols and we need to unlink them then that would - * require 4 item modifications, but if they are both normal inodes it - * would require 5 item modifications, so we'll assume their normal - * inodes. So 5 * 2 is 10, plus 2 for the new links, so 12 total items - * should cover the worst case number of items we'll modify. + * The same math from btrfs_rename applies here, except we need an extra + * 2 items for the new links. */ - trans = btrfs_start_transaction(root, 12); + trans = btrfs_start_transaction(root, + (BTRFS_NEW_INODE_ITEMS << 1) + 2); if (IS_ERR(trans)) { ret = PTR_ERR(trans); goto out_notrans; @@ -9768,19 +9758,19 @@ static int btrfs_rename(struct inode *old_dir, struct dentry *old_dentry, if (old_ino == BTRFS_FIRST_FREE_OBJECTID) down_read(&fs_info->subvol_sem); /* - * We want to reserve the absolute worst case amount of items. So if - * both inodes are subvols and we need to unlink them then that would - * require 4 item modifications, but if they are both normal inodes it - * would require 5 item modifications, so we'll assume they are normal - * inodes. So 5 * 2 is 10, plus 1 for the new link, so 11 total items - * should cover the worst case number of items we'll modify. - * If our rename has the whiteout flag, we need more 5 units for the - * new inode (1 inode item, 1 inode ref, 2 dir items and 1 xattr item - * when selinux is enabled). + * We want to reserve the absolute worst case amount of items. Subvol + * inodes don't have an inode item to worry about and don't have a + * selinux attr, so we use the BTRFS_NEW_INODE_ITEMS counter for how + * much it costs per inode to modify. Worse case we'll have to mess + * with 2 inodes, so 2 x BTRFS_NEW_INODE_ITEMS, and then we need an + * extra reservation for the new link. + * + * If our rename has the whiteout flag we need a full new inode which + * means another set of BTRFS_NEW_INODE_ITEMS. */ - trans_num_items = 11; + trans_num_items = (BTRFS_NEW_INODE_ITEMS << 1) + 1; if (flags & RENAME_WHITEOUT) - trans_num_items += 5; + trans_num_items += BTRFS_NEW_INODE_ITEMS; trans = btrfs_start_transaction(root, trans_num_items); if (IS_ERR(trans)) { ret = PTR_ERR(trans); @@ -10149,14 +10139,8 @@ static int btrfs_symlink(struct inode *dir, struct dentry *dentry, if (name_len > BTRFS_MAX_INLINE_DATA_SIZE(fs_info)) return -ENAMETOOLONG; - /* - * 2 items for inode item and ref - * 2 items for dir items - * 1 item for updating parent inode item - * 1 item for the inline extent item - * 1 item for xattr if selinux is on - */ - trans = btrfs_start_transaction(root, 7); + /* 1 item for the inline extent item */ + trans = btrfs_start_transaction(root, BTRFS_NEW_INODE_ITEMS + 1); if (IS_ERR(trans)) return PTR_ERR(trans); @@ -10427,10 +10411,8 @@ static int btrfs_tmpfile(struct inode *dir, struct dentry *dentry, umode_t mode) u64 index; int ret = 0; - /* - * 5 units required for adding orphan entry - */ - trans = btrfs_start_transaction(root, 5); + /* 1 unit required for adding orphan entry */ + trans = btrfs_start_transaction(root, BTRFS_NEW_INODE_ITEMS + 1); if (IS_ERR(trans)) return PTR_ERR(trans); diff --git a/fs/btrfs/ioctl.c b/fs/btrfs/ioctl.c index f38a659c918c..21f8ab2d8570 100644 --- a/fs/btrfs/ioctl.c +++ b/fs/btrfs/ioctl.c @@ -83,6 +83,17 @@ struct btrfs_ioctl_send_args_32 { struct btrfs_ioctl_send_args_32) #endif +/* + * 1 - parent dir inode + * 2 - dir entries + * 1 - root item + * 2 - root ref/backref + * 1 - root of snapshot + * 1 - UUID item + * 1 - properties + */ +#define BTRFS_NEW_ROOT_ITEMS 9 + static int btrfs_clone(struct inode *src, struct inode *inode, u64 off, u64 olen, u64 olen_aligned, u64 destoff, int no_time_update); @@ -596,7 +607,8 @@ static noinline int create_subvol(struct inode *dir, * The same as the snapshot creation, please see the comment * of create_snapshot(). */ - ret = btrfs_subvolume_reserve_metadata(root, &block_rsv, 8, false); + ret = btrfs_subvolume_reserve_metadata(root, &block_rsv, + BTRFS_NEW_ROOT_ITEMS, false); if (ret) goto fail_free; @@ -804,17 +816,10 @@ static int create_snapshot(struct btrfs_root *root, struct inode *dir, btrfs_init_block_rsv(&pending_snapshot->block_rsv, BTRFS_BLOCK_RSV_TEMP); - /* - * 1 - parent dir inode - * 2 - dir entries - * 1 - root item - * 2 - root ref/backref - * 1 - root of snapshot - * 1 - UUID item - */ + ret = btrfs_subvolume_reserve_metadata(BTRFS_I(dir)->root, - &pending_snapshot->block_rsv, 8, - false); + &pending_snapshot->block_rsv, + BTRFS_NEW_ROOT_ITEMS, false); if (ret) goto dec_and_free; -- 2.14.3