linux-kernel.vger.kernel.org archive mirror
 help / color / mirror / Atom feed
* [PATCH] block: modify __bio_add_page check to accept pages that don't start a new segment
@ 2013-02-21  8:30 Jan Vesely
  2013-03-07 11:23 ` Jan Vesely
  0 siblings, 1 reply; 4+ messages in thread
From: Jan Vesely @ 2013-02-21  8:30 UTC (permalink / raw)
  To: linux-kernel; +Cc: linux-scsi, linux-fsdevel, linux-kernel, Alexander Viro

The original behavior was to refuse all pages after the maximum number of
segments has been reached. However, some drivers (like st) craft their buffers
to potentially require exactly max segments and multiple pages in the last
segment. This patch modifies the check to allow pages that can be merged into
the last segment.

This change fixes EBUSY failures when using large (1mb) tape block size in high
memory fragmentation condition.

Signed-off-by: Jan Vesely <jvesely@redhat.com>
---
  fs/bio.c |   26 ++++++++++++++++----------
  1 files changed, 16 insertions(+), 10 deletions(-)

diff --git a/fs/bio.c b/fs/bio.c
index b96fc6c..02efbd5 100644
--- a/fs/bio.c
+++ b/fs/bio.c
@@ -500,7 +500,6 @@ static int __bio_add_page(struct request_queue *q, struct 
bio *bio, struct page
  			  *page, unsigned int len, unsigned int offset,
  			  unsigned short max_sectors)
  {
-	int retried_segments = 0;
  	struct bio_vec *bvec;

  	/*
@@ -551,18 +550,12 @@ static int __bio_add_page(struct request_queue *q, struct 
bio *bio, struct page
  		return 0;

  	/*
-	 * we might lose a segment or two here, but rather that than
-	 * make this too complex.
+	 * prepare segment count check, reduce segment count if possible
  	 */

-	while (bio->bi_phys_segments >= queue_max_segments(q)) {
-
-		if (retried_segments)
-			return 0;
-
-		retried_segments = 1;
+	if (bio->bi_phys_segments >= queue_max_segments(q))
  		blk_recount_segments(q, bio);
-	}
+

  	/*
  	 * setup the new entry, we might clear it again later if we
@@ -572,6 +565,19 @@ static int __bio_add_page(struct request_queue *q, struct 
bio *bio, struct page
  	bvec->bv_page = page;
  	bvec->bv_len = len;
  	bvec->bv_offset = offset;
+	
+	/*
+	 * the other part of the segment count check, allow mergeable pages
+	 */
+	if ((bio->bi_phys_segments > queue_max_segments(q)) ||
+		( (bio->bi_phys_segments == queue_max_segments(q)) &&
+		!BIOVEC_PHYS_MERGEABLE(bvec - 1, bvec))) {
+			bvec->bv_page = NULL;
+			bvec->bv_len = 0;
+			bvec->bv_offset = 0;
+			return 0;
+	}
+

  	/*
  	 * if queue has other restrictions (eg varying max sector size
-- 
1.7.1

^ permalink raw reply related	[flat|nested] 4+ messages in thread

* Re: [PATCH] block: modify __bio_add_page check to accept pages that don't start a new segment
  2013-02-21  8:30 [PATCH] block: modify __bio_add_page check to accept pages that don't start a new segment Jan Vesely
@ 2013-03-07 11:23 ` Jan Vesely
  2013-03-25 13:09   ` Jan Vesely
  0 siblings, 1 reply; 4+ messages in thread
From: Jan Vesely @ 2013-03-07 11:23 UTC (permalink / raw)
  To: linux-kernel; +Cc: linux-scsi, linux-fsdevel, Alexander Viro, Jens Axboe

Hi Jens,

I have added you to cc, I'm not sure who to bug to get this patch 
merged.

thanks,
Jan Vesely

On Thu 21 Feb 2013 09:30:26 CET, Jan Vesely wrote:
> The original behavior was to refuse all pages after the maximum number of
> segments has been reached. However, some drivers (like st) craft their buffers
> to potentially require exactly max segments and multiple pages in the last
> segment. This patch modifies the check to allow pages that can be merged into
> the last segment.
>
> This change fixes EBUSY failures when using large (1mb) tape block size in high
> memory fragmentation condition.
>
> Signed-off-by: Jan Vesely <jvesely@redhat.com>
> ---
>  fs/bio.c |   26 ++++++++++++++++----------
>  1 files changed, 16 insertions(+), 10 deletions(-)
>
> diff --git a/fs/bio.c b/fs/bio.c
> index b96fc6c..02efbd5 100644
> --- a/fs/bio.c
> +++ b/fs/bio.c
> @@ -500,7 +500,6 @@ static int __bio_add_page(struct request_queue *q, struct
> bio *bio, struct page
>                *page, unsigned int len, unsigned int offset,
>                unsigned short max_sectors)
>  {
> -    int retried_segments = 0;
>      struct bio_vec *bvec;
>
>      /*
> @@ -551,18 +550,12 @@ static int __bio_add_page(struct request_queue *q,
> struct bio *bio, struct page
>          return 0;
>
>      /*
> -     * we might lose a segment or two here, but rather that than
> -     * make this too complex.
> +     * prepare segment count check, reduce segment count if possible
>       */
>
> -    while (bio->bi_phys_segments >= queue_max_segments(q)) {
> -
> -        if (retried_segments)
> -            return 0;
> -
> -        retried_segments = 1;
> +    if (bio->bi_phys_segments >= queue_max_segments(q))
>          blk_recount_segments(q, bio);
> -    }
> +
>
>      /*
>       * setup the new entry, we might clear it again later if we
> @@ -572,6 +565,19 @@ static int __bio_add_page(struct request_queue *q, struct
> bio *bio, struct page
>      bvec->bv_page = page;
>      bvec->bv_len = len;
>      bvec->bv_offset = offset;
> +
> +    /*
> +     * the other part of the segment count check, allow mergeable pages
> +     */
> +    if ((bio->bi_phys_segments > queue_max_segments(q)) ||
> +        ( (bio->bi_phys_segments == queue_max_segments(q)) &&
> +        !BIOVEC_PHYS_MERGEABLE(bvec - 1, bvec))) {
> +            bvec->bv_page = NULL;
> +            bvec->bv_len = 0;
> +            bvec->bv_offset = 0;
> +            return 0;
> +    }
> +
>
>      /*
>       * if queue has other restrictions (eg varying max sector size

--
Jan Vesely <jvesely@redhat.com>

^ permalink raw reply	[flat|nested] 4+ messages in thread

* Re: [PATCH] block: modify __bio_add_page check to accept pages that don't start a new segment
  2013-03-07 11:23 ` Jan Vesely
@ 2013-03-25 13:09   ` Jan Vesely
  2013-03-25 13:31     ` Jens Axboe
  0 siblings, 1 reply; 4+ messages in thread
From: Jan Vesely @ 2013-03-25 13:09 UTC (permalink / raw)
  To: linux-kernel
  Cc: linux-scsi, linux-fsdevel, Alexander Viro, Jens Axboe,
	James Bottomley, Kai Mäkisara, fujita.tomonori

On Thu 07 Mar 2013 12:23:13 CET, Jan Vesely wrote:

> On Thu 21 Feb 2013 09:30:26 CET, Jan Vesely wrote:
>> The original behavior was to refuse all pages after the maximum number of
>> segments has been reached. However, some drivers (like st) craft their buffers
>> to potentially require exactly max segments and multiple pages in the last
>> segment. This patch modifies the check to allow pages that can be merged into
>> the last segment.
>>
>> This change fixes EBUSY failures when using large (1mb) tape block size in high
>> memory fragmentation condition.
>>
>> Signed-off-by: Jan Vesely <jvesely@redhat.com>
>> ---
>>  fs/bio.c |   26 ++++++++++++++++----------
>>  1 files changed, 16 insertions(+), 10 deletions(-)
>>
>> diff --git a/fs/bio.c b/fs/bio.c
>> index b96fc6c..02efbd5 100644
>> --- a/fs/bio.c
>> +++ b/fs/bio.c
>> @@ -500,7 +500,6 @@ static int __bio_add_page(struct request_queue *q, struct
>> bio *bio, struct page
>>                *page, unsigned int len, unsigned int offset,
>>                unsigned short max_sectors)
>>  {
>> -    int retried_segments = 0;
>>      struct bio_vec *bvec;
>>
>>      /*
>> @@ -551,18 +550,12 @@ static int __bio_add_page(struct request_queue *q,
>> struct bio *bio, struct page
>>          return 0;
>>
>>      /*
>> -     * we might lose a segment or two here, but rather that than
>> -     * make this too complex.
>> +     * prepare segment count check, reduce segment count if possible
>>       */
>>
>> -    while (bio->bi_phys_segments >= queue_max_segments(q)) {
>> -
>> -        if (retried_segments)
>> -            return 0;
>> -
>> -        retried_segments = 1;
>> +    if (bio->bi_phys_segments >= queue_max_segments(q))
>>          blk_recount_segments(q, bio);
>> -    }
>> +
>>
>>      /*
>>       * setup the new entry, we might clear it again later if we
>> @@ -572,6 +565,19 @@ static int __bio_add_page(struct request_queue *q, struct
>> bio *bio, struct page
>>      bvec->bv_page = page;
>>      bvec->bv_len = len;
>>      bvec->bv_offset = offset;
>> +
>> +    /*
>> +     * the other part of the segment count check, allow mergeable pages
>> +     */
>> +    if ((bio->bi_phys_segments > queue_max_segments(q)) ||
>> +        ( (bio->bi_phys_segments == queue_max_segments(q)) &&
>> +        !BIOVEC_PHYS_MERGEABLE(bvec - 1, bvec))) {
>> +            bvec->bv_page = NULL;
>> +            bvec->bv_len = 0;
>> +            bvec->bv_offset = 0;
>> +            return 0;
>> +    }
>> +
>>
>>      /*
>>       * if queue has other restrictions (eg varying max sector size

ping?

The described failure is a regression introduced in
    46081b166415acb66d4b3150ecefcd9460bb48a1
    st: Increase success probability in driver buffer allocation

I have added the signers to cc. I can resend the patch if it is 
necessary

thank you,

--
Jan Vesely <jvesely@redhat.com>

^ permalink raw reply	[flat|nested] 4+ messages in thread

* Re: [PATCH] block: modify __bio_add_page check to accept pages that don't start a new segment
  2013-03-25 13:09   ` Jan Vesely
@ 2013-03-25 13:31     ` Jens Axboe
  0 siblings, 0 replies; 4+ messages in thread
From: Jens Axboe @ 2013-03-25 13:31 UTC (permalink / raw)
  To: Jan Vesely
  Cc: linux-kernel, linux-scsi, linux-fsdevel, Alexander Viro,
	James Bottomley, Kai Mäkisara, fujita.tomonori

On Mon, Mar 25 2013, Jan Vesely wrote:
> On Thu 07 Mar 2013 12:23:13 CET, Jan Vesely wrote:
> 
> > On Thu 21 Feb 2013 09:30:26 CET, Jan Vesely wrote:
> >> The original behavior was to refuse all pages after the maximum number of
> >> segments has been reached. However, some drivers (like st) craft their buffers
> >> to potentially require exactly max segments and multiple pages in the last
> >> segment. This patch modifies the check to allow pages that can be merged into
> >> the last segment.
> >>
> >> This change fixes EBUSY failures when using large (1mb) tape block size in high
> >> memory fragmentation condition.
> >>
> >> Signed-off-by: Jan Vesely <jvesely@redhat.com>
> >> ---
> >>  fs/bio.c |   26 ++++++++++++++++----------
> >>  1 files changed, 16 insertions(+), 10 deletions(-)
> >>
> >> diff --git a/fs/bio.c b/fs/bio.c
> >> index b96fc6c..02efbd5 100644
> >> --- a/fs/bio.c
> >> +++ b/fs/bio.c
> >> @@ -500,7 +500,6 @@ static int __bio_add_page(struct request_queue *q, struct
> >> bio *bio, struct page
> >>                *page, unsigned int len, unsigned int offset,
> >>                unsigned short max_sectors)
> >>  {
> >> -    int retried_segments = 0;
> >>      struct bio_vec *bvec;
> >>
> >>      /*
> >> @@ -551,18 +550,12 @@ static int __bio_add_page(struct request_queue *q,
> >> struct bio *bio, struct page
> >>          return 0;
> >>
> >>      /*
> >> -     * we might lose a segment or two here, but rather that than
> >> -     * make this too complex.
> >> +     * prepare segment count check, reduce segment count if possible
> >>       */
> >>
> >> -    while (bio->bi_phys_segments >= queue_max_segments(q)) {
> >> -
> >> -        if (retried_segments)
> >> -            return 0;
> >> -
> >> -        retried_segments = 1;
> >> +    if (bio->bi_phys_segments >= queue_max_segments(q))
> >>          blk_recount_segments(q, bio);
> >> -    }
> >> +
> >>
> >>      /*
> >>       * setup the new entry, we might clear it again later if we
> >> @@ -572,6 +565,19 @@ static int __bio_add_page(struct request_queue *q, struct
> >> bio *bio, struct page
> >>      bvec->bv_page = page;
> >>      bvec->bv_len = len;
> >>      bvec->bv_offset = offset;
> >> +
> >> +    /*
> >> +     * the other part of the segment count check, allow mergeable pages
> >> +     */
> >> +    if ((bio->bi_phys_segments > queue_max_segments(q)) ||
> >> +        ( (bio->bi_phys_segments == queue_max_segments(q)) &&
> >> +        !BIOVEC_PHYS_MERGEABLE(bvec - 1, bvec))) {
> >> +            bvec->bv_page = NULL;
> >> +            bvec->bv_len = 0;
> >> +            bvec->bv_offset = 0;
> >> +            return 0;
> >> +    }
> >> +
> >>
> >>      /*
> >>       * if queue has other restrictions (eg varying max sector size
> 
> ping?
> 
> The described failure is a regression introduced in
>     46081b166415acb66d4b3150ecefcd9460bb48a1
>     st: Increase success probability in driver buffer allocation
> 
> I have added the signers to cc. I can resend the patch if it is 
> necessary

Can you resend the patch? The above is mangled for me.

-- 
Jens Axboe


^ permalink raw reply	[flat|nested] 4+ messages in thread

end of thread, other threads:[~2013-03-25 13:31 UTC | newest]

Thread overview: 4+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2013-02-21  8:30 [PATCH] block: modify __bio_add_page check to accept pages that don't start a new segment Jan Vesely
2013-03-07 11:23 ` Jan Vesely
2013-03-25 13:09   ` Jan Vesely
2013-03-25 13:31     ` Jens Axboe

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).