lkml.org 
[lkml]   [2000]   [Aug]   [23]   [last100]   RSS Feed
Views: [wrap][no wrap]   [headers]  [forward] 
 
Messages in this thread
Patch in this message
/
Date
From
Subject: [PATCH]v2: sd.c: handling resource allocation failure
Hi,

Here it is again, with no casts to kmalloc, please consider applying.

- Arnaldo

--- linux-2.4.0-test7-pre7/drivers/scsi/sd.c Sat Jul 8 23:33:40 2000
+++ linux-2.4.0-test7-pre7.acme/drivers/scsi/sd.c Wed Aug 23 13:16:36 2000
@@ -19,6 +19,9 @@
* scsi disks using eight major numbers.
*
* Modified by Richard Gooch rgooch@atnf.csiro.au to support devfs.
+ *
+ * Modified by Arnaldo Carvalho de Melo <acme@conectiva.com.br> to
+ * check resource allocation and cleanups in sd_init - 2000/08/22
*/

#include <linux/config.h>
@@ -77,7 +80,7 @@

struct hd_struct *sd;

-static Scsi_Disk *rscsi_disks = NULL;
+static Scsi_Disk *rscsi_disks;
static int *sd_sizes;
static int *sd_blocksizes;
static int *sd_hardsizes; /* Hardware sector size */
@@ -522,26 +525,7 @@
revalidate: fop_revalidate_scsidisk
};

-/*
- * If we need more than one SCSI disk major (i.e. more than
- * 16 SCSI disks), we'll have to kmalloc() more gendisks later.
- */
-
-static struct gendisk sd_gendisk =
-{
- SCSI_DISK0_MAJOR, /* Major number */
- "sd", /* Major name */
- 4, /* Bits to shift to get real from partition */
- 1 << 4, /* Number of partitions per real */
- NULL, /* hd struct */
- NULL, /* block sizes */
- 0, /* number */
- NULL, /* internal */
- NULL, /* next */
- &sd_fops, /* file operations */
-};
-
-static struct gendisk *sd_gendisks = &sd_gendisk;
+static struct gendisk *sd_gendisks;

#define SD_GENDISK(i) sd_gendisks[(i) / SCSI_DISKS_PER_MAJOR]
#define LAST_SD_GENDISK sd_gendisks[N_USED_SD_MAJORS - 1]
@@ -1010,6 +994,7 @@
static int sd_init()
{
int i;
+ const int nr_majors = sd_template.dev_max << 4;

if (sd_template.dev_noticed == 0)
return 0;
@@ -1033,16 +1018,23 @@
if (rscsi_disks)
return 0;

- rscsi_disks = (Scsi_Disk *)
- kmalloc(sd_template.dev_max * sizeof(Scsi_Disk), GFP_ATOMIC);
+ rscsi_disks = kmalloc(sd_template.dev_max * sizeof(Scsi_Disk), GFP_ATOMIC);
+ if (!rscsi_disks)
+ goto cleanup_devfs;
memset(rscsi_disks, 0, sd_template.dev_max * sizeof(Scsi_Disk));

/* for every (necessary) major: */
- sd_sizes = (int *) kmalloc((sd_template.dev_max << 4) * sizeof(int), GFP_ATOMIC);
- memset(sd_sizes, 0, (sd_template.dev_max << 4) * sizeof(int));
-
- sd_blocksizes = (int *) kmalloc((sd_template.dev_max << 4) * sizeof(int), GFP_ATOMIC);
- sd_hardsizes = (int *) kmalloc((sd_template.dev_max << 4) * sizeof(int), GFP_ATOMIC);
+ sd_sizes = kmalloc(nr_majors * sizeof(int), GFP_ATOMIC);
+ if (!sd_sizes)
+ goto cleanup_rscsi_disks;
+ memset(sd_sizes, 0, nr_majors * sizeof(int));
+
+ sd_blocksizes = kmalloc(nr_majors * sizeof(int), GFP_ATOMIC);
+ if (!sd_blocksizes)
+ goto cleanup_sd_sizes;
+ sd_hardsizes = kmalloc(nr_majors * sizeof(int), GFP_ATOMIC);
+ if (!sd_hardsizes)
+ goto cleanup_sd_blocksizes;

for (i = 0; i < sd_template.dev_max << 4; i++) {
sd_blocksizes[i] = 1024;
@@ -1053,22 +1045,25 @@
blksize_size[SD_MAJOR(i)] = sd_blocksizes + i * (SCSI_DISKS_PER_MAJOR << 4);
hardsect_size[SD_MAJOR(i)] = sd_hardsizes + i * (SCSI_DISKS_PER_MAJOR << 4);
}
- sd = (struct hd_struct *) kmalloc((sd_template.dev_max << 4) *
- sizeof(struct hd_struct),
- GFP_ATOMIC);
- memset(sd, 0, (sd_template.dev_max << 4) * sizeof(struct hd_struct));
-
- if (N_USED_SD_MAJORS > 1)
- sd_gendisks = (struct gendisk *)
- kmalloc(N_USED_SD_MAJORS * sizeof(struct gendisk), GFP_ATOMIC);
+ sd = kmalloc(nr_majors * sizeof(struct hd_struct), GFP_ATOMIC);
+ if (!sd)
+ goto cleanup_sd_hardsizes;
+ memset(sd, 0, nr_majors * sizeof(struct hd_struct));
+
+ sd_gendisks = kmalloc(N_USED_SD_MAJORS * sizeof(struct gendisk), GFP_ATOMIC);
+ if (!sd_gendisks)
+ goto cleanup_sd;
+ memset(sd_gendisks, 0, N_USED_SD_MAJORS * sizeof(struct gendisk));
+
for (i = 0; i < N_USED_SD_MAJORS; i++) {
- sd_gendisks[i] = sd_gendisk;
sd_gendisks[i].de_arr = kmalloc (SCSI_DISKS_PER_MAJOR * sizeof *sd_gendisks[i].de_arr,
GFP_ATOMIC);
- memset (sd_gendisks[i].de_arr, 0,
- SCSI_DISKS_PER_MAJOR * sizeof *sd_gendisks[i].de_arr);
sd_gendisks[i].flags = kmalloc (SCSI_DISKS_PER_MAJOR * sizeof *sd_gendisks[i].flags,
GFP_ATOMIC);
+ if (!sd_gendisks[i].de_arr || !sd_gendisks[i].flags)
+ goto cleanup_sd_gendisks;
+ memset (sd_gendisks[i].de_arr, 0,
+ SCSI_DISKS_PER_MAJOR * sizeof *sd_gendisks[i].de_arr);
memset (sd_gendisks[i].flags, 0,
SCSI_DISKS_PER_MAJOR * sizeof *sd_gendisks[i].flags);
sd_gendisks[i].major = SD_MAJOR(i);
@@ -1085,6 +1080,36 @@

LAST_SD_GENDISK.next = NULL;
return 0;
+
+cleanup_sd_gendisks:
+ do {
+ if (sd_gendisks[i].de_arr) {
+ kfree(sd_gendisks[i].de_arr);
+ sd_gendisks[i].de_arr = NULL;
+ }
+ if (sd_gendisks[i].flags) {
+ kfree(sd_gendisks[i].flags);
+ sd_gendisks[i].flags = NULL;
+ }
+ } while(i--);
+
+ kfree(sd_gendisks);
+cleanup_sd:
+ kfree(sd);
+cleanup_sd_hardsizes:
+ kfree(sd_hardsizes);
+cleanup_sd_blocksizes:
+ kfree(sd_blocksizes);
+cleanup_sd_sizes:
+ kfree(sd_sizes);
+cleanup_rscsi_disks:
+ kfree(rscsi_disks);
+cleanup_devfs:
+ for (i = 0; i <= (sd_template.dev_max - 1) / SCSI_DISKS_PER_MAJOR; i++)
+ devfs_unregister_blkdev(SD_MAJOR(i), "sd");
+
+ sd_registered--;
+ return 1;
}


@@ -1256,8 +1281,8 @@

/* If we are disconnecting a disk driver, sync and invalidate
* everything */
- max_p = sd_gendisk.max_p;
- start = i << sd_gendisk.minor_shift;
+ max_p = sd_gendisks->max_p;
+ start = i << sd_gendisks->minor_shift;

for (j = max_p - 1; j >= 0; j--) {
int index = start + j;
@@ -1337,8 +1362,7 @@
read_ahead[SD_MAJOR(i)] = 0;
}
sd_template.dev_max = 0;
- if (sd_gendisks != &sd_gendisk)
- kfree(sd_gendisks);
+ kfree(sd_gendisks);
}
#endif /* MODULE */

-
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/
\
 
 \ /
  Last update: 2005-03-22 12:38    [W:0.039 / U:1.340 seconds]
©2003-2018 Jasper Spaans|hosted at Digital Ocean and TransIP|Read the blog|Advertise on this site