Merge branch 'for-4.14-rc3' of git://git.kernel.org/pub/scm/linux/kernel/git/kdave/linux

Pull btrfs fixes from David Sterba:
 "We've collected a bunch of isolated fixes, for crashes, user-visible
  behaviour or missing bits from other subsystem cleanups from the past.

  The overall number is not small but I was not able to make it
  significantly smaller. Most of the patches are supposed to go to
  stable"

* 'for-4.14-rc3' of git://git.kernel.org/pub/scm/linux/kernel/git/kdave/linux:
  btrfs: log csums for all modified extents
  Btrfs: fix unexpected result when dio reading corrupted blocks
  btrfs: Report error on removing qgroup if del_qgroup_item fails
  Btrfs: skip checksum when reading compressed data if some IO have failed
  Btrfs: fix kernel oops while reading compressed data
  Btrfs: use btrfs_op instead of bio_op in __btrfs_map_block
  Btrfs: do not backup tree roots when fsync
  btrfs: remove BTRFS_FS_QUOTA_DISABLING flag
  btrfs: propagate error to btrfs_cmp_data_prepare caller
  btrfs: prevent to set invalid default subvolid
  Btrfs: send: fix error number for unknown inode types
  btrfs: fix NULL pointer dereference from free_reloc_roots()
  btrfs: finish ordered extent cleaning if no progress is found
  btrfs: clear ordered flag on cleaning up ordered extents
  Btrfs: fix incorrect {node,sector}size endianness from BTRFS_IOC_FS_INFO
  Btrfs: do not reset bio->bi_ops while writing bio
  Btrfs: use the new helper wbc_to_write_flags
This commit is contained in:
Linus Torvalds 2017-09-29 12:57:35 -07:00
commit 5ba88cd6e9
11 changed files with 72 additions and 27 deletions

View File

@ -107,7 +107,8 @@ static void end_compressed_bio_read(struct bio *bio)
struct inode *inode; struct inode *inode;
struct page *page; struct page *page;
unsigned long index; unsigned long index;
int ret; unsigned int mirror = btrfs_io_bio(bio)->mirror_num;
int ret = 0;
if (bio->bi_status) if (bio->bi_status)
cb->errors = 1; cb->errors = 1;
@ -118,6 +119,21 @@ static void end_compressed_bio_read(struct bio *bio)
if (!refcount_dec_and_test(&cb->pending_bios)) if (!refcount_dec_and_test(&cb->pending_bios))
goto out; goto out;
/*
* Record the correct mirror_num in cb->orig_bio so that
* read-repair can work properly.
*/
ASSERT(btrfs_io_bio(cb->orig_bio));
btrfs_io_bio(cb->orig_bio)->mirror_num = mirror;
cb->mirror_num = mirror;
/*
* Some IO in this cb have failed, just skip checksum as there
* is no way it could be correct.
*/
if (cb->errors == 1)
goto csum_failed;
inode = cb->inode; inode = cb->inode;
ret = check_compressed_csum(BTRFS_I(inode), cb, ret = check_compressed_csum(BTRFS_I(inode), cb,
(u64)bio->bi_iter.bi_sector << 9); (u64)bio->bi_iter.bi_sector << 9);

View File

@ -709,7 +709,6 @@ struct btrfs_delayed_root;
#define BTRFS_FS_OPEN 5 #define BTRFS_FS_OPEN 5
#define BTRFS_FS_QUOTA_ENABLED 6 #define BTRFS_FS_QUOTA_ENABLED 6
#define BTRFS_FS_QUOTA_ENABLING 7 #define BTRFS_FS_QUOTA_ENABLING 7
#define BTRFS_FS_QUOTA_DISABLING 8
#define BTRFS_FS_UPDATE_UUID_TREE_GEN 9 #define BTRFS_FS_UPDATE_UUID_TREE_GEN 9
#define BTRFS_FS_CREATING_FREE_SPACE_TREE 10 #define BTRFS_FS_CREATING_FREE_SPACE_TREE 10
#define BTRFS_FS_BTREE_ERR 11 #define BTRFS_FS_BTREE_ERR 11

View File

@ -3643,7 +3643,14 @@ int write_all_supers(struct btrfs_fs_info *fs_info, int max_mirrors)
u64 flags; u64 flags;
do_barriers = !btrfs_test_opt(fs_info, NOBARRIER); do_barriers = !btrfs_test_opt(fs_info, NOBARRIER);
backup_super_roots(fs_info);
/*
* max_mirrors == 0 indicates we're from commit_transaction,
* not from fsync where the tree roots in fs_info have not
* been consistent on disk.
*/
if (max_mirrors == 0)
backup_super_roots(fs_info);
sb = fs_info->super_for_commit; sb = fs_info->super_for_commit;
dev_item = &sb->dev_item; dev_item = &sb->dev_item;

View File

@ -3471,8 +3471,7 @@ static int __extent_writepage(struct page *page, struct writeback_control *wbc,
unsigned int write_flags = 0; unsigned int write_flags = 0;
unsigned long nr_written = 0; unsigned long nr_written = 0;
if (wbc->sync_mode == WB_SYNC_ALL) write_flags = wbc_to_write_flags(wbc);
write_flags = REQ_SYNC;
trace___extent_writepage(page, inode, wbc); trace___extent_writepage(page, inode, wbc);
@ -3718,7 +3717,7 @@ static noinline_for_stack int write_one_eb(struct extent_buffer *eb,
unsigned long i, num_pages; unsigned long i, num_pages;
unsigned long bio_flags = 0; unsigned long bio_flags = 0;
unsigned long start, end; unsigned long start, end;
unsigned int write_flags = (epd->sync_io ? REQ_SYNC : 0) | REQ_META; unsigned int write_flags = wbc_to_write_flags(wbc) | REQ_META;
int ret = 0; int ret = 0;
clear_bit(EXTENT_BUFFER_WRITE_ERR, &eb->bflags); clear_bit(EXTENT_BUFFER_WRITE_ERR, &eb->bflags);
@ -4063,9 +4062,6 @@ static void flush_epd_write_bio(struct extent_page_data *epd)
if (epd->bio) { if (epd->bio) {
int ret; int ret;
bio_set_op_attrs(epd->bio, REQ_OP_WRITE,
epd->sync_io ? REQ_SYNC : 0);
ret = submit_one_bio(epd->bio, 0, epd->bio_flags); ret = submit_one_bio(epd->bio, 0, epd->bio_flags);
BUG_ON(ret < 0); /* -ENOMEM */ BUG_ON(ret < 0); /* -ENOMEM */
epd->bio = NULL; epd->bio = NULL;

View File

@ -135,6 +135,18 @@ static inline void btrfs_cleanup_ordered_extents(struct inode *inode,
const u64 offset, const u64 offset,
const u64 bytes) const u64 bytes)
{ {
unsigned long index = offset >> PAGE_SHIFT;
unsigned long end_index = (offset + bytes - 1) >> PAGE_SHIFT;
struct page *page;
while (index <= end_index) {
page = find_get_page(inode->i_mapping, index);
index++;
if (!page)
continue;
ClearPagePrivate2(page);
put_page(page);
}
return __endio_write_update_ordered(inode, offset + PAGE_SIZE, return __endio_write_update_ordered(inode, offset + PAGE_SIZE,
bytes - PAGE_SIZE, false); bytes - PAGE_SIZE, false);
} }
@ -8357,11 +8369,8 @@ static void btrfs_endio_direct_read(struct bio *bio)
struct btrfs_io_bio *io_bio = btrfs_io_bio(bio); struct btrfs_io_bio *io_bio = btrfs_io_bio(bio);
blk_status_t err = bio->bi_status; blk_status_t err = bio->bi_status;
if (dip->flags & BTRFS_DIO_ORIG_BIO_SUBMITTED) { if (dip->flags & BTRFS_DIO_ORIG_BIO_SUBMITTED)
err = btrfs_subio_endio_read(inode, io_bio, err); err = btrfs_subio_endio_read(inode, io_bio, err);
if (!err)
bio->bi_status = 0;
}
unlock_extent(&BTRFS_I(inode)->io_tree, dip->logical_offset, unlock_extent(&BTRFS_I(inode)->io_tree, dip->logical_offset,
dip->logical_offset + dip->bytes - 1); dip->logical_offset + dip->bytes - 1);
@ -8369,7 +8378,7 @@ static void btrfs_endio_direct_read(struct bio *bio)
kfree(dip); kfree(dip);
dio_bio->bi_status = bio->bi_status; dio_bio->bi_status = err;
dio_end_io(dio_bio); dio_end_io(dio_bio);
if (io_bio->end_io) if (io_bio->end_io)
@ -8387,6 +8396,7 @@ static void __endio_write_update_ordered(struct inode *inode,
btrfs_work_func_t func; btrfs_work_func_t func;
u64 ordered_offset = offset; u64 ordered_offset = offset;
u64 ordered_bytes = bytes; u64 ordered_bytes = bytes;
u64 last_offset;
int ret; int ret;
if (btrfs_is_free_space_inode(BTRFS_I(inode))) { if (btrfs_is_free_space_inode(BTRFS_I(inode))) {
@ -8398,6 +8408,7 @@ static void __endio_write_update_ordered(struct inode *inode,
} }
again: again:
last_offset = ordered_offset;
ret = btrfs_dec_test_first_ordered_pending(inode, &ordered, ret = btrfs_dec_test_first_ordered_pending(inode, &ordered,
&ordered_offset, &ordered_offset,
ordered_bytes, ordered_bytes,
@ -8408,6 +8419,12 @@ again:
btrfs_init_work(&ordered->work, func, finish_ordered_fn, NULL, NULL); btrfs_init_work(&ordered->work, func, finish_ordered_fn, NULL, NULL);
btrfs_queue_work(wq, &ordered->work); btrfs_queue_work(wq, &ordered->work);
out_test: out_test:
/*
* If btrfs_dec_test_ordered_pending does not find any ordered extent
* in the range, we can exit.
*/
if (ordered_offset == last_offset)
return;
/* /*
* our bio might span multiple ordered extents. If we haven't * our bio might span multiple ordered extents. If we haven't
* completed the accounting for the whole dio, go back and try again * completed the accounting for the whole dio, go back and try again

View File

@ -2773,9 +2773,9 @@ static long btrfs_ioctl_fs_info(struct btrfs_fs_info *fs_info,
} }
mutex_unlock(&fs_devices->device_list_mutex); mutex_unlock(&fs_devices->device_list_mutex);
fi_args->nodesize = fs_info->super_copy->nodesize; fi_args->nodesize = fs_info->nodesize;
fi_args->sectorsize = fs_info->super_copy->sectorsize; fi_args->sectorsize = fs_info->sectorsize;
fi_args->clone_alignment = fs_info->super_copy->sectorsize; fi_args->clone_alignment = fs_info->sectorsize;
if (copy_to_user(arg, fi_args, sizeof(*fi_args))) if (copy_to_user(arg, fi_args, sizeof(*fi_args)))
ret = -EFAULT; ret = -EFAULT;
@ -3032,7 +3032,7 @@ static int btrfs_cmp_data_prepare(struct inode *src, u64 loff,
out: out:
if (ret) if (ret)
btrfs_cmp_data_free(cmp); btrfs_cmp_data_free(cmp);
return 0; return ret;
} }
static int btrfs_cmp_data(u64 len, struct cmp_pages *cmp) static int btrfs_cmp_data(u64 len, struct cmp_pages *cmp)
@ -4061,6 +4061,10 @@ static long btrfs_ioctl_default_subvol(struct file *file, void __user *argp)
ret = PTR_ERR(new_root); ret = PTR_ERR(new_root);
goto out; goto out;
} }
if (!is_fstree(new_root->objectid)) {
ret = -ENOENT;
goto out;
}
path = btrfs_alloc_path(); path = btrfs_alloc_path();
if (!path) { if (!path) {

View File

@ -807,7 +807,6 @@ static int btrfs_clean_quota_tree(struct btrfs_trans_handle *trans,
} }
ret = 0; ret = 0;
out: out:
set_bit(BTRFS_FS_QUOTA_DISABLING, &root->fs_info->flags);
btrfs_free_path(path); btrfs_free_path(path);
return ret; return ret;
} }
@ -953,7 +952,6 @@ int btrfs_quota_disable(struct btrfs_trans_handle *trans,
if (!fs_info->quota_root) if (!fs_info->quota_root)
goto out; goto out;
clear_bit(BTRFS_FS_QUOTA_ENABLED, &fs_info->flags); clear_bit(BTRFS_FS_QUOTA_ENABLED, &fs_info->flags);
set_bit(BTRFS_FS_QUOTA_DISABLING, &fs_info->flags);
btrfs_qgroup_wait_for_completion(fs_info, false); btrfs_qgroup_wait_for_completion(fs_info, false);
spin_lock(&fs_info->qgroup_lock); spin_lock(&fs_info->qgroup_lock);
quota_root = fs_info->quota_root; quota_root = fs_info->quota_root;
@ -1307,6 +1305,8 @@ int btrfs_remove_qgroup(struct btrfs_trans_handle *trans,
} }
} }
ret = del_qgroup_item(trans, quota_root, qgroupid); ret = del_qgroup_item(trans, quota_root, qgroupid);
if (ret && ret != -ENOENT)
goto out;
while (!list_empty(&qgroup->groups)) { while (!list_empty(&qgroup->groups)) {
list = list_first_entry(&qgroup->groups, list = list_first_entry(&qgroup->groups,
@ -2086,8 +2086,6 @@ int btrfs_run_qgroups(struct btrfs_trans_handle *trans,
if (test_and_clear_bit(BTRFS_FS_QUOTA_ENABLING, &fs_info->flags)) if (test_and_clear_bit(BTRFS_FS_QUOTA_ENABLING, &fs_info->flags))
set_bit(BTRFS_FS_QUOTA_ENABLED, &fs_info->flags); set_bit(BTRFS_FS_QUOTA_ENABLED, &fs_info->flags);
if (test_and_clear_bit(BTRFS_FS_QUOTA_DISABLING, &fs_info->flags))
clear_bit(BTRFS_FS_QUOTA_ENABLED, &fs_info->flags);
spin_lock(&fs_info->qgroup_lock); spin_lock(&fs_info->qgroup_lock);
while (!list_empty(&fs_info->dirty_qgroups)) { while (!list_empty(&fs_info->dirty_qgroups)) {

View File

@ -2400,11 +2400,11 @@ void free_reloc_roots(struct list_head *list)
while (!list_empty(list)) { while (!list_empty(list)) {
reloc_root = list_entry(list->next, struct btrfs_root, reloc_root = list_entry(list->next, struct btrfs_root,
root_list); root_list);
__del_reloc_root(reloc_root);
free_extent_buffer(reloc_root->node); free_extent_buffer(reloc_root->node);
free_extent_buffer(reloc_root->commit_root); free_extent_buffer(reloc_root->commit_root);
reloc_root->node = NULL; reloc_root->node = NULL;
reloc_root->commit_root = NULL; reloc_root->commit_root = NULL;
__del_reloc_root(reloc_root);
} }
} }

View File

@ -2630,7 +2630,7 @@ static int send_create_inode(struct send_ctx *sctx, u64 ino)
} else { } else {
btrfs_warn(sctx->send_root->fs_info, "unexpected inode type %o", btrfs_warn(sctx->send_root->fs_info, "unexpected inode type %o",
(int)(mode & S_IFMT)); (int)(mode & S_IFMT));
ret = -ENOTSUPP; ret = -EOPNOTSUPP;
goto out; goto out;
} }

View File

@ -4181,6 +4181,7 @@ static int btrfs_log_changed_extents(struct btrfs_trans_handle *trans,
struct extent_map *em, *n; struct extent_map *em, *n;
struct list_head extents; struct list_head extents;
struct extent_map_tree *tree = &inode->extent_tree; struct extent_map_tree *tree = &inode->extent_tree;
u64 logged_start, logged_end;
u64 test_gen; u64 test_gen;
int ret = 0; int ret = 0;
int num = 0; int num = 0;
@ -4190,10 +4191,11 @@ static int btrfs_log_changed_extents(struct btrfs_trans_handle *trans,
down_write(&inode->dio_sem); down_write(&inode->dio_sem);
write_lock(&tree->lock); write_lock(&tree->lock);
test_gen = root->fs_info->last_trans_committed; test_gen = root->fs_info->last_trans_committed;
logged_start = start;
logged_end = end;
list_for_each_entry_safe(em, n, &tree->modified_extents, list) { list_for_each_entry_safe(em, n, &tree->modified_extents, list) {
list_del_init(&em->list); list_del_init(&em->list);
/* /*
* Just an arbitrary number, this can be really CPU intensive * Just an arbitrary number, this can be really CPU intensive
* once we start getting a lot of extents, and really once we * once we start getting a lot of extents, and really once we
@ -4208,6 +4210,12 @@ static int btrfs_log_changed_extents(struct btrfs_trans_handle *trans,
if (em->generation <= test_gen) if (em->generation <= test_gen)
continue; continue;
if (em->start < logged_start)
logged_start = em->start;
if ((em->start + em->len - 1) > logged_end)
logged_end = em->start + em->len - 1;
/* Need a ref to keep it from getting evicted from cache */ /* Need a ref to keep it from getting evicted from cache */
refcount_inc(&em->refs); refcount_inc(&em->refs);
set_bit(EXTENT_FLAG_LOGGING, &em->flags); set_bit(EXTENT_FLAG_LOGGING, &em->flags);
@ -4216,7 +4224,7 @@ static int btrfs_log_changed_extents(struct btrfs_trans_handle *trans,
} }
list_sort(NULL, &extents, extent_cmp); list_sort(NULL, &extents, extent_cmp);
btrfs_get_logged_extents(inode, logged_list, start, end); btrfs_get_logged_extents(inode, logged_list, logged_start, logged_end);
/* /*
* Some ordered extents started by fsync might have completed * Some ordered extents started by fsync might have completed
* before we could collect them into the list logged_list, which * before we could collect them into the list logged_list, which

View File

@ -6166,7 +6166,7 @@ blk_status_t btrfs_map_bio(struct btrfs_fs_info *fs_info, struct bio *bio,
map_length = length; map_length = length;
btrfs_bio_counter_inc_blocked(fs_info); btrfs_bio_counter_inc_blocked(fs_info);
ret = __btrfs_map_block(fs_info, bio_op(bio), logical, ret = __btrfs_map_block(fs_info, btrfs_op(bio), logical,
&map_length, &bbio, mirror_num, 1); &map_length, &bbio, mirror_num, 1);
if (ret) { if (ret) {
btrfs_bio_counter_dec(fs_info); btrfs_bio_counter_dec(fs_info);