Skip to contentSkip to conversation

2tb limit in sd.c

RFC New Alex Tomas 1 participant 1 message Dec 13, 2002 SCSI

lore
Share & tools
lore

Alex Tomas

author
#0 lore raw

RFC 1/1 2tb limit in sd.c

Good day!

modern storage boxes support >2TB arrays, but READ CAPACITY may return 2TB only (with 512 bytes blocksize). According to SBC, target may return 0xffffffff as device size in order to notify initiator that device size can't fit into 32 bits and that initiator should use Long READ CAPACITY with 64bits LBA field. Following patch implements this logic. Is it possible to include patch into 2.5 ?

drivers/scsi/sd.c +33 -9
diff -uNr linux-2.5.47/drivers/scsi/sd.c linux-2.5.51/drivers/scsi/sd.c
@@ -908,11 +908,15 @@
 	struct scsi_device *sdp = sdkp->device;
 	int the_result, retries;
 	int sector_size;
+	int longrc = 0;
 
+repeat:
 	retries = 3;
 	do {
 		cmd[0] = READ_CAPACITY;
 		memset((void *) &cmd[1], 0, 9);
+		if (longrc)
+			cmd[1] = 0x02;	/* Long LBA */
 		memset((void *) buffer, 0, 8);
 
 		SRpnt->sr_cmd_len = 0;
@@ -921,7 +925,7 @@
 		SRpnt->sr_data_direction = SCSI_DATA_READ;
 
 		scsi_wait_req(SRpnt, (void *) cmd, (void *) buffer,
-			      8, SD_TIMEOUT, SD_MAX_RETRIES);
+			      longrc ? 12 : 8, SD_TIMEOUT, SD_MAX_RETRIES);
 
 		if (media_not_present(sdkp, SRpnt))
 			return;
@@ -958,14 +962,34 @@
 
 		return;
 	}
-
-	sdkp->capacity = 1 + (((sector_t)buffer[0] << 24) |
-			      (buffer[1] << 16) |
-			      (buffer[2] << 8) |
-			      buffer[3]);
-
-	sector_size = (buffer[4] << 24) |
-		(buffer[5] << 16) | (buffer[6] << 8) | buffer[7];
+	
+	if (!longrc) {
+		if (buffer[0] == 0xff && buffer[1] == 0xff &&
+			buffer[2] == 0xff && buffer[3] == 0xff) {
+			printk ("very big device. try to send long\n");
+			longrc = 1;
+			goto repeat;
+		}
+		sdkp->capacity = 1 + (((sector_t)buffer[0] << 24) |
+			(buffer[1] << 16) |
+			(buffer[2] << 8) |
+			buffer[3]);
+			
+		sector_size = (buffer[4] << 24) |
+			(buffer[5] << 16) | (buffer[6] << 8) | buffer[7];
+	} else {
+		sdkp->capacity = 1 + (((sector_t)buffer[0] << 56) |
+			((sector_t)buffer[1] << 48) |
+			((sector_t)buffer[2] << 40) |
+			((sector_t)buffer[3] << 32) |
+			((sector_t)buffer[4] << 24) |
+			((sector_t)buffer[5] << 16) |
+			((sector_t)buffer[6] << 8)  |
+			(sector_t)buffer[7]);
+			
+		sector_size = (buffer[8] << 24) |
+			(buffer[9] << 16) | (buffer[10] << 8) | buffer[11];
+	}	
 
 	if (sector_size == 0) {
 		sector_size = 512;