Messages in this thread Patch in this message |  | | Date | Thu, 24 Aug 2000 10:24:02 -0300 | From | Arnaldo Carvalho de Melo <> | Subject | [PATCH] st.c: cleanups and checking resource allocation |
| |
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/
|  |