for-4.15-rc2-tag

-----BEGIN PGP SIGNATURE-----
 
 iQIzBAABCgAdFiEE8rQSAMVO+zA4DBdWxWXV+ddtWDsFAlofBpkACgkQxWXV+ddt
 WDvtTQ//emI1QsD4N0e4BxMcZ1bcigiEk3jc4gj+biRapnMHHAHOqJbVtpK1v8gS
 PCTw+4uD5UOGvhBtS4kXJn8e2qxWCESWJDXwVlW0RHmWLfwd9z7ly0sBMi3oiIqH
 qief8CIkk3oTexiuuJ3mZGxqnDQjRGtWx2LM+bRJBWMk+jN32v2ObSlv9V505a5M
 1daDBsjWojFWa8d4r3YZNJq1df2om/dwVQZ0Wk59bacIo9Xbvok0X459cOlWuv0p
 mjx8m8uA/z+HVdkTYlzyKpq08O8Z4shj3GrBbSnZ511gKzV+c9jJPxij5pKm3Z2z
 KW4Mp17+/7GSNcSsJiqnOYi+wtOrak2lD0COlZTijnY2jrv18h8ianoIM6CpzUdy
 +b09yuFXbPLoUfyl6vFaO/JHuvAkQdaR2tJbds6lvW+liC1ReoL4W1WcUjY6nv9f
 6wTaIv0vwgrHaxeIzxKNpnsTlpHAgorFFk0/w8nLb40WX8AoJ/95lo2zws8oaFDN
 0Fylu3NYhoDrJZK+D8dbsWx2eTsFVCqep4w0+iEVZl3lfuy3FZl1pu8CL7ru9vJl
 DNieh+lUvK1Fk+SYIoilGoriW96RbU8+jPo2W4A1ENzeMJfrNCSWtUSZZp4XT4tO
 8m1PGud07XBLSxd62bAEDV3KZO2DnY1WxgXbKuIHSi9D5CI1LMo=
 =7UW+
 -----END PGP SIGNATURE-----

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

Pull btrfs fixes from David Sterba:
 "We've collected some fixes in since the pre-merge window freeze.

  There's technically only one regression fix for 4.15, but the rest
  seems important and candidates for stable.

   - fix missing flush bio puts in error cases (is serious, but rarely
     happens)

   - fix reporting stat::st_blocks for buffered append writes

   - fix space cache invalidation

   - fix out of bound memory access when setting zlib level

   - fix potential memory corruption when fsync fails in the middle

   - fix crash in integrity checker

   - incremetnal send fix, path mixup for certain unlink/rename
     combination

   - pass flags to writeback so compressed writes can be throttled
     properly

   - error handling fixes"

* tag 'for-4.15-rc2-tag' of git://git.kernel.org/pub/scm/linux/kernel/git/kdave/linux:
  Btrfs: incremental send, fix wrong unlink path after renaming file
  btrfs: tree-checker: Fix false panic for sanity test
  Btrfs: fix list_add corruption and soft lockups in fsync
  btrfs: Fix wild memory access in compression level parser
  btrfs: fix deadlock when writing out space cache
  btrfs: clear space cache inode generation always
  Btrfs: fix reported number of inode blocks after buffered append writes
  Btrfs: move definition of the function btrfs_find_new_delalloc_bytes
  Btrfs: bail out gracefully rather than BUG_ON
  btrfs: dev_alloc_list is not protected by RCU, use normal list_del
  btrfs: add missing device::flush_bio puts
  btrfs: Fix transaction abort during failure in btrfs_rm_dev_item
  Btrfs: add write_flags for compression bio
This commit is contained in:
Linus Torvalds 2017-11-29 14:26:50 -08:00
commit 26cd94744e
19 changed files with 317 additions and 138 deletions

View File

@ -295,7 +295,8 @@ blk_status_t btrfs_submit_compressed_write(struct inode *inode, u64 start,
unsigned long len, u64 disk_start, unsigned long len, u64 disk_start,
unsigned long compressed_len, unsigned long compressed_len,
struct page **compressed_pages, struct page **compressed_pages,
unsigned long nr_pages) unsigned long nr_pages,
unsigned int write_flags)
{ {
struct btrfs_fs_info *fs_info = btrfs_sb(inode->i_sb); struct btrfs_fs_info *fs_info = btrfs_sb(inode->i_sb);
struct bio *bio = NULL; struct bio *bio = NULL;
@ -327,7 +328,7 @@ blk_status_t btrfs_submit_compressed_write(struct inode *inode, u64 start,
bdev = fs_info->fs_devices->latest_bdev; bdev = fs_info->fs_devices->latest_bdev;
bio = btrfs_bio_alloc(bdev, first_byte); bio = btrfs_bio_alloc(bdev, first_byte);
bio_set_op_attrs(bio, REQ_OP_WRITE, 0); bio->bi_opf = REQ_OP_WRITE | write_flags;
bio->bi_private = cb; bio->bi_private = cb;
bio->bi_end_io = end_compressed_bio_write; bio->bi_end_io = end_compressed_bio_write;
refcount_set(&cb->pending_bios, 1); refcount_set(&cb->pending_bios, 1);
@ -374,7 +375,7 @@ blk_status_t btrfs_submit_compressed_write(struct inode *inode, u64 start,
bio_put(bio); bio_put(bio);
bio = btrfs_bio_alloc(bdev, first_byte); bio = btrfs_bio_alloc(bdev, first_byte);
bio_set_op_attrs(bio, REQ_OP_WRITE, 0); bio->bi_opf = REQ_OP_WRITE | write_flags;
bio->bi_private = cb; bio->bi_private = cb;
bio->bi_end_io = end_compressed_bio_write; bio->bi_end_io = end_compressed_bio_write;
bio_add_page(bio, page, PAGE_SIZE, 0); bio_add_page(bio, page, PAGE_SIZE, 0);
@ -1528,5 +1529,5 @@ unsigned int btrfs_compress_str2level(const char *str)
if (str[4] == ':' && '1' <= str[5] && str[5] <= '9' && str[6] == 0) if (str[4] == ':' && '1' <= str[5] && str[5] <= '9' && str[6] == 0)
return str[5] - '0'; return str[5] - '0';
return 0; return BTRFS_ZLIB_DEFAULT_LEVEL;
} }

View File

@ -34,6 +34,8 @@
/* Maximum size of data before compression */ /* Maximum size of data before compression */
#define BTRFS_MAX_UNCOMPRESSED (SZ_128K) #define BTRFS_MAX_UNCOMPRESSED (SZ_128K)
#define BTRFS_ZLIB_DEFAULT_LEVEL 3
struct compressed_bio { struct compressed_bio {
/* number of bios pending for this compressed extent */ /* number of bios pending for this compressed extent */
refcount_t pending_bios; refcount_t pending_bios;
@ -91,7 +93,8 @@ blk_status_t btrfs_submit_compressed_write(struct inode *inode, u64 start,
unsigned long len, u64 disk_start, unsigned long len, u64 disk_start,
unsigned long compressed_len, unsigned long compressed_len,
struct page **compressed_pages, struct page **compressed_pages,
unsigned long nr_pages); unsigned long nr_pages,
unsigned int write_flags);
blk_status_t btrfs_submit_compressed_read(struct inode *inode, struct bio *bio, blk_status_t btrfs_submit_compressed_read(struct inode *inode, struct bio *bio,
int mirror_num, unsigned long bio_flags); int mirror_num, unsigned long bio_flags);

View File

@ -3180,6 +3180,7 @@ int btrfs_start_delalloc_inodes(struct btrfs_root *root, int delay_iput);
int btrfs_start_delalloc_roots(struct btrfs_fs_info *fs_info, int delay_iput, int btrfs_start_delalloc_roots(struct btrfs_fs_info *fs_info, int delay_iput,
int nr); int nr);
int btrfs_set_extent_delalloc(struct inode *inode, u64 start, u64 end, int btrfs_set_extent_delalloc(struct inode *inode, u64 start, u64 end,
unsigned int extra_bits,
struct extent_state **cached_state, int dedupe); struct extent_state **cached_state, int dedupe);
int btrfs_create_subvol_root(struct btrfs_trans_handle *trans, int btrfs_create_subvol_root(struct btrfs_trans_handle *trans,
struct btrfs_root *new_root, struct btrfs_root *new_root,

View File

@ -610,7 +610,7 @@ static int btree_readpage_end_io_hook(struct btrfs_io_bio *io_bio,
* that we don't try and read the other copies of this block, just * that we don't try and read the other copies of this block, just
* return -EIO. * return -EIO.
*/ */
if (found_level == 0 && btrfs_check_leaf(root, eb)) { if (found_level == 0 && btrfs_check_leaf_full(root, eb)) {
set_bit(EXTENT_BUFFER_CORRUPT, &eb->bflags); set_bit(EXTENT_BUFFER_CORRUPT, &eb->bflags);
ret = -EIO; ret = -EIO;
} }
@ -3848,7 +3848,13 @@ void btrfs_mark_buffer_dirty(struct extent_buffer *buf)
buf->len, buf->len,
fs_info->dirty_metadata_batch); fs_info->dirty_metadata_batch);
#ifdef CONFIG_BTRFS_FS_CHECK_INTEGRITY #ifdef CONFIG_BTRFS_FS_CHECK_INTEGRITY
if (btrfs_header_level(buf) == 0 && btrfs_check_leaf(root, buf)) { /*
* Since btrfs_mark_buffer_dirty() can be called with item pointer set
* but item data not updated.
* So here we should only check item pointers, not item data.
*/
if (btrfs_header_level(buf) == 0 &&
btrfs_check_leaf_relaxed(root, buf)) {
btrfs_print_leaf(buf); btrfs_print_leaf(buf);
ASSERT(0); ASSERT(0);
} }

View File

@ -3502,13 +3502,6 @@ again:
goto again; goto again;
} }
/* We've already setup this transaction, go ahead and exit */
if (block_group->cache_generation == trans->transid &&
i_size_read(inode)) {
dcs = BTRFS_DC_SETUP;
goto out_put;
}
/* /*
* We want to set the generation to 0, that way if anything goes wrong * We want to set the generation to 0, that way if anything goes wrong
* from here on out we know not to trust this cache when we load up next * from here on out we know not to trust this cache when we load up next
@ -3532,6 +3525,13 @@ again:
} }
WARN_ON(ret); WARN_ON(ret);
/* We've already setup this transaction, go ahead and exit */
if (block_group->cache_generation == trans->transid &&
i_size_read(inode)) {
dcs = BTRFS_DC_SETUP;
goto out_put;
}
if (i_size_read(inode) > 0) { if (i_size_read(inode) > 0) {
ret = btrfs_check_trunc_cache_free_space(fs_info, ret = btrfs_check_trunc_cache_free_space(fs_info,
&fs_info->global_block_rsv); &fs_info->global_block_rsv);

View File

@ -3253,7 +3253,7 @@ static noinline_for_stack int writepage_delalloc(struct inode *inode,
delalloc_start, delalloc_start,
delalloc_end, delalloc_end,
&page_started, &page_started,
nr_written); nr_written, wbc);
/* File system has been set read-only */ /* File system has been set read-only */
if (ret) { if (ret) {
SetPageError(page); SetPageError(page);

View File

@ -116,7 +116,8 @@ struct extent_io_ops {
*/ */
int (*fill_delalloc)(void *private_data, struct page *locked_page, int (*fill_delalloc)(void *private_data, struct page *locked_page,
u64 start, u64 end, int *page_started, u64 start, u64 end, int *page_started,
unsigned long *nr_written); unsigned long *nr_written,
struct writeback_control *wbc);
int (*writepage_start_hook)(struct page *page, u64 start, u64 end); int (*writepage_start_hook)(struct page *page, u64 start, u64 end);
void (*writepage_end_io_hook)(struct page *page, u64 start, u64 end, void (*writepage_end_io_hook)(struct page *page, u64 start, u64 end,
@ -365,10 +366,11 @@ int convert_extent_bit(struct extent_io_tree *tree, u64 start, u64 end,
struct extent_state **cached_state); struct extent_state **cached_state);
static inline int set_extent_delalloc(struct extent_io_tree *tree, u64 start, static inline int set_extent_delalloc(struct extent_io_tree *tree, u64 start,
u64 end, struct extent_state **cached_state) u64 end, unsigned int extra_bits,
struct extent_state **cached_state)
{ {
return set_extent_bit(tree, start, end, return set_extent_bit(tree, start, end,
EXTENT_DELALLOC | EXTENT_UPTODATE, EXTENT_DELALLOC | EXTENT_UPTODATE | extra_bits,
NULL, cached_state, GFP_NOFS); NULL, cached_state, GFP_NOFS);
} }

View File

@ -477,6 +477,47 @@ static void btrfs_drop_pages(struct page **pages, size_t num_pages)
} }
} }
static int btrfs_find_new_delalloc_bytes(struct btrfs_inode *inode,
const u64 start,
const u64 len,
struct extent_state **cached_state)
{
u64 search_start = start;
const u64 end = start + len - 1;
while (search_start < end) {
const u64 search_len = end - search_start + 1;
struct extent_map *em;
u64 em_len;
int ret = 0;
em = btrfs_get_extent(inode, NULL, 0, search_start,
search_len, 0);
if (IS_ERR(em))
return PTR_ERR(em);
if (em->block_start != EXTENT_MAP_HOLE)
goto next;
em_len = em->len;
if (em->start < search_start)
em_len -= search_start - em->start;
if (em_len > search_len)
em_len = search_len;
ret = set_extent_bit(&inode->io_tree, search_start,
search_start + em_len - 1,
EXTENT_DELALLOC_NEW,
NULL, cached_state, GFP_NOFS);
next:
search_start = extent_map_end(em);
free_extent_map(em);
if (ret)
return ret;
}
return 0;
}
/* /*
* after copy_from_user, pages need to be dirtied and we need to make * after copy_from_user, pages need to be dirtied and we need to make
* sure holes are created between the current EOF and the start of * sure holes are created between the current EOF and the start of
@ -497,14 +538,34 @@ int btrfs_dirty_pages(struct inode *inode, struct page **pages,
u64 end_of_last_block; u64 end_of_last_block;
u64 end_pos = pos + write_bytes; u64 end_pos = pos + write_bytes;
loff_t isize = i_size_read(inode); loff_t isize = i_size_read(inode);
unsigned int extra_bits = 0;
start_pos = pos & ~((u64) fs_info->sectorsize - 1); start_pos = pos & ~((u64) fs_info->sectorsize - 1);
num_bytes = round_up(write_bytes + pos - start_pos, num_bytes = round_up(write_bytes + pos - start_pos,
fs_info->sectorsize); fs_info->sectorsize);
end_of_last_block = start_pos + num_bytes - 1; end_of_last_block = start_pos + num_bytes - 1;
if (!btrfs_is_free_space_inode(BTRFS_I(inode))) {
if (start_pos >= isize &&
!(BTRFS_I(inode)->flags & BTRFS_INODE_PREALLOC)) {
/*
* There can't be any extents following eof in this case
* so just set the delalloc new bit for the range
* directly.
*/
extra_bits |= EXTENT_DELALLOC_NEW;
} else {
err = btrfs_find_new_delalloc_bytes(BTRFS_I(inode),
start_pos,
num_bytes, cached);
if (err)
return err;
}
}
err = btrfs_set_extent_delalloc(inode, start_pos, end_of_last_block, err = btrfs_set_extent_delalloc(inode, start_pos, end_of_last_block,
cached, 0); extra_bits, cached, 0);
if (err) if (err)
return err; return err;
@ -1404,47 +1465,6 @@ fail:
} }
static int btrfs_find_new_delalloc_bytes(struct btrfs_inode *inode,
const u64 start,
const u64 len,
struct extent_state **cached_state)
{
u64 search_start = start;
const u64 end = start + len - 1;
while (search_start < end) {
const u64 search_len = end - search_start + 1;
struct extent_map *em;
u64 em_len;
int ret = 0;
em = btrfs_get_extent(inode, NULL, 0, search_start,
search_len, 0);
if (IS_ERR(em))
return PTR_ERR(em);
if (em->block_start != EXTENT_MAP_HOLE)
goto next;
em_len = em->len;
if (em->start < search_start)
em_len -= search_start - em->start;
if (em_len > search_len)
em_len = search_len;
ret = set_extent_bit(&inode->io_tree, search_start,
search_start + em_len - 1,
EXTENT_DELALLOC_NEW,
NULL, cached_state, GFP_NOFS);
next:
search_start = extent_map_end(em);
free_extent_map(em);
if (ret)
return ret;
}
return 0;
}
/* /*
* This function locks the extent and properly waits for data=ordered extents * This function locks the extent and properly waits for data=ordered extents
* to finish before allowing the pages to be modified if need. * to finish before allowing the pages to be modified if need.
@ -1473,10 +1493,8 @@ lock_and_cleanup_extent_if_need(struct btrfs_inode *inode, struct page **pages,
+ round_up(pos + write_bytes - start_pos, + round_up(pos + write_bytes - start_pos,
fs_info->sectorsize) - 1; fs_info->sectorsize) - 1;
if (start_pos < inode->vfs_inode.i_size || if (start_pos < inode->vfs_inode.i_size) {
(inode->flags & BTRFS_INODE_PREALLOC)) {
struct btrfs_ordered_extent *ordered; struct btrfs_ordered_extent *ordered;
unsigned int clear_bits;
lock_extent_bits(&inode->io_tree, start_pos, last_pos, lock_extent_bits(&inode->io_tree, start_pos, last_pos,
cached_state); cached_state);
@ -1498,19 +1516,10 @@ lock_and_cleanup_extent_if_need(struct btrfs_inode *inode, struct page **pages,
} }
if (ordered) if (ordered)
btrfs_put_ordered_extent(ordered); btrfs_put_ordered_extent(ordered);
ret = btrfs_find_new_delalloc_bytes(inode, start_pos, clear_extent_bit(&inode->io_tree, start_pos, last_pos,
last_pos - start_pos + 1, EXTENT_DIRTY | EXTENT_DELALLOC |
cached_state); EXTENT_DO_ACCOUNTING | EXTENT_DEFRAG,
clear_bits = EXTENT_DIRTY | EXTENT_DELALLOC | 0, 0, cached_state, GFP_NOFS);
EXTENT_DO_ACCOUNTING | EXTENT_DEFRAG;
if (ret)
clear_bits |= EXTENT_DELALLOC_NEW | EXTENT_LOCKED;
clear_extent_bit(&inode->io_tree, start_pos,
last_pos, clear_bits,
(clear_bits & EXTENT_LOCKED) ? 1 : 0,
0, cached_state, GFP_NOFS);
if (ret)
return ret;
*lockstart = start_pos; *lockstart = start_pos;
*lockend = last_pos; *lockend = last_pos;
ret = 1; ret = 1;
@ -2048,6 +2057,8 @@ int btrfs_sync_file(struct file *file, loff_t start, loff_t end, int datasync)
len = (u64)end - (u64)start + 1; len = (u64)end - (u64)start + 1;
trace_btrfs_sync_file(file, datasync); trace_btrfs_sync_file(file, datasync);
btrfs_init_log_ctx(&ctx, inode);
/* /*
* We write the dirty pages in the range and wait until they complete * We write the dirty pages in the range and wait until they complete
* out of the ->i_mutex. If so, we can flush the dirty pages by * out of the ->i_mutex. If so, we can flush the dirty pages by
@ -2194,8 +2205,6 @@ int btrfs_sync_file(struct file *file, loff_t start, loff_t end, int datasync)
} }
trans->sync = true; trans->sync = true;
btrfs_init_log_ctx(&ctx, inode);
ret = btrfs_log_dentry_safe(trans, root, dentry, start, end, &ctx); ret = btrfs_log_dentry_safe(trans, root, dentry, start, end, &ctx);
if (ret < 0) { if (ret < 0) {
/* Fallthrough and commit/free transaction. */ /* Fallthrough and commit/free transaction. */
@ -2253,6 +2262,7 @@ int btrfs_sync_file(struct file *file, loff_t start, loff_t end, int datasync)
ret = btrfs_end_transaction(trans); ret = btrfs_end_transaction(trans);
} }
out: out:
ASSERT(list_empty(&ctx.list));
err = file_check_and_advance_wb_err(file); err = file_check_and_advance_wb_err(file);
if (!ret) if (!ret)
ret = err; ret = err;

View File

@ -1264,7 +1264,7 @@ static int __btrfs_write_out_cache(struct btrfs_root *root, struct inode *inode,
/* Lock all pages first so we can lock the extent safely. */ /* Lock all pages first so we can lock the extent safely. */
ret = io_ctl_prepare_pages(io_ctl, inode, 0); ret = io_ctl_prepare_pages(io_ctl, inode, 0);
if (ret) if (ret)
goto out; goto out_unlock;
lock_extent_bits(&BTRFS_I(inode)->io_tree, 0, i_size_read(inode) - 1, lock_extent_bits(&BTRFS_I(inode)->io_tree, 0, i_size_read(inode) - 1,
&cached_state); &cached_state);
@ -1358,6 +1358,7 @@ out_nospc_locked:
out_nospc: out_nospc:
cleanup_write_cache_enospc(inode, io_ctl, &cached_state); cleanup_write_cache_enospc(inode, io_ctl, &cached_state);
out_unlock:
if (block_group && (block_group->flags & BTRFS_BLOCK_GROUP_DATA)) if (block_group && (block_group->flags & BTRFS_BLOCK_GROUP_DATA))
up_write(&block_group->data_rwsem); up_write(&block_group->data_rwsem);

View File

@ -378,6 +378,7 @@ struct async_cow {
struct page *locked_page; struct page *locked_page;
u64 start; u64 start;
u64 end; u64 end;
unsigned int write_flags;
struct list_head extents; struct list_head extents;
struct btrfs_work work; struct btrfs_work work;
}; };
@ -857,7 +858,8 @@ retry:
async_extent->ram_size, async_extent->ram_size,
ins.objectid, ins.objectid,
ins.offset, async_extent->pages, ins.offset, async_extent->pages,
async_extent->nr_pages)) { async_extent->nr_pages,
async_cow->write_flags)) {
struct extent_io_tree *tree = &BTRFS_I(inode)->io_tree; struct extent_io_tree *tree = &BTRFS_I(inode)->io_tree;
struct page *p = async_extent->pages[0]; struct page *p = async_extent->pages[0];
const u64 start = async_extent->start; const u64 start = async_extent->start;
@ -1191,7 +1193,8 @@ static noinline void async_cow_free(struct btrfs_work *work)
static int cow_file_range_async(struct inode *inode, struct page *locked_page, static int cow_file_range_async(struct inode *inode, struct page *locked_page,
u64 start, u64 end, int *page_started, u64 start, u64 end, int *page_started,
unsigned long *nr_written) unsigned long *nr_written,
unsigned int write_flags)
{ {
struct btrfs_fs_info *fs_info = btrfs_sb(inode->i_sb); struct btrfs_fs_info *fs_info = btrfs_sb(inode->i_sb);
struct async_cow *async_cow; struct async_cow *async_cow;
@ -1208,6 +1211,7 @@ static int cow_file_range_async(struct inode *inode, struct page *locked_page,
async_cow->root = root; async_cow->root = root;
async_cow->locked_page = locked_page; async_cow->locked_page = locked_page;
async_cow->start = start; async_cow->start = start;
async_cow->write_flags = write_flags;
if (BTRFS_I(inode)->flags & BTRFS_INODE_NOCOMPRESS && if (BTRFS_I(inode)->flags & BTRFS_INODE_NOCOMPRESS &&
!btrfs_test_opt(fs_info, FORCE_COMPRESS)) !btrfs_test_opt(fs_info, FORCE_COMPRESS))
@ -1577,11 +1581,13 @@ static inline int need_force_cow(struct inode *inode, u64 start, u64 end)
*/ */
static int run_delalloc_range(void *private_data, struct page *locked_page, static int run_delalloc_range(void *private_data, struct page *locked_page,
u64 start, u64 end, int *page_started, u64 start, u64 end, int *page_started,
unsigned long *nr_written) unsigned long *nr_written,
struct writeback_control *wbc)
{ {
struct inode *inode = private_data; struct inode *inode = private_data;
int ret; int ret;
int force_cow = need_force_cow(inode, start, end); int force_cow = need_force_cow(inode, start, end);
unsigned int write_flags = wbc_to_write_flags(wbc);
if (BTRFS_I(inode)->flags & BTRFS_INODE_NODATACOW && !force_cow) { if (BTRFS_I(inode)->flags & BTRFS_INODE_NODATACOW && !force_cow) {
ret = run_delalloc_nocow(inode, locked_page, start, end, ret = run_delalloc_nocow(inode, locked_page, start, end,
@ -1596,7 +1602,8 @@ static int run_delalloc_range(void *private_data, struct page *locked_page,
set_bit(BTRFS_INODE_HAS_ASYNC_EXTENT, set_bit(BTRFS_INODE_HAS_ASYNC_EXTENT,
&BTRFS_I(inode)->runtime_flags); &BTRFS_I(inode)->runtime_flags);
ret = cow_file_range_async(inode, locked_page, start, end, ret = cow_file_range_async(inode, locked_page, start, end,
page_started, nr_written); page_started, nr_written,
write_flags);
} }
if (ret) if (ret)
btrfs_cleanup_ordered_extents(inode, start, end - start + 1); btrfs_cleanup_ordered_extents(inode, start, end - start + 1);
@ -2025,11 +2032,12 @@ static noinline int add_pending_csums(struct btrfs_trans_handle *trans,
} }
int btrfs_set_extent_delalloc(struct inode *inode, u64 start, u64 end, int btrfs_set_extent_delalloc(struct inode *inode, u64 start, u64 end,
unsigned int extra_bits,
struct extent_state **cached_state, int dedupe) struct extent_state **cached_state, int dedupe)
{ {
WARN_ON((end & (PAGE_SIZE - 1)) == 0); WARN_ON((end & (PAGE_SIZE - 1)) == 0);
return set_extent_delalloc(&BTRFS_I(inode)->io_tree, start, end, return set_extent_delalloc(&BTRFS_I(inode)->io_tree, start, end,
cached_state); extra_bits, cached_state);
} }
/* see btrfs_writepage_start_hook for details on why this is required */ /* see btrfs_writepage_start_hook for details on why this is required */
@ -2090,7 +2098,7 @@ again:
goto out; goto out;
} }
btrfs_set_extent_delalloc(inode, page_start, page_end, &cached_state, btrfs_set_extent_delalloc(inode, page_start, page_end, 0, &cached_state,
0); 0);
ClearPageChecked(page); ClearPageChecked(page);
set_page_dirty(page); set_page_dirty(page);
@ -4790,7 +4798,7 @@ again:
EXTENT_DO_ACCOUNTING | EXTENT_DEFRAG, EXTENT_DO_ACCOUNTING | EXTENT_DEFRAG,
0, 0, &cached_state, GFP_NOFS); 0, 0, &cached_state, GFP_NOFS);
ret = btrfs_set_extent_delalloc(inode, block_start, block_end, ret = btrfs_set_extent_delalloc(inode, block_start, block_end, 0,
&cached_state, 0); &cached_state, 0);
if (ret) { if (ret) {
unlock_extent_cached(io_tree, block_start, block_end, unlock_extent_cached(io_tree, block_start, block_end,
@ -5438,6 +5446,14 @@ static int btrfs_inode_by_name(struct inode *dir, struct dentry *dentry,
goto out_err; goto out_err;
btrfs_dir_item_key_to_cpu(path->nodes[0], di, location); btrfs_dir_item_key_to_cpu(path->nodes[0], di, location);
if (location->type != BTRFS_INODE_ITEM_KEY &&
location->type != BTRFS_ROOT_ITEM_KEY) {
btrfs_warn(root->fs_info,
"%s gets something invalid in DIR_ITEM (name %s, directory ino %llu, location(%llu %u %llu))",
__func__, name, btrfs_ino(BTRFS_I(dir)),
location->objectid, location->type, location->offset);
goto out_err;
}
out: out:
btrfs_free_path(path); btrfs_free_path(path);
return ret; return ret;
@ -5754,8 +5770,6 @@ struct inode *btrfs_lookup_dentry(struct inode *dir, struct dentry *dentry)
return inode; return inode;
} }
BUG_ON(location.type != BTRFS_ROOT_ITEM_KEY);
index = srcu_read_lock(&fs_info->subvol_srcu); index = srcu_read_lock(&fs_info->subvol_srcu);
ret = fixup_tree_root_location(fs_info, dir, dentry, ret = fixup_tree_root_location(fs_info, dir, dentry,
&location, &sub_root); &location, &sub_root);
@ -9150,7 +9164,7 @@ again:
EXTENT_DO_ACCOUNTING | EXTENT_DEFRAG, EXTENT_DO_ACCOUNTING | EXTENT_DEFRAG,
0, 0, &cached_state, GFP_NOFS); 0, 0, &cached_state, GFP_NOFS);
ret = btrfs_set_extent_delalloc(inode, page_start, end, ret = btrfs_set_extent_delalloc(inode, page_start, end, 0,
&cached_state, 0); &cached_state, 0);
if (ret) { if (ret) {
unlock_extent_cached(io_tree, page_start, page_end, unlock_extent_cached(io_tree, page_start, page_end,

View File

@ -3268,7 +3268,8 @@ static int relocate_file_extent_cluster(struct inode *inode,
nr++; nr++;
} }
btrfs_set_extent_delalloc(inode, page_start, page_end, NULL, 0); btrfs_set_extent_delalloc(inode, page_start, page_end, 0, NULL,
0);
set_page_dirty(page); set_page_dirty(page);
unlock_extent(&BTRFS_I(inode)->io_tree, unlock_extent(&BTRFS_I(inode)->io_tree,

View File

@ -3521,7 +3521,40 @@ out:
} }
/* /*
* Check if ino ino1 is an ancestor of inode ino2 in the given root. * Check if inode ino2, or any of its ancestors, is inode ino1.
* Return 1 if true, 0 if false and < 0 on error.
*/
static int check_ino_in_path(struct btrfs_root *root,
const u64 ino1,
const u64 ino1_gen,
const u64 ino2,
const u64 ino2_gen,
struct fs_path *fs_path)
{
u64 ino = ino2;
if (ino1 == ino2)
return ino1_gen == ino2_gen;
while (ino > BTRFS_FIRST_FREE_OBJECTID) {
u64 parent;
u64 parent_gen;
int ret;
fs_path_reset(fs_path);
ret = get_first_ref(root, ino, &parent, &parent_gen, fs_path);
if (ret < 0)
return ret;
if (parent == ino1)
return parent_gen == ino1_gen;
ino = parent;
}
return 0;
}
/*
* Check if ino ino1 is an ancestor of inode ino2 in the given root for any
* possible path (in case ino2 is not a directory and has multiple hard links).
* Return 1 if true, 0 if false and < 0 on error. * Return 1 if true, 0 if false and < 0 on error.
*/ */
static int is_ancestor(struct btrfs_root *root, static int is_ancestor(struct btrfs_root *root,
@ -3530,36 +3563,91 @@ static int is_ancestor(struct btrfs_root *root,
const u64 ino2, const u64 ino2,
struct fs_path *fs_path) struct fs_path *fs_path)
{ {
u64 ino = ino2; bool free_fs_path = false;
bool free_path = false;
int ret = 0; int ret = 0;
struct btrfs_path *path = NULL;
struct btrfs_key key;
if (!fs_path) { if (!fs_path) {
fs_path = fs_path_alloc(); fs_path = fs_path_alloc();
if (!fs_path) if (!fs_path)
return -ENOMEM; return -ENOMEM;
free_path = true; free_fs_path = true;
} }
while (ino > BTRFS_FIRST_FREE_OBJECTID) { path = alloc_path_for_send();
u64 parent; if (!path) {
u64 parent_gen; ret = -ENOMEM;
goto out;
fs_path_reset(fs_path);
ret = get_first_ref(root, ino, &parent, &parent_gen, fs_path);
if (ret < 0) {
if (ret == -ENOENT && ino == ino2)
ret = 0;
goto out;
}
if (parent == ino1) {
ret = parent_gen == ino1_gen ? 1 : 0;
goto out;
}
ino = parent;
} }
key.objectid = ino2;
key.type = BTRFS_INODE_REF_KEY;
key.offset = 0;
ret = btrfs_search_slot(NULL, root, &key, path, 0, 0);
if (ret < 0)
goto out;
while (true) {
struct extent_buffer *leaf = path->nodes[0];
int slot = path->slots[0];
u32 cur_offset = 0;
u32 item_size;
if (slot >= btrfs_header_nritems(leaf)) {
ret = btrfs_next_leaf(root, path);
if (ret < 0)
goto out;
if (ret > 0)
break;
continue;
}
btrfs_item_key_to_cpu(leaf, &key, slot);
if (key.objectid != ino2)
break;
if (key.type != BTRFS_INODE_REF_KEY &&
key.type != BTRFS_INODE_EXTREF_KEY)
break;
item_size = btrfs_item_size_nr(leaf, slot);
while (cur_offset < item_size) {
u64 parent;
u64 parent_gen;
if (key.type == BTRFS_INODE_EXTREF_KEY) {
unsigned long ptr;
struct btrfs_inode_extref *extref;
ptr = btrfs_item_ptr_offset(leaf, slot);
extref = (struct btrfs_inode_extref *)
(ptr + cur_offset);
parent = btrfs_inode_extref_parent(leaf,
extref);
cur_offset += sizeof(*extref);
cur_offset += btrfs_inode_extref_name_len(leaf,
extref);
} else {
parent = key.offset;
cur_offset = item_size;
}
ret = get_inode_info(root, parent, NULL, &parent_gen,
NULL, NULL, NULL, NULL);
if (ret < 0)
goto out;
ret = check_ino_in_path(root, ino1, ino1_gen,
parent, parent_gen, fs_path);
if (ret)
goto out;
}
path->slots[0]++;
}
ret = 0;
out: out:
if (free_path) btrfs_free_path(path);
if (free_fs_path)
fs_path_free(fs_path); fs_path_free(fs_path);
return ret; return ret;
} }

View File

@ -507,9 +507,18 @@ int btrfs_parse_options(struct btrfs_fs_info *info, char *options,
token == Opt_compress_force || token == Opt_compress_force ||
strncmp(args[0].from, "zlib", 4) == 0) { strncmp(args[0].from, "zlib", 4) == 0) {
compress_type = "zlib"; compress_type = "zlib";
info->compress_type = BTRFS_COMPRESS_ZLIB; info->compress_type = BTRFS_COMPRESS_ZLIB;
info->compress_level = info->compress_level = BTRFS_ZLIB_DEFAULT_LEVEL;
btrfs_compress_str2level(args[0].from); /*
* args[0] contains uninitialized data since
* for these tokens we don't expect any
* parameter.
*/
if (token != Opt_compress &&
token != Opt_compress_force)
info->compress_level =
btrfs_compress_str2level(args[0].from);
btrfs_set_opt(info->mount_opt, COMPRESS); btrfs_set_opt(info->mount_opt, COMPRESS);
btrfs_clear_opt(info->mount_opt, NODATACOW); btrfs_clear_opt(info->mount_opt, NODATACOW);
btrfs_clear_opt(info->mount_opt, NODATASUM); btrfs_clear_opt(info->mount_opt, NODATASUM);

View File

@ -114,7 +114,7 @@ static int test_find_delalloc(u32 sectorsize)
* |--- delalloc ---| * |--- delalloc ---|
* |--- search ---| * |--- search ---|
*/ */
set_extent_delalloc(&tmp, 0, sectorsize - 1, NULL); set_extent_delalloc(&tmp, 0, sectorsize - 1, 0, NULL);
start = 0; start = 0;
end = 0; end = 0;
found = find_lock_delalloc_range(inode, &tmp, locked_page, &start, found = find_lock_delalloc_range(inode, &tmp, locked_page, &start,
@ -145,7 +145,7 @@ static int test_find_delalloc(u32 sectorsize)
test_msg("Couldn't find the locked page\n"); test_msg("Couldn't find the locked page\n");
goto out_bits; goto out_bits;
} }
set_extent_delalloc(&tmp, sectorsize, max_bytes - 1, NULL); set_extent_delalloc(&tmp, sectorsize, max_bytes - 1, 0, NULL);
start = test_start; start = test_start;
end = 0; end = 0;
found = find_lock_delalloc_range(inode, &tmp, locked_page, &start, found = find_lock_delalloc_range(inode, &tmp, locked_page, &start,
@ -200,7 +200,7 @@ static int test_find_delalloc(u32 sectorsize)
* *
* We are re-using our test_start from above since it works out well. * We are re-using our test_start from above since it works out well.
*/ */
set_extent_delalloc(&tmp, max_bytes, total_dirty - 1, NULL); set_extent_delalloc(&tmp, max_bytes, total_dirty - 1, 0, NULL);
start = test_start; start = test_start;
end = 0; end = 0;
found = find_lock_delalloc_range(inode, &tmp, locked_page, &start, found = find_lock_delalloc_range(inode, &tmp, locked_page, &start,

View File

@ -968,7 +968,7 @@ static int test_extent_accounting(u32 sectorsize, u32 nodesize)
btrfs_test_inode_set_ops(inode); btrfs_test_inode_set_ops(inode);
/* [BTRFS_MAX_EXTENT_SIZE] */ /* [BTRFS_MAX_EXTENT_SIZE] */
ret = btrfs_set_extent_delalloc(inode, 0, BTRFS_MAX_EXTENT_SIZE - 1, ret = btrfs_set_extent_delalloc(inode, 0, BTRFS_MAX_EXTENT_SIZE - 1, 0,
NULL, 0); NULL, 0);
if (ret) { if (ret) {
test_msg("btrfs_set_extent_delalloc returned %d\n", ret); test_msg("btrfs_set_extent_delalloc returned %d\n", ret);
@ -984,7 +984,7 @@ static int test_extent_accounting(u32 sectorsize, u32 nodesize)
/* [BTRFS_MAX_EXTENT_SIZE][sectorsize] */ /* [BTRFS_MAX_EXTENT_SIZE][sectorsize] */
ret = btrfs_set_extent_delalloc(inode, BTRFS_MAX_EXTENT_SIZE, ret = btrfs_set_extent_delalloc(inode, BTRFS_MAX_EXTENT_SIZE,
BTRFS_MAX_EXTENT_SIZE + sectorsize - 1, BTRFS_MAX_EXTENT_SIZE + sectorsize - 1,
NULL, 0); 0, NULL, 0);
if (ret) { if (ret) {
test_msg("btrfs_set_extent_delalloc returned %d\n", ret); test_msg("btrfs_set_extent_delalloc returned %d\n", ret);
goto out; goto out;
@ -1018,7 +1018,7 @@ static int test_extent_accounting(u32 sectorsize, u32 nodesize)
ret = btrfs_set_extent_delalloc(inode, BTRFS_MAX_EXTENT_SIZE >> 1, ret = btrfs_set_extent_delalloc(inode, BTRFS_MAX_EXTENT_SIZE >> 1,
(BTRFS_MAX_EXTENT_SIZE >> 1) (BTRFS_MAX_EXTENT_SIZE >> 1)
+ sectorsize - 1, + sectorsize - 1,
NULL, 0); 0, NULL, 0);
if (ret) { if (ret) {
test_msg("btrfs_set_extent_delalloc returned %d\n", ret); test_msg("btrfs_set_extent_delalloc returned %d\n", ret);
goto out; goto out;
@ -1036,7 +1036,7 @@ static int test_extent_accounting(u32 sectorsize, u32 nodesize)
ret = btrfs_set_extent_delalloc(inode, ret = btrfs_set_extent_delalloc(inode,
BTRFS_MAX_EXTENT_SIZE + 2 * sectorsize, BTRFS_MAX_EXTENT_SIZE + 2 * sectorsize,
(BTRFS_MAX_EXTENT_SIZE << 1) + 3 * sectorsize - 1, (BTRFS_MAX_EXTENT_SIZE << 1) + 3 * sectorsize - 1,
NULL, 0); 0, NULL, 0);
if (ret) { if (ret) {
test_msg("btrfs_set_extent_delalloc returned %d\n", ret); test_msg("btrfs_set_extent_delalloc returned %d\n", ret);
goto out; goto out;
@ -1053,7 +1053,7 @@ static int test_extent_accounting(u32 sectorsize, u32 nodesize)
*/ */
ret = btrfs_set_extent_delalloc(inode, ret = btrfs_set_extent_delalloc(inode,
BTRFS_MAX_EXTENT_SIZE + sectorsize, BTRFS_MAX_EXTENT_SIZE + sectorsize,
BTRFS_MAX_EXTENT_SIZE + 2 * sectorsize - 1, NULL, 0); BTRFS_MAX_EXTENT_SIZE + 2 * sectorsize - 1, 0, NULL, 0);
if (ret) { if (ret) {
test_msg("btrfs_set_extent_delalloc returned %d\n", ret); test_msg("btrfs_set_extent_delalloc returned %d\n", ret);
goto out; goto out;
@ -1089,7 +1089,7 @@ static int test_extent_accounting(u32 sectorsize, u32 nodesize)
*/ */
ret = btrfs_set_extent_delalloc(inode, ret = btrfs_set_extent_delalloc(inode,
BTRFS_MAX_EXTENT_SIZE + sectorsize, BTRFS_MAX_EXTENT_SIZE + sectorsize,
BTRFS_MAX_EXTENT_SIZE + 2 * sectorsize - 1, NULL, 0); BTRFS_MAX_EXTENT_SIZE + 2 * sectorsize - 1, 0, NULL, 0);
if (ret) { if (ret) {
test_msg("btrfs_set_extent_delalloc returned %d\n", ret); test_msg("btrfs_set_extent_delalloc returned %d\n", ret);
goto out; goto out;

View File

@ -242,7 +242,8 @@ static int check_leaf_item(struct btrfs_root *root,
return ret; return ret;
} }
int btrfs_check_leaf(struct btrfs_root *root, struct extent_buffer *leaf) static int check_leaf(struct btrfs_root *root, struct extent_buffer *leaf,
bool check_item_data)
{ {
struct btrfs_fs_info *fs_info = root->fs_info; struct btrfs_fs_info *fs_info = root->fs_info;
/* No valid key type is 0, so all key should be larger than this key */ /* No valid key type is 0, so all key should be larger than this key */
@ -361,10 +362,15 @@ int btrfs_check_leaf(struct btrfs_root *root, struct extent_buffer *leaf)
return -EUCLEAN; return -EUCLEAN;
} }
/* Check if the item size and content meet other criteria */ if (check_item_data) {
ret = check_leaf_item(root, leaf, &key, slot); /*
if (ret < 0) * Check if the item size and content meet other
return ret; * criteria
*/
ret = check_leaf_item(root, leaf, &key, slot);
if (ret < 0)
return ret;
}
prev_key.objectid = key.objectid; prev_key.objectid = key.objectid;
prev_key.type = key.type; prev_key.type = key.type;
@ -374,6 +380,17 @@ int btrfs_check_leaf(struct btrfs_root *root, struct extent_buffer *leaf)
return 0; return 0;
} }
int btrfs_check_leaf_full(struct btrfs_root *root, struct extent_buffer *leaf)
{
return check_leaf(root, leaf, true);
}
int btrfs_check_leaf_relaxed(struct btrfs_root *root,
struct extent_buffer *leaf)
{
return check_leaf(root, leaf, false);
}
int btrfs_check_node(struct btrfs_root *root, struct extent_buffer *node) int btrfs_check_node(struct btrfs_root *root, struct extent_buffer *node)
{ {
unsigned long nr = btrfs_header_nritems(node); unsigned long nr = btrfs_header_nritems(node);

View File

@ -20,7 +20,19 @@
#include "ctree.h" #include "ctree.h"
#include "extent_io.h" #include "extent_io.h"
int btrfs_check_leaf(struct btrfs_root *root, struct extent_buffer *leaf); /*
* Comprehensive leaf checker.
* Will check not only the item pointers, but also every possible member
* in item data.
*/
int btrfs_check_leaf_full(struct btrfs_root *root, struct extent_buffer *leaf);
/*
* Less strict leaf checker.
* Will only check item pointers, not reading item data.
*/
int btrfs_check_leaf_relaxed(struct btrfs_root *root,
struct extent_buffer *leaf);
int btrfs_check_node(struct btrfs_root *root, struct extent_buffer *node); int btrfs_check_node(struct btrfs_root *root, struct extent_buffer *node);
#endif #endif

View File

@ -4102,7 +4102,7 @@ static int log_one_extent(struct btrfs_trans_handle *trans,
if (ordered_io_err) { if (ordered_io_err) {
ctx->io_err = -EIO; ctx->io_err = -EIO;
return 0; return ctx->io_err;
} }
btrfs_init_map_token(&token); btrfs_init_map_token(&token);

View File

@ -189,6 +189,7 @@ static void free_fs_devices(struct btrfs_fs_devices *fs_devices)
struct btrfs_device, dev_list); struct btrfs_device, dev_list);
list_del(&device->dev_list); list_del(&device->dev_list);
rcu_string_free(device->name); rcu_string_free(device->name);
bio_put(device->flush_bio);
kfree(device); kfree(device);
} }
kfree(fs_devices); kfree(fs_devices);
@ -578,6 +579,7 @@ static void btrfs_free_stale_device(struct btrfs_device *cur_dev)
fs_devs->num_devices--; fs_devs->num_devices--;
list_del(&dev->dev_list); list_del(&dev->dev_list);
rcu_string_free(dev->name); rcu_string_free(dev->name);
bio_put(dev->flush_bio);
kfree(dev); kfree(dev);
} }
break; break;
@ -630,6 +632,7 @@ static noinline int device_list_add(const char *path,
name = rcu_string_strdup(path, GFP_NOFS); name = rcu_string_strdup(path, GFP_NOFS);
if (!name) { if (!name) {
bio_put(device->flush_bio);
kfree(device); kfree(device);
return -ENOMEM; return -ENOMEM;
} }
@ -742,6 +745,7 @@ static struct btrfs_fs_devices *clone_fs_devices(struct btrfs_fs_devices *orig)
name = rcu_string_strdup(orig_dev->name->str, name = rcu_string_strdup(orig_dev->name->str,
GFP_KERNEL); GFP_KERNEL);
if (!name) { if (!name) {
bio_put(device->flush_bio);
kfree(device); kfree(device);
goto error; goto error;
} }
@ -807,6 +811,7 @@ again:
list_del_init(&device->dev_list); list_del_init(&device->dev_list);
fs_devices->num_devices--; fs_devices->num_devices--;
rcu_string_free(device->name); rcu_string_free(device->name);
bio_put(device->flush_bio);
kfree(device); kfree(device);
} }
@ -1750,20 +1755,24 @@ static int btrfs_rm_dev_item(struct btrfs_fs_info *fs_info,
key.offset = device->devid; key.offset = device->devid;
ret = btrfs_search_slot(trans, root, &key, path, -1, 1); ret = btrfs_search_slot(trans, root, &key, path, -1, 1);
if (ret < 0) if (ret) {
goto out; if (ret > 0)
ret = -ENOENT;
if (ret > 0) { btrfs_abort_transaction(trans, ret);
ret = -ENOENT; btrfs_end_transaction(trans);
goto out; goto out;
} }
ret = btrfs_del_item(trans, root, path); ret = btrfs_del_item(trans, root, path);
if (ret) if (ret) {
goto out; btrfs_abort_transaction(trans, ret);
btrfs_end_transaction(trans);
}
out: out:
btrfs_free_path(path); btrfs_free_path(path);
btrfs_commit_transaction(trans); if (!ret)
ret = btrfs_commit_transaction(trans);
return ret; return ret;
} }
@ -1993,7 +2002,7 @@ void btrfs_rm_dev_replace_remove_srcdev(struct btrfs_fs_info *fs_info,
fs_devices = srcdev->fs_devices; fs_devices = srcdev->fs_devices;
list_del_rcu(&srcdev->dev_list); list_del_rcu(&srcdev->dev_list);
list_del_rcu(&srcdev->dev_alloc_list); list_del(&srcdev->dev_alloc_list);
fs_devices->num_devices--; fs_devices->num_devices--;
if (srcdev->missing) if (srcdev->missing)
fs_devices->missing_devices--; fs_devices->missing_devices--;
@ -2349,6 +2358,7 @@ int btrfs_init_new_device(struct btrfs_fs_info *fs_info, const char *device_path
name = rcu_string_strdup(device_path, GFP_KERNEL); name = rcu_string_strdup(device_path, GFP_KERNEL);
if (!name) { if (!name) {
bio_put(device->flush_bio);
kfree(device); kfree(device);
ret = -ENOMEM; ret = -ENOMEM;
goto error; goto error;
@ -2358,6 +2368,7 @@ int btrfs_init_new_device(struct btrfs_fs_info *fs_info, const char *device_path
trans = btrfs_start_transaction(root, 0); trans = btrfs_start_transaction(root, 0);
if (IS_ERR(trans)) { if (IS_ERR(trans)) {
rcu_string_free(device->name); rcu_string_free(device->name);
bio_put(device->flush_bio);
kfree(device); kfree(device);
ret = PTR_ERR(trans); ret = PTR_ERR(trans);
goto error; goto error;
@ -2501,6 +2512,7 @@ error_trans:
if (trans) if (trans)
btrfs_end_transaction(trans); btrfs_end_transaction(trans);
rcu_string_free(device->name); rcu_string_free(device->name);
bio_put(device->flush_bio);
kfree(device); kfree(device);
error: error:
blkdev_put(bdev, FMODE_EXCL); blkdev_put(bdev, FMODE_EXCL);
@ -2567,6 +2579,7 @@ int btrfs_init_dev_replace_tgtdev(struct btrfs_fs_info *fs_info,
name = rcu_string_strdup(device_path, GFP_KERNEL); name = rcu_string_strdup(device_path, GFP_KERNEL);
if (!name) { if (!name) {
bio_put(device->flush_bio);
kfree(device); kfree(device);
ret = -ENOMEM; ret = -ENOMEM;
goto error; goto error;
@ -6284,6 +6297,7 @@ struct btrfs_device *btrfs_alloc_device(struct btrfs_fs_info *fs_info,
ret = find_next_devid(fs_info, &tmp); ret = find_next_devid(fs_info, &tmp);
if (ret) { if (ret) {
bio_put(dev->flush_bio);
kfree(dev); kfree(dev);
return ERR_PTR(ret); return ERR_PTR(ret);
} }