On 17/01/2020, 16:01, "linux-btrfs-owner@xxxxxxxxxxxxxxx on behalf of Nikolay Borisov" <linux-btrfs-owner@xxxxxxxxxxxxxxx on behalf of nborisov@xxxxxxxx> wrote:
On 17.01.20 г. 14:51 ч., Johannes Thumshirn wrote:
> Similar to the superblock read path, change the write path to using BIOs
> and pages instead of buffer_heads.
>
> This is based on a patch originally authored by Nikolay Borisov.
>
> Co-developed-by: Nikolay Borisov <nborisov@xxxxxxxx>
> Signed-off-by: Johannes Thumshirn <johannes.thumshirn@xxxxxxx>
> ---
> fs/btrfs/disk-io.c | 107 ++++++++++++++++++++++++++-------------------
> 1 file changed, 61 insertions(+), 46 deletions(-)
>
> diff --git a/fs/btrfs/disk-io.c b/fs/btrfs/disk-io.c
> index 50c93ffe8d03..51e7b832c8fd 100644
> --- a/fs/btrfs/disk-io.c
> +++ b/fs/btrfs/disk-io.c
> @@ -3353,25 +3353,33 @@ int __cold open_ctree(struct super_block *sb,
> }
> ALLOW_ERROR_INJECTION(open_ctree, ERRNO);
>
> -static void btrfs_end_buffer_write_sync(struct buffer_head *bh, int uptodate)
> +static void btrfs_end_super_write(struct bio *bio)
> {
> - if (uptodate) {
> - set_buffer_uptodate(bh);
> - } else {
> - struct btrfs_device *device = (struct btrfs_device *)
> - bh->b_private;
> -
> - btrfs_warn_rl_in_rcu(device->fs_info,
> - "lost page write due to IO error on %s",
> - rcu_str_deref(device->name));
> - /* note, we don't set_buffer_write_io_error because we have
> - * our own ways of dealing with the IO errors
> - */
> - clear_buffer_uptodate(bh);
> - btrfs_dev_stat_inc_and_print(device, BTRFS_DEV_STAT_WRITE_ERRS);
> + struct btrfs_device *device = bio->bi_private;
> + struct bio_vec *bvec;
> + struct bvec_iter_all iter_all;
> + struct page *page;
> +
> + bio_for_each_segment_all(bvec, bio, iter_all) {
> + page = bvec->bv_page;
> +
> + if (blk_status_to_errno(bio->bi_status)) {
> + btrfs_warn_rl_in_rcu(device->fs_info,
> + "lost page write due to IO error on %s",
> + rcu_str_deref(device->name));
> + ClearPageUptodate(page);
> + SetPageError(page);
> + btrfs_dev_stat_inc_and_print(device,
> + BTRFS_DEV_STAT_WRITE_ERRS);
> + } else {
> + SetPageUptodate(page);
> + }
> +
> + put_page(page);
Isn't this extra put page? Perhahps it's not because that would be the
reference from find_or_create_page in write_dev_supers. In any case I'd
rather have it in that function.
No we can't do the put_page() in in write_dev_supers() as btrfs_end_super_write()
is the bio endio hook and it's called upon completion of the bio. This happens
asynchronous to write_dev_supers().