From: Ming Lei <tom.leiming@gmail.com> Date: 2017-02-16 11:46:09
In MD's resync I/O path, there are lots of direct access to bio's
bvec table. This patchset kills most of them, and the conversion
is quite straightforward.
Once direct access to bvec table in MD is cleaned up, we may make
multipage bvec moving on.
Thanks,
Ming
Ming Lei (17):
block: introduce bio_segments_all()
block: introduce bio_remove_last_page()
md: raid1/raid10: use bio_remove_last_page()
md: introduce helpers for dealing with fetch/store preallocated pages
in bio
md: raid1/raid10: use the introduced helpers
md: raid1/raid10: borrow .bi_error as pre-allocated page index
md: raid1/raid10: don't use .bi_vcnt to check if all pages are added
md: raid1: simplify r1buf_pool_free()
md: raid1/raid10: use bio helper in *_pool_free
md: raid1: remove direct access to bvec table in fix_sync_read_error
md: raid1: use bio helper in process_checks()
md: raid1: avoid direct access to bvec table in process_checks()
md: raid1: use bio_segments_all()
md: raid10: avoid direct access to bvec table in sync_request_write()
md: raid10: avoid direct access to bvec table in
fix_recovery_read_error
md: raid10: avoid direct access to bvec table in reshape_request
md: raid10: avoid direct access to bvec table in
handle_reshape_read_error
block/bio.c | 23 ++++++++++++++
drivers/md/md.h | 21 +++++++++++++
drivers/md/raid1.c | 87 +++++++++++++++++++++++++++++++++++++----------------
drivers/md/raid10.c | 76 ++++++++++++++++++++++++++++++++++------------
include/linux/bio.h | 8 +++++
5 files changed, 169 insertions(+), 46 deletions(-)
--
2.7.4
From: Ming Lei <tom.leiming@gmail.com> Date: 2017-02-16 11:46:13
So that we can replace the direct access to .bi_vcnt.
Signed-off-by: Ming Lei <tom.leiming@gmail.com>
---
include/linux/bio.h | 7 +++++++
1 file changed, 7 insertions(+)
@@ -293,6 +293,13 @@ static inline void bio_get_last_bvec(struct bio *bio, struct bio_vec *bv)bv->bv_len=iter.bi_bvec_done;}+staticinlineunsignedbio_segments_all(structbio*bio)+{+WARN_ON_ONCE(bio_flagged(bio,BIO_CLONED));++returnbio->bi_vcnt;+}+enumbip_flags{BIP_BLOCK_INTEGRITY=1<<0,/* block layer owns integrity data */BIP_MAPPED_INTEGRITY=1<<1,/* ref tag has been remapped */
From: Ming Lei <tom.leiming@gmail.com> Date: 2017-02-16 11:46:16
MD need this helper to remove the last added page, so introduce
it.
Signed-off-by: Ming Lei <tom.leiming@gmail.com>
---
block/bio.c | 23 +++++++++++++++++++++++
include/linux/bio.h | 1 +
2 files changed, 24 insertions(+)
@@ -2824,8 +2824,7 @@ static sector_t raid1_sync_request(struct mddev *mddev, sector_t sector_nr,if(bio->bi_end_io==NULL)continue;/* remove last page from this bio */-bio->bi_vcnt--;-bio->bi_iter.bi_size-=len;+bio_remove_last_page(bio);bio_clear_flag(bio,BIO_SEG_VALID);}gotobio_full;
@@ -3447,8 +3447,7 @@ static sector_t raid10_sync_request(struct mddev *mddev, sector_t sector_nr,bio2&&bio2!=bio;bio2=bio2->bi_next){/* remove last page from this bio */-bio2->bi_vcnt--;-bio2->bi_iter.bi_size-=len;+bio_remove_last_page(bio2);bio_clear_flag(bio2,BIO_SEG_VALID);}gotobio_full;
@@ -4538,8 +4537,7 @@ static sector_t reshape_request(struct mddev *mddev, sector_t sector_nr,bio2&&bio2!=bio;bio2=bio2->bi_next){/* Remove last page from this bio */-bio2->bi_vcnt--;-bio2->bi_iter.bi_size-=len;+bio_remove_last_page(bio2);bio_clear_flag(bio2,BIO_SEG_VALID);}gotobio_full;
From: Ming Lei <tom.leiming@gmail.com> Date: 2017-02-16 11:46:34
This patch uses the introduced helpers to fetch pre-allocated
page from bio bvec table, and store it back.
Signed-off-by: Ming Lei <tom.leiming@gmail.com>
---
drivers/md/raid1.c | 4 ++--
drivers/md/raid10.c | 4 ++--
2 files changed, 4 insertions(+), 4 deletions(-)
From: Ming Lei <tom.leiming@gmail.com> Date: 2017-02-16 11:46:40
Instead we use the index of the pre-allocated pages buffer, it should
be more explicit because the index(.bi_error) just means how many pages
are added to the bio.
Signed-off-by: Ming Lei <tom.leiming@gmail.com>
---
drivers/md/raid1.c | 2 +-
drivers/md/raid10.c | 2 +-
2 files changed, 2 insertions(+), 2 deletions(-)
@@ -3453,7 +3453,7 @@ static sector_t raid10_sync_request(struct mddev *mddev, sector_t sector_nr,}nr_sectors+=len>>9;sector_nr+=len>>9;-}while(biolist->bi_vcnt<RESYNC_PAGES);+}while(biolist->bi_error<RESYNC_PAGES);bio_full:/* return .bi_error back to bio, and set resync's as -EIO */for(bio=biolist;bio;bio=bio->bi_next)
From: Ming Lei <tom.leiming@gmail.com> Date: 2017-02-16 11:46:44
This patch gets each page's reference of each bio for resync,
then r1buf_pool_free() gets simplified.
The same policy has been taken in raid10's buf pool allocation/free
too.
Signed-off-by: Ming Lei <tom.leiming@gmail.com>
---
drivers/md/raid1.c | 15 +++++++--------
1 file changed, 7 insertions(+), 8 deletions(-)
@@ -143,9 +143,12 @@ static void * r1buf_pool_alloc(gfp_t gfp_flags, void *data)/* If not user-requests, copy the page pointers to all bios */if(!test_bit(MD_RECOVERY_REQUESTED,&pi->mddev->recovery)){for(i=0;i<RESYNC_PAGES;i++)-for(j=1;j<pi->raid_disks;j++)-r1_bio->bios[j]->bi_io_vec[i].bv_page=+for(j=1;j<pi->raid_disks;j++){+structpage*page=r1_bio->bios[0]->bi_io_vec[i].bv_page;+get_page(page);+r1_bio->bios[j]->bi_io_vec[i].bv_page=page;+}}r1_bio->master_bio=NULL;
@@ -172,9 +172,16 @@ static void r1buf_pool_free(void *__r1_bio, void *data)inti,j;structr1bio*r1bio=__r1_bio;-for(i=0;i<RESYNC_PAGES;i++)-for(j=pi->raid_disks;j--;)-safe_put_page(r1bio->bios[j]->bi_io_vec[i].bv_page);+for(i=0;i<pi->raid_disks;i++){+structbio_vec*bvl;+structbio*bio=r1bio->bios[i];++/* make sure all pages can be freed */+bio->bi_vcnt=RESYNC_PAGES;++bio_for_each_segment_all(bvl,bio,j)+safe_put_page(bvl->bv_page);+}for(i=0;i<pi->raid_disks;i++)bio_put(r1bio->bios[i]);
@@ -230,10 +230,13 @@ static void r10buf_pool_free(void *__r10_bio, void *data)for(j=0;j<conf->copies;j++){structbio*bio=r10bio->devs[j].bio;if(bio){-for(i=0;i<RESYNC_PAGES;i++){-safe_put_page(bio->bi_io_vec[i].bv_page);-bio->bi_io_vec[i].bv_page=NULL;-}+structbio_vec*bvl;++/* make sure all pages can be freed */+bio->bi_vcnt=RESYNC_PAGES;++bio_for_each_segment_all(bvl,bio,i)+safe_put_page(bvl->bv_page);bio_put(bio);}bio=r10bio->devs[j].repl_bio;
From: Ming Lei <tom.leiming@gmail.com> Date: 2017-02-16 11:46:56
Use this helper, instead of direct access to .bi_vcnt.
Signed-off-by: Ming Lei <tom.leiming@gmail.com>
---
drivers/md/raid1.c | 7 ++++---
1 file changed, 4 insertions(+), 3 deletions(-)
From: Ming Lei <tom.leiming@gmail.com> Date: 2017-02-16 11:46:59
The cost is 256bytes(8*16*2) stack space, and just use the bio
helper to retrieve pages from bio.
Signed-off-by: Ming Lei <tom.leiming@gmail.com>
---
drivers/md/raid10.c | 15 +++++++++++++--
1 file changed, 13 insertions(+), 2 deletions(-)
@@ -2052,6 +2054,10 @@ static void sync_request_write(struct mddev *mddev, struct r10bio *r10_bio)fbio->bi_iter.bi_size=r10_bio->sectors<<9;fbio->bi_iter.bi_idx=0;+/* the bio has been filled up in raid10_sync_request */+bio_for_each_segment_all(bvl,fbio,i)+fbio_pages[i]=bvl->bv_page;+vcnt=(r10_bio->sectors+(PAGE_SIZE>>9)-1)>>(PAGE_SHIFT-9);/* now find blocks with errors */for(i=0;i<conf->copies;i++){
@@ -2072,12 +2078,17 @@ static void sync_request_write(struct mddev *mddev, struct r10bio *r10_bio)*AllvecentriesarePAGE_SIZE;*/intsectors=r10_bio->sectors;++/* the bio has been filled up in raid10_sync_request */+bio_for_each_segment_all(bvl,tbio,j)+tbio_pages[j]=bvl->bv_page;+for(j=0;j<vcnt;j++){intlen=PAGE_SIZE;if(sectors<(len/512))len=sectors*512;-if(memcmp(page_address(fbio->bi_io_vec[j].bv_page),-page_address(tbio->bi_io_vec[j].bv_page),+if(memcmp(page_address(fbio_pages[j]),+page_address(tbio_pages[j]),len))break;sectors-=len/512;
From: Ming Lei <tom.leiming@gmail.com> Date: 2017-02-16 11:47:02
Avoid to direct access to bvec table.
Signed-off-by: Ming Lei <tom.leiming@gmail.com>
---
drivers/md/raid1.c | 5 ++---
1 file changed, 2 insertions(+), 3 deletions(-)
From: Ming Lei <tom.leiming@gmail.com> Date: 2017-02-16 11:47:04
This patch uses a stack variable to hold the pages in bio, so
that we can remove direct access to bvec table in fix_sync_read_error().
This 16*8 stack variable is just fine for kernel thread context.
Signed-off-by: Ming Lei <tom.leiming@gmail.com>
---
drivers/md/raid1.c | 16 +++++++++++++---
1 file changed, 13 insertions(+), 3 deletions(-)
From: Ming Lei <tom.leiming@gmail.com> Date: 2017-02-16 11:47:07
The cost is 128bytes(8*16) stack space in kernel thread context, and just
use the bio helper to retrieve pages from bio.
Signed-off-by: Ming Lei <tom.leiming@gmail.com>
---
drivers/md/raid10.c | 9 +++++++--
1 file changed, 7 insertions(+), 2 deletions(-)
From: Ming Lei <tom.leiming@gmail.com> Date: 2017-02-16 11:47:11
The cost is 128bytes(8*16) stack space in kernel thread context, and
just use the bio helper to retrieve pages from bio.
Signed-off-by: Ming Lei <tom.leiming@gmail.com>
---
drivers/md/raid10.c | 7 ++++++-
1 file changed, 6 insertions(+), 1 deletion(-)
@@ -4383,6 +4383,8 @@ static sector_t reshape_request(struct mddev *mddev, sector_t sector_nr,structbio*blist;structbio*bio,*read_bio;intsectors_done=0;+structbio_vec*bvl;+structpage*pages[RESYNC_PAGES];if(sector_nr==0){/* If restarting in the middle, skip the initial sectors */
@@ -4546,9 +4548,12 @@ static sector_t reshape_request(struct mddev *mddev, sector_t sector_nr,/* Now add as many pages as possible to all of these bios. */+bio_for_each_segment_all(bvl,r10_bio->devs[0].bio,s)+pages[s]=bvl->bv_page;+nr_sectors=0;for(s=0;s<max_sectors;s+=PAGE_SIZE>>9){-structpage*page=r10_bio->devs[0].bio->bi_io_vec[s/(PAGE_SIZE>>9)].bv_page;+structpage*page=pages[s/(PAGE_SIZE>>9)];intlen=(max_sectors-s)<<9;if(len>PAGE_SIZE)len=PAGE_SIZE;
From: Ming Lei <tom.leiming@gmail.com> Date: 2017-02-16 11:47:32
The cost is 128bytes(8*16) stack space in kernel thread context, and
just use the bio helper to retrieve pages from bio.
Signed-off-by: Ming Lei <tom.leiming@gmail.com>
---
drivers/md/raid10.c | 12 ++++++++++--
1 file changed, 10 insertions(+), 2 deletions(-)
From: Ming Lei <tom.leiming@gmail.com> Date: 2017-02-16 11:49:13
Given process_checks is only called in resync path, it should be
ok to allocate three stack variable(total 320byteds) to store
pages from bios.
Signed-off-by: Ming Lei <tom.leiming@gmail.com>
---
drivers/md/raid1.c | 20 ++++++++++++++++----
1 file changed, 16 insertions(+), 4 deletions(-)
@@ -2051,6 +2053,11 @@ static void process_checks(struct r1bio *r1_bio)break;}r1_bio->read_disk=primary;++/* .bi_vcnt has been set for all read bios */+bio_for_each_segment_all(bi,r1_bio->bios[primary],i)+pbio_pages[i]=bi->bv_page;+for(i=0;i<conf->raid_disks*2;i++){intj;structbio*pbio=r1_bio->bios[primary];
@@ -2062,14 +2069,19 @@ static void process_checks(struct r1bio *r1_bio)/* Now we can 'fixup' the error value */sbio->bi_error=0;+bio_for_each_segment_all(bi,sbio,j){+sbio_pages[j]=bi->bv_page;+page_len[j]=bi->bv_len;+}+if(!error){for(j=vcnt;j--;){structpage*p,*s;-p=pbio->bi_io_vec[j].bv_page;-s=sbio->bi_io_vec[j].bv_page;+p=pbio_pages[j];+s=sbio_pages[j];if(memcmp(page_address(p),page_address(s),-sbio->bi_io_vec[j].bv_len))+page_len[j]))break;}}else
From: Ming Lei <tom.leiming@gmail.com> Date: 2017-02-16 11:51:01
Before bio is submitted, it is safe to borrow .bi_error. This
patch uses .bi_error as index of pre-allocated page in bio, so
that we can avoid to mess .bi_vcnt. Especially the old way
will not work any more when multipage bvec is introduced.
Signed-off-by: Ming Lei <tom.leiming@gmail.com>
---
drivers/md/raid1.c | 12 ++++++++++--
drivers/md/raid10.c | 14 ++++++++++----
2 files changed, 20 insertions(+), 6 deletions(-)
@@ -3392,7 +3391,6 @@ static sector_t raid10_sync_request(struct mddev *mddev, sector_t sector_nr,/* Need to set up for writing to the replacement */bio=r10_bio->devs[i].repl_bio;bio_reset(bio);-bio->bi_error=-EIO;sector=r10_bio->devs[i].addr;bio->bi_next=biolist;
@@ -3435,14 +3433,15 @@ static sector_t raid10_sync_request(struct mddev *mddev, sector_t sector_nr,len=(max_sector-sector_nr)<<9;if(len==0)break;+/* borrow .bi_error as pre-allocated page index */for(bio=biolist;bio;bio=bio->bi_next){structbio*bio2;-page=mdev_get_page_from_bio(bio,bio->bi_vcnt);+page=mdev_get_page_from_bio(bio,bio->bi_error++);if(bio_add_page(bio,page,len,0))continue;/* stop here */-mdev_put_page_to_bio(bio,bio->bi_vcnt,page);+mdev_put_page_to_bio(bio,--bio->bi_error,page);for(bio2=biolist;bio2&&bio2!=bio;bio2=bio2->bi_next){
@@ -3456,6 +3455,13 @@ static sector_t raid10_sync_request(struct mddev *mddev, sector_t sector_nr,sector_nr+=len>>9;}while(biolist->bi_vcnt<RESYNC_PAGES);bio_full:+/* return .bi_error back to bio, and set resync's as -EIO */+for(bio=biolist;bio;bio=bio->bi_next)+if(test_bit(MD_RECOVERY_SYNC,&mddev->recovery))+bio->bi_error=-EIO;+else+bio->bi_error=0;+r10_bio->sectors=nr_sectors;while(biolist){
From: Ming Lei <tom.leiming@gmail.com> Date: 2017-02-16 11:51:23
Both raid1 and raid10 uses bio's bvec table to store pre-allocated
pages, then fetch and add it to bio.
This patch introduces two helpers for dealing with the special case,
like what bio_iov_iter_get_pages() does.
Signed-off-by: Ming Lei <tom.leiming@gmail.com>
---
drivers/md/md.h | 21 +++++++++++++++++++++
1 file changed, 21 insertions(+)
From: Johannes Thumshirn <hidden> Date: 2017-02-16 12:08:26
On 02/16/2017 12:45 PM, Ming Lei wrote:
quoted hunk
MD need this helper to remove the last added page, so introduce
it.
Signed-off-by: Ming Lei <tom.leiming@gmail.com>
---
block/bio.c | 23 +++++++++++++++++++++++
include/linux/bio.h | 1 +
2 files changed, 24 insertions(+)
@@ -837,6 +837,29 @@ int bio_add_pc_page(struct request_queue *q, struct bio *bio, struct pageEXPORT_SYMBOL(bio_add_pc_page);/**+*bio_remove_last_page-removethelastaddedpage+*@bio:destinationbio+*+*Attempttoremovethelastaddedpagefromthebio_vecmaplist.+*/+voidbio_remove_last_page(structbio*bio)+{+/*+*clonedbiomustnotmodifyveclist+*/+if(WARN_ON_ONCE(bio_flagged(bio,BIO_CLONED)))+return;++if(bio->bi_vcnt>0){
In patch 1 you introduce bio_segments_all() with the log message 'So
that we can replace the direct access to .bi_vcnt.' Here you introduce a
new direct access to it (plus the duplicated WARN_ON_ONCE()).
Maybe use the helper directly here (I admit I haven't gone through the
whole series yet, so I can't see if the change is made later).
Byte,
Johannes
--
Johannes Thumshirn Storage
jthumshirn@suse.de +49 911 74053 689
SUSE LINUX GmbH, Maxfeldstr. 5, 90409 Nürnberg
GF: Felix Imendörffer, Jane Smithard, Graham Norton
HRB 21284 (AG Nürnberg)
Key fingerprint = EC38 9CAB C2C4 F25D 8600 D0D0 0393 969D 2D76 0850
From: Ming Lei <tom.leiming@gmail.com> Date: 2017-02-16 13:30:50
On Thu, Feb 16, 2017 at 8:08 PM, Johannes Thumshirn [off-list ref] wrote:
On 02/16/2017 12:45 PM, Ming Lei wrote:
quoted
MD need this helper to remove the last added page, so introduce
it.
Signed-off-by: Ming Lei <tom.leiming@gmail.com>
---
block/bio.c | 23 +++++++++++++++++++++++
include/linux/bio.h | 1 +
2 files changed, 24 insertions(+)
@@ -837,6 +837,29 @@ int bio_add_pc_page(struct request_queue *q, struct bio *bio, struct pageEXPORT_SYMBOL(bio_add_pc_page);/**+*bio_remove_last_page-removethelastaddedpage+*@bio:destinationbio+*+*Attempttoremovethelastaddedpagefromthebio_vecmaplist.+*/+voidbio_remove_last_page(structbio*bio)+{+/*+*clonedbiomustnotmodifyveclist+*/+if(WARN_ON_ONCE(bio_flagged(bio,BIO_CLONED)))+return;++if(bio->bi_vcnt>0){
In patch 1 you introduce bio_segments_all() with the log message 'So
that we can replace the direct access to .bi_vcnt.' Here you introduce a
new direct access to it (plus the duplicated WARN_ON_ONCE()).
Maybe use the helper directly here (I admit I haven't gone through the
whole series yet, so I can't see if the change is made later).
Firstly MD does need one helper to remove the last added page, as you
can see there are three such uses in patch3.
Secondly both the two helpers will be changed once multipage bvec
is supported, that means we have to change MD too after multipage bvec
if just using bio_segments_all() to replace .bi_vcnt for removing
the last added page.
Thanks,
Ming Lei
Maybe use kcalloc() instead of kzalloc() with a multiplication.
That doesn't belong to this patch, which just wants to remove direct
access to .bi_vcnt.
But you're touching it anyways, aren't you?
Don't you know the policy of 'do one thing, do it better' in one patch?
If you want to switch to kcalloc(), just post a patch, that is fine, but
please don't push me to do that in this patch.
Thanks,
Ming Lei
From: Johannes Thumshirn <hidden> Date: 2017-02-16 13:40:14
On 02/16/2017 02:30 PM, Ming Lei wrote:
On Thu, Feb 16, 2017 at 8:08 PM, Johannes Thumshirn [off-list ref] wrote:
quoted
On 02/16/2017 12:45 PM, Ming Lei wrote:
quoted
MD need this helper to remove the last added page, so introduce
it.
Signed-off-by: Ming Lei <tom.leiming@gmail.com>
---
block/bio.c | 23 +++++++++++++++++++++++
include/linux/bio.h | 1 +
2 files changed, 24 insertions(+)
@@ -837,6 +837,29 @@ int bio_add_pc_page(struct request_queue *q, struct bio *bio, struct pageEXPORT_SYMBOL(bio_add_pc_page);/**+*bio_remove_last_page-removethelastaddedpage+*@bio:destinationbio+*+*Attempttoremovethelastaddedpagefromthebio_vecmaplist.+*/+voidbio_remove_last_page(structbio*bio)+{+/*+*clonedbiomustnotmodifyveclist+*/+if(WARN_ON_ONCE(bio_flagged(bio,BIO_CLONED)))+return;++if(bio->bi_vcnt>0){
In patch 1 you introduce bio_segments_all() with the log message 'So
that we can replace the direct access to .bi_vcnt.' Here you introduce a
new direct access to it (plus the duplicated WARN_ON_ONCE()).
Maybe use the helper directly here (I admit I haven't gone through the
whole series yet, so I can't see if the change is made later).
Firstly MD does need one helper to remove the last added page, as you
can see there are three such uses in patch3.
Secondly both the two helpers will be changed once multipage bvec
is supported, that means we have to change MD too after multipage bvec
if just using bio_segments_all() to replace .bi_vcnt for removing
the last added page.
I'm not sure if we're talking past each other here, I assumed you'd do
something like:
void bio_remove_last_page(struct bio *bio)
{
int vcnt = bio_segments_all(bio);
if (bio_flagged(bio, BIO_CLONED))
return;
if (vcnt > 0) {
struct bio_vec *bv = &bio->bi_io_vec[vcnt - 1];
bio->bi_iter.bi_size -= bv->bv_len;
bio->bi_vcnt--;
}
}
--
Johannes Thumshirn Storage
jthumshirn@suse.de +49 911 74053 689
SUSE LINUX GmbH, Maxfeldstr. 5, 90409 Nürnberg
GF: Felix Imendörffer, Jane Smithard, Graham Norton
HRB 21284 (AG Nürnberg)
Key fingerprint = EC38 9CAB C2C4 F25D 8600 D0D0 0393 969D 2D76 0850
From: Ming Lei <tom.leiming@gmail.com> Date: 2017-02-16 13:59:26
On Thu, Feb 16, 2017 at 9:40 PM, Johannes Thumshirn [off-list ref] wrote:
On 02/16/2017 02:30 PM, Ming Lei wrote:
quoted
On Thu, Feb 16, 2017 at 8:08 PM, Johannes Thumshirn [off-list ref] wrote:
quoted
On 02/16/2017 12:45 PM, Ming Lei wrote:
quoted
MD need this helper to remove the last added page, so introduce
it.
Signed-off-by: Ming Lei <tom.leiming@gmail.com>
---
block/bio.c | 23 +++++++++++++++++++++++
include/linux/bio.h | 1 +
2 files changed, 24 insertions(+)
@@ -837,6 +837,29 @@ int bio_add_pc_page(struct request_queue *q, struct bio *bio, struct pageEXPORT_SYMBOL(bio_add_pc_page);/**+*bio_remove_last_page-removethelastaddedpage+*@bio:destinationbio+*+*Attempttoremovethelastaddedpagefromthebio_vecmaplist.+*/+voidbio_remove_last_page(structbio*bio)+{+/*+*clonedbiomustnotmodifyveclist+*/+if(WARN_ON_ONCE(bio_flagged(bio,BIO_CLONED)))+return;++if(bio->bi_vcnt>0){
In patch 1 you introduce bio_segments_all() with the log message 'So
that we can replace the direct access to .bi_vcnt.' Here you introduce a
new direct access to it (plus the duplicated WARN_ON_ONCE()).
Maybe use the helper directly here (I admit I haven't gone through the
whole series yet, so I can't see if the change is made later).
Firstly MD does need one helper to remove the last added page, as you
can see there are three such uses in patch3.
Secondly both the two helpers will be changed once multipage bvec
is supported, that means we have to change MD too after multipage bvec
if just using bio_segments_all() to replace .bi_vcnt for removing
the last added page.
I'm not sure if we're talking past each other here, I assumed you'd do
something like:
void bio_remove_last_page(struct bio *bio)
{
int vcnt = bio_segments_all(bio);
if (bio_flagged(bio, BIO_CLONED))
return;
if (vcnt > 0) {
struct bio_vec *bv = &bio->bi_io_vec[vcnt - 1];
bio->bi_iter.bi_size -= bv->bv_len;
bio->bi_vcnt--;
}
}
What we are doing is to remove the external direct access to bvec
table in drivers or filesystems because they may misuse that, for
example, drivers often use .bi_vcnt to get the page count in the bio,
but the actual meaning is just bvec's count.
And the implementation in block layer still need to play the table directly,
especially for sake of efficiency, cause we understand the details and won't
misuse that.
Thanks,
Ming Lei
From: Johannes Thumshirn <hidden> Date: 2017-02-16 14:10:40
On 02/16/2017 02:59 PM, Ming Lei wrote:
On Thu, Feb 16, 2017 at 9:40 PM, Johannes Thumshirn [off-list ref] wrote:
quoted
On 02/16/2017 02:30 PM, Ming Lei wrote:
quoted
On Thu, Feb 16, 2017 at 8:08 PM, Johannes Thumshirn [off-list ref] wrote:
quoted
On 02/16/2017 12:45 PM, Ming Lei wrote:
quoted
MD need this helper to remove the last added page, so introduce
it.
Signed-off-by: Ming Lei <tom.leiming@gmail.com>
---
block/bio.c | 23 +++++++++++++++++++++++
include/linux/bio.h | 1 +
2 files changed, 24 insertions(+)
@@ -837,6 +837,29 @@ int bio_add_pc_page(struct request_queue *q, struct bio *bio, struct pageEXPORT_SYMBOL(bio_add_pc_page);/**+*bio_remove_last_page-removethelastaddedpage+*@bio:destinationbio+*+*Attempttoremovethelastaddedpagefromthebio_vecmaplist.+*/+voidbio_remove_last_page(structbio*bio)+{+/*+*clonedbiomustnotmodifyveclist+*/+if(WARN_ON_ONCE(bio_flagged(bio,BIO_CLONED)))+return;++if(bio->bi_vcnt>0){
In patch 1 you introduce bio_segments_all() with the log message 'So
that we can replace the direct access to .bi_vcnt.' Here you introduce a
new direct access to it (plus the duplicated WARN_ON_ONCE()).
Maybe use the helper directly here (I admit I haven't gone through the
whole series yet, so I can't see if the change is made later).
Firstly MD does need one helper to remove the last added page, as you
can see there are three such uses in patch3.
Secondly both the two helpers will be changed once multipage bvec
is supported, that means we have to change MD too after multipage bvec
if just using bio_segments_all() to replace .bi_vcnt for removing
the last added page.
I'm not sure if we're talking past each other here, I assumed you'd do
something like:
void bio_remove_last_page(struct bio *bio)
{
int vcnt = bio_segments_all(bio);
if (bio_flagged(bio, BIO_CLONED))
return;
if (vcnt > 0) {
struct bio_vec *bv = &bio->bi_io_vec[vcnt - 1];
bio->bi_iter.bi_size -= bv->bv_len;
bio->bi_vcnt--;
}
}
What we are doing is to remove the external direct access to bvec
table in drivers or filesystems because they may misuse that, for
example, drivers often use .bi_vcnt to get the page count in the bio,
but the actual meaning is just bvec's count.
And the implementation in block layer still need to play the table directly,
especially for sake of efficiency, cause we understand the details and won't
misuse that.
Ah OK, so bio_segments_all() is intended for drivers.
Thanks for the clarification,
Johannes
--
Johannes Thumshirn Storage
jthumshirn@suse.de +49 911 74053 689
SUSE LINUX GmbH, Maxfeldstr. 5, 90409 Nürnberg
GF: Felix Imendörffer, Jane Smithard, Graham Norton
HRB 21284 (AG Nürnberg)
Key fingerprint = EC38 9CAB C2C4 F25D 8600 D0D0 0393 969D 2D76 0850
From: Shaohua Li <shli@kernel.org> Date: 2017-02-16 22:16:48
On Thu, Feb 16, 2017 at 07:45:30PM +0800, Ming Lei wrote:
In MD's resync I/O path, there are lots of direct access to bio's
bvec table. This patchset kills most of them, and the conversion
is quite straightforward.
I don't like this approach. The MD uses a hacky way to manage pages allocated,
this is the root of the problem. The patches add another hack way to do the
management. I'd like to see explict management of the pages, for example, add
data structure in r1bio to manage the pages, then we can use existing API for
all the stuffes we need.
Thanks,
Shaohua
From: Ming Lei <tom.leiming@gmail.com> Date: 2017-02-17 01:25:31
Hi Shaohua,
On Fri, Feb 17, 2017 at 6:16 AM, Shaohua Li [off-list ref] wrote:
On Thu, Feb 16, 2017 at 07:45:30PM +0800, Ming Lei wrote:
quoted
In MD's resync I/O path, there are lots of direct access to bio's
bvec table. This patchset kills most of them, and the conversion
is quite straightforward.
I don't like this approach. The MD uses a hacky way to manage pages allocated,
this is the root of the problem. The patches add another hack way to do the
Yes, I agree, and bio_iov_iter_get_pages() uses this kind of hacky way too
actually.
management. I'd like to see explict management of the pages, for example, add
data structure in r1bio to manage the pages, then we can use existing API for
all the stuffes we need.
Yeah, that is definitely clean, but we have to pay the following cost:
- allocate at least N * (128 + 4) bytes per each r1_bio/r10_bio
- N is pool_info.raid_disks for raid1, and conf->copies for raid10
If we are happy to introduce the cost, I can take this way in V1.
Thanks,
Ming Lei
From: Shaohua Li <shli@kernel.org> Date: 2017-02-17 04:16:42
On Fri, Feb 17, 2017 at 09:25:27AM +0800, Ming Lei wrote:
Hi Shaohua,
On Fri, Feb 17, 2017 at 6:16 AM, Shaohua Li [off-list ref] wrote:
quoted
On Thu, Feb 16, 2017 at 07:45:30PM +0800, Ming Lei wrote:
quoted
In MD's resync I/O path, there are lots of direct access to bio's
bvec table. This patchset kills most of them, and the conversion
is quite straightforward.
I don't like this approach. The MD uses a hacky way to manage pages allocated,
this is the root of the problem. The patches add another hack way to do the
Yes, I agree, and bio_iov_iter_get_pages() uses this kind of hacky way too
actually.
quoted
management. I'd like to see explict management of the pages, for example, add
data structure in r1bio to manage the pages, then we can use existing API for
all the stuffes we need.
Yeah, that is definitely clean, but we have to pay the following cost:
- allocate at least N * (128 + 4) bytes per each r1_bio/r10_bio
- N is pool_info.raid_disks for raid1, and conf->copies for raid10
If we are happy to introduce the cost, I can take this way in V1.
It's not a big deal. The inflight bio shouldn't be big, so the r1_bio count
isn't big. We don't waste much.
Thanks,
Shaohua
From: kbuild test robot <hidden> Date: 2017-02-17 08:34:10
Hi Ming,
[auto build test WARNING on linus/master]
[also build test WARNING on v4.10-rc8]
[cannot apply to next-20170216]
[if your patch is applied to the wrong git tree, please drop us a note to help improve the system]
url: https://github.com/0day-ci/linux/commits/Ming-Lei/md-cleanup-on-direct-access-to-bvec-table/20170216-210357
config: powerpc-cell_defconfig (attached as .config)
compiler: powerpc64-linux-gnu-gcc (Debian 6.1.1-9) 6.1.1 20160705
reproduce:
wget https://git.kernel.org/cgit/linux/kernel/git/wfg/lkp-tests.git/plain/sbin/make.cross -O ~/bin/make.cross
chmod +x ~/bin/make.cross
# save the attached .config to linux build tree
make.cross ARCH=powerpc
Note: it may well be a FALSE warning. FWIW you are at least aware of it now.
http://gcc.gnu.org/wiki/Better_Uninitialized_Warnings
All warnings (new ones prefixed by >>):
In file included from arch/powerpc/include/asm/page.h:331:0,
from arch/powerpc/include/asm/thread_info.h:34,
from include/linux/thread_info.h:25,
from include/asm-generic/preempt.h:4,
from ./arch/powerpc/include/generated/asm/preempt.h:1,
from include/linux/preempt.h:59,
from include/linux/spinlock.h:50,
from include/linux/mmzone.h:7,
from include/linux/gfp.h:5,
from include/linux/slab.h:14,
from drivers/md/raid1.c:34:
drivers/md/raid1.c: In function 'raid1d':
quoted
include/asm-generic/memory_model.h:54:52: warning: 'sbio_pages$' may be used uninitialized in this function [-Wmaybe-uninitialized]
#define __page_to_pfn(page) (unsigned long)((page) - vmemmap)
^
drivers/md/raid1.c:2008:42: note: 'sbio_pages$' was declared here
struct page *pbio_pages[RESYNC_PAGES], *sbio_pages[RESYNC_PAGES];
^~~~~~~~~~
drivers/md/raid1.c:2075:9: warning: 'page_len$' may be used uninitialized in this function [-Wmaybe-uninitialized]
if (memcmp(page_address(p),
^~~~~~~~~~~~~~~~~~~~~~~
page_address(s),
~~~~~~~~~~~~~~~~
page_len[j]))
~~~~~~~~~~~~
drivers/md/raid1.c:2007:6: note: 'page_len$' was declared here
int page_len[RESYNC_PAGES];
^~~~~~~~
In file included from arch/powerpc/include/asm/page.h:331:0,
from arch/powerpc/include/asm/thread_info.h:34,
from include/linux/thread_info.h:25,
from include/asm-generic/preempt.h:4,
from ./arch/powerpc/include/generated/asm/preempt.h:1,
from include/linux/preempt.h:59,
from include/linux/spinlock.h:50,
from include/linux/mmzone.h:7,
from include/linux/gfp.h:5,
from include/linux/slab.h:14,
from drivers/md/raid1.c:34:
quoted
include/asm-generic/memory_model.h:54:52: warning: 'pbio_pages$' may be used uninitialized in this function [-Wmaybe-uninitialized]
#define __page_to_pfn(page) (unsigned long)((page) - vmemmap)
^
drivers/md/raid1.c:2008:15: note: 'pbio_pages$' was declared here
struct page *pbio_pages[RESYNC_PAGES], *sbio_pages[RESYNC_PAGES];
^~~~~~~~~~
drivers/md/raid1.c:1978:8: warning: 'pages$' may be used uninitialized in this function [-Wmaybe-uninitialized]
if (r1_sync_page_io(rdev, sect, s,
^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
pages[idx],
~~~~~~~~~~~
READ) != 0)
~~~~~
drivers/md/raid1.c:1872:15: note: 'pages$' was declared here
struct page *pages[RESYNC_PAGES];
^~~~~
vim +54 include/asm-generic/memory_model.h
a117e66e KAMEZAWA Hiroyuki 2006-03-27 38 ({ unsigned long __pfn = (pfn); \
c5d71243 Rafael J. Wysocki 2008-11-08 39 unsigned long __nid = arch_pfn_to_nid(__pfn); \
a117e66e KAMEZAWA Hiroyuki 2006-03-27 40 NODE_DATA(__nid)->node_mem_map + arch_local_page_offset(__pfn, __nid);\
a117e66e KAMEZAWA Hiroyuki 2006-03-27 41 })
a117e66e KAMEZAWA Hiroyuki 2006-03-27 42
67de6482 Andy Whitcroft 2006-06-23 43 #define __page_to_pfn(pg) \
aa462abe Ian Campbell 2011-08-17 44 ({ const struct page *__pg = (pg); \
a0140c1d KAMEZAWA Hiroyuki 2006-03-27 45 struct pglist_data *__pgdat = NODE_DATA(page_to_nid(__pg)); \
a0140c1d KAMEZAWA Hiroyuki 2006-03-27 46 (unsigned long)(__pg - __pgdat->node_mem_map) + \
a0140c1d KAMEZAWA Hiroyuki 2006-03-27 47 __pgdat->node_start_pfn; \
a117e66e KAMEZAWA Hiroyuki 2006-03-27 48 })
a117e66e KAMEZAWA Hiroyuki 2006-03-27 49
8f6aac41 Christoph Lameter 2007-10-16 50 #elif defined(CONFIG_SPARSEMEM_VMEMMAP)
8f6aac41 Christoph Lameter 2007-10-16 51
af901ca1 André Goddard Rosa 2009-11-14 52 /* memmap is virtually contiguous. */
8f6aac41 Christoph Lameter 2007-10-16 53 #define __pfn_to_page(pfn) (vmemmap + (pfn))
32272a26 Martin Schwidefsky 2008-12-25 @54 #define __page_to_pfn(page) (unsigned long)((page) - vmemmap)
8f6aac41 Christoph Lameter 2007-10-16 55
a117e66e KAMEZAWA Hiroyuki 2006-03-27 56 #elif defined(CONFIG_SPARSEMEM)
a117e66e KAMEZAWA Hiroyuki 2006-03-27 57 /*
1a49123b Zhang Yanfei 2013-10-03 58 * Note: section's mem_map is encoded to reflect its start_pfn.
a117e66e KAMEZAWA Hiroyuki 2006-03-27 59 * section[i].section_mem_map == mem_map's address - start_pfn;
a117e66e KAMEZAWA Hiroyuki 2006-03-27 60 */
67de6482 Andy Whitcroft 2006-06-23 61 #define __page_to_pfn(pg) \
aa462abe Ian Campbell 2011-08-17 62 ({ const struct page *__pg = (pg); \
:::::: The code at line 54 was first introduced by commit
:::::: 32272a26974d2027384fd4010cd1780fca425d94 [S390] __page_to_pfn warnings
:::::: TO: Martin Schwidefsky [off-list ref]
:::::: CC: Martin Schwidefsky [off-list ref]
---
0-DAY kernel test infrastructure Open Source Technology Center
https://lists.01.org/pipermail/kbuild-all Intel Corporation