diff options
author | kxie@chelsio.com <kxie@chelsio.com> | 2009-04-21 16:32:35 -0400 |
---|---|---|
committer | James Bottomley <James.Bottomley@HansenPartnership.com> | 2009-04-27 11:11:07 -0400 |
commit | a53922ddcf69f4bd8aa321b1fb30418df7a86c61 (patch) | |
tree | bbb64365c591b680ec0639a0c18ce4e3bbc4676c /drivers/scsi | |
parent | 1393109f23f8ad753a60a3e461c6caa96d8524f3 (diff) |
[SCSI] cxgb3i: fix ddp map overrun
(version 2)
Fixed a bug in calculating ddp map range when search for free entries:
it was going beyond the end by one, thus corrupting gl_skb[0].
Signed-off-by: Karen Xie <kxie@chelsio.com>
Signed-off-by: Mike Christie <michaelc@cs.wisc.edu>
Signed-off-by: James Bottomley <James.Bottomley@HansenPartnership.com>
Diffstat (limited to 'drivers/scsi')
-rw-r--r-- | drivers/scsi/cxgb3i/cxgb3i_ddp.c | 32 |
1 files changed, 19 insertions, 13 deletions
diff --git a/drivers/scsi/cxgb3i/cxgb3i_ddp.c b/drivers/scsi/cxgb3i/cxgb3i_ddp.c index d06a661c209f..99c912547902 100644 --- a/drivers/scsi/cxgb3i/cxgb3i_ddp.c +++ b/drivers/scsi/cxgb3i/cxgb3i_ddp.c | |||
@@ -120,20 +120,26 @@ static void clear_ddp_map(struct cxgb3i_ddp_info *ddp, unsigned int tag, | |||
120 | } | 120 | } |
121 | 121 | ||
122 | static inline int ddp_find_unused_entries(struct cxgb3i_ddp_info *ddp, | 122 | static inline int ddp_find_unused_entries(struct cxgb3i_ddp_info *ddp, |
123 | int start, int max, int count, | 123 | unsigned int start, unsigned int max, |
124 | unsigned int count, | ||
124 | struct cxgb3i_gather_list *gl) | 125 | struct cxgb3i_gather_list *gl) |
125 | { | 126 | { |
126 | unsigned int i, j; | 127 | unsigned int i, j, k; |
127 | 128 | ||
129 | /* not enough entries */ | ||
130 | if ((max - start) < count) | ||
131 | return -EBUSY; | ||
132 | |||
133 | max -= count; | ||
128 | spin_lock(&ddp->map_lock); | 134 | spin_lock(&ddp->map_lock); |
129 | for (i = start; i <= max;) { | 135 | for (i = start; i < max;) { |
130 | for (j = 0; j < count; j++) { | 136 | for (j = 0, k = i; j < count; j++, k++) { |
131 | if (ddp->gl_map[i + j]) | 137 | if (ddp->gl_map[k]) |
132 | break; | 138 | break; |
133 | } | 139 | } |
134 | if (j == count) { | 140 | if (j == count) { |
135 | for (j = 0; j < count; j++) | 141 | for (j = 0, k = i; j < count; j++, k++) |
136 | ddp->gl_map[i + j] = gl; | 142 | ddp->gl_map[k] = gl; |
137 | spin_unlock(&ddp->map_lock); | 143 | spin_unlock(&ddp->map_lock); |
138 | return i; | 144 | return i; |
139 | } | 145 | } |
@@ -354,7 +360,7 @@ int cxgb3i_ddp_tag_reserve(struct t3cdev *tdev, unsigned int tid, | |||
354 | struct cxgb3i_ddp_info *ddp = tdev->ulp_iscsi; | 360 | struct cxgb3i_ddp_info *ddp = tdev->ulp_iscsi; |
355 | struct pagepod_hdr hdr; | 361 | struct pagepod_hdr hdr; |
356 | unsigned int npods; | 362 | unsigned int npods; |
357 | int idx = -1, idx_max; | 363 | int idx = -1; |
358 | int err = -ENOMEM; | 364 | int err = -ENOMEM; |
359 | u32 sw_tag = *tagp; | 365 | u32 sw_tag = *tagp; |
360 | u32 tag; | 366 | u32 tag; |
@@ -367,17 +373,17 @@ int cxgb3i_ddp_tag_reserve(struct t3cdev *tdev, unsigned int tid, | |||
367 | } | 373 | } |
368 | 374 | ||
369 | npods = (gl->nelem + PPOD_PAGES_MAX - 1) >> PPOD_PAGES_SHIFT; | 375 | npods = (gl->nelem + PPOD_PAGES_MAX - 1) >> PPOD_PAGES_SHIFT; |
370 | idx_max = ddp->nppods - npods + 1; | ||
371 | 376 | ||
372 | if (ddp->idx_last == ddp->nppods) | 377 | if (ddp->idx_last == ddp->nppods) |
373 | idx = ddp_find_unused_entries(ddp, 0, idx_max, npods, gl); | 378 | idx = ddp_find_unused_entries(ddp, 0, ddp->nppods, npods, gl); |
374 | else { | 379 | else { |
375 | idx = ddp_find_unused_entries(ddp, ddp->idx_last + 1, | 380 | idx = ddp_find_unused_entries(ddp, ddp->idx_last + 1, |
376 | idx_max, npods, gl); | 381 | ddp->nppods, npods, gl); |
377 | if (idx < 0 && ddp->idx_last >= npods) | 382 | if (idx < 0 && ddp->idx_last >= npods) { |
378 | idx = ddp_find_unused_entries(ddp, 0, | 383 | idx = ddp_find_unused_entries(ddp, 0, |
379 | ddp->idx_last - npods + 1, | 384 | min(ddp->idx_last + npods, ddp->nppods), |
380 | npods, gl); | 385 | npods, gl); |
386 | } | ||
381 | } | 387 | } |
382 | if (idx < 0) { | 388 | if (idx < 0) { |
383 | ddp_log_debug("xferlen %u, gl %u, npods %u NO DDP.\n", | 389 | ddp_log_debug("xferlen %u, gl %u, npods %u NO DDP.\n", |