Received: by 2002:ac0:a594:0:0:0:0:0 with SMTP id m20-v6csp2999659imm; Thu, 24 May 2018 20:52:24 -0700 (PDT) X-Google-Smtp-Source: AB8JxZpGtWyu5Sb5cPlBTztZIfrqv/BZhfeyJ1ACxtsQUUx5pZ4xjxmnu+xhNsatJPZUKnOc0R++ X-Received: by 2002:a63:69c3:: with SMTP id e186-v6mr608925pgc.353.1527220344915; Thu, 24 May 2018 20:52:24 -0700 (PDT) ARC-Seal: i=1; a=rsa-sha256; t=1527220344; cv=none; d=google.com; s=arc-20160816; b=Pm4e7Svzsei1TSqJbqcpjww29W+BqthklD/4viEV5KBfd3Z9rdgvJv4smSIFUbsTFL uX8N3NY1Msz0+WIZV852/cfQQEqLQhadpc7BSD/e1h7sasD9kD7ls2zpwFnPnXJlJieZ A7dbCcWEPl2m8C70IrfVFCp0HER803q+OBUCJSf8WGE6Sq+c0PkWxP4TiyVeyAwsQ6wP rhrcDr0OoJ+FbibRnmqE6TbNUltfWp8iPDLvj25HJZ7aRotr0ctCfErM4k40DRykSTdt yuNjPgQeh3VsC6cCdohpAGeJEGYz+HGDhjICfMRUWKu2mvq2uzXtN7x/EEOSwvbCF/gt o/wA== ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=arc-20160816; h=list-id:precedence:sender:references:in-reply-to:message-id:date :subject:cc:to:from:arc-authentication-results; bh=qnww7szmb6+qMhargpUtkVxmYjcWTTnOzObOCJ6yAQA=; b=mOsl5PHdHOMiVAr8+212W1OwiANE+eUxlJ3ysxmQOSYO+7mbdvAxhCEkVtHesgfUm0 UvOmeoqMipkJqSRZMcGGGr46m7zWewBTVaqFzqhBkwNnpvxa4vWuXo603wH7Ezp6V7sf T4X5OgHXqZrYpm9NQilSW4CuS/KnUsoMb1iIAxKziX5u8Sbe0LSSl5VDhCBLllqXdZdv W+1d+kgg9Y91lrAHc++t6CHrSf0Ld1x8JfwAfKsObDGRDldp/Vg8VjlBLm5chGZcZESD fNNhLqZnFLJt2p6s9OKpTUiu6t4Uv5KhED7ztY4+XIWnxbTIeTkkDdRb8DlHuosXLujY /fgQ== ARC-Authentication-Results: i=1; mx.google.com; spf=pass (google.com: best guess record for domain of linux-kernel-owner@vger.kernel.org designates 209.132.180.67 as permitted sender) smtp.mailfrom=linux-kernel-owner@vger.kernel.org; dmarc=fail (p=NONE sp=NONE dis=NONE) header.from=redhat.com Return-Path: Received: from vger.kernel.org (vger.kernel.org. [209.132.180.67]) by mx.google.com with ESMTP id t8-v6si5609412pgq.19.2018.05.24.20.52.10; Thu, 24 May 2018 20:52:24 -0700 (PDT) Received-SPF: pass (google.com: best guess record for domain of linux-kernel-owner@vger.kernel.org designates 209.132.180.67 as permitted sender) client-ip=209.132.180.67; Authentication-Results: mx.google.com; spf=pass (google.com: best guess record for domain of linux-kernel-owner@vger.kernel.org designates 209.132.180.67 as permitted sender) smtp.mailfrom=linux-kernel-owner@vger.kernel.org; dmarc=fail (p=NONE sp=NONE dis=NONE) header.from=redhat.com Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S935724AbeEYDuQ (ORCPT + 99 others); Thu, 24 May 2018 23:50:16 -0400 Received: from mx3-rdu2.redhat.com ([66.187.233.73]:38050 "EHLO mx1.redhat.com" rhost-flags-OK-OK-OK-FAIL) by vger.kernel.org with ESMTP id S932618AbeEYDuP (ORCPT ); Thu, 24 May 2018 23:50:15 -0400 Received: from smtp.corp.redhat.com (int-mx06.intmail.prod.int.rdu2.redhat.com [10.11.54.6]) (using TLSv1.2 with cipher AECDH-AES256-SHA (256/256 bits)) (No client certificate requested) by mx1.redhat.com (Postfix) with ESMTPS id B696E402290A; Fri, 25 May 2018 03:50:14 +0000 (UTC) Received: from localhost (ovpn-12-30.pek2.redhat.com [10.72.12.30]) by smtp.corp.redhat.com (Postfix) with ESMTP id 97CF72166BB2; Fri, 25 May 2018 03:50:06 +0000 (UTC) From: Ming Lei To: Jens Axboe , Christoph Hellwig , Alexander Viro , Kent Overstreet Cc: David Sterba , Huang Ying , linux-kernel@vger.kernel.org, linux-block@vger.kernel.org, linux-fsdevel@vger.kernel.org, linux-mm@kvack.org, Theodore Ts'o , "Darrick J . Wong" , Coly Li , Filipe Manana , Ming Lei Subject: [RESEND PATCH V5 18/33] block: deal with dirtying pages for multipage bvec Date: Fri, 25 May 2018 11:46:06 +0800 Message-Id: <20180525034621.31147-19-ming.lei@redhat.com> In-Reply-To: <20180525034621.31147-1-ming.lei@redhat.com> References: <20180525034621.31147-1-ming.lei@redhat.com> X-Scanned-By: MIMEDefang 2.78 on 10.11.54.6 X-Greylist: Sender IP whitelisted, not delayed by milter-greylist-4.5.16 (mx1.redhat.com [10.11.55.6]); Fri, 25 May 2018 03:50:14 +0000 (UTC) X-Greylist: inspected by milter-greylist-4.5.16 (mx1.redhat.com [10.11.55.6]); Fri, 25 May 2018 03:50:14 +0000 (UTC) for IP:'10.11.54.6' DOMAIN:'int-mx06.intmail.prod.int.rdu2.redhat.com' HELO:'smtp.corp.redhat.com' FROM:'ming.lei@redhat.com' RCPT:'' Sender: linux-kernel-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: linux-kernel@vger.kernel.org In bio_check_pages_dirty(), bvec->bv_page is used as flag for marking if the page has been dirtied & released, and if no, it will be dirtied in deferred workqueue. With multipage bvec, we can't do that any more, so change the logic into checking all pages in one mp bvec, and only release all these pages if all are dirtied, otherwise dirty them all in deferred wrokqueue. This patch introduces segment_for_each_page_all() to deal with the case a bit easier. Signed-off-by: Ming Lei --- block/bio.c | 45 +++++++++++++++++++++++++++++++++++++-------- include/linux/bvec.h | 7 +++++++ 2 files changed, 44 insertions(+), 8 deletions(-) diff --git a/block/bio.c b/block/bio.c index 63d4fe85f42e..a200c42e55dc 100644 --- a/block/bio.c +++ b/block/bio.c @@ -1630,8 +1630,9 @@ void bio_set_pages_dirty(struct bio *bio) { struct bio_vec *bvec; int i; + struct bvec_iter_all bia; - bio_for_each_page_all(bvec, bio, i) { + bio_for_each_page_all2(bvec, bio, i, bia) { struct page *page = bvec->bv_page; if (page && !PageCompound(page)) @@ -1640,16 +1641,26 @@ void bio_set_pages_dirty(struct bio *bio) } EXPORT_SYMBOL_GPL(bio_set_pages_dirty); +static inline void release_mp_bvec_pages(struct bio_vec *bvec) +{ + struct bio_vec bv; + struct bvec_iter iter; + + segment_for_each_page_all(bv, bvec, iter) + put_page(bv.bv_page); +} + static void bio_release_pages(struct bio *bio) { struct bio_vec *bvec; int i; - bio_for_each_page_all(bvec, bio, i) { + /* iterate each mp bvec */ + bio_for_each_segment_all(bvec, bio, i) { struct page *page = bvec->bv_page; if (page) - put_page(page); + release_mp_bvec_pages(bvec); } } @@ -1693,20 +1704,38 @@ static void bio_dirty_fn(struct work_struct *work) } } +static inline void check_mp_bvec_pages(struct bio_vec *bvec, + int *nr_dirty, int *nr_pages) +{ + struct bio_vec bv; + struct bvec_iter iter; + + segment_for_each_page_all(bv, bvec, iter) { + struct page *page = bv.bv_page; + + if (PageDirty(page) || PageCompound(page)) + (*nr_dirty)++; + (*nr_pages)++; + } +} + void bio_check_pages_dirty(struct bio *bio) { struct bio_vec *bvec; int nr_clean_pages = 0; int i; - bio_for_each_page_all(bvec, bio, i) { - struct page *page = bvec->bv_page; + bio_for_each_segment_all(bvec, bio, i) { + int nr_dirty = 0, nr_pages = 0; + + check_mp_bvec_pages(bvec, &nr_dirty, &nr_pages); - if (PageDirty(page) || PageCompound(page)) { - put_page(page); + /* release all pages in the mp bvec if all are dirtied */ + if (nr_dirty == nr_pages) { + release_mp_bvec_pages(bvec); bvec->bv_page = NULL; } else { - nr_clean_pages++; + nr_clean_pages += nr_pages; } } diff --git a/include/linux/bvec.h b/include/linux/bvec.h index 2deee87b823e..893e8fef0dd0 100644 --- a/include/linux/bvec.h +++ b/include/linux/bvec.h @@ -225,6 +225,13 @@ static inline bool bvec_iter_seg_advance(const struct bio_vec *bv, .bi_bvec_done = 0, \ } +#define segment_for_each_page_all(pg_bvl, seg_bvec, iter) \ + for (iter = BVEC_ITER_ALL_INIT, \ + (iter).bi_size = (seg_bvec)->bv_len - (iter).bi_bvec_done;\ + (iter).bi_size && \ + ((pg_bvl = bvec_iter_bvec((seg_bvec), (iter))), 1); \ + bvec_iter_advance((seg_bvec), &(iter), (pg_bvl).bv_len)) + /* get the last page from the multipage bvec and store it in @pg */ static inline void segment_last_page(const struct bio_vec *seg, struct bio_vec *pg) -- 2.9.5