diff options
author | Ingo Molnar <mingo@elte.hu> | 2008-10-24 12:48:46 +0200 |
---|---|---|
committer | Ingo Molnar <mingo@elte.hu> | 2008-10-24 12:48:46 +0200 |
commit | 8c82a17e9c924c0e9f13e75e4c2f6bca19a4b516 (patch) | |
tree | d535f46a917e14e90deccb29ad00aac016ad18dd /drivers/scsi/sd.c | |
parent | 4ce72a2c063a7fa8e42a9435440ae3364115a58d (diff) | |
parent | 57f8f7b60db6f1ed2c6918ab9230c4623a9dbe37 (diff) |
Merge commit 'v2.6.28-rc1' into sched/urgent
Diffstat (limited to 'drivers/scsi/sd.c')
-rw-r--r-- | drivers/scsi/sd.c | 73 |
1 files changed, 33 insertions, 40 deletions
diff --git a/drivers/scsi/sd.c b/drivers/scsi/sd.c index a7b53be6336..c9e1242eaf2 100644 --- a/drivers/scsi/sd.c +++ b/drivers/scsi/sd.c @@ -384,7 +384,7 @@ static int sd_prep_fn(struct request_queue *q, struct request *rq) sector_t block = rq->sector; sector_t threshold; unsigned int this_count = rq->nr_sectors; - int ret; + int ret, host_dif; if (rq->cmd_type == REQ_TYPE_BLOCK_PC) { ret = scsi_setup_blk_pc_cmnd(sdp, rq); @@ -515,7 +515,8 @@ static int sd_prep_fn(struct request_queue *q, struct request *rq) rq->nr_sectors)); /* Set RDPROTECT/WRPROTECT if disk is formatted with DIF */ - if (scsi_host_dif_capable(sdp->host, sdkp->protection_type)) + host_dif = scsi_host_dif_capable(sdp->host, sdkp->protection_type); + if (host_dif) SCpnt->cmnd[1] = 1 << 5; else SCpnt->cmnd[1] = 0; @@ -573,8 +574,9 @@ static int sd_prep_fn(struct request_queue *q, struct request *rq) SCpnt->sdb.length = this_count * sdp->sector_size; /* If DIF or DIX is enabled, tell HBA how to handle request */ - if (sdkp->protection_type || scsi_prot_sg_count(SCpnt)) - sd_dif_op(SCpnt, sdkp->protection_type, scsi_prot_sg_count(SCpnt)); + if (host_dif || scsi_prot_sg_count(SCpnt)) + sd_dif_op(SCpnt, host_dif, scsi_prot_sg_count(SCpnt), + sdkp->protection_type); /* * We shouldn't disconnect in the middle of a sector, so with a dumb @@ -607,17 +609,15 @@ static int sd_prep_fn(struct request_queue *q, struct request *rq) * In the latter case @inode and @filp carry an abridged amount * of information as noted above. **/ -static int sd_open(struct inode *inode, struct file *filp) +static int sd_open(struct block_device *bdev, fmode_t mode) { - struct gendisk *disk = inode->i_bdev->bd_disk; - struct scsi_disk *sdkp; + struct scsi_disk *sdkp = scsi_disk_get(bdev->bd_disk); struct scsi_device *sdev; int retval; - if (!(sdkp = scsi_disk_get(disk))) + if (!sdkp) return -ENXIO; - SCSI_LOG_HLQUEUE(3, sd_printk(KERN_INFO, sdkp, "sd_open\n")); sdev = sdkp->device; @@ -631,14 +631,13 @@ static int sd_open(struct inode *inode, struct file *filp) goto error_out; if (sdev->removable || sdkp->write_prot) - check_disk_change(inode->i_bdev); + check_disk_change(bdev); /* * If the drive is empty, just let the open fail. */ retval = -ENOMEDIUM; - if (sdev->removable && !sdkp->media_present && - !(filp->f_flags & O_NDELAY)) + if (sdev->removable && !sdkp->media_present && !(mode & FMODE_NDELAY)) goto error_out; /* @@ -646,7 +645,7 @@ static int sd_open(struct inode *inode, struct file *filp) * if the user expects to be able to write to the thing. */ retval = -EROFS; - if (sdkp->write_prot && (filp->f_mode & FMODE_WRITE)) + if (sdkp->write_prot && (mode & FMODE_WRITE)) goto error_out; /* @@ -682,9 +681,8 @@ error_out: * Note: may block (uninterruptible) if error recovery is underway * on this disk. **/ -static int sd_release(struct inode *inode, struct file *filp) +static int sd_release(struct gendisk *disk, fmode_t mode) { - struct gendisk *disk = inode->i_bdev->bd_disk; struct scsi_disk *sdkp = scsi_disk(disk); struct scsi_device *sdev = sdkp->device; @@ -741,10 +739,9 @@ static int sd_getgeo(struct block_device *bdev, struct hd_geometry *geo) * Note: most ioctls are forward onto the block subsystem or further * down in the scsi subsystem. **/ -static int sd_ioctl(struct inode * inode, struct file * filp, +static int sd_ioctl(struct block_device *bdev, fmode_t mode, unsigned int cmd, unsigned long arg) { - struct block_device *bdev = inode->i_bdev; struct gendisk *disk = bdev->bd_disk; struct scsi_device *sdp = scsi_disk(disk)->device; void __user *p = (void __user *)arg; @@ -759,7 +756,8 @@ static int sd_ioctl(struct inode * inode, struct file * filp, * may try and take the device offline, in which case all further * access to the device is prohibited. */ - error = scsi_nonblockable_ioctl(sdp, cmd, p, filp); + error = scsi_nonblockable_ioctl(sdp, cmd, p, + (mode & FMODE_NDELAY_NOW) != 0); if (!scsi_block_when_processing_errors(sdp) || !error) return error; @@ -773,7 +771,7 @@ static int sd_ioctl(struct inode * inode, struct file * filp, case SCSI_IOCTL_GET_BUS_NUMBER: return scsi_ioctl(sdp, cmd, p); default: - error = scsi_cmd_ioctl(filp, disk->queue, disk, cmd, p); + error = scsi_cmd_ioctl(disk->queue, disk, mode, cmd, p); if (error != -ENOTTY) return error; } @@ -926,11 +924,10 @@ static void sd_rescan(struct device *dev) * This gets directly called from VFS. When the ioctl * is not recognized we go back to the other translation paths. */ -static long sd_compat_ioctl(struct file *file, unsigned int cmd, unsigned long arg) +static int sd_compat_ioctl(struct block_device *bdev, fmode_t mode, + unsigned int cmd, unsigned long arg) { - struct block_device *bdev = file->f_path.dentry->d_inode->i_bdev; - struct gendisk *disk = bdev->bd_disk; - struct scsi_device *sdev = scsi_disk(disk)->device; + struct scsi_device *sdev = scsi_disk(bdev->bd_disk)->device; /* * If we are in the middle of error recovery, don't let anyone @@ -960,7 +957,7 @@ static struct block_device_operations sd_fops = { .owner = THIS_MODULE, .open = sd_open, .release = sd_release, - .ioctl = sd_ioctl, + .locked_ioctl = sd_ioctl, .getgeo = sd_getgeo, #ifdef CONFIG_COMPAT .compat_ioctl = sd_compat_ioctl, @@ -1052,7 +1049,6 @@ static int sd_done(struct scsi_cmnd *SCpnt) good_bytes = sd_completed_bytes(SCpnt); break; case RECOVERED_ERROR: - case NO_SENSE: /* Inform the user, but make sure that it's not treated * as a hard error. */ @@ -1061,6 +1057,15 @@ static int sd_done(struct scsi_cmnd *SCpnt) memset(SCpnt->sense_buffer, 0, SCSI_SENSE_BUFFERSIZE); good_bytes = scsi_bufflen(SCpnt); break; + case NO_SENSE: + /* This indicates a false check condition, so ignore it. An + * unknown amount of data was transferred so treat it as an + * error. + */ + scsi_print_sense("sd", SCpnt); + SCpnt->result = 0; + memset(SCpnt->sense_buffer, 0, SCSI_SENSE_BUFFERSIZE); + break; case ABORTED_COMMAND: if (sshdr.asc == 0x10) { /* DIF: Disk detected corruption */ scsi_print_result(SCpnt); @@ -1074,15 +1079,6 @@ static int sd_done(struct scsi_cmnd *SCpnt) scsi_print_sense("sd", SCpnt); good_bytes = sd_completed_bytes(SCpnt); } - if (!scsi_device_protection(SCpnt->device) && - SCpnt->device->use_10_for_rw && - (SCpnt->cmnd[0] == READ_10 || - SCpnt->cmnd[0] == WRITE_10)) - SCpnt->device->use_10_for_rw = 0; - if (SCpnt->device->use_10_for_ms && - (SCpnt->cmnd[0] == MODE_SENSE_10 || - SCpnt->cmnd[0] == MODE_SELECT_10)) - SCpnt->device->use_10_for_ms = 0; break; default: break; @@ -1252,14 +1248,12 @@ void sd_read_protection_type(struct scsi_disk *sdkp, unsigned char *buffer) else type = ((buffer[12] >> 1) & 7) + 1; /* P_TYPE 0 = Type 1 */ + sdkp->protection_type = type; + switch (type) { case SD_DIF_TYPE0_PROTECTION: - sdkp->protection_type = 0; - break; - case SD_DIF_TYPE1_PROTECTION: case SD_DIF_TYPE3_PROTECTION: - sdkp->protection_type = type; break; case SD_DIF_TYPE2_PROTECTION: @@ -1277,7 +1271,6 @@ void sd_read_protection_type(struct scsi_disk *sdkp, unsigned char *buffer) return; disable: - sdkp->protection_type = 0; sdkp->capacity = 0; } @@ -1438,7 +1431,7 @@ got_data: { char cap_str_2[10], cap_str_10[10]; - u64 sz = sdkp->capacity << ffz(~sector_size); + u64 sz = (u64)sdkp->capacity << ilog2(sector_size); string_get_size(sz, STRING_UNITS_2, cap_str_2, sizeof(cap_str_2)); |