Commit f09b04cc authored by Linus Torvalds's avatar Linus Torvalds

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

Pull btrfs fixes from David Sterba:
 "More regression fixes and stabilization.

  Regressions:

   - zoned mode
      - count zone sizes in wider int types
      - fix space accounting for read-only block groups

   - subpage: fix page tail zeroing

  Fixes:

   - fix spurious warning when remounting with free space tree

   - fix warning when creating a directory with smack enabled

   - ioctl checks for qgroup inheritance when creating a snapshot

   - qgroup
      - fix missing unlock on error path in zero range
      - fix amount of released reservation on error
      - fix flushing from unsafe context with open transaction,
        potentially deadlocking

   - minor build warning fixes"

* tag 'for-5.12-rc1-tag' of git://git.kernel.org/pub/scm/linux/kernel/git/kdave/linux:
  btrfs: zoned: do not account freed region of read-only block group as zone_unusable
  btrfs: zoned: use sector_t for zone sectors
  btrfs: subpage: fix the false data csum mismatch error
  btrfs: fix warning when creating a directory with smack enabled
  btrfs: don't flush from btrfs_delayed_inode_reserve_metadata
  btrfs: export and rename qgroup_reserve_meta
  btrfs: free correct amount of space in btrfs_delayed_inode_reserve_metadata
  btrfs: fix spurious free_space_tree remount warning
  btrfs: validate qgroup inherit for SNAP_CREATE_V2 ioctl
  btrfs: unlock extents in btrfs_zero_range in case of quota reservation errors
  btrfs: ref-verify: use 'inline void' keyword ordering
parents 6bf331d5 badae9c8
...@@ -627,7 +627,8 @@ static int btrfs_delayed_inode_reserve_metadata( ...@@ -627,7 +627,8 @@ static int btrfs_delayed_inode_reserve_metadata(
*/ */
if (!src_rsv || (!trans->bytes_reserved && if (!src_rsv || (!trans->bytes_reserved &&
src_rsv->type != BTRFS_BLOCK_RSV_DELALLOC)) { src_rsv->type != BTRFS_BLOCK_RSV_DELALLOC)) {
ret = btrfs_qgroup_reserve_meta_prealloc(root, num_bytes, true); ret = btrfs_qgroup_reserve_meta(root, num_bytes,
BTRFS_QGROUP_RSV_META_PREALLOC, true);
if (ret < 0) if (ret < 0)
return ret; return ret;
ret = btrfs_block_rsv_add(root, dst_rsv, num_bytes, ret = btrfs_block_rsv_add(root, dst_rsv, num_bytes,
...@@ -649,7 +650,7 @@ static int btrfs_delayed_inode_reserve_metadata( ...@@ -649,7 +650,7 @@ static int btrfs_delayed_inode_reserve_metadata(
btrfs_ino(inode), btrfs_ino(inode),
num_bytes, 1); num_bytes, 1);
} else { } else {
btrfs_qgroup_free_meta_prealloc(root, fs_info->nodesize); btrfs_qgroup_free_meta_prealloc(root, num_bytes);
} }
return ret; return ret;
} }
......
...@@ -3008,12 +3008,23 @@ static void end_bio_extent_readpage(struct bio *bio) ...@@ -3008,12 +3008,23 @@ static void end_bio_extent_readpage(struct bio *bio)
if (likely(uptodate)) { if (likely(uptodate)) {
loff_t i_size = i_size_read(inode); loff_t i_size = i_size_read(inode);
pgoff_t end_index = i_size >> PAGE_SHIFT; pgoff_t end_index = i_size >> PAGE_SHIFT;
unsigned off;
/* Zero out the end if this page straddles i_size */ /*
off = offset_in_page(i_size); * Zero out the remaining part if this range straddles
if (page->index == end_index && off) * i_size.
zero_user_segment(page, off, PAGE_SIZE); *
* Here we should only zero the range inside the bvec,
* not touch anything else.
*
* NOTE: i_size is exclusive while end is inclusive.
*/
if (page->index == end_index && i_size <= end) {
u32 zero_start = max(offset_in_page(i_size),
offset_in_page(end));
zero_user_segment(page, zero_start,
offset_in_page(end) + 1);
}
} }
ASSERT(bio_offset + len > bio_offset); ASSERT(bio_offset + len > bio_offset);
bio_offset += len; bio_offset += len;
......
...@@ -3260,8 +3260,11 @@ static int btrfs_zero_range(struct inode *inode, ...@@ -3260,8 +3260,11 @@ static int btrfs_zero_range(struct inode *inode,
goto out; goto out;
ret = btrfs_qgroup_reserve_data(BTRFS_I(inode), &data_reserved, ret = btrfs_qgroup_reserve_data(BTRFS_I(inode), &data_reserved,
alloc_start, bytes_to_reserve); alloc_start, bytes_to_reserve);
if (ret) if (ret) {
unlock_extent_cached(&BTRFS_I(inode)->io_tree, lockstart,
lockend, &cached_state);
goto out; goto out;
}
ret = btrfs_prealloc_file_range(inode, mode, alloc_start, ret = btrfs_prealloc_file_range(inode, mode, alloc_start,
alloc_end - alloc_start, alloc_end - alloc_start,
i_blocksize(inode), i_blocksize(inode),
......
...@@ -2555,7 +2555,12 @@ static int __btrfs_add_free_space_zoned(struct btrfs_block_group *block_group, ...@@ -2555,7 +2555,12 @@ static int __btrfs_add_free_space_zoned(struct btrfs_block_group *block_group,
to_unusable = size - to_free; to_unusable = size - to_free;
ctl->free_space += to_free; ctl->free_space += to_free;
block_group->zone_unusable += to_unusable; /*
* If the block group is read-only, we should account freed space into
* bytes_readonly.
*/
if (!block_group->ro)
block_group->zone_unusable += to_unusable;
spin_unlock(&ctl->tree_lock); spin_unlock(&ctl->tree_lock);
if (!used) { if (!used) {
spin_lock(&block_group->lock); spin_lock(&block_group->lock);
......
...@@ -6083,7 +6083,7 @@ static int btrfs_dirty_inode(struct inode *inode) ...@@ -6083,7 +6083,7 @@ static int btrfs_dirty_inode(struct inode *inode)
return PTR_ERR(trans); return PTR_ERR(trans);
ret = btrfs_update_inode(trans, root, BTRFS_I(inode)); ret = btrfs_update_inode(trans, root, BTRFS_I(inode));
if (ret && ret == -ENOSPC) { if (ret && (ret == -ENOSPC || ret == -EDQUOT)) {
/* whoops, lets try again with the full transaction */ /* whoops, lets try again with the full transaction */
btrfs_end_transaction(trans); btrfs_end_transaction(trans);
trans = btrfs_start_transaction(root, 1); trans = btrfs_start_transaction(root, 1);
......
...@@ -1936,7 +1936,10 @@ static noinline int btrfs_ioctl_snap_create_v2(struct file *file, ...@@ -1936,7 +1936,10 @@ static noinline int btrfs_ioctl_snap_create_v2(struct file *file,
if (vol_args->flags & BTRFS_SUBVOL_RDONLY) if (vol_args->flags & BTRFS_SUBVOL_RDONLY)
readonly = true; readonly = true;
if (vol_args->flags & BTRFS_SUBVOL_QGROUP_INHERIT) { if (vol_args->flags & BTRFS_SUBVOL_QGROUP_INHERIT) {
if (vol_args->size > PAGE_SIZE) { u64 nums;
if (vol_args->size < sizeof(*inherit) ||
vol_args->size > PAGE_SIZE) {
ret = -EINVAL; ret = -EINVAL;
goto free_args; goto free_args;
} }
...@@ -1945,6 +1948,20 @@ static noinline int btrfs_ioctl_snap_create_v2(struct file *file, ...@@ -1945,6 +1948,20 @@ static noinline int btrfs_ioctl_snap_create_v2(struct file *file,
ret = PTR_ERR(inherit); ret = PTR_ERR(inherit);
goto free_args; goto free_args;
} }
if (inherit->num_qgroups > PAGE_SIZE ||
inherit->num_ref_copies > PAGE_SIZE ||
inherit->num_excl_copies > PAGE_SIZE) {
ret = -EINVAL;
goto free_inherit;
}
nums = inherit->num_qgroups + 2 * inherit->num_ref_copies +
2 * inherit->num_excl_copies;
if (vol_args->size != struct_size(inherit, qgroups, nums)) {
ret = -EINVAL;
goto free_inherit;
}
} }
ret = __btrfs_ioctl_snap_create(file, vol_args->name, vol_args->fd, ret = __btrfs_ioctl_snap_create(file, vol_args->name, vol_args->fd,
......
...@@ -3841,8 +3841,8 @@ static int sub_root_meta_rsv(struct btrfs_root *root, int num_bytes, ...@@ -3841,8 +3841,8 @@ static int sub_root_meta_rsv(struct btrfs_root *root, int num_bytes,
return num_bytes; return num_bytes;
} }
static int qgroup_reserve_meta(struct btrfs_root *root, int num_bytes, int btrfs_qgroup_reserve_meta(struct btrfs_root *root, int num_bytes,
enum btrfs_qgroup_rsv_type type, bool enforce) enum btrfs_qgroup_rsv_type type, bool enforce)
{ {
struct btrfs_fs_info *fs_info = root->fs_info; struct btrfs_fs_info *fs_info = root->fs_info;
int ret; int ret;
...@@ -3873,14 +3873,14 @@ int __btrfs_qgroup_reserve_meta(struct btrfs_root *root, int num_bytes, ...@@ -3873,14 +3873,14 @@ int __btrfs_qgroup_reserve_meta(struct btrfs_root *root, int num_bytes,
{ {
int ret; int ret;
ret = qgroup_reserve_meta(root, num_bytes, type, enforce); ret = btrfs_qgroup_reserve_meta(root, num_bytes, type, enforce);
if (ret <= 0 && ret != -EDQUOT) if (ret <= 0 && ret != -EDQUOT)
return ret; return ret;
ret = try_flush_qgroup(root); ret = try_flush_qgroup(root);
if (ret < 0) if (ret < 0)
return ret; return ret;
return qgroup_reserve_meta(root, num_bytes, type, enforce); return btrfs_qgroup_reserve_meta(root, num_bytes, type, enforce);
} }
void btrfs_qgroup_free_meta_all_pertrans(struct btrfs_root *root) void btrfs_qgroup_free_meta_all_pertrans(struct btrfs_root *root)
......
...@@ -361,6 +361,8 @@ int btrfs_qgroup_release_data(struct btrfs_inode *inode, u64 start, u64 len); ...@@ -361,6 +361,8 @@ int btrfs_qgroup_release_data(struct btrfs_inode *inode, u64 start, u64 len);
int btrfs_qgroup_free_data(struct btrfs_inode *inode, int btrfs_qgroup_free_data(struct btrfs_inode *inode,
struct extent_changeset *reserved, u64 start, struct extent_changeset *reserved, u64 start,
u64 len); u64 len);
int btrfs_qgroup_reserve_meta(struct btrfs_root *root, int num_bytes,
enum btrfs_qgroup_rsv_type type, bool enforce);
int __btrfs_qgroup_reserve_meta(struct btrfs_root *root, int num_bytes, int __btrfs_qgroup_reserve_meta(struct btrfs_root *root, int num_bytes,
enum btrfs_qgroup_rsv_type type, bool enforce); enum btrfs_qgroup_rsv_type type, bool enforce);
/* Reserve metadata space for pertrans and prealloc type */ /* Reserve metadata space for pertrans and prealloc type */
......
...@@ -218,11 +218,11 @@ static void __print_stack_trace(struct btrfs_fs_info *fs_info, ...@@ -218,11 +218,11 @@ static void __print_stack_trace(struct btrfs_fs_info *fs_info,
stack_trace_print(ra->trace, ra->trace_len, 2); stack_trace_print(ra->trace, ra->trace_len, 2);
} }
#else #else
static void inline __save_stack_trace(struct ref_action *ra) static inline void __save_stack_trace(struct ref_action *ra)
{ {
} }
static void inline __print_stack_trace(struct btrfs_fs_info *fs_info, static inline void __print_stack_trace(struct btrfs_fs_info *fs_info,
struct ref_action *ra) struct ref_action *ra)
{ {
btrfs_err(fs_info, " ref-verify: no stacktrace support"); btrfs_err(fs_info, " ref-verify: no stacktrace support");
......
...@@ -1918,8 +1918,8 @@ static int btrfs_remount(struct super_block *sb, int *flags, char *data) ...@@ -1918,8 +1918,8 @@ static int btrfs_remount(struct super_block *sb, int *flags, char *data)
btrfs_resize_thread_pool(fs_info, btrfs_resize_thread_pool(fs_info,
fs_info->thread_pool_size, old_thread_pool_size); fs_info->thread_pool_size, old_thread_pool_size);
if (btrfs_test_opt(fs_info, FREE_SPACE_TREE) != if ((bool)btrfs_test_opt(fs_info, FREE_SPACE_TREE) !=
btrfs_fs_compat_ro(fs_info, FREE_SPACE_TREE) && (bool)btrfs_fs_compat_ro(fs_info, FREE_SPACE_TREE) &&
(!sb_rdonly(sb) || (*flags & SB_RDONLY))) { (!sb_rdonly(sb) || (*flags & SB_RDONLY))) {
btrfs_warn(fs_info, btrfs_warn(fs_info,
"remount supports changing free space tree only from ro to rw"); "remount supports changing free space tree only from ro to rw");
......
...@@ -229,11 +229,33 @@ int btrfs_setxattr_trans(struct inode *inode, const char *name, ...@@ -229,11 +229,33 @@ int btrfs_setxattr_trans(struct inode *inode, const char *name,
{ {
struct btrfs_root *root = BTRFS_I(inode)->root; struct btrfs_root *root = BTRFS_I(inode)->root;
struct btrfs_trans_handle *trans; struct btrfs_trans_handle *trans;
const bool start_trans = (current->journal_info == NULL);
int ret; int ret;
trans = btrfs_start_transaction(root, 2); if (start_trans) {
if (IS_ERR(trans)) /*
return PTR_ERR(trans); * 1 unit for inserting/updating/deleting the xattr
* 1 unit for the inode item update
*/
trans = btrfs_start_transaction(root, 2);
if (IS_ERR(trans))
return PTR_ERR(trans);
} else {
/*
* This can happen when smack is enabled and a directory is being
* created. It happens through d_instantiate_new(), which calls
* smack_d_instantiate(), which in turn calls __vfs_setxattr() to
* set the transmute xattr (XATTR_NAME_SMACKTRANSMUTE) on the
* inode. We have already reserved space for the xattr and inode
* update at btrfs_mkdir(), so just use the transaction handle.
* We don't join or start a transaction, as that will reset the
* block_rsv of the handle and trigger a warning for the start
* case.
*/
ASSERT(strncmp(name, XATTR_SECURITY_PREFIX,
XATTR_SECURITY_PREFIX_LEN) == 0);
trans = current->journal_info;
}
ret = btrfs_setxattr(trans, inode, name, value, size, flags); ret = btrfs_setxattr(trans, inode, name, value, size, flags);
if (ret) if (ret)
...@@ -244,7 +266,8 @@ int btrfs_setxattr_trans(struct inode *inode, const char *name, ...@@ -244,7 +266,8 @@ int btrfs_setxattr_trans(struct inode *inode, const char *name,
ret = btrfs_update_inode(trans, root, BTRFS_I(inode)); ret = btrfs_update_inode(trans, root, BTRFS_I(inode));
BUG_ON(ret); BUG_ON(ret);
out: out:
btrfs_end_transaction(trans); if (start_trans)
btrfs_end_transaction(trans);
return ret; return ret;
} }
......
...@@ -269,7 +269,7 @@ int btrfs_get_dev_zone_info(struct btrfs_device *device) ...@@ -269,7 +269,7 @@ int btrfs_get_dev_zone_info(struct btrfs_device *device)
sector_t sector = 0; sector_t sector = 0;
struct blk_zone *zones = NULL; struct blk_zone *zones = NULL;
unsigned int i, nreported = 0, nr_zones; unsigned int i, nreported = 0, nr_zones;
unsigned int zone_sectors; sector_t zone_sectors;
char *model, *emulated; char *model, *emulated;
int ret; int ret;
...@@ -658,7 +658,7 @@ int btrfs_sb_log_location_bdev(struct block_device *bdev, int mirror, int rw, ...@@ -658,7 +658,7 @@ int btrfs_sb_log_location_bdev(struct block_device *bdev, int mirror, int rw,
u64 *bytenr_ret) u64 *bytenr_ret)
{ {
struct blk_zone zones[BTRFS_NR_SB_LOG_ZONES]; struct blk_zone zones[BTRFS_NR_SB_LOG_ZONES];
unsigned int zone_sectors; sector_t zone_sectors;
u32 sb_zone; u32 sb_zone;
int ret; int ret;
u8 zone_sectors_shift; u8 zone_sectors_shift;
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment