Skip to content

Commit 271fd5d

Browse files
committed
Merge branch 'for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/mason/linux-btrfs
Pull btrfs fixes from Chris Mason: "The big ones here are a memory leak we introduced in rc1, and a scheduling while atomic if the transid on disk doesn't match the transid we expected. This happens for corrupt blocks, or out of date disks. It also fixes up the ioctl definition for our ioctl to resolve logical inode numbers. The __u32 was a merging error and doesn't match what we ship in the progs." * 'for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/mason/linux-btrfs: Btrfs: avoid sleeping in verify_parent_transid while atomic Btrfs: fix crash in scrub repair code when device is missing btrfs: Fix mismatching struct members in ioctl.h Btrfs: fix page leak when allocing extent buffers Btrfs: Add properly locking around add_root_to_dirty_list
2 parents ce7e5d2 + b9fab91 commit 271fd5d

File tree

8 files changed

+47
-21
lines changed

8 files changed

+47
-21
lines changed

fs/btrfs/ctree.c

Lines changed: 19 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -220,10 +220,12 @@ struct extent_buffer *btrfs_read_lock_root_node(struct btrfs_root *root)
220220
*/
221221
static void add_root_to_dirty_list(struct btrfs_root *root)
222222
{
223+
spin_lock(&root->fs_info->trans_lock);
223224
if (root->track_dirty && list_empty(&root->dirty_list)) {
224225
list_add(&root->dirty_list,
225226
&root->fs_info->dirty_cowonly_roots);
226227
}
228+
spin_unlock(&root->fs_info->trans_lock);
227229
}
228230

229231
/*
@@ -723,7 +725,7 @@ int btrfs_realloc_node(struct btrfs_trans_handle *trans,
723725

724726
cur = btrfs_find_tree_block(root, blocknr, blocksize);
725727
if (cur)
726-
uptodate = btrfs_buffer_uptodate(cur, gen);
728+
uptodate = btrfs_buffer_uptodate(cur, gen, 0);
727729
else
728730
uptodate = 0;
729731
if (!cur || !uptodate) {
@@ -1358,15 +1360,20 @@ static noinline int reada_for_balance(struct btrfs_root *root,
13581360
block1 = btrfs_node_blockptr(parent, slot - 1);
13591361
gen = btrfs_node_ptr_generation(parent, slot - 1);
13601362
eb = btrfs_find_tree_block(root, block1, blocksize);
1361-
if (eb && btrfs_buffer_uptodate(eb, gen))
1363+
/*
1364+
* if we get -eagain from btrfs_buffer_uptodate, we
1365+
* don't want to return eagain here. That will loop
1366+
* forever
1367+
*/
1368+
if (eb && btrfs_buffer_uptodate(eb, gen, 1) != 0)
13621369
block1 = 0;
13631370
free_extent_buffer(eb);
13641371
}
13651372
if (slot + 1 < nritems) {
13661373
block2 = btrfs_node_blockptr(parent, slot + 1);
13671374
gen = btrfs_node_ptr_generation(parent, slot + 1);
13681375
eb = btrfs_find_tree_block(root, block2, blocksize);
1369-
if (eb && btrfs_buffer_uptodate(eb, gen))
1376+
if (eb && btrfs_buffer_uptodate(eb, gen, 1) != 0)
13701377
block2 = 0;
13711378
free_extent_buffer(eb);
13721379
}
@@ -1504,8 +1511,9 @@ read_block_for_search(struct btrfs_trans_handle *trans,
15041511

15051512
tmp = btrfs_find_tree_block(root, blocknr, blocksize);
15061513
if (tmp) {
1507-
if (btrfs_buffer_uptodate(tmp, 0)) {
1508-
if (btrfs_buffer_uptodate(tmp, gen)) {
1514+
/* first we do an atomic uptodate check */
1515+
if (btrfs_buffer_uptodate(tmp, 0, 1) > 0) {
1516+
if (btrfs_buffer_uptodate(tmp, gen, 1) > 0) {
15091517
/*
15101518
* we found an up to date block without
15111519
* sleeping, return
@@ -1523,8 +1531,9 @@ read_block_for_search(struct btrfs_trans_handle *trans,
15231531
free_extent_buffer(tmp);
15241532
btrfs_set_path_blocking(p);
15251533

1534+
/* now we're allowed to do a blocking uptodate check */
15261535
tmp = read_tree_block(root, blocknr, blocksize, gen);
1527-
if (tmp && btrfs_buffer_uptodate(tmp, gen)) {
1536+
if (tmp && btrfs_buffer_uptodate(tmp, gen, 0) > 0) {
15281537
*eb_ret = tmp;
15291538
return 0;
15301539
}
@@ -1559,7 +1568,7 @@ read_block_for_search(struct btrfs_trans_handle *trans,
15591568
* and give up so that our caller doesn't loop forever
15601569
* on our EAGAINs.
15611570
*/
1562-
if (!btrfs_buffer_uptodate(tmp, 0))
1571+
if (!btrfs_buffer_uptodate(tmp, 0, 0))
15631572
ret = -EIO;
15641573
free_extent_buffer(tmp);
15651574
}
@@ -4043,7 +4052,7 @@ int btrfs_search_forward(struct btrfs_root *root, struct btrfs_key *min_key,
40434052
tmp = btrfs_find_tree_block(root, blockptr,
40444053
btrfs_level_size(root, level - 1));
40454054

4046-
if (tmp && btrfs_buffer_uptodate(tmp, gen)) {
4055+
if (tmp && btrfs_buffer_uptodate(tmp, gen, 1) > 0) {
40474056
free_extent_buffer(tmp);
40484057
break;
40494058
}
@@ -4166,7 +4175,8 @@ int btrfs_find_next_key(struct btrfs_root *root, struct btrfs_path *path,
41664175
struct extent_buffer *cur;
41674176
cur = btrfs_find_tree_block(root, blockptr,
41684177
btrfs_level_size(root, level - 1));
4169-
if (!cur || !btrfs_buffer_uptodate(cur, gen)) {
4178+
if (!cur ||
4179+
btrfs_buffer_uptodate(cur, gen, 1) <= 0) {
41704180
slot++;
41714181
if (cur)
41724182
free_extent_buffer(cur);

fs/btrfs/disk-io.c

Lines changed: 13 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -323,14 +323,18 @@ static int csum_tree_block(struct btrfs_root *root, struct extent_buffer *buf,
323323
* in the wrong place.
324324
*/
325325
static int verify_parent_transid(struct extent_io_tree *io_tree,
326-
struct extent_buffer *eb, u64 parent_transid)
326+
struct extent_buffer *eb, u64 parent_transid,
327+
int atomic)
327328
{
328329
struct extent_state *cached_state = NULL;
329330
int ret;
330331

331332
if (!parent_transid || btrfs_header_generation(eb) == parent_transid)
332333
return 0;
333334

335+
if (atomic)
336+
return -EAGAIN;
337+
334338
lock_extent_bits(io_tree, eb->start, eb->start + eb->len - 1,
335339
0, &cached_state);
336340
if (extent_buffer_uptodate(eb) &&
@@ -372,7 +376,8 @@ static int btree_read_extent_buffer_pages(struct btrfs_root *root,
372376
ret = read_extent_buffer_pages(io_tree, eb, start,
373377
WAIT_COMPLETE,
374378
btree_get_extent, mirror_num);
375-
if (!ret && !verify_parent_transid(io_tree, eb, parent_transid))
379+
if (!ret && !verify_parent_transid(io_tree, eb,
380+
parent_transid, 0))
376381
break;
377382

378383
/*
@@ -1202,7 +1207,7 @@ static int __must_check find_and_setup_root(struct btrfs_root *tree_root,
12021207
root->commit_root = NULL;
12031208
root->node = read_tree_block(root, btrfs_root_bytenr(&root->root_item),
12041209
blocksize, generation);
1205-
if (!root->node || !btrfs_buffer_uptodate(root->node, generation)) {
1210+
if (!root->node || !btrfs_buffer_uptodate(root->node, generation, 0)) {
12061211
free_extent_buffer(root->node);
12071212
root->node = NULL;
12081213
return -EIO;
@@ -3143,7 +3148,8 @@ int close_ctree(struct btrfs_root *root)
31433148
return 0;
31443149
}
31453150

3146-
int btrfs_buffer_uptodate(struct extent_buffer *buf, u64 parent_transid)
3151+
int btrfs_buffer_uptodate(struct extent_buffer *buf, u64 parent_transid,
3152+
int atomic)
31473153
{
31483154
int ret;
31493155
struct inode *btree_inode = buf->pages[0]->mapping->host;
@@ -3153,7 +3159,9 @@ int btrfs_buffer_uptodate(struct extent_buffer *buf, u64 parent_transid)
31533159
return ret;
31543160

31553161
ret = verify_parent_transid(&BTRFS_I(btree_inode)->io_tree, buf,
3156-
parent_transid);
3162+
parent_transid, atomic);
3163+
if (ret == -EAGAIN)
3164+
return ret;
31573165
return !ret;
31583166
}
31593167

fs/btrfs/disk-io.h

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -66,7 +66,8 @@ void btrfs_btree_balance_dirty(struct btrfs_root *root, unsigned long nr);
6666
void __btrfs_btree_balance_dirty(struct btrfs_root *root, unsigned long nr);
6767
void btrfs_free_fs_root(struct btrfs_fs_info *fs_info, struct btrfs_root *root);
6868
void btrfs_mark_buffer_dirty(struct extent_buffer *buf);
69-
int btrfs_buffer_uptodate(struct extent_buffer *buf, u64 parent_transid);
69+
int btrfs_buffer_uptodate(struct extent_buffer *buf, u64 parent_transid,
70+
int atomic);
7071
int btrfs_set_buffer_uptodate(struct extent_buffer *buf);
7172
int btrfs_read_buffer(struct extent_buffer *buf, u64 parent_transid);
7273
u32 btrfs_csum_data(struct btrfs_root *root, char *data, u32 seed, size_t len);

fs/btrfs/extent-tree.c

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6568,7 +6568,7 @@ static noinline int do_walk_down(struct btrfs_trans_handle *trans,
65686568
goto skip;
65696569
}
65706570

6571-
if (!btrfs_buffer_uptodate(next, generation)) {
6571+
if (!btrfs_buffer_uptodate(next, generation, 0)) {
65726572
btrfs_tree_unlock(next);
65736573
free_extent_buffer(next);
65746574
next = NULL;

fs/btrfs/extent_io.c

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -4120,6 +4120,7 @@ struct extent_buffer *alloc_extent_buffer(struct extent_io_tree *tree,
41204120
if (atomic_inc_not_zero(&exists->refs)) {
41214121
spin_unlock(&mapping->private_lock);
41224122
unlock_page(p);
4123+
page_cache_release(p);
41234124
mark_extent_buffer_accessed(exists);
41244125
goto free_eb;
41254126
}
@@ -4199,8 +4200,7 @@ struct extent_buffer *alloc_extent_buffer(struct extent_io_tree *tree,
41994200
unlock_page(eb->pages[i]);
42004201
}
42014202

4202-
if (!atomic_dec_and_test(&eb->refs))
4203-
return exists;
4203+
WARN_ON(!atomic_dec_and_test(&eb->refs));
42044204
btrfs_release_extent_buffer(eb);
42054205
return exists;
42064206
}

fs/btrfs/ioctl.h

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -252,15 +252,15 @@ struct btrfs_data_container {
252252

253253
struct btrfs_ioctl_ino_path_args {
254254
__u64 inum; /* in */
255-
__u32 size; /* in */
255+
__u64 size; /* in */
256256
__u64 reserved[4];
257257
/* struct btrfs_data_container *fspath; out */
258258
__u64 fspath; /* out */
259259
};
260260

261261
struct btrfs_ioctl_logical_ino_args {
262262
__u64 logical; /* in */
263-
__u32 size; /* in */
263+
__u64 size; /* in */
264264
__u64 reserved[4];
265265
/* struct btrfs_data_container *inodes; out */
266266
__u64 inodes;

fs/btrfs/scrub.c

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -998,6 +998,7 @@ static int scrub_setup_recheck_block(struct scrub_dev *sdev,
998998
page = sblock->pagev + page_index;
999999
page->logical = logical;
10001000
page->physical = bbio->stripes[mirror_index].physical;
1001+
/* for missing devices, bdev is NULL */
10011002
page->bdev = bbio->stripes[mirror_index].dev->bdev;
10021003
page->mirror_num = mirror_index + 1;
10031004
page->page = alloc_page(GFP_NOFS);
@@ -1042,6 +1043,12 @@ static int scrub_recheck_block(struct btrfs_fs_info *fs_info,
10421043
struct scrub_page *page = sblock->pagev + page_num;
10431044
DECLARE_COMPLETION_ONSTACK(complete);
10441045

1046+
if (page->bdev == NULL) {
1047+
page->io_error = 1;
1048+
sblock->no_io_error_seen = 0;
1049+
continue;
1050+
}
1051+
10451052
BUG_ON(!page->page);
10461053
bio = bio_alloc(GFP_NOFS, 1);
10471054
if (!bio)

fs/btrfs/tree-log.c

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -279,7 +279,7 @@ static int process_one_buffer(struct btrfs_root *log,
279279
log->fs_info->extent_root,
280280
eb->start, eb->len);
281281

282-
if (btrfs_buffer_uptodate(eb, gen)) {
282+
if (btrfs_buffer_uptodate(eb, gen, 0)) {
283283
if (wc->write)
284284
btrfs_write_tree_block(eb);
285285
if (wc->wait)

0 commit comments

Comments
 (0)