Skip to content

Commit f877987

Browse files
committed
Merge tag 'for-5.4-rc2-tag' of git://git.kernel.org/pub/scm/linux/kernel/git/kdave/linux
Pull btrfs fixes from David Sterba: "A few more stabitly fixes, one build warning fix. - fix inode allocation under NOFS context - fix leak in fiemap due to concurrent append writes - fix log-root tree updates - fix balance convert of single profile on 32bit architectures - silence false positive warning on old GCCs (code moved in rc1)" * tag 'for-5.4-rc2-tag' of git://git.kernel.org/pub/scm/linux/kernel/git/kdave/linux: btrfs: silence maybe-uninitialized warning in clone_range btrfs: fix uninitialized ret in ref-verify btrfs: allocate new inode in NOFS context btrfs: fix balance convert to single on 32-bit host CPUs btrfs: fix incorrect updating of log root tree Btrfs: fix memory leak due to concurrent append writes with fiemap
2 parents ad338d0 + 431d398 commit f877987

File tree

6 files changed

+49
-13
lines changed

6 files changed

+49
-13
lines changed

fs/btrfs/file.c

Lines changed: 12 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1591,7 +1591,6 @@ static noinline ssize_t btrfs_buffered_write(struct kiocb *iocb,
15911591
struct btrfs_fs_info *fs_info = btrfs_sb(inode->i_sb);
15921592
struct btrfs_root *root = BTRFS_I(inode)->root;
15931593
struct page **pages = NULL;
1594-
struct extent_state *cached_state = NULL;
15951594
struct extent_changeset *data_reserved = NULL;
15961595
u64 release_bytes = 0;
15971596
u64 lockstart;
@@ -1611,6 +1610,7 @@ static noinline ssize_t btrfs_buffered_write(struct kiocb *iocb,
16111610
return -ENOMEM;
16121611

16131612
while (iov_iter_count(i) > 0) {
1613+
struct extent_state *cached_state = NULL;
16141614
size_t offset = offset_in_page(pos);
16151615
size_t sector_offset;
16161616
size_t write_bytes = min(iov_iter_count(i),
@@ -1758,9 +1758,20 @@ static noinline ssize_t btrfs_buffered_write(struct kiocb *iocb,
17581758
if (copied > 0)
17591759
ret = btrfs_dirty_pages(inode, pages, dirty_pages,
17601760
pos, copied, &cached_state);
1761+
1762+
/*
1763+
* If we have not locked the extent range, because the range's
1764+
* start offset is >= i_size, we might still have a non-NULL
1765+
* cached extent state, acquired while marking the extent range
1766+
* as delalloc through btrfs_dirty_pages(). Therefore free any
1767+
* possible cached extent state to avoid a memory leak.
1768+
*/
17611769
if (extents_locked)
17621770
unlock_extent_cached(&BTRFS_I(inode)->io_tree,
17631771
lockstart, lockend, &cached_state);
1772+
else
1773+
free_extent_state(cached_state);
1774+
17641775
btrfs_delalloc_release_extents(BTRFS_I(inode), reserve_bytes,
17651776
true);
17661777
if (ret) {

fs/btrfs/inode.c

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6305,13 +6305,16 @@ static struct inode *btrfs_new_inode(struct btrfs_trans_handle *trans,
63056305
u32 sizes[2];
63066306
int nitems = name ? 2 : 1;
63076307
unsigned long ptr;
6308+
unsigned int nofs_flag;
63086309
int ret;
63096310

63106311
path = btrfs_alloc_path();
63116312
if (!path)
63126313
return ERR_PTR(-ENOMEM);
63136314

6315+
nofs_flag = memalloc_nofs_save();
63146316
inode = new_inode(fs_info->sb);
6317+
memalloc_nofs_restore(nofs_flag);
63156318
if (!inode) {
63166319
btrfs_free_path(path);
63176320
return ERR_PTR(-ENOMEM);

fs/btrfs/ref-verify.c

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -500,7 +500,7 @@ static int process_leaf(struct btrfs_root *root,
500500
struct btrfs_extent_data_ref *dref;
501501
struct btrfs_shared_data_ref *sref;
502502
u32 count;
503-
int i = 0, tree_block_level = 0, ret;
503+
int i = 0, tree_block_level = 0, ret = 0;
504504
struct btrfs_key key;
505505
int nritems = btrfs_header_nritems(leaf);
506506

fs/btrfs/send.c

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5085,7 +5085,7 @@ static int clone_range(struct send_ctx *sctx,
50855085
struct btrfs_path *path;
50865086
struct btrfs_key key;
50875087
int ret;
5088-
u64 clone_src_i_size;
5088+
u64 clone_src_i_size = 0;
50895089

50905090
/*
50915091
* Prevent cloning from a zero offset with a length matching the sector

fs/btrfs/tree-log.c

Lines changed: 27 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -2932,18 +2932,19 @@ static int walk_log_tree(struct btrfs_trans_handle *trans,
29322932
* in the tree of log roots
29332933
*/
29342934
static int update_log_root(struct btrfs_trans_handle *trans,
2935-
struct btrfs_root *log)
2935+
struct btrfs_root *log,
2936+
struct btrfs_root_item *root_item)
29362937
{
29372938
struct btrfs_fs_info *fs_info = log->fs_info;
29382939
int ret;
29392940

29402941
if (log->log_transid == 1) {
29412942
/* insert root item on the first sync */
29422943
ret = btrfs_insert_root(trans, fs_info->log_root_tree,
2943-
&log->root_key, &log->root_item);
2944+
&log->root_key, root_item);
29442945
} else {
29452946
ret = btrfs_update_root(trans, fs_info->log_root_tree,
2946-
&log->root_key, &log->root_item);
2947+
&log->root_key, root_item);
29472948
}
29482949
return ret;
29492950
}
@@ -3041,6 +3042,7 @@ int btrfs_sync_log(struct btrfs_trans_handle *trans,
30413042
struct btrfs_fs_info *fs_info = root->fs_info;
30423043
struct btrfs_root *log = root->log_root;
30433044
struct btrfs_root *log_root_tree = fs_info->log_root_tree;
3045+
struct btrfs_root_item new_root_item;
30443046
int log_transid = 0;
30453047
struct btrfs_log_ctx root_log_ctx;
30463048
struct blk_plug plug;
@@ -3104,17 +3106,25 @@ int btrfs_sync_log(struct btrfs_trans_handle *trans,
31043106
goto out;
31053107
}
31063108

3109+
/*
3110+
* We _must_ update under the root->log_mutex in order to make sure we
3111+
* have a consistent view of the log root we are trying to commit at
3112+
* this moment.
3113+
*
3114+
* We _must_ copy this into a local copy, because we are not holding the
3115+
* log_root_tree->log_mutex yet. This is important because when we
3116+
* commit the log_root_tree we must have a consistent view of the
3117+
* log_root_tree when we update the super block to point at the
3118+
* log_root_tree bytenr. If we update the log_root_tree here we'll race
3119+
* with the commit and possibly point at the new block which we may not
3120+
* have written out.
3121+
*/
31073122
btrfs_set_root_node(&log->root_item, log->node);
3123+
memcpy(&new_root_item, &log->root_item, sizeof(new_root_item));
31083124

31093125
root->log_transid++;
31103126
log->log_transid = root->log_transid;
31113127
root->log_start_pid = 0;
3112-
/*
3113-
* Update or create log root item under the root's log_mutex to prevent
3114-
* races with concurrent log syncs that can lead to failure to update
3115-
* log root item because it was not created yet.
3116-
*/
3117-
ret = update_log_root(trans, log);
31183128
/*
31193129
* IO has been started, blocks of the log tree have WRITTEN flag set
31203130
* in their headers. new modifications of the log will be written to
@@ -3135,6 +3145,14 @@ int btrfs_sync_log(struct btrfs_trans_handle *trans,
31353145
mutex_unlock(&log_root_tree->log_mutex);
31363146

31373147
mutex_lock(&log_root_tree->log_mutex);
3148+
3149+
/*
3150+
* Now we are safe to update the log_root_tree because we're under the
3151+
* log_mutex, and we're a current writer so we're holding the commit
3152+
* open until we drop the log_mutex.
3153+
*/
3154+
ret = update_log_root(trans, log, &new_root_item);
3155+
31383156
if (atomic_dec_and_test(&log_root_tree->log_writers)) {
31393157
/* atomic_dec_and_test implies a barrier */
31403158
cond_wake_up_nomb(&log_root_tree->log_writer_wait);

fs/btrfs/volumes.c

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3845,7 +3845,11 @@ static int alloc_profile_is_valid(u64 flags, int extended)
38453845
return !extended; /* "0" is valid for usual profiles */
38463846

38473847
/* true if exactly one bit set */
3848-
return is_power_of_2(flags);
3848+
/*
3849+
* Don't use is_power_of_2(unsigned long) because it won't work
3850+
* for the single profile (1ULL << 48) on 32-bit CPUs.
3851+
*/
3852+
return flags != 0 && (flags & (flags - 1)) == 0;
38493853
}
38503854

38513855
static inline int balance_need_close(struct btrfs_fs_info *fs_info)

0 commit comments

Comments
 (0)