Commit 12e6cced authored by Linus Torvalds's avatar Linus Torvalds

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

Pull btrfs fixes from David Sterba:

 - fix infinite loop in readdir(), could happen in a big directory when
   files get renamed during enumeration

 - fix extent map handling of skipped pinned ranges

 - fix a corner case when handling ordered extent length

 - fix a potential crash when balance cancel races with pause

 - verify correct uuid when starting scrub or device replace

* tag 'for-6.5-rc6-tag' of git://git.kernel.org/pub/scm/linux/kernel/git/kdave/linux:
  btrfs: fix incorrect splitting in btrfs_drop_extent_map_range
  btrfs: fix BUG_ON condition in btrfs_cancel_balance
  btrfs: only subtract from len_to_oe_boundary when it is tracking an extent
  btrfs: fix replace/scrub failure with metadata_uuid
  btrfs: fix infinite directory reads
parents b5cab28b c962098c
...@@ -443,6 +443,7 @@ struct btrfs_drop_extents_args { ...@@ -443,6 +443,7 @@ struct btrfs_drop_extents_args {
struct btrfs_file_private { struct btrfs_file_private {
void *filldir_buf; void *filldir_buf;
u64 last_index;
struct extent_state *llseek_cached_state; struct extent_state *llseek_cached_state;
}; };
......
...@@ -1632,6 +1632,7 @@ int btrfs_inode_delayed_dir_index_count(struct btrfs_inode *inode) ...@@ -1632,6 +1632,7 @@ int btrfs_inode_delayed_dir_index_count(struct btrfs_inode *inode)
} }
bool btrfs_readdir_get_delayed_items(struct inode *inode, bool btrfs_readdir_get_delayed_items(struct inode *inode,
u64 last_index,
struct list_head *ins_list, struct list_head *ins_list,
struct list_head *del_list) struct list_head *del_list)
{ {
...@@ -1651,14 +1652,14 @@ bool btrfs_readdir_get_delayed_items(struct inode *inode, ...@@ -1651,14 +1652,14 @@ bool btrfs_readdir_get_delayed_items(struct inode *inode,
mutex_lock(&delayed_node->mutex); mutex_lock(&delayed_node->mutex);
item = __btrfs_first_delayed_insertion_item(delayed_node); item = __btrfs_first_delayed_insertion_item(delayed_node);
while (item) { while (item && item->index <= last_index) {
refcount_inc(&item->refs); refcount_inc(&item->refs);
list_add_tail(&item->readdir_list, ins_list); list_add_tail(&item->readdir_list, ins_list);
item = __btrfs_next_delayed_item(item); item = __btrfs_next_delayed_item(item);
} }
item = __btrfs_first_delayed_deletion_item(delayed_node); item = __btrfs_first_delayed_deletion_item(delayed_node);
while (item) { while (item && item->index <= last_index) {
refcount_inc(&item->refs); refcount_inc(&item->refs);
list_add_tail(&item->readdir_list, del_list); list_add_tail(&item->readdir_list, del_list);
item = __btrfs_next_delayed_item(item); item = __btrfs_next_delayed_item(item);
......
...@@ -148,6 +148,7 @@ void btrfs_destroy_delayed_inodes(struct btrfs_fs_info *fs_info); ...@@ -148,6 +148,7 @@ void btrfs_destroy_delayed_inodes(struct btrfs_fs_info *fs_info);
/* Used for readdir() */ /* Used for readdir() */
bool btrfs_readdir_get_delayed_items(struct inode *inode, bool btrfs_readdir_get_delayed_items(struct inode *inode,
u64 last_index,
struct list_head *ins_list, struct list_head *ins_list,
struct list_head *del_list); struct list_head *del_list);
void btrfs_readdir_put_delayed_items(struct inode *inode, void btrfs_readdir_put_delayed_items(struct inode *inode,
......
...@@ -902,7 +902,30 @@ static void submit_extent_page(struct btrfs_bio_ctrl *bio_ctrl, ...@@ -902,7 +902,30 @@ static void submit_extent_page(struct btrfs_bio_ctrl *bio_ctrl,
size -= len; size -= len;
pg_offset += len; pg_offset += len;
disk_bytenr += len; disk_bytenr += len;
bio_ctrl->len_to_oe_boundary -= len;
/*
* len_to_oe_boundary defaults to U32_MAX, which isn't page or
* sector aligned. alloc_new_bio() then sets it to the end of
* our ordered extent for writes into zoned devices.
*
* When len_to_oe_boundary is tracking an ordered extent, we
* trust the ordered extent code to align things properly, and
* the check above to cap our write to the ordered extent
* boundary is correct.
*
* When len_to_oe_boundary is U32_MAX, the cap above would
* result in a 4095 byte IO for the last page right before
* we hit the bio limit of UINT_MAX. bio_add_page() has all
* the checks required to make sure we don't overflow the bio,
* and we should just ignore len_to_oe_boundary completely
* unless we're using it to track an ordered extent.
*
* It's pretty hard to make a bio sized U32_MAX, but it can
* happen when the page cache is able to feed us contiguous
* pages for large extents.
*/
if (bio_ctrl->len_to_oe_boundary != U32_MAX)
bio_ctrl->len_to_oe_boundary -= len;
/* Ordered extent boundary: move on to a new bio. */ /* Ordered extent boundary: move on to a new bio. */
if (bio_ctrl->len_to_oe_boundary == 0) if (bio_ctrl->len_to_oe_boundary == 0)
......
...@@ -760,8 +760,6 @@ void btrfs_drop_extent_map_range(struct btrfs_inode *inode, u64 start, u64 end, ...@@ -760,8 +760,6 @@ void btrfs_drop_extent_map_range(struct btrfs_inode *inode, u64 start, u64 end,
if (skip_pinned && test_bit(EXTENT_FLAG_PINNED, &em->flags)) { if (skip_pinned && test_bit(EXTENT_FLAG_PINNED, &em->flags)) {
start = em_end; start = em_end;
if (end != (u64)-1)
len = start + len - em_end;
goto next; goto next;
} }
...@@ -829,8 +827,8 @@ void btrfs_drop_extent_map_range(struct btrfs_inode *inode, u64 start, u64 end, ...@@ -829,8 +827,8 @@ void btrfs_drop_extent_map_range(struct btrfs_inode *inode, u64 start, u64 end,
if (!split) if (!split)
goto remove_em; goto remove_em;
} }
split->start = start + len; split->start = end;
split->len = em_end - (start + len); split->len = em_end - end;
split->block_start = em->block_start; split->block_start = em->block_start;
split->flags = flags; split->flags = flags;
split->compress_type = em->compress_type; split->compress_type = em->compress_type;
......
...@@ -5872,6 +5872,74 @@ static struct dentry *btrfs_lookup(struct inode *dir, struct dentry *dentry, ...@@ -5872,6 +5872,74 @@ static struct dentry *btrfs_lookup(struct inode *dir, struct dentry *dentry,
return d_splice_alias(inode, dentry); return d_splice_alias(inode, dentry);
} }
/*
* Find the highest existing sequence number in a directory and then set the
* in-memory index_cnt variable to the first free sequence number.
*/
static int btrfs_set_inode_index_count(struct btrfs_inode *inode)
{
struct btrfs_root *root = inode->root;
struct btrfs_key key, found_key;
struct btrfs_path *path;
struct extent_buffer *leaf;
int ret;
key.objectid = btrfs_ino(inode);
key.type = BTRFS_DIR_INDEX_KEY;
key.offset = (u64)-1;
path = btrfs_alloc_path();
if (!path)
return -ENOMEM;
ret = btrfs_search_slot(NULL, root, &key, path, 0, 0);
if (ret < 0)
goto out;
/* FIXME: we should be able to handle this */
if (ret == 0)
goto out;
ret = 0;
if (path->slots[0] == 0) {
inode->index_cnt = BTRFS_DIR_START_INDEX;
goto out;
}
path->slots[0]--;
leaf = path->nodes[0];
btrfs_item_key_to_cpu(leaf, &found_key, path->slots[0]);
if (found_key.objectid != btrfs_ino(inode) ||
found_key.type != BTRFS_DIR_INDEX_KEY) {
inode->index_cnt = BTRFS_DIR_START_INDEX;
goto out;
}
inode->index_cnt = found_key.offset + 1;
out:
btrfs_free_path(path);
return ret;
}
static int btrfs_get_dir_last_index(struct btrfs_inode *dir, u64 *index)
{
if (dir->index_cnt == (u64)-1) {
int ret;
ret = btrfs_inode_delayed_dir_index_count(dir);
if (ret) {
ret = btrfs_set_inode_index_count(dir);
if (ret)
return ret;
}
}
*index = dir->index_cnt;
return 0;
}
/* /*
* All this infrastructure exists because dir_emit can fault, and we are holding * All this infrastructure exists because dir_emit can fault, and we are holding
* the tree lock when doing readdir. For now just allocate a buffer and copy * the tree lock when doing readdir. For now just allocate a buffer and copy
...@@ -5884,10 +5952,17 @@ static struct dentry *btrfs_lookup(struct inode *dir, struct dentry *dentry, ...@@ -5884,10 +5952,17 @@ static struct dentry *btrfs_lookup(struct inode *dir, struct dentry *dentry,
static int btrfs_opendir(struct inode *inode, struct file *file) static int btrfs_opendir(struct inode *inode, struct file *file)
{ {
struct btrfs_file_private *private; struct btrfs_file_private *private;
u64 last_index;
int ret;
ret = btrfs_get_dir_last_index(BTRFS_I(inode), &last_index);
if (ret)
return ret;
private = kzalloc(sizeof(struct btrfs_file_private), GFP_KERNEL); private = kzalloc(sizeof(struct btrfs_file_private), GFP_KERNEL);
if (!private) if (!private)
return -ENOMEM; return -ENOMEM;
private->last_index = last_index;
private->filldir_buf = kzalloc(PAGE_SIZE, GFP_KERNEL); private->filldir_buf = kzalloc(PAGE_SIZE, GFP_KERNEL);
if (!private->filldir_buf) { if (!private->filldir_buf) {
kfree(private); kfree(private);
...@@ -5954,7 +6029,8 @@ static int btrfs_real_readdir(struct file *file, struct dir_context *ctx) ...@@ -5954,7 +6029,8 @@ static int btrfs_real_readdir(struct file *file, struct dir_context *ctx)
INIT_LIST_HEAD(&ins_list); INIT_LIST_HEAD(&ins_list);
INIT_LIST_HEAD(&del_list); INIT_LIST_HEAD(&del_list);
put = btrfs_readdir_get_delayed_items(inode, &ins_list, &del_list); put = btrfs_readdir_get_delayed_items(inode, private->last_index,
&ins_list, &del_list);
again: again:
key.type = BTRFS_DIR_INDEX_KEY; key.type = BTRFS_DIR_INDEX_KEY;
...@@ -5972,6 +6048,8 @@ static int btrfs_real_readdir(struct file *file, struct dir_context *ctx) ...@@ -5972,6 +6048,8 @@ static int btrfs_real_readdir(struct file *file, struct dir_context *ctx)
break; break;
if (found_key.offset < ctx->pos) if (found_key.offset < ctx->pos)
continue; continue;
if (found_key.offset > private->last_index)
break;
if (btrfs_should_delete_dir_index(&del_list, found_key.offset)) if (btrfs_should_delete_dir_index(&del_list, found_key.offset))
continue; continue;
di = btrfs_item_ptr(leaf, path->slots[0], struct btrfs_dir_item); di = btrfs_item_ptr(leaf, path->slots[0], struct btrfs_dir_item);
...@@ -6107,57 +6185,6 @@ static int btrfs_update_time(struct inode *inode, struct timespec64 *now, ...@@ -6107,57 +6185,6 @@ static int btrfs_update_time(struct inode *inode, struct timespec64 *now,
return dirty ? btrfs_dirty_inode(BTRFS_I(inode)) : 0; return dirty ? btrfs_dirty_inode(BTRFS_I(inode)) : 0;
} }
/*
* find the highest existing sequence number in a directory
* and then set the in-memory index_cnt variable to reflect
* free sequence numbers
*/
static int btrfs_set_inode_index_count(struct btrfs_inode *inode)
{
struct btrfs_root *root = inode->root;
struct btrfs_key key, found_key;
struct btrfs_path *path;
struct extent_buffer *leaf;
int ret;
key.objectid = btrfs_ino(inode);
key.type = BTRFS_DIR_INDEX_KEY;
key.offset = (u64)-1;
path = btrfs_alloc_path();
if (!path)
return -ENOMEM;
ret = btrfs_search_slot(NULL, root, &key, path, 0, 0);
if (ret < 0)
goto out;
/* FIXME: we should be able to handle this */
if (ret == 0)
goto out;
ret = 0;
if (path->slots[0] == 0) {
inode->index_cnt = BTRFS_DIR_START_INDEX;
goto out;
}
path->slots[0]--;
leaf = path->nodes[0];
btrfs_item_key_to_cpu(leaf, &found_key, path->slots[0]);
if (found_key.objectid != btrfs_ino(inode) ||
found_key.type != BTRFS_DIR_INDEX_KEY) {
inode->index_cnt = BTRFS_DIR_START_INDEX;
goto out;
}
inode->index_cnt = found_key.offset + 1;
out:
btrfs_free_path(path);
return ret;
}
/* /*
* helper to find a free sequence number in a given directory. This current * helper to find a free sequence number in a given directory. This current
* code is very simple, later versions will do smarter things in the btree * code is very simple, later versions will do smarter things in the btree
......
...@@ -605,7 +605,8 @@ static void scrub_verify_one_metadata(struct scrub_stripe *stripe, int sector_nr ...@@ -605,7 +605,8 @@ static void scrub_verify_one_metadata(struct scrub_stripe *stripe, int sector_nr
btrfs_stack_header_bytenr(header), logical); btrfs_stack_header_bytenr(header), logical);
return; return;
} }
if (memcmp(header->fsid, fs_info->fs_devices->fsid, BTRFS_FSID_SIZE) != 0) { if (memcmp(header->fsid, fs_info->fs_devices->metadata_uuid,
BTRFS_FSID_SIZE) != 0) {
bitmap_set(&stripe->meta_error_bitmap, sector_nr, sectors_per_tree); bitmap_set(&stripe->meta_error_bitmap, sector_nr, sectors_per_tree);
bitmap_set(&stripe->error_bitmap, sector_nr, sectors_per_tree); bitmap_set(&stripe->error_bitmap, sector_nr, sectors_per_tree);
btrfs_warn_rl(fs_info, btrfs_warn_rl(fs_info,
......
...@@ -4638,8 +4638,7 @@ int btrfs_cancel_balance(struct btrfs_fs_info *fs_info) ...@@ -4638,8 +4638,7 @@ int btrfs_cancel_balance(struct btrfs_fs_info *fs_info)
} }
} }
BUG_ON(fs_info->balance_ctl || ASSERT(!test_bit(BTRFS_FS_BALANCE_RUNNING, &fs_info->flags));
test_bit(BTRFS_FS_BALANCE_RUNNING, &fs_info->flags));
atomic_dec(&fs_info->balance_cancel_req); atomic_dec(&fs_info->balance_cancel_req);
mutex_unlock(&fs_info->balance_mutex); mutex_unlock(&fs_info->balance_mutex);
return 0; return 0;
......
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