Skip to content

Commit

Permalink
Merge tag 'for-6.3-rc1-tag' of git://git.kernel.org/pub/scm/linux/ker…
Browse files Browse the repository at this point in the history
…nel/git/kdave/linux

Pull btrfs fixes from David Sterba:
 "First batch of fixes. Among them there are two updates to sysfs and
  ioctl which are not strictly fixes but are used for testing so there's
  no reason to delay them.

   - fix block group item corruption after inserting new block group

   - fix extent map logging bit not cleared for split maps after
     dropping range

   - fix calculation of unusable block group space reporting bogus
     values due to 32/64b division

   - fix unnecessary increment of read error stat on write error

   - improve error handling in inode update

   - export per-device fsid in DEV_INFO ioctl to distinguish seeding
     devices, needed for testing

   - allocator size classes:
      - fix potential dead lock in size class loading logic
      - print sysfs stats for the allocation classes"

* tag 'for-6.3-rc1-tag' of git://git.kernel.org/pub/scm/linux/kernel/git/kdave/linux:
  btrfs: fix block group item corruption after inserting new block group
  btrfs: fix extent map logging bit not cleared for split maps after dropping range
  btrfs: fix percent calculation for bg reclaim message
  btrfs: fix unnecessary increment of read error stat on write error
  btrfs: handle btrfs_del_item errors in __btrfs_update_delayed_inode
  btrfs: ioctl: return device fsid from DEV_INFO ioctl
  btrfs: fix potential dead lock in size class loading logic
  btrfs: sysfs: add size class stats
  • Loading branch information
torvalds committed Mar 10, 2023
2 parents f331c5d + 675dfe1 commit ae195ca
Show file tree
Hide file tree
Showing 7 changed files with 92 additions and 32 deletions.
2 changes: 1 addition & 1 deletion fs/btrfs/bio.c
Original file line number Diff line number Diff line change
Expand Up @@ -287,7 +287,7 @@ static void btrfs_log_dev_io_error(struct bio *bio, struct btrfs_device *dev)

if (btrfs_op(bio) == BTRFS_MAP_WRITE)
btrfs_dev_stat_inc_and_print(dev, BTRFS_DEV_STAT_WRITE_ERRS);
if (!(bio->bi_opf & REQ_RAHEAD))
else if (!(bio->bi_opf & REQ_RAHEAD))
btrfs_dev_stat_inc_and_print(dev, BTRFS_DEV_STAT_READ_ERRS);
if (bio->bi_opf & REQ_PREFLUSH)
btrfs_dev_stat_inc_and_print(dev, BTRFS_DEV_STAT_FLUSH_ERRS);
Expand Down
58 changes: 30 additions & 28 deletions fs/btrfs/block-group.c
Original file line number Diff line number Diff line change
Expand Up @@ -558,14 +558,15 @@ u64 add_new_free_space(struct btrfs_block_group *block_group, u64 start, u64 end
static int sample_block_group_extent_item(struct btrfs_caching_control *caching_ctl,
struct btrfs_block_group *block_group,
int index, int max_index,
struct btrfs_key *key)
struct btrfs_key *found_key)
{
struct btrfs_fs_info *fs_info = block_group->fs_info;
struct btrfs_root *extent_root;
int ret = 0;
u64 search_offset;
u64 search_end = block_group->start + block_group->length;
struct btrfs_path *path;
struct btrfs_key search_key;
int ret = 0;

ASSERT(index >= 0);
ASSERT(index <= max_index);
Expand All @@ -585,37 +586,24 @@ static int sample_block_group_extent_item(struct btrfs_caching_control *caching_
path->reada = READA_FORWARD;

search_offset = index * div_u64(block_group->length, max_index);
key->objectid = block_group->start + search_offset;
key->type = BTRFS_EXTENT_ITEM_KEY;
key->offset = 0;
search_key.objectid = block_group->start + search_offset;
search_key.type = BTRFS_EXTENT_ITEM_KEY;
search_key.offset = 0;

while (1) {
ret = btrfs_search_forward(extent_root, key, path, 0);
if (ret != 0)
goto out;
btrfs_for_each_slot(extent_root, &search_key, found_key, path, ret) {
/* Success; sampled an extent item in the block group */
if (key->type == BTRFS_EXTENT_ITEM_KEY &&
key->objectid >= block_group->start &&
key->objectid + key->offset <= search_end)
goto out;
if (found_key->type == BTRFS_EXTENT_ITEM_KEY &&
found_key->objectid >= block_group->start &&
found_key->objectid + found_key->offset <= search_end)
break;

/* We can't possibly find a valid extent item anymore */
if (key->objectid >= search_end) {
if (found_key->objectid >= search_end) {
ret = 1;
break;
}
if (key->type < BTRFS_EXTENT_ITEM_KEY)
key->type = BTRFS_EXTENT_ITEM_KEY;
else
key->objectid++;
btrfs_release_path(path);
up_read(&fs_info->commit_root_sem);
mutex_unlock(&caching_ctl->mutex);
cond_resched();
mutex_lock(&caching_ctl->mutex);
down_read(&fs_info->commit_root_sem);
}
out:

lockdep_assert_held(&caching_ctl->mutex);
lockdep_assert_held_read(&fs_info->commit_root_sem);
btrfs_free_path(path);
Expand Down Expand Up @@ -659,6 +647,7 @@ static int sample_block_group_extent_item(struct btrfs_caching_control *caching_
static int load_block_group_size_class(struct btrfs_caching_control *caching_ctl,
struct btrfs_block_group *block_group)
{
struct btrfs_fs_info *fs_info = block_group->fs_info;
struct btrfs_key key;
int i;
u64 min_size = block_group->length;
Expand All @@ -668,6 +657,8 @@ static int load_block_group_size_class(struct btrfs_caching_control *caching_ctl
if (!btrfs_block_group_should_use_size_class(block_group))
return 0;

lockdep_assert_held(&caching_ctl->mutex);
lockdep_assert_held_read(&fs_info->commit_root_sem);
for (i = 0; i < 5; ++i) {
ret = sample_block_group_extent_item(caching_ctl, block_group, i, 5, &key);
if (ret < 0)
Expand All @@ -682,7 +673,6 @@ static int load_block_group_size_class(struct btrfs_caching_control *caching_ctl
block_group->size_class = size_class;
spin_unlock(&block_group->lock);
}

out:
return ret;
}
Expand Down Expand Up @@ -1836,7 +1826,8 @@ void btrfs_reclaim_bgs_work(struct work_struct *work)

btrfs_info(fs_info,
"reclaiming chunk %llu with %llu%% used %llu%% unusable",
bg->start, div_u64(bg->used * 100, bg->length),
bg->start,
div64_u64(bg->used * 100, bg->length),
div64_u64(zone_unusable * 100, bg->length));
trace_btrfs_reclaim_block_group(bg);
ret = btrfs_relocate_chunk(fs_info, bg->start);
Expand Down Expand Up @@ -2493,18 +2484,29 @@ static int insert_block_group_item(struct btrfs_trans_handle *trans,
struct btrfs_block_group_item bgi;
struct btrfs_root *root = btrfs_block_group_root(fs_info);
struct btrfs_key key;
u64 old_commit_used;
int ret;

spin_lock(&block_group->lock);
btrfs_set_stack_block_group_used(&bgi, block_group->used);
btrfs_set_stack_block_group_chunk_objectid(&bgi,
block_group->global_root_id);
btrfs_set_stack_block_group_flags(&bgi, block_group->flags);
old_commit_used = block_group->commit_used;
block_group->commit_used = block_group->used;
key.objectid = block_group->start;
key.type = BTRFS_BLOCK_GROUP_ITEM_KEY;
key.offset = block_group->length;
spin_unlock(&block_group->lock);

return btrfs_insert_item(trans, root, &key, &bgi, sizeof(bgi));
ret = btrfs_insert_item(trans, root, &key, &bgi, sizeof(bgi));
if (ret < 0) {
spin_lock(&block_group->lock);
block_group->commit_used = old_commit_used;
spin_unlock(&block_group->lock);
}

return ret;
}

static int insert_dev_extent(struct btrfs_trans_handle *trans,
Expand Down
2 changes: 1 addition & 1 deletion fs/btrfs/delayed-inode.c
Original file line number Diff line number Diff line change
Expand Up @@ -1048,7 +1048,7 @@ static int __btrfs_update_delayed_inode(struct btrfs_trans_handle *trans,
* so there is only one iref. The case that several irefs are
* in the same item doesn't exist.
*/
btrfs_del_item(trans, root, path);
ret = btrfs_del_item(trans, root, path);
out:
btrfs_release_delayed_iref(node);
btrfs_release_path(path);
Expand Down
7 changes: 6 additions & 1 deletion fs/btrfs/extent_map.c
Original file line number Diff line number Diff line change
Expand Up @@ -763,7 +763,13 @@ void btrfs_drop_extent_map_range(struct btrfs_inode *inode, u64 start, u64 end,
goto next;
}

flags = em->flags;
clear_bit(EXTENT_FLAG_PINNED, &em->flags);
/*
* In case we split the extent map, we want to preserve the
* EXTENT_FLAG_LOGGING flag on our extent map, but we don't want
* it on the new extent maps.
*/
clear_bit(EXTENT_FLAG_LOGGING, &flags);
modified = !list_empty(&em->list);

Expand All @@ -774,7 +780,6 @@ void btrfs_drop_extent_map_range(struct btrfs_inode *inode, u64 start, u64 end,
if (em->start >= start && em_end <= end)
goto remove_em;

flags = em->flags;
gen = em->generation;
compressed = test_bit(EXTENT_FLAG_COMPRESSED, &em->flags);

Expand Down
1 change: 1 addition & 0 deletions fs/btrfs/ioctl.c
Original file line number Diff line number Diff line change
Expand Up @@ -2859,6 +2859,7 @@ static long btrfs_ioctl_dev_info(struct btrfs_fs_info *fs_info,
di_args->bytes_used = btrfs_device_get_bytes_used(dev);
di_args->total_bytes = btrfs_device_get_total_bytes(dev);
memcpy(di_args->uuid, dev->uuid, sizeof(di_args->uuid));
memcpy(di_args->fsid, dev->fs_devices->fsid, BTRFS_UUID_SIZE);
if (dev->name)
strscpy(di_args->path, btrfs_dev_name(dev), sizeof(di_args->path));
else
Expand Down
42 changes: 42 additions & 0 deletions fs/btrfs/sysfs.c
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@
#include <linux/spinlock.h>
#include <linux/completion.h>
#include <linux/bug.h>
#include <linux/list.h>
#include <crypto/hash.h>
#include "messages.h"
#include "ctree.h"
Expand Down Expand Up @@ -778,6 +779,45 @@ static ssize_t btrfs_chunk_size_store(struct kobject *kobj,
return len;
}

static ssize_t btrfs_size_classes_show(struct kobject *kobj,
struct kobj_attribute *a, char *buf)
{
struct btrfs_space_info *sinfo = to_space_info(kobj);
struct btrfs_block_group *bg;
u32 none = 0;
u32 small = 0;
u32 medium = 0;
u32 large = 0;

for (int i = 0; i < BTRFS_NR_RAID_TYPES; ++i) {
down_read(&sinfo->groups_sem);
list_for_each_entry(bg, &sinfo->block_groups[i], list) {
if (!btrfs_block_group_should_use_size_class(bg))
continue;
switch (bg->size_class) {
case BTRFS_BG_SZ_NONE:
none++;
break;
case BTRFS_BG_SZ_SMALL:
small++;
break;
case BTRFS_BG_SZ_MEDIUM:
medium++;
break;
case BTRFS_BG_SZ_LARGE:
large++;
break;
}
}
up_read(&sinfo->groups_sem);
}
return sysfs_emit(buf, "none %u\n"
"small %u\n"
"medium %u\n"
"large %u\n",
none, small, medium, large);
}

#ifdef CONFIG_BTRFS_DEBUG
/*
* Request chunk allocation with current chunk size.
Expand Down Expand Up @@ -835,6 +875,7 @@ SPACE_INFO_ATTR(bytes_zone_unusable);
SPACE_INFO_ATTR(disk_used);
SPACE_INFO_ATTR(disk_total);
BTRFS_ATTR_RW(space_info, chunk_size, btrfs_chunk_size_show, btrfs_chunk_size_store);
BTRFS_ATTR(space_info, size_classes, btrfs_size_classes_show);

static ssize_t btrfs_sinfo_bg_reclaim_threshold_show(struct kobject *kobj,
struct kobj_attribute *a,
Expand Down Expand Up @@ -887,6 +928,7 @@ static struct attribute *space_info_attrs[] = {
BTRFS_ATTR_PTR(space_info, disk_total),
BTRFS_ATTR_PTR(space_info, bg_reclaim_threshold),
BTRFS_ATTR_PTR(space_info, chunk_size),
BTRFS_ATTR_PTR(space_info, size_classes),
#ifdef CONFIG_BTRFS_DEBUG
BTRFS_ATTR_PTR(space_info, force_chunk_alloc),
#endif
Expand Down
12 changes: 11 additions & 1 deletion include/uapi/linux/btrfs.h
Original file line number Diff line number Diff line change
Expand Up @@ -245,7 +245,17 @@ struct btrfs_ioctl_dev_info_args {
__u8 uuid[BTRFS_UUID_SIZE]; /* in/out */
__u64 bytes_used; /* out */
__u64 total_bytes; /* out */
__u64 unused[379]; /* pad to 4k */
/*
* Optional, out.
*
* Showing the fsid of the device, allowing user space to check if this
* device is a seeding one.
*
* Introduced in v6.3, thus user space still needs to check if kernel
* changed this value. Older kernel will not touch the values here.
*/
__u8 fsid[BTRFS_UUID_SIZE];
__u64 unused[377]; /* pad to 4k */
__u8 path[BTRFS_DEVICE_PATH_NAME_MAX]; /* out */
};

Expand Down

0 comments on commit ae195ca

Please sign in to comment.