Commit 5aaef24b authored by Linus Torvalds's avatar Linus Torvalds

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

Pull btrfs fixes from David Sterba:
 "A few more fixes and regression fixes:

   - fix a corner case when handling tree-mod-log chagnes in reallocated
     notes

   - fix crash on raid0 filesystems created with <5.4 mkfs.btrfs that
     could lead to division by zero

   - add missing super block checksum verification after thawing
     filesystem

   - handle one more case in send when dealing with orphan files

   - fix parameter type mismatch for generation when reading dentry

   - improved error handling in raid56 code

   - better struct bio packing after recent cleanups"

* tag 'for-6.1-rc3-tag' of git://git.kernel.org/pub/scm/linux/kernel/git/kdave/linux:
  btrfs: don't use btrfs_chunk::sub_stripes from disk
  btrfs: fix type of parameter generation in btrfs_get_dentry
  btrfs: send: fix send failure of a subcase of orphan inodes
  btrfs: make thaw time super block check to also verify checksum
  btrfs: fix tree mod log mishandling of reallocated nodes
  btrfs: reorder btrfs_bio for better packing
  btrfs: raid56: avoid double freeing for rbio if full_stripe_write() failed
  btrfs: raid56: properly handle the error when unable to find the missing stripe
parents 78a089d0 76a66ba1
...@@ -166,11 +166,9 @@ static bool btrfs_supported_super_csum(u16 csum_type) ...@@ -166,11 +166,9 @@ static bool btrfs_supported_super_csum(u16 csum_type)
* Return 0 if the superblock checksum type matches the checksum value of that * Return 0 if the superblock checksum type matches the checksum value of that
* algorithm. Pass the raw disk superblock data. * algorithm. Pass the raw disk superblock data.
*/ */
static int btrfs_check_super_csum(struct btrfs_fs_info *fs_info, int btrfs_check_super_csum(struct btrfs_fs_info *fs_info,
char *raw_disk_sb) const struct btrfs_super_block *disk_sb)
{ {
struct btrfs_super_block *disk_sb =
(struct btrfs_super_block *)raw_disk_sb;
char result[BTRFS_CSUM_SIZE]; char result[BTRFS_CSUM_SIZE];
SHASH_DESC_ON_STACK(shash, fs_info->csum_shash); SHASH_DESC_ON_STACK(shash, fs_info->csum_shash);
...@@ -181,7 +179,7 @@ static int btrfs_check_super_csum(struct btrfs_fs_info *fs_info, ...@@ -181,7 +179,7 @@ static int btrfs_check_super_csum(struct btrfs_fs_info *fs_info,
* BTRFS_SUPER_INFO_SIZE range, we expect that the unused space is * BTRFS_SUPER_INFO_SIZE range, we expect that the unused space is
* filled with zeros and is included in the checksum. * filled with zeros and is included in the checksum.
*/ */
crypto_shash_digest(shash, raw_disk_sb + BTRFS_CSUM_SIZE, crypto_shash_digest(shash, (const u8 *)disk_sb + BTRFS_CSUM_SIZE,
BTRFS_SUPER_INFO_SIZE - BTRFS_CSUM_SIZE, result); BTRFS_SUPER_INFO_SIZE - BTRFS_CSUM_SIZE, result);
if (memcmp(disk_sb->csum, result, fs_info->csum_size)) if (memcmp(disk_sb->csum, result, fs_info->csum_size))
...@@ -3479,7 +3477,7 @@ int __cold open_ctree(struct super_block *sb, struct btrfs_fs_devices *fs_device ...@@ -3479,7 +3477,7 @@ int __cold open_ctree(struct super_block *sb, struct btrfs_fs_devices *fs_device
* We want to check superblock checksum, the type is stored inside. * We want to check superblock checksum, the type is stored inside.
* Pass the whole disk block of size BTRFS_SUPER_INFO_SIZE (4k). * Pass the whole disk block of size BTRFS_SUPER_INFO_SIZE (4k).
*/ */
if (btrfs_check_super_csum(fs_info, (u8 *)disk_super)) { if (btrfs_check_super_csum(fs_info, disk_super)) {
btrfs_err(fs_info, "superblock checksum mismatch"); btrfs_err(fs_info, "superblock checksum mismatch");
err = -EINVAL; err = -EINVAL;
btrfs_release_disk_super(disk_super); btrfs_release_disk_super(disk_super);
......
...@@ -42,6 +42,8 @@ struct extent_buffer *btrfs_find_create_tree_block( ...@@ -42,6 +42,8 @@ struct extent_buffer *btrfs_find_create_tree_block(
void btrfs_clean_tree_block(struct extent_buffer *buf); void btrfs_clean_tree_block(struct extent_buffer *buf);
void btrfs_clear_oneshot_options(struct btrfs_fs_info *fs_info); void btrfs_clear_oneshot_options(struct btrfs_fs_info *fs_info);
int btrfs_start_pre_rw_mount(struct btrfs_fs_info *fs_info); int btrfs_start_pre_rw_mount(struct btrfs_fs_info *fs_info);
int btrfs_check_super_csum(struct btrfs_fs_info *fs_info,
const struct btrfs_super_block *disk_sb);
int __cold open_ctree(struct super_block *sb, int __cold open_ctree(struct super_block *sb,
struct btrfs_fs_devices *fs_devices, struct btrfs_fs_devices *fs_devices,
char *options); char *options);
......
...@@ -58,7 +58,7 @@ static int btrfs_encode_fh(struct inode *inode, u32 *fh, int *max_len, ...@@ -58,7 +58,7 @@ static int btrfs_encode_fh(struct inode *inode, u32 *fh, int *max_len,
} }
struct dentry *btrfs_get_dentry(struct super_block *sb, u64 objectid, struct dentry *btrfs_get_dentry(struct super_block *sb, u64 objectid,
u64 root_objectid, u32 generation, u64 root_objectid, u64 generation,
int check_generation) int check_generation)
{ {
struct btrfs_fs_info *fs_info = btrfs_sb(sb); struct btrfs_fs_info *fs_info = btrfs_sb(sb);
......
...@@ -19,7 +19,7 @@ struct btrfs_fid { ...@@ -19,7 +19,7 @@ struct btrfs_fid {
} __attribute__ ((packed)); } __attribute__ ((packed));
struct dentry *btrfs_get_dentry(struct super_block *sb, u64 objectid, struct dentry *btrfs_get_dentry(struct super_block *sb, u64 objectid,
u64 root_objectid, u32 generation, u64 root_objectid, u64 generation,
int check_generation); int check_generation);
struct dentry *btrfs_get_parent(struct dentry *child); struct dentry *btrfs_get_parent(struct dentry *child);
......
...@@ -3295,21 +3295,22 @@ void btrfs_free_tree_block(struct btrfs_trans_handle *trans, ...@@ -3295,21 +3295,22 @@ void btrfs_free_tree_block(struct btrfs_trans_handle *trans,
} }
/* /*
* If this is a leaf and there are tree mod log users, we may * If there are tree mod log users we may have recorded mod log
* have recorded mod log operations that point to this leaf. * operations for this node. If we re-allocate this node we
* So we must make sure no one reuses this leaf's extent before * could replay operations on this node that happened when it
* mod log operations are applied to a node, otherwise after * existed in a completely different root. For example if it
* rewinding a node using the mod log operations we get an * was part of root A, then was reallocated to root B, and we
* inconsistent btree, as the leaf's extent may now be used as * are doing a btrfs_old_search_slot(root b), we could replay
* a node or leaf for another different btree. * operations that happened when the block was part of root A,
* giving us an inconsistent view of the btree.
*
* We are safe from races here because at this point no other * We are safe from races here because at this point no other
* node or root points to this extent buffer, so if after this * node or root points to this extent buffer, so if after this
* check a new tree mod log user joins, it will not be able to * check a new tree mod log user joins we will not have an
* find a node pointing to this leaf and record operations that * existing log of operations on this node that we have to
* point to this leaf. * contend with.
*/ */
if (btrfs_header_level(buf) == 0 && if (test_bit(BTRFS_FS_TREE_MOD_LOG_USERS, &fs_info->flags))
test_bit(BTRFS_FS_TREE_MOD_LOG_USERS, &fs_info->flags))
must_pin = true; must_pin = true;
if (must_pin || btrfs_is_zoned(fs_info)) { if (must_pin || btrfs_is_zoned(fs_info)) {
......
...@@ -1632,10 +1632,8 @@ static int full_stripe_write(struct btrfs_raid_bio *rbio) ...@@ -1632,10 +1632,8 @@ static int full_stripe_write(struct btrfs_raid_bio *rbio)
int ret; int ret;
ret = alloc_rbio_parity_pages(rbio); ret = alloc_rbio_parity_pages(rbio);
if (ret) { if (ret)
__free_raid_bio(rbio);
return ret; return ret;
}
ret = lock_stripe_add(rbio); ret = lock_stripe_add(rbio);
if (ret == 0) if (ret == 0)
...@@ -1823,8 +1821,10 @@ void raid56_parity_write(struct bio *bio, struct btrfs_io_context *bioc) ...@@ -1823,8 +1821,10 @@ void raid56_parity_write(struct bio *bio, struct btrfs_io_context *bioc)
*/ */
if (rbio_is_full(rbio)) { if (rbio_is_full(rbio)) {
ret = full_stripe_write(rbio); ret = full_stripe_write(rbio);
if (ret) if (ret) {
__free_raid_bio(rbio);
goto fail; goto fail;
}
return; return;
} }
...@@ -1838,9 +1838,11 @@ void raid56_parity_write(struct bio *bio, struct btrfs_io_context *bioc) ...@@ -1838,9 +1838,11 @@ void raid56_parity_write(struct bio *bio, struct btrfs_io_context *bioc)
list_add_tail(&rbio->plug_list, &plug->rbio_list); list_add_tail(&rbio->plug_list, &plug->rbio_list);
} else { } else {
ret = __raid56_parity_write(rbio); ret = __raid56_parity_write(rbio);
if (ret) if (ret) {
__free_raid_bio(rbio);
goto fail; goto fail;
} }
}
return; return;
...@@ -2742,8 +2744,10 @@ raid56_alloc_missing_rbio(struct bio *bio, struct btrfs_io_context *bioc) ...@@ -2742,8 +2744,10 @@ raid56_alloc_missing_rbio(struct bio *bio, struct btrfs_io_context *bioc)
rbio->faila = find_logical_bio_stripe(rbio, bio); rbio->faila = find_logical_bio_stripe(rbio, bio);
if (rbio->faila == -1) { if (rbio->faila == -1) {
BUG(); btrfs_warn_rl(fs_info,
kfree(rbio); "can not determine the failed stripe number for full stripe %llu",
bioc->raid_map[0]);
__free_raid_bio(rbio);
return NULL; return NULL;
} }
......
...@@ -6668,6 +6668,7 @@ static int changed_inode(struct send_ctx *sctx, ...@@ -6668,6 +6668,7 @@ static int changed_inode(struct send_ctx *sctx,
/* /*
* First, process the inode as if it was deleted. * First, process the inode as if it was deleted.
*/ */
if (old_nlinks > 0) {
sctx->cur_inode_gen = right_gen; sctx->cur_inode_gen = right_gen;
sctx->cur_inode_new = false; sctx->cur_inode_new = false;
sctx->cur_inode_deleted = true; sctx->cur_inode_deleted = true;
...@@ -6679,6 +6680,7 @@ static int changed_inode(struct send_ctx *sctx, ...@@ -6679,6 +6680,7 @@ static int changed_inode(struct send_ctx *sctx,
BTRFS_COMPARE_TREE_DELETED); BTRFS_COMPARE_TREE_DELETED);
if (ret < 0) if (ret < 0)
goto out; goto out;
}
/* /*
* Now process the inode as if it was new. * Now process the inode as if it was new.
......
...@@ -2555,6 +2555,7 @@ static int check_dev_super(struct btrfs_device *dev) ...@@ -2555,6 +2555,7 @@ static int check_dev_super(struct btrfs_device *dev)
{ {
struct btrfs_fs_info *fs_info = dev->fs_info; struct btrfs_fs_info *fs_info = dev->fs_info;
struct btrfs_super_block *sb; struct btrfs_super_block *sb;
u16 csum_type;
int ret = 0; int ret = 0;
/* This should be called with fs still frozen. */ /* This should be called with fs still frozen. */
...@@ -2569,6 +2570,21 @@ static int check_dev_super(struct btrfs_device *dev) ...@@ -2569,6 +2570,21 @@ static int check_dev_super(struct btrfs_device *dev)
if (IS_ERR(sb)) if (IS_ERR(sb))
return PTR_ERR(sb); return PTR_ERR(sb);
/* Verify the checksum. */
csum_type = btrfs_super_csum_type(sb);
if (csum_type != btrfs_super_csum_type(fs_info->super_copy)) {
btrfs_err(fs_info, "csum type changed, has %u expect %u",
csum_type, btrfs_super_csum_type(fs_info->super_copy));
ret = -EUCLEAN;
goto out;
}
if (btrfs_check_super_csum(fs_info, sb)) {
btrfs_err(fs_info, "csum for on-disk super block no longer matches");
ret = -EUCLEAN;
goto out;
}
/* Btrfs_validate_super() includes fsid check against super->fsid. */ /* Btrfs_validate_super() includes fsid check against super->fsid. */
ret = btrfs_validate_super(fs_info, sb, 0); ret = btrfs_validate_super(fs_info, sb, 0);
if (ret < 0) if (ret < 0)
......
...@@ -7142,6 +7142,7 @@ static int read_one_chunk(struct btrfs_key *key, struct extent_buffer *leaf, ...@@ -7142,6 +7142,7 @@ static int read_one_chunk(struct btrfs_key *key, struct extent_buffer *leaf,
u64 devid; u64 devid;
u64 type; u64 type;
u8 uuid[BTRFS_UUID_SIZE]; u8 uuid[BTRFS_UUID_SIZE];
int index;
int num_stripes; int num_stripes;
int ret; int ret;
int i; int i;
...@@ -7149,6 +7150,7 @@ static int read_one_chunk(struct btrfs_key *key, struct extent_buffer *leaf, ...@@ -7149,6 +7150,7 @@ static int read_one_chunk(struct btrfs_key *key, struct extent_buffer *leaf,
logical = key->offset; logical = key->offset;
length = btrfs_chunk_length(leaf, chunk); length = btrfs_chunk_length(leaf, chunk);
type = btrfs_chunk_type(leaf, chunk); type = btrfs_chunk_type(leaf, chunk);
index = btrfs_bg_flags_to_raid_index(type);
num_stripes = btrfs_chunk_num_stripes(leaf, chunk); num_stripes = btrfs_chunk_num_stripes(leaf, chunk);
#if BITS_PER_LONG == 32 #if BITS_PER_LONG == 32
...@@ -7202,7 +7204,15 @@ static int read_one_chunk(struct btrfs_key *key, struct extent_buffer *leaf, ...@@ -7202,7 +7204,15 @@ static int read_one_chunk(struct btrfs_key *key, struct extent_buffer *leaf,
map->io_align = btrfs_chunk_io_align(leaf, chunk); map->io_align = btrfs_chunk_io_align(leaf, chunk);
map->stripe_len = btrfs_chunk_stripe_len(leaf, chunk); map->stripe_len = btrfs_chunk_stripe_len(leaf, chunk);
map->type = type; map->type = type;
map->sub_stripes = btrfs_chunk_sub_stripes(leaf, chunk); /*
* We can't use the sub_stripes value, as for profiles other than
* RAID10, they may have 0 as sub_stripes for filesystems created by
* older mkfs (<v5.4).
* In that case, it can cause divide-by-zero errors later.
* Since currently sub_stripes is fixed for each profile, let's
* use the trusted value instead.
*/
map->sub_stripes = btrfs_raid_array[index].sub_stripes;
map->verified_stripes = 0; map->verified_stripes = 0;
em->orig_block_len = btrfs_calc_stripe_length(em); em->orig_block_len = btrfs_calc_stripe_length(em);
for (i = 0; i < num_stripes; i++) { for (i = 0; i < num_stripes; i++) {
......
...@@ -395,6 +395,7 @@ typedef void (*btrfs_bio_end_io_t)(struct btrfs_bio *bbio); ...@@ -395,6 +395,7 @@ typedef void (*btrfs_bio_end_io_t)(struct btrfs_bio *bbio);
*/ */
struct btrfs_bio { struct btrfs_bio {
unsigned int mirror_num; unsigned int mirror_num;
struct bvec_iter iter;
/* for direct I/O */ /* for direct I/O */
u64 file_offset; u64 file_offset;
...@@ -403,7 +404,6 @@ struct btrfs_bio { ...@@ -403,7 +404,6 @@ struct btrfs_bio {
struct btrfs_device *device; struct btrfs_device *device;
u8 *csum; u8 *csum;
u8 csum_inline[BTRFS_BIO_INLINE_CSUM_SIZE]; u8 csum_inline[BTRFS_BIO_INLINE_CSUM_SIZE];
struct bvec_iter iter;
/* End I/O information supplied to btrfs_bio_alloc */ /* End I/O information supplied to btrfs_bio_alloc */
btrfs_bio_end_io_t end_io; btrfs_bio_end_io_t end_io;
......
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