: [PATCH]v2: sd.c: handling resource allocation failure

From: Arnaldo Carvalho de Melo (acme@conectiva.com.br)
Date: Wed Aug 23 2000 - 11:26:05 EST


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/



This archive was generated by hypermail 2b29 : Wed Aug 23 2000 - 21:00:09 EST