Commit 4b97bac0 authored by Linus Torvalds's avatar Linus Torvalds

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

Pull btrfs fixes from David Sterba:
 "Regression fixes in zone activation:

   - move a loop invariant out of the loop to avoid checking space
     status

   - properly handle unlimited activation

  Other fixes:

   - for subpage, force the free space v2 mount to avoid a warning and
     make it easy to switch a filesystem on different page size systems

   - export sysfs status of exclusive operation 'balance paused', so the
     user space tools can recognize it and allow adding a device with
     paused balance

   - fix assertion failure when logging directory key range item"

* tag 'for-5.18-rc5-tag' of git://git.kernel.org/pub/scm/linux/kernel/git/kdave/linux:
  btrfs: sysfs: export the balance paused state of exclusive operation
  btrfs: fix assertion failure when logging directory key range item
  btrfs: zoned: activate block group properly on unlimited active zone device
  btrfs: zoned: move non-changing condition check out of the loop
  btrfs: force v2 space cache usage for subpage mount
parents adcffc17 3e1ad196
...@@ -3658,6 +3658,17 @@ int __cold open_ctree(struct super_block *sb, struct btrfs_fs_devices *fs_device ...@@ -3658,6 +3658,17 @@ int __cold open_ctree(struct super_block *sb, struct btrfs_fs_devices *fs_device
if (sectorsize < PAGE_SIZE) { if (sectorsize < PAGE_SIZE) {
struct btrfs_subpage_info *subpage_info; struct btrfs_subpage_info *subpage_info;
/*
* V1 space cache has some hardcoded PAGE_SIZE usage, and is
* going to be deprecated.
*
* Force to use v2 cache for subpage case.
*/
btrfs_clear_opt(fs_info->mount_opt, SPACE_CACHE);
btrfs_set_and_info(fs_info, FREE_SPACE_TREE,
"forcing free space tree for sector size %u with page size %lu",
sectorsize, PAGE_SIZE);
btrfs_warn(fs_info, btrfs_warn(fs_info,
"read-write for sector size %u with page size %lu is experimental", "read-write for sector size %u with page size %lu is experimental",
sectorsize, PAGE_SIZE); sectorsize, PAGE_SIZE);
......
...@@ -922,6 +922,9 @@ static ssize_t btrfs_exclusive_operation_show(struct kobject *kobj, ...@@ -922,6 +922,9 @@ static ssize_t btrfs_exclusive_operation_show(struct kobject *kobj,
case BTRFS_EXCLOP_BALANCE: case BTRFS_EXCLOP_BALANCE:
str = "balance\n"; str = "balance\n";
break; break;
case BTRFS_EXCLOP_BALANCE_PAUSED:
str = "balance paused\n";
break;
case BTRFS_EXCLOP_DEV_ADD: case BTRFS_EXCLOP_DEV_ADD:
str = "device add\n"; str = "device add\n";
break; break;
......
...@@ -3721,11 +3721,29 @@ static noinline int insert_dir_log_key(struct btrfs_trans_handle *trans, ...@@ -3721,11 +3721,29 @@ static noinline int insert_dir_log_key(struct btrfs_trans_handle *trans,
key.offset = first_offset; key.offset = first_offset;
key.type = BTRFS_DIR_LOG_INDEX_KEY; key.type = BTRFS_DIR_LOG_INDEX_KEY;
ret = btrfs_insert_empty_item(trans, log, path, &key, sizeof(*item)); ret = btrfs_insert_empty_item(trans, log, path, &key, sizeof(*item));
if (ret) /*
* -EEXIST is fine and can happen sporadically when we are logging a
* directory and have concurrent insertions in the subvolume's tree for
* items from other inodes and that result in pushing off some dir items
* from one leaf to another in order to accommodate for the new items.
* This results in logging the same dir index range key.
*/
if (ret && ret != -EEXIST)
return ret; return ret;
item = btrfs_item_ptr(path->nodes[0], path->slots[0], item = btrfs_item_ptr(path->nodes[0], path->slots[0],
struct btrfs_dir_log_item); struct btrfs_dir_log_item);
if (ret == -EEXIST) {
const u64 curr_end = btrfs_dir_log_end(path->nodes[0], item);
/*
* btrfs_del_dir_entries_in_log() might have been called during
* an unlink between the initial insertion of this key and the
* current update, or we might be logging a single entry deletion
* during a rename, so set the new last_offset to the max value.
*/
last_offset = max(last_offset, curr_end);
}
btrfs_set_dir_log_end(path->nodes[0], item, last_offset); btrfs_set_dir_log_end(path->nodes[0], item, last_offset);
btrfs_mark_buffer_dirty(path->nodes[0]); btrfs_mark_buffer_dirty(path->nodes[0]);
btrfs_release_path(path); btrfs_release_path(path);
...@@ -3849,13 +3867,6 @@ static int process_dir_items_leaf(struct btrfs_trans_handle *trans, ...@@ -3849,13 +3867,6 @@ static int process_dir_items_leaf(struct btrfs_trans_handle *trans,
ret = insert_dir_log_key(trans, log, dst_path, ret = insert_dir_log_key(trans, log, dst_path,
ino, *last_old_dentry_offset + 1, ino, *last_old_dentry_offset + 1,
key.offset - 1); key.offset - 1);
/*
* -EEXIST should never happen because when we
* log a directory in full mode (LOG_INODE_ALL)
* we drop all BTRFS_DIR_LOG_INDEX_KEY keys from
* the log tree.
*/
ASSERT(ret != -EEXIST);
if (ret < 0) if (ret < 0)
return ret; return ret;
} }
...@@ -7031,12 +7042,12 @@ void btrfs_log_new_name(struct btrfs_trans_handle *trans, ...@@ -7031,12 +7042,12 @@ void btrfs_log_new_name(struct btrfs_trans_handle *trans,
/* /*
* Other concurrent task might be logging the old directory, * Other concurrent task might be logging the old directory,
* as it can be triggered when logging other inode that had or * as it can be triggered when logging other inode that had or
* still has a dentry in the old directory. So take the old * still has a dentry in the old directory. We lock the old
* directory's log_mutex to prevent getting an -EEXIST when * directory's log_mutex to ensure the deletion of the old
* logging a key to record the deletion, or having that other * name is persisted, because during directory logging we
* task logging the old directory get an -EEXIST if it attempts * delete all BTRFS_DIR_LOG_INDEX_KEY keys and the deletion of
* to log the same key after we just did it. In both cases that * the old name's dir index item is in the delayed items, so
* would result in falling back to a transaction commit. * it could be missed by an in progress directory logging.
*/ */
mutex_lock(&old_dir->log_mutex); mutex_lock(&old_dir->log_mutex);
ret = del_logged_dentry(trans, log, path, btrfs_ino(old_dir), ret = del_logged_dentry(trans, log, path, btrfs_ino(old_dir),
......
...@@ -1835,6 +1835,12 @@ bool btrfs_zone_activate(struct btrfs_block_group *block_group) ...@@ -1835,6 +1835,12 @@ bool btrfs_zone_activate(struct btrfs_block_group *block_group)
goto out_unlock; goto out_unlock;
} }
/* No space left */
if (block_group->alloc_offset == block_group->zone_capacity) {
ret = false;
goto out_unlock;
}
for (i = 0; i < map->num_stripes; i++) { for (i = 0; i < map->num_stripes; i++) {
device = map->stripes[i].dev; device = map->stripes[i].dev;
physical = map->stripes[i].physical; physical = map->stripes[i].physical;
...@@ -1842,35 +1848,23 @@ bool btrfs_zone_activate(struct btrfs_block_group *block_group) ...@@ -1842,35 +1848,23 @@ bool btrfs_zone_activate(struct btrfs_block_group *block_group)
if (device->zone_info->max_active_zones == 0) if (device->zone_info->max_active_zones == 0)
continue; continue;
/* No space left */
if (block_group->alloc_offset == block_group->zone_capacity) {
ret = false;
goto out_unlock;
}
if (!btrfs_dev_set_active_zone(device, physical)) { if (!btrfs_dev_set_active_zone(device, physical)) {
/* Cannot activate the zone */ /* Cannot activate the zone */
ret = false; ret = false;
goto out_unlock; goto out_unlock;
} }
}
/* Successfully activated all the zones */ /* Successfully activated all the zones */
if (i == map->num_stripes - 1)
block_group->zone_is_active = 1; block_group->zone_is_active = 1;
}
spin_unlock(&block_group->lock); spin_unlock(&block_group->lock);
if (block_group->zone_is_active) {
/* For the active block group list */ /* For the active block group list */
btrfs_get_block_group(block_group); btrfs_get_block_group(block_group);
spin_lock(&fs_info->zone_active_bgs_lock); spin_lock(&fs_info->zone_active_bgs_lock);
list_add_tail(&block_group->active_bg_list, list_add_tail(&block_group->active_bg_list, &fs_info->zone_active_bgs);
&fs_info->zone_active_bgs);
spin_unlock(&fs_info->zone_active_bgs_lock); spin_unlock(&fs_info->zone_active_bgs_lock);
}
return true; return true;
......
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