Commit ae195ca1 authored by Linus Torvalds's avatar Linus Torvalds

Merge tag 'for-6.3-rc1-tag' of git://git.kernel.org/pub/scm/linux/kernel/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
parents f331c5de 675dfe12
......@@ -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);
......
......@@ -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);
......@@ -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);
......@@ -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;
......@@ -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)
......@@ -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;
}
......@@ -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);
......@@ -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,
......
......@@ -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);
......
......@@ -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);
......@@ -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);
......
......@@ -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
......
......@@ -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"
......@@ -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.
......@@ -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,
......@@ -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
......
......@@ -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 */
};
......
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