diff options
author | Bodo Stroesser <bstroesser@ts.fujitsu.com> | 2013-12-02 12:52:10 -0500 |
---|---|---|
committer | James Bottomley <JBottomley@Parallels.com> | 2013-12-19 23:56:28 -0500 |
commit | 769989a4a09d7c825e182cf60604c06d8f2f70e4 (patch) | |
tree | 273cb753047de8d2f10cd916acbabc8bc1587af6 /drivers/scsi/st.c | |
parent | 762a86a901417280b2af9e2004f05d7481f30441 (diff) |
[SCSI] st: fix enlarge_buffer
This patch removes a bug in enlarge_buffer() that can make a
read or write fail under special conditions.
After changing TRY_DIRECT_IO to 0 and ST_MAX_SG to 32 in
st_options.h, a program that writes a first block of 128k and
than a second bigger block (e.g. 256k) fails. The second write
returns errno EOVERFLOW, as enlarge_buffer() checks the sg list
and detects that it already is full.
As enlarge_buffer uses different page allocation orders
depending on the size of the buffer needed, the check does not
make sense.
Signed-off-by: Bodo Stroesser <bstroesser@ts.fujitsu.com>
Acked-by: Kai Mäkisara <kai.makisara@kolumbus.fi>
Signed-off-by: James Bottomley <JBottomley@Parallels.com>
Diffstat (limited to 'drivers/scsi/st.c')
-rw-r--r-- | drivers/scsi/st.c | 5 |
1 files changed, 1 insertions, 4 deletions
diff --git a/drivers/scsi/st.c b/drivers/scsi/st.c index ff44b3c2cff2..a1d6986261a3 100644 --- a/drivers/scsi/st.c +++ b/drivers/scsi/st.c | |||
@@ -3719,7 +3719,7 @@ static struct st_buffer *new_tape_buffer(int need_dma, int max_sg) | |||
3719 | 3719 | ||
3720 | static int enlarge_buffer(struct st_buffer * STbuffer, int new_size, int need_dma) | 3720 | static int enlarge_buffer(struct st_buffer * STbuffer, int new_size, int need_dma) |
3721 | { | 3721 | { |
3722 | int segs, nbr, max_segs, b_size, order, got; | 3722 | int segs, max_segs, b_size, order, got; |
3723 | gfp_t priority; | 3723 | gfp_t priority; |
3724 | 3724 | ||
3725 | if (new_size <= STbuffer->buffer_size) | 3725 | if (new_size <= STbuffer->buffer_size) |
@@ -3729,9 +3729,6 @@ static int enlarge_buffer(struct st_buffer * STbuffer, int new_size, int need_dm | |||
3729 | normalize_buffer(STbuffer); /* Avoid extra segment */ | 3729 | normalize_buffer(STbuffer); /* Avoid extra segment */ |
3730 | 3730 | ||
3731 | max_segs = STbuffer->use_sg; | 3731 | max_segs = STbuffer->use_sg; |
3732 | nbr = max_segs - STbuffer->frp_segs; | ||
3733 | if (nbr <= 0) | ||
3734 | return 0; | ||
3735 | 3732 | ||
3736 | priority = GFP_KERNEL | __GFP_NOWARN; | 3733 | priority = GFP_KERNEL | __GFP_NOWARN; |
3737 | if (need_dma) | 3734 | if (need_dma) |