Skip to content

Commit 5404525

Browse files
committed
Merge tag 'for-4.19-rc2-tag' of git://git.kernel.org/pub/scm/linux/kernel/git/kdave/linux
Pull btrfs fixes from David Sterba: - fix for improper fsync after hardlink - fix for a corruption during file deduplication - use after free fixes - RCU warning fix - fix for buffered write to nodatacow file * tag 'for-4.19-rc2-tag' of git://git.kernel.org/pub/scm/linux/kernel/git/kdave/linux: btrfs: Fix suspicious RCU usage warning in btrfs_debug_in_rcu btrfs: use after free in btrfs_quota_enable btrfs: btrfs_shrink_device should call commit transaction at the end btrfs: fix qgroup_free wrong num_bytes in btrfs_subvolume_reserve_metadata Btrfs: fix data corruption when deduplicating between different files Btrfs: sync log after logging new name Btrfs: fix unexpected failure of nocow buffered writes after snapshotting when low on space
2 parents b36fdc6 + b6fdfbf commit 5404525

File tree

9 files changed

+197
-55
lines changed

9 files changed

+197
-55
lines changed

fs/btrfs/ctree.h

Lines changed: 10 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1280,6 +1280,7 @@ struct btrfs_root {
12801280
int send_in_progress;
12811281
struct btrfs_subvolume_writers *subv_writers;
12821282
atomic_t will_be_snapshotted;
1283+
atomic_t snapshot_force_cow;
12831284

12841285
/* For qgroup metadata reserved space */
12851286
spinlock_t qgroup_meta_rsv_lock;
@@ -3390,9 +3391,9 @@ do { \
33903391
#define btrfs_debug(fs_info, fmt, args...) \
33913392
btrfs_no_printk(fs_info, KERN_DEBUG fmt, ##args)
33923393
#define btrfs_debug_in_rcu(fs_info, fmt, args...) \
3393-
btrfs_no_printk(fs_info, KERN_DEBUG fmt, ##args)
3394+
btrfs_no_printk_in_rcu(fs_info, KERN_DEBUG fmt, ##args)
33943395
#define btrfs_debug_rl_in_rcu(fs_info, fmt, args...) \
3395-
btrfs_no_printk(fs_info, KERN_DEBUG fmt, ##args)
3396+
btrfs_no_printk_in_rcu(fs_info, KERN_DEBUG fmt, ##args)
33963397
#define btrfs_debug_rl(fs_info, fmt, args...) \
33973398
btrfs_no_printk(fs_info, KERN_DEBUG fmt, ##args)
33983399
#endif
@@ -3404,6 +3405,13 @@ do { \
34043405
rcu_read_unlock(); \
34053406
} while (0)
34063407

3408+
#define btrfs_no_printk_in_rcu(fs_info, fmt, args...) \
3409+
do { \
3410+
rcu_read_lock(); \
3411+
btrfs_no_printk(fs_info, fmt, ##args); \
3412+
rcu_read_unlock(); \
3413+
} while (0)
3414+
34073415
#define btrfs_printk_ratelimited(fs_info, fmt, args...) \
34083416
do { \
34093417
static DEFINE_RATELIMIT_STATE(_rs, \

fs/btrfs/disk-io.c

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1187,6 +1187,7 @@ static void __setup_root(struct btrfs_root *root, struct btrfs_fs_info *fs_info,
11871187
atomic_set(&root->log_batch, 0);
11881188
refcount_set(&root->refs, 1);
11891189
atomic_set(&root->will_be_snapshotted, 0);
1190+
atomic_set(&root->snapshot_force_cow, 0);
11901191
root->log_transid = 0;
11911192
root->log_transid_committed = -1;
11921193
root->last_log_commit = 0;

fs/btrfs/extent-tree.c

Lines changed: 8 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -5800,7 +5800,7 @@ void btrfs_trans_release_chunk_metadata(struct btrfs_trans_handle *trans)
58005800
* root: the root of the parent directory
58015801
* rsv: block reservation
58025802
* items: the number of items that we need do reservation
5803-
* qgroup_reserved: used to return the reserved size in qgroup
5803+
* use_global_rsv: allow fallback to the global block reservation
58045804
*
58055805
* This function is used to reserve the space for snapshot/subvolume
58065806
* creation and deletion. Those operations are different with the
@@ -5810,23 +5810,22 @@ void btrfs_trans_release_chunk_metadata(struct btrfs_trans_handle *trans)
58105810
* the space reservation mechanism in start_transaction().
58115811
*/
58125812
int btrfs_subvolume_reserve_metadata(struct btrfs_root *root,
5813-
struct btrfs_block_rsv *rsv,
5814-
int items,
5813+
struct btrfs_block_rsv *rsv, int items,
58155814
bool use_global_rsv)
58165815
{
5816+
u64 qgroup_num_bytes = 0;
58175817
u64 num_bytes;
58185818
int ret;
58195819
struct btrfs_fs_info *fs_info = root->fs_info;
58205820
struct btrfs_block_rsv *global_rsv = &fs_info->global_block_rsv;
58215821

58225822
if (test_bit(BTRFS_FS_QUOTA_ENABLED, &fs_info->flags)) {
58235823
/* One for parent inode, two for dir entries */
5824-
num_bytes = 3 * fs_info->nodesize;
5825-
ret = btrfs_qgroup_reserve_meta_prealloc(root, num_bytes, true);
5824+
qgroup_num_bytes = 3 * fs_info->nodesize;
5825+
ret = btrfs_qgroup_reserve_meta_prealloc(root,
5826+
qgroup_num_bytes, true);
58265827
if (ret)
58275828
return ret;
5828-
} else {
5829-
num_bytes = 0;
58305829
}
58315830

58325831
num_bytes = btrfs_calc_trans_metadata_size(fs_info, items);
@@ -5838,8 +5837,8 @@ int btrfs_subvolume_reserve_metadata(struct btrfs_root *root,
58385837
if (ret == -ENOSPC && use_global_rsv)
58395838
ret = btrfs_block_rsv_migrate(global_rsv, rsv, num_bytes, 1);
58405839

5841-
if (ret && num_bytes)
5842-
btrfs_qgroup_free_meta_prealloc(root, num_bytes);
5840+
if (ret && qgroup_num_bytes)
5841+
btrfs_qgroup_free_meta_prealloc(root, qgroup_num_bytes);
58435842

58445843
return ret;
58455844
}

fs/btrfs/inode.c

Lines changed: 84 additions & 33 deletions
Original file line numberDiff line numberDiff line change
@@ -1271,7 +1271,7 @@ static noinline int run_delalloc_nocow(struct inode *inode,
12711271
u64 disk_num_bytes;
12721272
u64 ram_bytes;
12731273
int extent_type;
1274-
int ret, err;
1274+
int ret;
12751275
int type;
12761276
int nocow;
12771277
int check_prev = 1;
@@ -1403,11 +1403,8 @@ static noinline int run_delalloc_nocow(struct inode *inode,
14031403
* if there are pending snapshots for this root,
14041404
* we fall into common COW way.
14051405
*/
1406-
if (!nolock) {
1407-
err = btrfs_start_write_no_snapshotting(root);
1408-
if (!err)
1409-
goto out_check;
1410-
}
1406+
if (!nolock && atomic_read(&root->snapshot_force_cow))
1407+
goto out_check;
14111408
/*
14121409
* force cow if csum exists in the range.
14131410
* this ensure that csum for a given extent are
@@ -1416,9 +1413,6 @@ static noinline int run_delalloc_nocow(struct inode *inode,
14161413
ret = csum_exist_in_range(fs_info, disk_bytenr,
14171414
num_bytes);
14181415
if (ret) {
1419-
if (!nolock)
1420-
btrfs_end_write_no_snapshotting(root);
1421-
14221416
/*
14231417
* ret could be -EIO if the above fails to read
14241418
* metadata.
@@ -1431,11 +1425,8 @@ static noinline int run_delalloc_nocow(struct inode *inode,
14311425
WARN_ON_ONCE(nolock);
14321426
goto out_check;
14331427
}
1434-
if (!btrfs_inc_nocow_writers(fs_info, disk_bytenr)) {
1435-
if (!nolock)
1436-
btrfs_end_write_no_snapshotting(root);
1428+
if (!btrfs_inc_nocow_writers(fs_info, disk_bytenr))
14371429
goto out_check;
1438-
}
14391430
nocow = 1;
14401431
} else if (extent_type == BTRFS_FILE_EXTENT_INLINE) {
14411432
extent_end = found_key.offset +
@@ -1448,8 +1439,6 @@ static noinline int run_delalloc_nocow(struct inode *inode,
14481439
out_check:
14491440
if (extent_end <= start) {
14501441
path->slots[0]++;
1451-
if (!nolock && nocow)
1452-
btrfs_end_write_no_snapshotting(root);
14531442
if (nocow)
14541443
btrfs_dec_nocow_writers(fs_info, disk_bytenr);
14551444
goto next_slot;
@@ -1471,8 +1460,6 @@ static noinline int run_delalloc_nocow(struct inode *inode,
14711460
end, page_started, nr_written, 1,
14721461
NULL);
14731462
if (ret) {
1474-
if (!nolock && nocow)
1475-
btrfs_end_write_no_snapshotting(root);
14761463
if (nocow)
14771464
btrfs_dec_nocow_writers(fs_info,
14781465
disk_bytenr);
@@ -1492,8 +1479,6 @@ static noinline int run_delalloc_nocow(struct inode *inode,
14921479
ram_bytes, BTRFS_COMPRESS_NONE,
14931480
BTRFS_ORDERED_PREALLOC);
14941481
if (IS_ERR(em)) {
1495-
if (!nolock && nocow)
1496-
btrfs_end_write_no_snapshotting(root);
14971482
if (nocow)
14981483
btrfs_dec_nocow_writers(fs_info,
14991484
disk_bytenr);
@@ -1532,8 +1517,6 @@ static noinline int run_delalloc_nocow(struct inode *inode,
15321517
EXTENT_CLEAR_DATA_RESV,
15331518
PAGE_UNLOCK | PAGE_SET_PRIVATE2);
15341519

1535-
if (!nolock && nocow)
1536-
btrfs_end_write_no_snapshotting(root);
15371520
cur_offset = extent_end;
15381521

15391522
/*
@@ -6639,6 +6622,8 @@ static int btrfs_link(struct dentry *old_dentry, struct inode *dir,
66396622
drop_inode = 1;
66406623
} else {
66416624
struct dentry *parent = dentry->d_parent;
6625+
int ret;
6626+
66426627
err = btrfs_update_inode(trans, root, inode);
66436628
if (err)
66446629
goto fail;
@@ -6652,7 +6637,12 @@ static int btrfs_link(struct dentry *old_dentry, struct inode *dir,
66526637
goto fail;
66536638
}
66546639
d_instantiate(dentry, inode);
6655-
btrfs_log_new_name(trans, BTRFS_I(inode), NULL, parent);
6640+
ret = btrfs_log_new_name(trans, BTRFS_I(inode), NULL, parent,
6641+
true, NULL);
6642+
if (ret == BTRFS_NEED_TRANS_COMMIT) {
6643+
err = btrfs_commit_transaction(trans);
6644+
trans = NULL;
6645+
}
66566646
}
66576647

66586648
fail:
@@ -9388,14 +9378,21 @@ static int btrfs_rename_exchange(struct inode *old_dir,
93889378
u64 new_idx = 0;
93899379
u64 root_objectid;
93909380
int ret;
9391-
int ret2;
93929381
bool root_log_pinned = false;
93939382
bool dest_log_pinned = false;
9383+
struct btrfs_log_ctx ctx_root;
9384+
struct btrfs_log_ctx ctx_dest;
9385+
bool sync_log_root = false;
9386+
bool sync_log_dest = false;
9387+
bool commit_transaction = false;
93949388

93959389
/* we only allow rename subvolume link between subvolumes */
93969390
if (old_ino != BTRFS_FIRST_FREE_OBJECTID && root != dest)
93979391
return -EXDEV;
93989392

9393+
btrfs_init_log_ctx(&ctx_root, old_inode);
9394+
btrfs_init_log_ctx(&ctx_dest, new_inode);
9395+
93999396
/* close the race window with snapshot create/destroy ioctl */
94009397
if (old_ino == BTRFS_FIRST_FREE_OBJECTID)
94019398
down_read(&fs_info->subvol_sem);
@@ -9542,15 +9539,29 @@ static int btrfs_rename_exchange(struct inode *old_dir,
95429539

95439540
if (root_log_pinned) {
95449541
parent = new_dentry->d_parent;
9545-
btrfs_log_new_name(trans, BTRFS_I(old_inode), BTRFS_I(old_dir),
9546-
parent);
9542+
ret = btrfs_log_new_name(trans, BTRFS_I(old_inode),
9543+
BTRFS_I(old_dir), parent,
9544+
false, &ctx_root);
9545+
if (ret == BTRFS_NEED_LOG_SYNC)
9546+
sync_log_root = true;
9547+
else if (ret == BTRFS_NEED_TRANS_COMMIT)
9548+
commit_transaction = true;
9549+
ret = 0;
95479550
btrfs_end_log_trans(root);
95489551
root_log_pinned = false;
95499552
}
95509553
if (dest_log_pinned) {
9551-
parent = old_dentry->d_parent;
9552-
btrfs_log_new_name(trans, BTRFS_I(new_inode), BTRFS_I(new_dir),
9553-
parent);
9554+
if (!commit_transaction) {
9555+
parent = old_dentry->d_parent;
9556+
ret = btrfs_log_new_name(trans, BTRFS_I(new_inode),
9557+
BTRFS_I(new_dir), parent,
9558+
false, &ctx_dest);
9559+
if (ret == BTRFS_NEED_LOG_SYNC)
9560+
sync_log_dest = true;
9561+
else if (ret == BTRFS_NEED_TRANS_COMMIT)
9562+
commit_transaction = true;
9563+
ret = 0;
9564+
}
95549565
btrfs_end_log_trans(dest);
95559566
dest_log_pinned = false;
95569567
}
@@ -9583,8 +9594,26 @@ static int btrfs_rename_exchange(struct inode *old_dir,
95839594
dest_log_pinned = false;
95849595
}
95859596
}
9586-
ret2 = btrfs_end_transaction(trans);
9587-
ret = ret ? ret : ret2;
9597+
if (!ret && sync_log_root && !commit_transaction) {
9598+
ret = btrfs_sync_log(trans, BTRFS_I(old_inode)->root,
9599+
&ctx_root);
9600+
if (ret)
9601+
commit_transaction = true;
9602+
}
9603+
if (!ret && sync_log_dest && !commit_transaction) {
9604+
ret = btrfs_sync_log(trans, BTRFS_I(new_inode)->root,
9605+
&ctx_dest);
9606+
if (ret)
9607+
commit_transaction = true;
9608+
}
9609+
if (commit_transaction) {
9610+
ret = btrfs_commit_transaction(trans);
9611+
} else {
9612+
int ret2;
9613+
9614+
ret2 = btrfs_end_transaction(trans);
9615+
ret = ret ? ret : ret2;
9616+
}
95889617
out_notrans:
95899618
if (new_ino == BTRFS_FIRST_FREE_OBJECTID)
95909619
up_read(&fs_info->subvol_sem);
@@ -9661,6 +9690,9 @@ static int btrfs_rename(struct inode *old_dir, struct dentry *old_dentry,
96619690
int ret;
96629691
u64 old_ino = btrfs_ino(BTRFS_I(old_inode));
96639692
bool log_pinned = false;
9693+
struct btrfs_log_ctx ctx;
9694+
bool sync_log = false;
9695+
bool commit_transaction = false;
96649696

96659697
if (btrfs_ino(BTRFS_I(new_dir)) == BTRFS_EMPTY_SUBVOL_DIR_OBJECTID)
96669698
return -EPERM;
@@ -9818,8 +9850,15 @@ static int btrfs_rename(struct inode *old_dir, struct dentry *old_dentry,
98189850
if (log_pinned) {
98199851
struct dentry *parent = new_dentry->d_parent;
98209852

9821-
btrfs_log_new_name(trans, BTRFS_I(old_inode), BTRFS_I(old_dir),
9822-
parent);
9853+
btrfs_init_log_ctx(&ctx, old_inode);
9854+
ret = btrfs_log_new_name(trans, BTRFS_I(old_inode),
9855+
BTRFS_I(old_dir), parent,
9856+
false, &ctx);
9857+
if (ret == BTRFS_NEED_LOG_SYNC)
9858+
sync_log = true;
9859+
else if (ret == BTRFS_NEED_TRANS_COMMIT)
9860+
commit_transaction = true;
9861+
ret = 0;
98239862
btrfs_end_log_trans(root);
98249863
log_pinned = false;
98259864
}
@@ -9856,7 +9895,19 @@ static int btrfs_rename(struct inode *old_dir, struct dentry *old_dentry,
98569895
btrfs_end_log_trans(root);
98579896
log_pinned = false;
98589897
}
9859-
btrfs_end_transaction(trans);
9898+
if (!ret && sync_log) {
9899+
ret = btrfs_sync_log(trans, BTRFS_I(old_inode)->root, &ctx);
9900+
if (ret)
9901+
commit_transaction = true;
9902+
}
9903+
if (commit_transaction) {
9904+
ret = btrfs_commit_transaction(trans);
9905+
} else {
9906+
int ret2;
9907+
9908+
ret2 = btrfs_end_transaction(trans);
9909+
ret = ret ? ret : ret2;
9910+
}
98609911
out_notrans:
98619912
if (old_ino == BTRFS_FIRST_FREE_OBJECTID)
98629913
up_read(&fs_info->subvol_sem);

0 commit comments

Comments
 (0)