Commit 661e504d authored by Linus Torvalds's avatar Linus Torvalds

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

Pull btrfs fixes from David Sterba:

 - fix folio refcounting when releasing them (encoded write, dummy
   extent buffer)

 - fix out of bounds read when checking qgroup inherit data

 - fix how configurable chunk size is handled in zoned mode

 - in the ref-verify tool, fix uninitialized return value when checking
   extent owner ref and simple quota are not enabled

* tag 'for-6.10-rc6-tag' of git://git.kernel.org/pub/scm/linux/kernel/git/kdave/linux:
  btrfs: fix folio refcount in __alloc_dummy_extent_buffer()
  btrfs: fix folio refcount in btrfs_do_encoded_write()
  btrfs: fix uninitialized return value in the ref-verify tool
  btrfs: always do the basic checks for btrfs_qgroup_inherit structure
  btrfs: zoned: fix calc_available_free_space() for zoned mode
parents 033771c0 a56c85fa
...@@ -3553,7 +3553,7 @@ struct extent_buffer *__alloc_dummy_extent_buffer(struct btrfs_fs_info *fs_info, ...@@ -3553,7 +3553,7 @@ struct extent_buffer *__alloc_dummy_extent_buffer(struct btrfs_fs_info *fs_info,
for (int i = 0; i < num_folios; i++) { for (int i = 0; i < num_folios; i++) {
if (eb->folios[i]) { if (eb->folios[i]) {
detach_extent_buffer_folio(eb, eb->folios[i]); detach_extent_buffer_folio(eb, eb->folios[i]);
__folio_put(eb->folios[i]); folio_put(eb->folios[i]);
} }
} }
__free_extent_buffer(eb); __free_extent_buffer(eb);
......
...@@ -10385,7 +10385,7 @@ ssize_t btrfs_do_encoded_write(struct kiocb *iocb, struct iov_iter *from, ...@@ -10385,7 +10385,7 @@ ssize_t btrfs_do_encoded_write(struct kiocb *iocb, struct iov_iter *from,
out_folios: out_folios:
for (i = 0; i < nr_folios; i++) { for (i = 0; i < nr_folios; i++) {
if (folios[i]) if (folios[i])
__folio_put(folios[i]); folio_put(folios[i]);
} }
kvfree(folios); kvfree(folios);
out: out:
......
...@@ -3062,8 +3062,6 @@ int btrfs_qgroup_check_inherit(struct btrfs_fs_info *fs_info, ...@@ -3062,8 +3062,6 @@ int btrfs_qgroup_check_inherit(struct btrfs_fs_info *fs_info,
struct btrfs_qgroup_inherit *inherit, struct btrfs_qgroup_inherit *inherit,
size_t size) size_t size)
{ {
if (!btrfs_qgroup_enabled(fs_info))
return 0;
if (inherit->flags & ~BTRFS_QGROUP_INHERIT_FLAGS_SUPP) if (inherit->flags & ~BTRFS_QGROUP_INHERIT_FLAGS_SUPP)
return -EOPNOTSUPP; return -EOPNOTSUPP;
if (size < sizeof(*inherit) || size > PAGE_SIZE) if (size < sizeof(*inherit) || size > PAGE_SIZE)
...@@ -3084,6 +3082,14 @@ int btrfs_qgroup_check_inherit(struct btrfs_fs_info *fs_info, ...@@ -3084,6 +3082,14 @@ int btrfs_qgroup_check_inherit(struct btrfs_fs_info *fs_info,
if (size != struct_size(inherit, qgroups, inherit->num_qgroups)) if (size != struct_size(inherit, qgroups, inherit->num_qgroups))
return -EINVAL; return -EINVAL;
/*
* Skip the inherit source qgroups check if qgroup is not enabled.
* Qgroup can still be later enabled causing problems, but in that case
* btrfs_qgroup_inherit() would just ignore those invalid ones.
*/
if (!btrfs_qgroup_enabled(fs_info))
return 0;
/* /*
* Now check all the remaining qgroups, they should all: * Now check all the remaining qgroups, they should all:
* *
......
...@@ -441,7 +441,8 @@ static int process_extent_item(struct btrfs_fs_info *fs_info, ...@@ -441,7 +441,8 @@ static int process_extent_item(struct btrfs_fs_info *fs_info,
u32 item_size = btrfs_item_size(leaf, slot); u32 item_size = btrfs_item_size(leaf, slot);
unsigned long end, ptr; unsigned long end, ptr;
u64 offset, flags, count; u64 offset, flags, count;
int type, ret; int type;
int ret = 0;
ei = btrfs_item_ptr(leaf, slot, struct btrfs_extent_item); ei = btrfs_item_ptr(leaf, slot, struct btrfs_extent_item);
flags = btrfs_extent_flags(leaf, ei); flags = btrfs_extent_flags(leaf, ei);
...@@ -486,7 +487,11 @@ static int process_extent_item(struct btrfs_fs_info *fs_info, ...@@ -486,7 +487,11 @@ static int process_extent_item(struct btrfs_fs_info *fs_info,
key->objectid, key->offset); key->objectid, key->offset);
break; break;
case BTRFS_EXTENT_OWNER_REF_KEY: case BTRFS_EXTENT_OWNER_REF_KEY:
WARN_ON(!btrfs_fs_incompat(fs_info, SIMPLE_QUOTA)); if (!btrfs_fs_incompat(fs_info, SIMPLE_QUOTA)) {
btrfs_err(fs_info,
"found extent owner ref without simple quotas enabled");
ret = -EINVAL;
}
break; break;
default: default:
btrfs_err(fs_info, "invalid key type in iref"); btrfs_err(fs_info, "invalid key type in iref");
......
...@@ -373,11 +373,18 @@ static u64 calc_available_free_space(struct btrfs_fs_info *fs_info, ...@@ -373,11 +373,18 @@ static u64 calc_available_free_space(struct btrfs_fs_info *fs_info,
* "optimal" chunk size based on the fs size. However when we actually * "optimal" chunk size based on the fs size. However when we actually
* allocate the chunk we will strip this down further, making it no more * allocate the chunk we will strip this down further, making it no more
* than 10% of the disk or 1G, whichever is smaller. * than 10% of the disk or 1G, whichever is smaller.
*
* On the zoned mode, we need to use zone_size (=
* data_sinfo->chunk_size) as it is.
*/ */
data_sinfo = btrfs_find_space_info(fs_info, BTRFS_BLOCK_GROUP_DATA); data_sinfo = btrfs_find_space_info(fs_info, BTRFS_BLOCK_GROUP_DATA);
data_chunk_size = min(data_sinfo->chunk_size, if (!btrfs_is_zoned(fs_info)) {
mult_perc(fs_info->fs_devices->total_rw_bytes, 10)); data_chunk_size = min(data_sinfo->chunk_size,
data_chunk_size = min_t(u64, data_chunk_size, SZ_1G); mult_perc(fs_info->fs_devices->total_rw_bytes, 10));
data_chunk_size = min_t(u64, data_chunk_size, SZ_1G);
} else {
data_chunk_size = data_sinfo->chunk_size;
}
/* /*
* Since data allocations immediately use block groups as part of the * Since data allocations immediately use block groups as part of the
...@@ -405,6 +412,17 @@ static u64 calc_available_free_space(struct btrfs_fs_info *fs_info, ...@@ -405,6 +412,17 @@ static u64 calc_available_free_space(struct btrfs_fs_info *fs_info,
avail >>= 3; avail >>= 3;
else else
avail >>= 1; avail >>= 1;
/*
* On the zoned mode, we always allocate one zone as one chunk.
* Returning non-zone size alingned bytes here will result in
* less pressure for the async metadata reclaim process, and it
* will over-commit too much leading to ENOSPC. Align down to the
* zone size to avoid that.
*/
if (btrfs_is_zoned(fs_info))
avail = ALIGN_DOWN(avail, fs_info->zone_size);
return avail; return avail;
} }
......
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