patch-2.4.0-test8 linux/drivers/scsi/sd.c

Next file: linux/drivers/scsi/sr.c
Previous file: linux/drivers/scsi/scsi_scan.c
Back to the patch index
Back to the overall index

diff -u --recursive --new-file v2.4.0-test7/linux/drivers/scsi/sd.c linux/drivers/scsi/sd.c
@@ -19,6 +19,9 @@
  *       scsi disks using eight major numbers.
  *
  *       Modified by Richard Gooch rgooch@atnf.csiro.au to support devfs.
+ *	
+ *	 Modified by Torben Mathiasen tmm@image.dk
+ *       Resource allocation fixes in sd_init and cleanups.
  */
 
 #include <linux/config.h>
@@ -957,17 +960,23 @@
 		/* FLOPTICAL */
 
 		/*
-		 *    for removable scsi disk ( FLOPTICAL ) we have to recognise
-		 * the Write Protect Flag. This flag is kept in the Scsi_Disk struct
-		 * and tested at open !
+		 * For removable scsi disk ( FLOPTICAL ) we have to recognise
+		 * the Write Protect Flag. This flag is kept in the Scsi_Disk
+		 * struct and tested at open !
 		 * Daniel Roche ( dan@lectra.fr )
+		 *
+		 * Changed to get all pages (0x3f) rather than page 1 to
+		 * get around devices which do not have a page 1.  Since
+		 * we're only interested in the header anyway, this should
+		 * be fine.
+		 *   -- Matthew Dharm (mdharm-scsi@one-eyed-alien.net)
 		 */
 
 		memset((void *) &cmd[0], 0, 8);
 		cmd[0] = MODE_SENSE;
 		cmd[1] = (rscsi_disks[i].device->lun << 5) & 0xe0;
-		cmd[2] = 1;	/* page code 1 ?? */
-		cmd[4] = 12;
+		cmd[2] = 0x3f;	/* Get all pages */
+		cmd[4] = 8;     /* But we only want the 8 byte header */
 		SRpnt->sr_cmd_len = 0;
 		SRpnt->sr_sense_buffer[0] = 0;
 		SRpnt->sr_sense_buffer[2] = 0;
@@ -1033,16 +1042,24 @@
 	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);
+	sd_sizes = kmalloc((sd_template.dev_max << 4) * sizeof(int), GFP_ATOMIC);
+	if (!sd_sizes)
+		goto cleanup_disks;
 	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_blocksizes = kmalloc((sd_template.dev_max << 4) * sizeof(int), GFP_ATOMIC);
+	if (!sd_blocksizes)
+		goto cleanup_sizes;
+	
+	sd_hardsizes = kmalloc((sd_template.dev_max << 4) * sizeof(int), GFP_ATOMIC);
+	if (!sd_hardsizes)
+		goto cleanup_blocksizes;
 
 	for (i = 0; i < sd_template.dev_max << 4; i++) {
 		sd_blocksizes[i] = 1024;
@@ -1053,22 +1070,29 @@
 		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) *
+	sd = kmalloc((sd_template.dev_max << 4) *
 					  sizeof(struct hd_struct),
 					  GFP_ATOMIC);
+	if (!sd)
+		goto cleanup_sd;
 	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_gendisks = kmalloc(N_USED_SD_MAJORS * sizeof(struct gendisk), GFP_ATOMIC);
+		if (!sd_gendisks)
+			goto cleanup_sd_gendisks;
 	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);
+		if (!sd_gendisks[i].de_arr)
+			goto cleanup_gendisks_de_arr;
                 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].flags)
+			goto cleanup_gendisks_flags;
                 memset (sd_gendisks[i].flags, 0,
                         SCSI_DISKS_PER_MAJOR * sizeof *sd_gendisks[i].flags);
 		sd_gendisks[i].major = SD_MAJOR(i);
@@ -1085,6 +1109,31 @@
 
 	LAST_SD_GENDISK.next = NULL;
 	return 0;
+
+cleanup_gendisks_flags:
+	kfree(sd_gendisks[i].de_arr);
+cleanup_gendisks_de_arr:
+	while (--i >= 0 ) {
+		kfree(sd_gendisks[i].de_arr);
+		kfree(sd_gendisks[i].flags);
+	}
+	kfree(sd_gendisks);
+cleanup_sd_gendisks:
+	kfree(sd);
+cleanup_sd:
+	kfree(sd_hardsizes);
+cleanup_blocksizes:
+	kfree(sd_blocksizes);
+cleanup_sizes:
+	kfree(sd_sizes);
+cleanup_disks:
+	kfree(rscsi_disks);
+cleanup_devfs:
+	for (i = 0; i < N_USED_SD_MAJORS; i++) {
+		devfs_unregister_blkdev(SD_MAJOR(i), "sd");
+	}
+	sd_registered--;
+	return 1;
 }
 
 
@@ -1286,14 +1335,12 @@
 	return;
 }
 
-#ifdef MODULE
-
-int init_module(void)
+int init_sd(void)
 {
-	sd_template.module = &__this_module;
+	sd_template.module = THIS_MODULE;
 	return scsi_register_module(MODULE_SCSI_DEV, &sd_template);
 }
-void cleanup_module(void)
+void exit_sd(void)
 {
 	struct gendisk **prev_sdgd_link;
 	struct gendisk *sdgd;
@@ -1307,10 +1354,10 @@
 
 	sd_registered--;
 	if (rscsi_disks != NULL) {
-		kfree((char *) rscsi_disks);
-		kfree((char *) sd_sizes);
-		kfree((char *) sd_blocksizes);
-		kfree((char *) sd_hardsizes);
+		kfree(rscsi_disks);
+		kfree(sd_sizes);
+		kfree(sd_blocksizes);
+		kfree(sd_hardsizes);
 		kfree((char *) sd);
 
 		/*
@@ -1340,23 +1387,6 @@
 	if (sd_gendisks != &sd_gendisk)
 		kfree(sd_gendisks);
 }
-#endif				/* MODULE */
 
-/*
- * Overrides for Emacs so that we almost follow Linus's tabbing style.
- * Emacs will notice this stuff at the end of the file and automatically
- * adjust the settings for this buffer only.  This must remain at the end
- * of the file.
- * ---------------------------------------------------------------------------
- * Local variables:
- * c-indent-level: 4
- * c-brace-imaginary-offset: 0
- * c-brace-offset: -4
- * c-argdecl-indent: 4
- * c-label-offset: -4
- * c-continued-statement-offset: 4
- * c-continued-brace-offset: 0
- * indent-tabs-mode: nil
- * tab-width: 8
- * End:
- */
+module_init(init_sd);
+module_exit(exit_sd);

FUNET's LINUX-ADM group, linux-adm@nic.funet.fi
TCL-scripts by Sam Shen (who was at: slshen@lbl.gov)