Skip to content

Commit 18d46e7

Browse files
committed
Merge tag 'for-6.7-rc3-tag' of git://git.kernel.org/pub/scm/linux/kernel/git/kdave/linux
Pull btrfs fixes from David Sterba: "A few fixes and message updates: - for simple quotas, handle the case when a snapshot is created and the target qgroup already exists - fix a warning when file descriptor given to send ioctl is not writable - fix off-by-one condition when checking chunk maps - free pages when page array allocation fails during compression read, other cases were handled - fix memory leak on error handling path in ref-verify debugging feature - copy missing struct member 'version' in 64/32bit compat send ioctl - tree-checker verifies inline backref ordering - print messages to syslog on first mount and last unmount - update error messages when reading chunk maps" * tag 'for-6.7-rc3-tag' of git://git.kernel.org/pub/scm/linux/kernel/git/kdave/linux: btrfs: send: ensure send_fd is writable btrfs: free the allocated memory if btrfs_alloc_page_array() fails btrfs: fix 64bit compat send ioctl arguments not initializing version member btrfs: make error messages more clear when getting a chunk map btrfs: fix off-by-one when checking chunk map includes logical address btrfs: ref-verify: fix memory leaks in btrfs_ref_tree_mod() btrfs: add dmesg output for first mount and last unmount of a filesystem btrfs: do not abort transaction if there is already an existing qgroup btrfs: tree-checker: add type and sequence check for inline backrefs
2 parents df60cee + 0ac1d13 commit 18d46e7

9 files changed

Lines changed: 62 additions & 10 deletions

File tree

fs/btrfs/disk-io.c

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3213,6 +3213,7 @@ int __cold open_ctree(struct super_block *sb, struct btrfs_fs_devices *fs_device
32133213
goto fail_alloc;
32143214
}
32153215

3216+
btrfs_info(fs_info, "first mount of filesystem %pU", disk_super->fsid);
32163217
/*
32173218
* Verify the type first, if that or the checksum value are
32183219
* corrupted, we'll find out

fs/btrfs/extent_io.c

Lines changed: 8 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -674,8 +674,8 @@ static void end_bio_extent_readpage(struct btrfs_bio *bbio)
674674
* the array will be skipped
675675
*
676676
* Return: 0 if all pages were able to be allocated;
677-
* -ENOMEM otherwise, and the caller is responsible for freeing all
678-
* non-null page pointers in the array.
677+
* -ENOMEM otherwise, the partially allocated pages would be freed and
678+
* the array slots zeroed
679679
*/
680680
int btrfs_alloc_page_array(unsigned int nr_pages, struct page **page_array)
681681
{
@@ -694,8 +694,13 @@ int btrfs_alloc_page_array(unsigned int nr_pages, struct page **page_array)
694694
* though alloc_pages_bulk_array() falls back to alloc_page()
695695
* if it could not bulk-allocate. So we must be out of memory.
696696
*/
697-
if (allocated == last)
697+
if (allocated == last) {
698+
for (int i = 0; i < allocated; i++) {
699+
__free_page(page_array[i]);
700+
page_array[i] = NULL;
701+
}
698702
return -ENOMEM;
703+
}
699704

700705
memalloc_retry_wait(GFP_NOFS);
701706
}

fs/btrfs/ioctl.c

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4356,6 +4356,7 @@ static int _btrfs_ioctl_send(struct inode *inode, void __user *argp, bool compat
43564356
arg->clone_sources = compat_ptr(args32.clone_sources);
43574357
arg->parent_root = args32.parent_root;
43584358
arg->flags = args32.flags;
4359+
arg->version = args32.version;
43594360
memcpy(arg->reserved, args32.reserved,
43604361
sizeof(args32.reserved));
43614362
#else

fs/btrfs/ref-verify.c

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -794,6 +794,7 @@ int btrfs_ref_tree_mod(struct btrfs_fs_info *fs_info,
794794
dump_ref_action(fs_info, ra);
795795
kfree(ref);
796796
kfree(ra);
797+
kfree(re);
797798
goto out_unlock;
798799
} else if (be->num_refs == 0) {
799800
btrfs_err(fs_info,
@@ -803,6 +804,7 @@ int btrfs_ref_tree_mod(struct btrfs_fs_info *fs_info,
803804
dump_ref_action(fs_info, ra);
804805
kfree(ref);
805806
kfree(ra);
807+
kfree(re);
806808
goto out_unlock;
807809
}
808810

fs/btrfs/send.c

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -8158,7 +8158,7 @@ long btrfs_ioctl_send(struct inode *inode, struct btrfs_ioctl_send_args *arg)
81588158
}
81598159

81608160
sctx->send_filp = fget(arg->send_fd);
8161-
if (!sctx->send_filp) {
8161+
if (!sctx->send_filp || !(sctx->send_filp->f_mode & FMODE_WRITE)) {
81628162
ret = -EBADF;
81638163
goto out;
81648164
}

fs/btrfs/super.c

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -80,7 +80,10 @@ static int btrfs_remount(struct super_block *sb, int *flags, char *data);
8080

8181
static void btrfs_put_super(struct super_block *sb)
8282
{
83-
close_ctree(btrfs_sb(sb));
83+
struct btrfs_fs_info *fs_info = btrfs_sb(sb);
84+
85+
btrfs_info(fs_info, "last unmount of filesystem %pU", fs_info->fs_devices->fsid);
86+
close_ctree(fs_info);
8487
}
8588

8689
enum {

fs/btrfs/transaction.c

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1774,7 +1774,7 @@ static noinline int create_pending_snapshot(struct btrfs_trans_handle *trans,
17741774
btrfs_release_path(path);
17751775

17761776
ret = btrfs_create_qgroup(trans, objectid);
1777-
if (ret) {
1777+
if (ret && ret != -EEXIST) {
17781778
btrfs_abort_transaction(trans, ret);
17791779
goto fail;
17801780
}

fs/btrfs/tree-checker.c

Lines changed: 39 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -31,6 +31,7 @@
3131
#include "inode-item.h"
3232
#include "dir-item.h"
3333
#include "raid-stripe-tree.h"
34+
#include "extent-tree.h"
3435

3536
/*
3637
* Error message should follow the following format:
@@ -1276,6 +1277,8 @@ static int check_extent_item(struct extent_buffer *leaf,
12761277
unsigned long ptr; /* Current pointer inside inline refs */
12771278
unsigned long end; /* Extent item end */
12781279
const u32 item_size = btrfs_item_size(leaf, slot);
1280+
u8 last_type = 0;
1281+
u64 last_seq = U64_MAX;
12791282
u64 flags;
12801283
u64 generation;
12811284
u64 total_refs; /* Total refs in btrfs_extent_item */
@@ -1322,6 +1325,18 @@ static int check_extent_item(struct extent_buffer *leaf,
13221325
* 2.2) Ref type specific data
13231326
* Either using btrfs_extent_inline_ref::offset, or specific
13241327
* data structure.
1328+
*
1329+
* All above inline items should follow the order:
1330+
*
1331+
* - All btrfs_extent_inline_ref::type should be in an ascending
1332+
* order
1333+
*
1334+
* - Within the same type, the items should follow a descending
1335+
* order by their sequence number. The sequence number is
1336+
* determined by:
1337+
* * btrfs_extent_inline_ref::offset for all types other than
1338+
* EXTENT_DATA_REF
1339+
* * hash_extent_data_ref() for EXTENT_DATA_REF
13251340
*/
13261341
if (unlikely(item_size < sizeof(*ei))) {
13271342
extent_err(leaf, slot,
@@ -1403,6 +1418,7 @@ static int check_extent_item(struct extent_buffer *leaf,
14031418
struct btrfs_extent_inline_ref *iref;
14041419
struct btrfs_extent_data_ref *dref;
14051420
struct btrfs_shared_data_ref *sref;
1421+
u64 seq;
14061422
u64 dref_offset;
14071423
u64 inline_offset;
14081424
u8 inline_type;
@@ -1416,6 +1432,7 @@ static int check_extent_item(struct extent_buffer *leaf,
14161432
iref = (struct btrfs_extent_inline_ref *)ptr;
14171433
inline_type = btrfs_extent_inline_ref_type(leaf, iref);
14181434
inline_offset = btrfs_extent_inline_ref_offset(leaf, iref);
1435+
seq = inline_offset;
14191436
if (unlikely(ptr + btrfs_extent_inline_ref_size(inline_type) > end)) {
14201437
extent_err(leaf, slot,
14211438
"inline ref item overflows extent item, ptr %lu iref size %u end %lu",
@@ -1446,6 +1463,10 @@ static int check_extent_item(struct extent_buffer *leaf,
14461463
case BTRFS_EXTENT_DATA_REF_KEY:
14471464
dref = (struct btrfs_extent_data_ref *)(&iref->offset);
14481465
dref_offset = btrfs_extent_data_ref_offset(leaf, dref);
1466+
seq = hash_extent_data_ref(
1467+
btrfs_extent_data_ref_root(leaf, dref),
1468+
btrfs_extent_data_ref_objectid(leaf, dref),
1469+
btrfs_extent_data_ref_offset(leaf, dref));
14491470
if (unlikely(!IS_ALIGNED(dref_offset,
14501471
fs_info->sectorsize))) {
14511472
extent_err(leaf, slot,
@@ -1475,6 +1496,24 @@ static int check_extent_item(struct extent_buffer *leaf,
14751496
inline_type);
14761497
return -EUCLEAN;
14771498
}
1499+
if (inline_type < last_type) {
1500+
extent_err(leaf, slot,
1501+
"inline ref out-of-order: has type %u, prev type %u",
1502+
inline_type, last_type);
1503+
return -EUCLEAN;
1504+
}
1505+
/* Type changed, allow the sequence starts from U64_MAX again. */
1506+
if (inline_type > last_type)
1507+
last_seq = U64_MAX;
1508+
if (seq > last_seq) {
1509+
extent_err(leaf, slot,
1510+
"inline ref out-of-order: has type %u offset %llu seq 0x%llx, prev type %u seq 0x%llx",
1511+
inline_type, inline_offset, seq,
1512+
last_type, last_seq);
1513+
return -EUCLEAN;
1514+
}
1515+
last_type = inline_type;
1516+
last_seq = seq;
14781517
ptr += btrfs_extent_inline_ref_size(inline_type);
14791518
}
14801519
/* No padding is allowed */

fs/btrfs/volumes.c

Lines changed: 5 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -3006,15 +3006,16 @@ struct extent_map *btrfs_get_chunk_map(struct btrfs_fs_info *fs_info,
30063006
read_unlock(&em_tree->lock);
30073007

30083008
if (!em) {
3009-
btrfs_crit(fs_info, "unable to find logical %llu length %llu",
3009+
btrfs_crit(fs_info,
3010+
"unable to find chunk map for logical %llu length %llu",
30103011
logical, length);
30113012
return ERR_PTR(-EINVAL);
30123013
}
30133014

3014-
if (em->start > logical || em->start + em->len < logical) {
3015+
if (em->start > logical || em->start + em->len <= logical) {
30153016
btrfs_crit(fs_info,
3016-
"found a bad mapping, wanted %llu-%llu, found %llu-%llu",
3017-
logical, length, em->start, em->start + em->len);
3017+
"found a bad chunk map, wanted %llu-%llu, found %llu-%llu",
3018+
logical, logical + length, em->start, em->start + em->len);
30183019
free_extent_map(em);
30193020
return ERR_PTR(-EINVAL);
30203021
}

0 commit comments

Comments
 (0)