Messages in this thread Patch in this message |  | | Date | Wed, 23 Aug 2000 13:26:05 -0300 | From | Arnaldo Carvalho de Melo <> | 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/
|  |