Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux
1
fork

Configure Feed

Select the types of activity you want to include in your feed.

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

Pull btrfs fixes from David Sterba:
"A few more fixes. There's one that stands out in size as it fixes an
edge case in fsync.

- fix issue on fsync where file with zero size appears as a non-zero
after log replay

- in zlib compression, handle a crash when data alignment causes
folio reference issues

- fix possible crash with enabled tracepoints on a overlayfs mount

- handle device stats update error

- on zoned filesystems, fix kobject leak on sub-block groups

- fix super block offset in an error message in validation"

* tag 'for-7.0-rc5-tag' of git://git.kernel.org/pub/scm/linux/kernel/git/kdave/linux:
btrfs: fix lost error when running device stats on multiple devices fs
btrfs: tracepoints: get correct superblock from dentry in event btrfs_sync_file()
btrfs: zlib: handle page aligned compressed size correctly
btrfs: fix leak of kobject name for sub-group space_info
btrfs: fix zero size inode with non-zero size after log replay
btrfs: fix super block offset in error message in btrfs_validate_super()

+81 -43
+1 -1
fs/btrfs/block-group.c
··· 4583 4583 for (int i = 0; i < BTRFS_SPACE_INFO_SUB_GROUP_MAX; i++) { 4584 4584 if (space_info->sub_group[i]) { 4585 4585 check_removing_space_info(space_info->sub_group[i]); 4586 - kfree(space_info->sub_group[i]); 4586 + btrfs_sysfs_remove_space_info(space_info->sub_group[i]); 4587 4587 space_info->sub_group[i] = NULL; 4588 4588 } 4589 4589 }
+2 -2
fs/btrfs/disk-io.c
··· 2531 2531 2532 2532 if (mirror_num >= 0 && 2533 2533 btrfs_super_bytenr(sb) != btrfs_sb_offset(mirror_num)) { 2534 - btrfs_err(fs_info, "super offset mismatch %llu != %u", 2535 - btrfs_super_bytenr(sb), BTRFS_SUPER_INFO_OFFSET); 2534 + btrfs_err(fs_info, "super offset mismatch %llu != %llu", 2535 + btrfs_super_bytenr(sb), btrfs_sb_offset(mirror_num)); 2536 2536 ret = -EINVAL; 2537 2537 } 2538 2538
+65 -33
fs/btrfs/tree-log.c
··· 4616 4616 struct inode *inode, bool log_inode_only, 4617 4617 u64 logged_isize) 4618 4618 { 4619 + u64 gen = BTRFS_I(inode)->generation; 4619 4620 u64 flags; 4620 4621 4621 4622 if (log_inode_only) { 4622 - /* set the generation to zero so the recover code 4623 - * can tell the difference between an logging 4624 - * just to say 'this inode exists' and a logging 4625 - * to say 'update this inode with these values' 4623 + /* 4624 + * Set the generation to zero so the recover code can tell the 4625 + * difference between a logging just to say 'this inode exists' 4626 + * and a logging to say 'update this inode with these values'. 4627 + * But only if the inode was not already logged before. 4628 + * We access ->logged_trans directly since it was already set 4629 + * up in the call chain by btrfs_log_inode(), and data_race() 4630 + * to avoid false alerts from KCSAN and since it was set already 4631 + * and one can set it to 0 since that only happens on eviction 4632 + * and we are holding a ref on the inode. 4626 4633 */ 4627 - btrfs_set_inode_generation(leaf, item, 0); 4634 + ASSERT(data_race(BTRFS_I(inode)->logged_trans) > 0); 4635 + if (data_race(BTRFS_I(inode)->logged_trans) < trans->transid) 4636 + gen = 0; 4637 + 4628 4638 btrfs_set_inode_size(leaf, item, logged_isize); 4629 4639 } else { 4630 - btrfs_set_inode_generation(leaf, item, BTRFS_I(inode)->generation); 4631 4640 btrfs_set_inode_size(leaf, item, inode->i_size); 4632 4641 } 4642 + 4643 + btrfs_set_inode_generation(leaf, item, gen); 4633 4644 4634 4645 btrfs_set_inode_uid(leaf, item, i_uid_read(inode)); 4635 4646 btrfs_set_inode_gid(leaf, item, i_gid_read(inode)); ··· 5459 5448 return 0; 5460 5449 } 5461 5450 5462 - static int logged_inode_size(struct btrfs_root *log, struct btrfs_inode *inode, 5463 - struct btrfs_path *path, u64 *size_ret) 5451 + static int get_inode_size_to_log(struct btrfs_trans_handle *trans, 5452 + struct btrfs_inode *inode, 5453 + struct btrfs_path *path, u64 *size_ret) 5464 5454 { 5465 5455 struct btrfs_key key; 5456 + struct btrfs_inode_item *item; 5466 5457 int ret; 5467 5458 5468 5459 key.objectid = btrfs_ino(inode); 5469 5460 key.type = BTRFS_INODE_ITEM_KEY; 5470 5461 key.offset = 0; 5471 5462 5472 - ret = btrfs_search_slot(NULL, log, &key, path, 0, 0); 5473 - if (ret < 0) { 5474 - return ret; 5475 - } else if (ret > 0) { 5476 - *size_ret = 0; 5477 - } else { 5478 - struct btrfs_inode_item *item; 5463 + /* 5464 + * Our caller called inode_logged(), so logged_trans is up to date. 5465 + * Use data_race() to silence any warning from KCSAN. Once logged_trans 5466 + * is set, it can only be reset to 0 after inode eviction. 5467 + */ 5468 + if (data_race(inode->logged_trans) == trans->transid) { 5469 + ret = btrfs_search_slot(NULL, inode->root->log_root, &key, path, 0, 0); 5470 + } else if (inode->generation < trans->transid) { 5471 + path->search_commit_root = true; 5472 + path->skip_locking = true; 5473 + ret = btrfs_search_slot(NULL, inode->root, &key, path, 0, 0); 5474 + path->search_commit_root = false; 5475 + path->skip_locking = false; 5479 5476 5480 - item = btrfs_item_ptr(path->nodes[0], path->slots[0], 5481 - struct btrfs_inode_item); 5482 - *size_ret = btrfs_inode_size(path->nodes[0], item); 5483 - /* 5484 - * If the in-memory inode's i_size is smaller then the inode 5485 - * size stored in the btree, return the inode's i_size, so 5486 - * that we get a correct inode size after replaying the log 5487 - * when before a power failure we had a shrinking truncate 5488 - * followed by addition of a new name (rename / new hard link). 5489 - * Otherwise return the inode size from the btree, to avoid 5490 - * data loss when replaying a log due to previously doing a 5491 - * write that expands the inode's size and logging a new name 5492 - * immediately after. 5493 - */ 5494 - if (*size_ret > inode->vfs_inode.i_size) 5495 - *size_ret = inode->vfs_inode.i_size; 5477 + } else { 5478 + *size_ret = 0; 5479 + return 0; 5496 5480 } 5481 + 5482 + /* 5483 + * If the inode was logged before or is from a past transaction, then 5484 + * its inode item must exist in the log root or in the commit root. 5485 + */ 5486 + ASSERT(ret <= 0); 5487 + if (WARN_ON_ONCE(ret > 0)) 5488 + ret = -ENOENT; 5489 + 5490 + if (ret < 0) 5491 + return ret; 5492 + 5493 + item = btrfs_item_ptr(path->nodes[0], path->slots[0], 5494 + struct btrfs_inode_item); 5495 + *size_ret = btrfs_inode_size(path->nodes[0], item); 5496 + /* 5497 + * If the in-memory inode's i_size is smaller then the inode size stored 5498 + * in the btree, return the inode's i_size, so that we get a correct 5499 + * inode size after replaying the log when before a power failure we had 5500 + * a shrinking truncate followed by addition of a new name (rename / new 5501 + * hard link). Otherwise return the inode size from the btree, to avoid 5502 + * data loss when replaying a log due to previously doing a write that 5503 + * expands the inode's size and logging a new name immediately after. 5504 + */ 5505 + if (*size_ret > inode->vfs_inode.i_size) 5506 + *size_ret = inode->vfs_inode.i_size; 5497 5507 5498 5508 btrfs_release_path(path); 5499 5509 return 0; ··· 7028 6996 ret = drop_inode_items(trans, log, path, inode, 7029 6997 BTRFS_XATTR_ITEM_KEY); 7030 6998 } else { 7031 - if (inode_only == LOG_INODE_EXISTS && ctx->logged_before) { 6999 + if (inode_only == LOG_INODE_EXISTS) { 7032 7000 /* 7033 7001 * Make sure the new inode item we write to the log has 7034 7002 * the same isize as the current one (if it exists). ··· 7042 7010 * (zeroes), as if an expanding truncate happened, 7043 7011 * instead of getting a file of 4Kb only. 7044 7012 */ 7045 - ret = logged_inode_size(log, inode, path, &logged_isize); 7013 + ret = get_inode_size_to_log(trans, inode, path, &logged_isize); 7046 7014 if (ret) 7047 7015 goto out_unlock; 7048 7016 }
+3 -2
fs/btrfs/volumes.c
··· 8099 8099 smp_rmb(); 8100 8100 8101 8101 ret = update_dev_stat_item(trans, device); 8102 - if (!ret) 8103 - atomic_sub(stats_cnt, &device->dev_stats_ccnt); 8102 + if (ret) 8103 + break; 8104 + atomic_sub(stats_cnt, &device->dev_stats_ccnt); 8104 8105 } 8105 8106 mutex_unlock(&fs_devices->device_list_mutex); 8106 8107
+3 -1
fs/btrfs/zlib.c
··· 308 308 } 309 309 /* Queue the remaining part of the folio. */ 310 310 if (workspace->strm.total_out > bio->bi_iter.bi_size) { 311 - u32 cur_len = offset_in_folio(out_folio, workspace->strm.total_out); 311 + const u32 cur_len = workspace->strm.total_out - bio->bi_iter.bi_size; 312 + 313 + ASSERT(cur_len <= folio_size(out_folio)); 312 314 313 315 if (!bio_add_folio(bio, out_folio, cur_len, 0)) { 314 316 ret = -E2BIG;
+7 -4
include/trace/events/btrfs.h
··· 769 769 ), 770 770 771 771 TP_fast_assign( 772 - const struct dentry *dentry = file->f_path.dentry; 773 - const struct inode *inode = d_inode(dentry); 772 + struct dentry *dentry = file_dentry(file); 773 + struct inode *inode = file_inode(file); 774 + struct dentry *parent = dget_parent(dentry); 775 + struct inode *parent_inode = d_inode(parent); 774 776 775 - TP_fast_assign_fsid(btrfs_sb(file->f_path.dentry->d_sb)); 777 + dput(parent); 778 + TP_fast_assign_fsid(btrfs_sb(inode->i_sb)); 776 779 __entry->ino = btrfs_ino(BTRFS_I(inode)); 777 - __entry->parent = btrfs_ino(BTRFS_I(d_inode(dentry->d_parent))); 780 + __entry->parent = btrfs_ino(BTRFS_I(parent_inode)); 778 781 __entry->datasync = datasync; 779 782 __entry->root_objectid = btrfs_root_id(BTRFS_I(inode)->root); 780 783 ),