X-Git-Url: http://git.onelab.eu/?a=blobdiff_plain;f=drivers%2Fscsi%2Fsd.c;h=99a8df70b8924753e476c6595727c8f36a944cdd;hb=918425d07b2fe2087ee7dabf90e69a17e914649c;hp=90dd5aee01f25d7fd6fbe0d910b6a1d167a7629f;hpb=86090fcac5e27b630656fe3d963a6b80e26dac44;p=linux-2.6.git diff --git a/drivers/scsi/sd.c b/drivers/scsi/sd.c index 90dd5aee0..99a8df70b 100644 --- a/drivers/scsi/sd.c +++ b/drivers/scsi/sd.c @@ -52,7 +52,7 @@ #include #include "scsi.h" -#include "hosts.h" +#include #include #include @@ -179,7 +179,16 @@ static struct scsi_disk *scsi_disk_get(struct gendisk *disk) goto out; sdkp = scsi_disk(disk); if (!kref_get(&sdkp->kref)) - sdkp = NULL; + goto out_sdkp; + if (scsi_device_get(sdkp->device)) + goto out_put; + up(&sd_ref_sem); + return sdkp; + + out_put: + kref_put(&sdkp->kref); + out_sdkp: + sdkp = NULL; out: up(&sd_ref_sem); return sdkp; @@ -188,6 +197,7 @@ static struct scsi_disk *scsi_disk_get(struct gendisk *disk) static void scsi_disk_put(struct scsi_disk *sdkp) { down(&sd_ref_sem); + scsi_device_put(sdkp->device); kref_put(&sdkp->kref); up(&sd_ref_sem); } @@ -207,9 +217,7 @@ static int sd_init_command(struct scsi_cmnd * SCpnt) sector_t block; struct scsi_device *sdp = SCpnt->device; - timeout = SD_TIMEOUT; - if (SCpnt->device->type != TYPE_DISK) - timeout = SD_MOD_TIMEOUT; + timeout = sdp->timeout; /* * these are already setup, just copy cdb basically @@ -503,7 +511,7 @@ static int sd_release(struct inode *inode, struct file *filp) return 0; } -static int sd_hdio_getgeo(struct block_device *bdev, struct hd_geometry *loc) +static int sd_hdio_getgeo(struct block_device *bdev, struct hd_geometry __user *loc) { struct scsi_disk *sdkp = scsi_disk(bdev->bd_disk); struct scsi_device *sdp = sdkp->device; @@ -528,7 +536,7 @@ static int sd_hdio_getgeo(struct block_device *bdev, struct hd_geometry *loc) if (put_user(diskinfo[2], &loc->cylinders)) return -EFAULT; if (put_user((unsigned)get_start_sect(bdev), - (unsigned long *)&loc->start)) + (unsigned long __user *)&loc->start)) return -EFAULT; return 0; } @@ -553,6 +561,7 @@ static int sd_ioctl(struct inode * inode, struct file * filp, 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; int error; SCSI_LOG_IOCTL(1, printk("sd_ioctl: disk=%s, cmd=0x%x\n", @@ -570,7 +579,7 @@ static int sd_ioctl(struct inode * inode, struct file * filp, if (cmd == HDIO_GETGEO) { if (!arg) return -EINVAL; - return sd_hdio_getgeo(bdev, (struct hd_geometry *)arg); + return sd_hdio_getgeo(bdev, p); } /* @@ -581,13 +590,13 @@ static int sd_ioctl(struct inode * inode, struct file * filp, switch (cmd) { case SCSI_IOCTL_GET_IDLUN: case SCSI_IOCTL_GET_BUS_NUMBER: - return scsi_ioctl(sdp, cmd, (void *)arg); + return scsi_ioctl(sdp, cmd, p); default: - error = scsi_cmd_ioctl(disk, cmd, arg); + error = scsi_cmd_ioctl(disk, cmd, p); if (error != -ENOTTY) return error; } - return scsi_ioctl(sdp, cmd, (void *)arg); + return scsi_ioctl(sdp, cmd, p); } static void set_media_not_present(struct scsi_disk *sdkp) @@ -1342,16 +1351,13 @@ static int sd_probe(struct device *dev) if ((sdp->type != TYPE_DISK) && (sdp->type != TYPE_MOD)) goto out; - if ((error = scsi_device_get(sdp)) != 0) - goto out; - SCSI_LOG_HLQUEUE(3, printk("sd_attach: scsi device: <%d,%d,%d,%d>\n", sdp->host->host_no, sdp->channel, sdp->id, sdp->lun)); error = -ENOMEM; sdkp = kmalloc(sizeof(*sdkp), GFP_KERNEL); if (!sdkp) - goto out_put_sdev; + goto out; memset (sdkp, 0, sizeof(*sdkp)); kref_init(&sdkp->kref, scsi_disk_release); @@ -1382,6 +1388,13 @@ static int sd_probe(struct device *dev) sdkp->index = index; sdkp->openers = 0; + if (!sdp->timeout) { + if (sdp->type == TYPE_DISK) + sdp->timeout = SD_TIMEOUT; + else + sdp->timeout = SD_MOD_TIMEOUT; + } + devno = make_sd_dev(index, 0); gd->major = MAJOR(devno); gd->first_minor = MINOR(devno); @@ -1427,8 +1440,6 @@ out_put: put_disk(gd); out_free: kfree(sdkp); -out_put_sdev: - scsi_device_put(sdp); out: return error; } @@ -1450,7 +1461,9 @@ static int sd_remove(struct device *dev) del_gendisk(sdkp->disk); sd_shutdown(dev); - scsi_disk_put(sdkp); + down(&sd_ref_sem); + kref_put(&sdkp->kref); + up(&sd_ref_sem); return 0; } @@ -1467,7 +1480,6 @@ static int sd_remove(struct device *dev) static void scsi_disk_release(struct kref *kref) { struct scsi_disk *sdkp = to_scsi_disk(kref); - struct scsi_device *sdev = sdkp->device; struct gendisk *disk = sdkp->disk; spin_lock(&sd_index_lock); @@ -1479,8 +1491,6 @@ static void scsi_disk_release(struct kref *kref) put_disk(disk); kfree(sdkp); - - scsi_device_put(sdev); } /*