| From 20618b21da0796115e81906d24ff1601552701b7 Mon Sep 17 00:00:00 2001 |
| From: Boaz Harrosh <bharrosh@panasas.com> |
| Date: Wed, 3 Aug 2011 21:54:33 -0700 |
| Subject: pnfs-obj: Bug when we are running out of bio |
| |
| From: Boaz Harrosh <bharrosh@panasas.com> |
| |
| commit 20618b21da0796115e81906d24ff1601552701b7 upstream. |
| |
| When we have a situation that the number of pages we want |
| to encode is bigger then the size of the bio. (Which can |
| currently happen only when all IO is going to a single device |
| .e.g group_width==1) then the IO is submitted short and we |
| report back only the amount of bytes we actually wrote/read |
| and all is fine. BUT ... |
| |
| There was a bug that the current length counter was advanced |
| before the fail to add the extra page, and we come to a situation |
| that the CDB length was one-page longer then the actual bio size, |
| which is of course rejected by the osd-target. |
| |
| While here also fix the bio size calculation, in the case |
| that we received more then one group of devices. |
| |
| Signed-off-by: Boaz Harrosh <bharrosh@panasas.com> |
| Signed-off-by: Trond Myklebust <Trond.Myklebust@netapp.com> |
| Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de> |
| |
| --- |
| fs/nfs/objlayout/objio_osd.c | 12 +++++------- |
| 1 file changed, 5 insertions(+), 7 deletions(-) |
| |
| --- a/fs/nfs/objlayout/objio_osd.c |
| +++ b/fs/nfs/objlayout/objio_osd.c |
| @@ -587,22 +587,19 @@ static void _calc_stripe_info(struct obj |
| } |
| |
| static int _add_stripe_unit(struct objio_state *ios, unsigned *cur_pg, |
| - unsigned pgbase, struct _objio_per_comp *per_dev, int cur_len, |
| + unsigned pgbase, struct _objio_per_comp *per_dev, int len, |
| gfp_t gfp_flags) |
| { |
| unsigned pg = *cur_pg; |
| + int cur_len = len; |
| struct request_queue *q = |
| osd_request_queue(_io_od(ios, per_dev->dev)); |
| |
| - per_dev->length += cur_len; |
| - |
| if (per_dev->bio == NULL) { |
| - unsigned stripes = ios->layout->num_comps / |
| - ios->layout->mirrors_p1; |
| - unsigned pages_in_stripe = stripes * |
| + unsigned pages_in_stripe = ios->layout->group_width * |
| (ios->layout->stripe_unit / PAGE_SIZE); |
| unsigned bio_size = (ios->ol_state.nr_pages + pages_in_stripe) / |
| - stripes; |
| + ios->layout->group_width; |
| |
| if (BIO_MAX_PAGES_KMALLOC < bio_size) |
| bio_size = BIO_MAX_PAGES_KMALLOC; |
| @@ -630,6 +627,7 @@ static int _add_stripe_unit(struct objio |
| } |
| BUG_ON(cur_len); |
| |
| + per_dev->length += len; |
| *cur_pg = pg; |
| return 0; |
| } |