Hi,
Please take a look and consider applying.
- Arnaldo
--- linux-2.4.0-test7/drivers/scsi/st.c Thu Aug 24 07:40:05 2000
+++ linux-2.4.0-test7.acme/drivers/scsi/st.c Thu Aug 24 10:13:02 2000
@@ -17,6 +17,9 @@
Last modified: 18-JAN-1998 Richard Gooch <rgooch@atnf.csiro.au> Devfs support
+ Arnaldo Carvalho de Melo <acme@conectiva.com.br> 2000/08/23
+ - cleanup and resource allocation checking in st_init and some other places
+
Reminder: write_lock_irqsave() can be replaced by write_lock() when the old SCSI
error handling will be discarded.
*/
@@ -3133,7 +3136,8 @@
static ST_buffer *
new_tape_buffer(int from_initialization, int need_dma, int in_use)
{
- int i, priority, b_size, order, got = 0, segs = 0;
+ int i, b_size, order, got = 0, segs = 0;
+ int priority = from_initialization ? GFP_ATOMIC : GFP_KERNEL;
unsigned long flags;
ST_buffer *tb;
@@ -3144,84 +3148,71 @@
}
read_unlock(&st_dev_arr_lock);
- if (from_initialization)
- priority = GFP_ATOMIC;
- else
- priority = GFP_KERNEL;
-
i = sizeof(ST_buffer) + (st_max_sg_segs - 1) * sizeof(struct scatterlist);
tb = kmalloc(i, priority);
- if (tb) {
- if (need_dma)
- priority |= GFP_DMA;
-
- /* Try to allocate the first segment up to ST_FIRST_ORDER and the
- others big enough to reach the goal */
- for (b_size = PAGE_SIZE, order=0;
- b_size < st_buffer_size && order < ST_FIRST_ORDER;
- order++, b_size *= 2)
- ;
- for ( ; b_size >= PAGE_SIZE; order--, b_size /= 2) {
- tb->sg[0].address =
- (unsigned char *) __get_free_pages(priority, order);
- if (tb->sg[0].address != NULL) {
- tb->sg[0].alt_address = NULL;
- tb->sg[0].length = b_size;
- break;
- }
- }
- if (tb->sg[segs].address == NULL) {
- kfree(tb);
- tb = NULL;
- } else { /* Got something, continue */
-
- for (b_size = PAGE_SIZE, order=0;
- st_buffer_size >
- tb->sg[0].length + (ST_FIRST_SG - 1) * b_size;
- order++, b_size *= 2)
- ;
- for (segs = 1, got = tb->sg[0].length;
- got < st_buffer_size && segs < ST_FIRST_SG;) {
- tb->sg[segs].address =
- (unsigned char *) __get_free_pages(priority,
- order);
- if (tb->sg[segs].address == NULL) {
- if (st_buffer_size - got <=
- (ST_FIRST_SG - segs) * b_size / 2) {
- b_size /= 2; /* Large enough for the
- rest of the buffers */
- order--;
- continue;
- }
- tb->sg_segs = segs;
- tb->orig_sg_segs = 0;
- DEB(tb->buffer_size = got);
- normalize_buffer(tb);
- kfree(tb);
- tb = NULL;
- break;
- }
- tb->sg[segs].alt_address = NULL;
- tb->sg[segs].length = b_size;
- got += b_size;
- segs++;
- }
+ if (!tb)
+ return NULL;
+
+ if (need_dma)
+ priority |= GFP_DMA;
+
+ /* Try to allocate the first segment up to ST_FIRST_ORDER and the
+ others big enough to reach the goal */
+ for (b_size = PAGE_SIZE, order=0;
+ b_size < st_buffer_size && order < ST_FIRST_ORDER;
+ order++, b_size *= 2)
+ ;
+ for ( ; b_size >= PAGE_SIZE; order--, b_size /= 2) {
+ tb->sg[0].address =
+ (unsigned char *) __get_free_pages(priority, order);
+ if (tb->sg[0].address) {
+ tb->sg[0].alt_address = NULL;
+ tb->sg[0].length = b_size;
+ break;
}
}
- if (!tb) {
- printk(KERN_NOTICE "st: Can't allocate new tape buffer (nbr %d).\n",
- st_nbr_buffers);
- return NULL;
+ if (!tb->sg[0].address)
+ goto cleanup_tb;
+
+ /* Got something, continue */
+
+ for (b_size = PAGE_SIZE, order=0;
+ st_buffer_size >
+ tb->sg[0].length + (ST_FIRST_SG - 1) * b_size;
+ order++, b_size *= 2)
+ ;
+ for (segs = 1, got = tb->sg[0].length;
+ got < st_buffer_size && segs < ST_FIRST_SG;) {
+ tb->sg[segs].address = (unsigned char *)
+ __get_free_pages(priority, order);
+ if (!tb->sg[segs].address) {
+ if (st_buffer_size - got <=
+ (ST_FIRST_SG - segs) * b_size / 2) {
+ b_size /= 2; /* Large enough for the
+ rest of the buffers */
+ order--;
+ continue;
+ }
+ tb->sg_segs = segs;
+ tb->orig_sg_segs = 0;
+ DEB(tb->buffer_size = got);
+ normalize_buffer(tb);
+ goto cleanup_tb;
+ }
+ tb->sg[segs].alt_address = NULL;
+ tb->sg[segs].length = b_size;
+ got += b_size;
+ segs++;
}
+
tb->sg_segs = tb->orig_sg_segs = segs;
tb->b_data = tb->sg[0].address;
DEBC(printk(ST_DEB_MSG
"st: Allocated tape buffer %d (%d bytes, %d segments, dma: %d, a: %p).\n",
st_nbr_buffers, got, tb->sg_segs, need_dma, tb->b_data);
- printk(ST_DEB_MSG
- "st: segment sizes: first %d, last %d bytes.\n",
+ printk(ST_DEB_MSG "st: segment sizes: first %d, last %d bytes.\n",
tb->sg[0].length, tb->sg[segs - 1].length);
)
tb->in_use = in_use;
@@ -3234,6 +3225,9 @@
write_unlock_irqrestore(&st_dev_arr_lock, flags);
return tb;
+cleanup_tb:
+ kfree(tb);
+ return NULL;
}
@@ -3484,8 +3478,10 @@
tmp_da = kmalloc(tmp_dev_max * sizeof(Scsi_Tape *), GFP_ATOMIC);
tmp_ba = kmalloc(tmp_dev_max * sizeof(ST_buffer *), GFP_ATOMIC);
if (tmp_da == NULL || tmp_ba == NULL) {
- if (tmp_da != NULL)
+ if (!tmp_da)
kfree(tmp_da);
+ if (!tmp_ba)
+ kfree(tmp_ba);
SDp->attached--;
write_unlock_irqrestore(&st_dev_arr_lock, flags);
printk(KERN_ERR "st: Can't extend device array.\n");
-
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to majordomo@vger.kernel.org
Please read the FAQ at http://www.tux.org/lkml/
This archive was generated by hypermail 2b29 : Thu Aug 31 2000 - 21:00:13 EST