mirror of
https://git.kernel.org/pub/scm/linux/kernel/git/stable/linux.git
synced 2025-01-08 14:13:53 +00:00
for-6.1-rc3-tag
-----BEGIN PGP SIGNATURE----- iQIzBAABCgAdFiEE8rQSAMVO+zA4DBdWxWXV+ddtWDsFAmNfzNwACgkQxWXV+ddt WDuC6Q//a72PAq1sjwvQqAcr+OOe3PWnmlwYZCnXxiab5c74Kc7rDhDZcO3m/Qt5 3YTwgK5FT4Y0AI8RN1NXx3+UOAYCWp/TGeBdbPHg35XIYKAnCh4pfql84Uiw1Awz HbqmSTma7sqVdRMehkKCkd7w4YoyAAsDdyXFQlSFm4ah9WHFZDswBc+m6xQZuWvU QVQS6wUTxkxuBZp0UComWGBNHiDeDZbga7VqO8UHPYOB394IV2mYP6fh8l0oB/BS bfKgsHjV9e0S0Ul0oPVADCGCiJcTbdnw3IA+Cje7MSgZ3kds/4Bo5IJWT5QRb94A yDAFpxc+t3+FgpoKS3/tZK7imXwgpXueiT2bBj+BjDDWD2VUVVBG4QmXYIW6tuqY vtEFw9+NCAvS2gRetHyXxQshYh/QW//+AZSkuI6/fuPSM+lRG5E0lnDxqrZiOMIo e6SJOGH3tCmtusL5VSXIQ8DPaLI9PBg4OXChytwmLHwPIusbQOvD5sTDpd99UezB dLXqZOGGScAc11HU1AFyZfAxTBybUgUxX/xCviJtf7ZOWKdcwiFrzSJOL5upSPz3 8qZTVjrD71mJlEa0Z8wj0Utuu4Psecp0GN+fs5JJxmqsFO0cYApU17OqPZ22+yEV RU26YNpqurYVarHVER4WxyXYraBYd1Cr6s6bFVDnuZynfiCOYIw= =3tvc -----END PGP SIGNATURE----- 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
This commit is contained in:
commit
5aaef24b5c
@ -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
|
||||
* algorithm. Pass the raw disk superblock data.
|
||||
*/
|
||||
static int btrfs_check_super_csum(struct btrfs_fs_info *fs_info,
|
||||
char *raw_disk_sb)
|
||||
int btrfs_check_super_csum(struct btrfs_fs_info *fs_info,
|
||||
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];
|
||||
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,
|
||||
* BTRFS_SUPER_INFO_SIZE range, we expect that the unused space is
|
||||
* 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);
|
||||
|
||||
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
|
||||
* We want to check superblock checksum, the type is stored inside.
|
||||
* 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");
|
||||
err = -EINVAL;
|
||||
btrfs_release_disk_super(disk_super);
|
||||
|
@ -42,6 +42,8 @@ struct extent_buffer *btrfs_find_create_tree_block(
|
||||
void btrfs_clean_tree_block(struct extent_buffer *buf);
|
||||
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_check_super_csum(struct btrfs_fs_info *fs_info,
|
||||
const struct btrfs_super_block *disk_sb);
|
||||
int __cold open_ctree(struct super_block *sb,
|
||||
struct btrfs_fs_devices *fs_devices,
|
||||
char *options);
|
||||
|
@ -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,
|
||||
u64 root_objectid, u32 generation,
|
||||
u64 root_objectid, u64 generation,
|
||||
int check_generation)
|
||||
{
|
||||
struct btrfs_fs_info *fs_info = btrfs_sb(sb);
|
||||
|
@ -19,7 +19,7 @@ struct btrfs_fid {
|
||||
} __attribute__ ((packed));
|
||||
|
||||
struct dentry *btrfs_get_dentry(struct super_block *sb, u64 objectid,
|
||||
u64 root_objectid, u32 generation,
|
||||
u64 root_objectid, u64 generation,
|
||||
int check_generation);
|
||||
struct dentry *btrfs_get_parent(struct dentry *child);
|
||||
|
||||
|
@ -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
|
||||
* have recorded mod log operations that point to this leaf.
|
||||
* So we must make sure no one reuses this leaf's extent before
|
||||
* mod log operations are applied to a node, otherwise after
|
||||
* rewinding a node using the mod log operations we get an
|
||||
* inconsistent btree, as the leaf's extent may now be used as
|
||||
* a node or leaf for another different btree.
|
||||
* If there are tree mod log users we may have recorded mod log
|
||||
* operations for this node. If we re-allocate this node we
|
||||
* could replay operations on this node that happened when it
|
||||
* existed in a completely different root. For example if it
|
||||
* was part of root A, then was reallocated to root B, and we
|
||||
* are doing a btrfs_old_search_slot(root b), we could replay
|
||||
* 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
|
||||
* 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
|
||||
* find a node pointing to this leaf and record operations that
|
||||
* point to this leaf.
|
||||
* check a new tree mod log user joins we will not have an
|
||||
* existing log of operations on this node that we have to
|
||||
* contend with.
|
||||
*/
|
||||
if (btrfs_header_level(buf) == 0 &&
|
||||
test_bit(BTRFS_FS_TREE_MOD_LOG_USERS, &fs_info->flags))
|
||||
if (test_bit(BTRFS_FS_TREE_MOD_LOG_USERS, &fs_info->flags))
|
||||
must_pin = true;
|
||||
|
||||
if (must_pin || btrfs_is_zoned(fs_info)) {
|
||||
|
@ -1632,10 +1632,8 @@ static int full_stripe_write(struct btrfs_raid_bio *rbio)
|
||||
int ret;
|
||||
|
||||
ret = alloc_rbio_parity_pages(rbio);
|
||||
if (ret) {
|
||||
__free_raid_bio(rbio);
|
||||
if (ret)
|
||||
return ret;
|
||||
}
|
||||
|
||||
ret = lock_stripe_add(rbio);
|
||||
if (ret == 0)
|
||||
@ -1823,8 +1821,10 @@ void raid56_parity_write(struct bio *bio, struct btrfs_io_context *bioc)
|
||||
*/
|
||||
if (rbio_is_full(rbio)) {
|
||||
ret = full_stripe_write(rbio);
|
||||
if (ret)
|
||||
if (ret) {
|
||||
__free_raid_bio(rbio);
|
||||
goto fail;
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
@ -1838,8 +1838,10 @@ void raid56_parity_write(struct bio *bio, struct btrfs_io_context *bioc)
|
||||
list_add_tail(&rbio->plug_list, &plug->rbio_list);
|
||||
} else {
|
||||
ret = __raid56_parity_write(rbio);
|
||||
if (ret)
|
||||
if (ret) {
|
||||
__free_raid_bio(rbio);
|
||||
goto fail;
|
||||
}
|
||||
}
|
||||
|
||||
return;
|
||||
@ -2742,8 +2744,10 @@ raid56_alloc_missing_rbio(struct bio *bio, struct btrfs_io_context *bioc)
|
||||
|
||||
rbio->faila = find_logical_bio_stripe(rbio, bio);
|
||||
if (rbio->faila == -1) {
|
||||
BUG();
|
||||
kfree(rbio);
|
||||
btrfs_warn_rl(fs_info,
|
||||
"can not determine the failed stripe number for full stripe %llu",
|
||||
bioc->raid_map[0]);
|
||||
__free_raid_bio(rbio);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
|
@ -6668,17 +6668,19 @@ static int changed_inode(struct send_ctx *sctx,
|
||||
/*
|
||||
* First, process the inode as if it was deleted.
|
||||
*/
|
||||
sctx->cur_inode_gen = right_gen;
|
||||
sctx->cur_inode_new = false;
|
||||
sctx->cur_inode_deleted = true;
|
||||
sctx->cur_inode_size = btrfs_inode_size(
|
||||
sctx->right_path->nodes[0], right_ii);
|
||||
sctx->cur_inode_mode = btrfs_inode_mode(
|
||||
sctx->right_path->nodes[0], right_ii);
|
||||
ret = process_all_refs(sctx,
|
||||
BTRFS_COMPARE_TREE_DELETED);
|
||||
if (ret < 0)
|
||||
goto out;
|
||||
if (old_nlinks > 0) {
|
||||
sctx->cur_inode_gen = right_gen;
|
||||
sctx->cur_inode_new = false;
|
||||
sctx->cur_inode_deleted = true;
|
||||
sctx->cur_inode_size = btrfs_inode_size(
|
||||
sctx->right_path->nodes[0], right_ii);
|
||||
sctx->cur_inode_mode = btrfs_inode_mode(
|
||||
sctx->right_path->nodes[0], right_ii);
|
||||
ret = process_all_refs(sctx,
|
||||
BTRFS_COMPARE_TREE_DELETED);
|
||||
if (ret < 0)
|
||||
goto out;
|
||||
}
|
||||
|
||||
/*
|
||||
* Now process the inode as if it was new.
|
||||
|
@ -2555,6 +2555,7 @@ static int check_dev_super(struct btrfs_device *dev)
|
||||
{
|
||||
struct btrfs_fs_info *fs_info = dev->fs_info;
|
||||
struct btrfs_super_block *sb;
|
||||
u16 csum_type;
|
||||
int ret = 0;
|
||||
|
||||
/* This should be called with fs still frozen. */
|
||||
@ -2569,6 +2570,21 @@ static int check_dev_super(struct btrfs_device *dev)
|
||||
if (IS_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. */
|
||||
ret = btrfs_validate_super(fs_info, sb, 0);
|
||||
if (ret < 0)
|
||||
|
@ -7142,6 +7142,7 @@ static int read_one_chunk(struct btrfs_key *key, struct extent_buffer *leaf,
|
||||
u64 devid;
|
||||
u64 type;
|
||||
u8 uuid[BTRFS_UUID_SIZE];
|
||||
int index;
|
||||
int num_stripes;
|
||||
int ret;
|
||||
int i;
|
||||
@ -7149,6 +7150,7 @@ static int read_one_chunk(struct btrfs_key *key, struct extent_buffer *leaf,
|
||||
logical = key->offset;
|
||||
length = btrfs_chunk_length(leaf, chunk);
|
||||
type = btrfs_chunk_type(leaf, chunk);
|
||||
index = btrfs_bg_flags_to_raid_index(type);
|
||||
num_stripes = btrfs_chunk_num_stripes(leaf, chunk);
|
||||
|
||||
#if BITS_PER_LONG == 32
|
||||
@ -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->stripe_len = btrfs_chunk_stripe_len(leaf, chunk);
|
||||
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;
|
||||
em->orig_block_len = btrfs_calc_stripe_length(em);
|
||||
for (i = 0; i < num_stripes; i++) {
|
||||
|
@ -395,6 +395,7 @@ typedef void (*btrfs_bio_end_io_t)(struct btrfs_bio *bbio);
|
||||
*/
|
||||
struct btrfs_bio {
|
||||
unsigned int mirror_num;
|
||||
struct bvec_iter iter;
|
||||
|
||||
/* for direct I/O */
|
||||
u64 file_offset;
|
||||
@ -403,7 +404,6 @@ struct btrfs_bio {
|
||||
struct btrfs_device *device;
|
||||
u8 *csum;
|
||||
u8 csum_inline[BTRFS_BIO_INLINE_CSUM_SIZE];
|
||||
struct bvec_iter iter;
|
||||
|
||||
/* End I/O information supplied to btrfs_bio_alloc */
|
||||
btrfs_bio_end_io_t end_io;
|
||||
|
Loading…
Reference in New Issue
Block a user