X-Git-Url: http://ftp.safe.ca/?a=blobdiff_plain;f=drivers%2Fscsi%2Fst.c;h=71952703125a634a05869e1c6d44fe929a02f1ba;hb=691b4773aa556d0975dbc25c93e6c8b839dad325;hp=b5218fc0ac8611eea4d68fa600573ca851f27747;hpb=d6e05edc59ecd79e8badf440c0d295a979bdfa3e;p=safe%2Fjmp%2Flinux-2.6 diff --git a/drivers/scsi/st.c b/drivers/scsi/st.c index b5218fc..7195270 100644 --- a/drivers/scsi/st.c +++ b/drivers/scsi/st.c @@ -9,7 +9,7 @@ Steve Hirsch, Andreas Koppenh"ofer, Michael Leodolter, Eyal Lebedinsky, Michael Schaefer, J"org Weule, and Eric Youngdale. - Copyright 1992 - 2005 Kai Makisara + Copyright 1992 - 2008 Kai Makisara email Kai.Makisara@kolumbus.fi Some small formal changes - aeb, 950809 @@ -17,7 +17,7 @@ Last modified: 18-JAN-1998 Richard Gooch Devfs support */ -static const char *verstr = "20050830"; +static const char *verstr = "20080117"; #include @@ -89,6 +89,7 @@ MODULE_AUTHOR("Kai Makisara"); MODULE_DESCRIPTION("SCSI tape (st) driver"); MODULE_LICENSE("GPL"); MODULE_ALIAS_CHARDEV_MAJOR(SCSI_TAPE_MAJOR); +MODULE_ALIAS_SCSI_DEVICE(TYPE_TAPE); /* Set 'perm' (4th argument) to 0 to disable module_param's definition * of sysfs parameters (which module_param doesn't yet support). @@ -195,9 +196,9 @@ static int sgl_unmap_user_pages(struct scatterlist *, const unsigned int, int); static int st_probe(struct device *); static int st_remove(struct device *); -static void do_create_driverfs_files(void); -static void do_remove_driverfs_files(void); -static void do_create_class_files(struct scsi_tape *, int, int); +static int do_create_sysfs_files(void); +static void do_remove_sysfs_files(void); +static int do_create_class_files(struct scsi_tape *, int, int); static struct scsi_driver st_template = { .owner = THIS_MODULE, @@ -368,7 +369,7 @@ static int st_chk_result(struct scsi_tape *STp, struct st_request * SRpnt) SRpnt->cmd[0], SRpnt->cmd[1], SRpnt->cmd[2], SRpnt->cmd[3], SRpnt->cmd[4], SRpnt->cmd[5]); if (cmdstatp->have_sense) - __scsi_print_sense("st", SRpnt->sense, SCSI_SENSE_BUFFERSIZE); + __scsi_print_sense(name, SRpnt->sense, SCSI_SENSE_BUFFERSIZE); } ) /* end DEB */ if (!debugging) { /* Abnormal conditions for tape */ if (!cmdstatp->have_sense) @@ -384,9 +385,8 @@ static int st_chk_result(struct scsi_tape *STp, struct st_request * SRpnt) scode != VOLUME_OVERFLOW && SRpnt->cmd[0] != MODE_SENSE && SRpnt->cmd[0] != TEST_UNIT_READY) { - printk(KERN_WARNING "%s: Error with sense data: ", name); - __scsi_print_sense("st", SRpnt->sense, - SCSI_SENSE_BUFFERSIZE); + + __scsi_print_sense(name, SRpnt->sense, SCSI_SENSE_BUFFERSIZE); } } @@ -923,7 +923,7 @@ static int check_tape(struct scsi_tape *STp, struct file *filp) struct st_modedef *STm; struct st_partstat *STps; char *name = tape_name(STp); - struct inode *inode = filp->f_dentry->d_inode; + struct inode *inode = filp->f_path.dentry->d_inode; int mode = TAPE_MODE(inode); STp->ready = ST_READY; @@ -1000,7 +1000,7 @@ static int check_tape(struct scsi_tape *STp, struct file *filp) STp->min_block = ((STp->buffer)->b_data[4] << 8) | (STp->buffer)->b_data[5]; if ( DEB( debugging || ) !STp->inited) - printk(KERN_WARNING + printk(KERN_INFO "%s: Block limits %d - %d bytes.\n", name, STp->min_block, STp->max_block); } else { @@ -1169,6 +1169,7 @@ static int st_open(struct inode *inode, struct file *filp) STps = &(STp->ps[i]); STps->rw = ST_IDLE; } + STp->try_dio_now = STp->try_dio; STp->recover_count = 0; DEB( STp->nbr_waits = STp->nbr_finished = 0; STp->nbr_requests = STp->nbr_dio = STp->nbr_pages = STp->nbr_combinable = 0; ) @@ -1178,7 +1179,10 @@ static int st_open(struct inode *inode, struct file *filp) goto err_out; if ((filp->f_flags & O_NONBLOCK) == 0 && retval != CHKRES_READY) { - retval = (-EIO); + if (STp->ready == NO_TAPE) + retval = (-ENOMEDIUM); + else + retval = (-EIO); goto err_out; } return 0; @@ -1222,7 +1226,7 @@ static int st_flush(struct file *filp, fl_owner_t id) } DEBC( if (STp->nbr_requests) - printk(KERN_WARNING "%s: Number of r/w requests %d, dio used in %d, pages %d (%d).\n", + printk(KERN_DEBUG "%s: Number of r/w requests %d, dio used in %d, pages %d (%d).\n", name, STp->nbr_requests, STp->nbr_dio, STp->nbr_pages, STp->nbr_combinable)); if (STps->rw == ST_WRITING && !STp->pos_unknown) { @@ -1398,9 +1402,9 @@ static int setup_buffering(struct scsi_tape *STp, const char __user *buf, struct st_buffer *STbp = STp->buffer; if (is_read) - i = STp->try_dio && try_rdio; + i = STp->try_dio_now && try_rdio; else - i = STp->try_dio && try_wdio; + i = STp->try_dio_now && try_wdio; if (i && ((unsigned long)buf & queue_dma_alignment( STp->device->request_queue)) == 0) { @@ -1481,7 +1485,7 @@ st_write(struct file *filp, const char __user *buf, size_t count, loff_t * ppos) struct st_buffer *STbp; char *name = tape_name(STp); - if (down_interruptible(&STp->lock)) + if (mutex_lock_interruptible(&STp->lock)) return -ERESTARTSYS; retval = rw_checks(STp, filp, count); @@ -1597,7 +1601,7 @@ st_write(struct file *filp, const char __user *buf, size_t count, loff_t * ppos) STm->do_async_writes && STps->eof < ST_EOM_OK; if (STp->block_size != 0 && STm->do_buffer_writes && - !(STp->try_dio && try_wdio) && STps->eof < ST_EOM_OK && + !(STp->try_dio_now && try_wdio) && STps->eof < ST_EOM_OK && STbp->buffer_bytes < STbp->buffer_size) { STp->dirty = 1; /* Don't write a buffer that is not full enough. */ @@ -1732,7 +1736,7 @@ st_write(struct file *filp, const char __user *buf, size_t count, loff_t * ppos) if (SRpnt != NULL) st_release_request(SRpnt); release_buffering(STp, 0); - up(&STp->lock); + mutex_unlock(&STp->lock); return retval; } @@ -1767,7 +1771,7 @@ static long read_tape(struct scsi_tape *STp, long count, if (STp->block_size == 0) blks = bytes = count; else { - if (!(STp->try_dio && try_rdio) && STm->do_read_ahead) { + if (!(STp->try_dio_now && try_rdio) && STm->do_read_ahead) { blks = (STp->buffer)->buffer_blocks; bytes = blks * STp->block_size; } else { @@ -1938,7 +1942,7 @@ st_read(struct file *filp, char __user *buf, size_t count, loff_t * ppos) struct st_buffer *STbp = STp->buffer; DEB( char *name = tape_name(STp); ) - if (down_interruptible(&STp->lock)) + if (mutex_lock_interruptible(&STp->lock)) return -ERESTARTSYS; retval = rw_checks(STp, filp, count); @@ -1946,10 +1950,12 @@ st_read(struct file *filp, char __user *buf, size_t count, loff_t * ppos) goto out; STm = &(STp->modes[STp->current_mode]); - if (!(STm->do_read_ahead) && STp->block_size != 0 && - (count % STp->block_size) != 0) { - retval = (-EINVAL); /* Read must be integral number of blocks */ - goto out; + if (STp->block_size != 0 && (count % STp->block_size) != 0) { + if (!STm->do_read_ahead) { + retval = (-EINVAL); /* Read must be integral number of blocks */ + goto out; + } + STp->try_dio_now = 0; /* Direct i/o can't handle split blocks */ } STps = &(STp->ps[STp->partition]); @@ -2063,7 +2069,7 @@ st_read(struct file *filp, char __user *buf, size_t count, loff_t * ppos) release_buffering(STp, 1); STbp->buffer_bytes = 0; } - up(&STp->lock); + mutex_unlock(&STp->lock); return retval; } @@ -2814,15 +2820,18 @@ static int st_int_ioctl(struct scsi_tape *STp, unsigned int cmd_in, unsigned lon if (cmd_in == MTWEOF && cmdstatp->have_sense && - (cmdstatp->flags & SENSE_EOM) && - (cmdstatp->sense_hdr.sense_key == NO_SENSE || - cmdstatp->sense_hdr.sense_key == RECOVERED_ERROR) && - undone == 0) { - ioctl_result = 0; /* EOF written successfully at EOM */ - if (fileno >= 0) - fileno++; + (cmdstatp->flags & SENSE_EOM)) { + if (cmdstatp->sense_hdr.sense_key == NO_SENSE || + cmdstatp->sense_hdr.sense_key == RECOVERED_ERROR) { + ioctl_result = 0; /* EOF(s) written successfully at EOM */ + STps->eof = ST_NOEOF; + } else { /* Writing EOF(s) failed */ + if (fileno >= 0) + fileno -= undone; + if (undone < arg) + STps->eof = ST_NOEOF; + } STps->drv_file = fileno; - STps->eof = ST_NOEOF; } else if ((cmd_in == MTFSF) || (cmd_in == MTFSFM)) { if (fileno >= 0) STps->drv_file = fileno - undone; @@ -3205,8 +3214,7 @@ static int partition_tape(struct scsi_tape *STp, int size) /* The ioctl command */ -static int st_ioctl(struct inode *inode, struct file *file, - unsigned int cmd_in, unsigned long arg) +static long st_ioctl(struct file *file, unsigned int cmd_in, unsigned long arg) { int i, cmd_nr, cmd_type, bt; int retval = 0; @@ -3217,7 +3225,7 @@ static int st_ioctl(struct inode *inode, struct file *file, char *name = tape_name(STp); void __user *p = (void __user *)arg; - if (down_interruptible(&STp->lock)) + if (mutex_lock_interruptible(&STp->lock)) return -ERESTARTSYS; DEB( @@ -3528,7 +3536,7 @@ static int st_ioctl(struct inode *inode, struct file *file, retval = (-EFAULT); goto out; } - up(&STp->lock); + mutex_unlock(&STp->lock); switch (cmd_in) { case SCSI_IOCTL_GET_IDLUN: case SCSI_IOCTL_GET_BUS_NUMBER: @@ -3540,7 +3548,8 @@ static int st_ioctl(struct inode *inode, struct file *file, !capable(CAP_SYS_RAWIO)) i = -EPERM; else - i = scsi_cmd_ioctl(file, STp->disk, cmd_in, p); + i = scsi_cmd_ioctl(file, STp->disk->queue, + STp->disk, cmd_in, p); if (i != -ENOTTY) return i; break; @@ -3553,7 +3562,7 @@ static int st_ioctl(struct inode *inode, struct file *file, return retval; out: - up(&STp->lock); + mutex_unlock(&STp->lock); return retval; } @@ -3599,9 +3608,9 @@ static struct st_buffer * tb->use_sg = max_sg; tb->frp = (struct st_buf_fragment *)(&(tb->sg[0]) + max_sg); - tb->in_use = 1; tb->dma = need_dma; tb->buffer_size = got; + sg_init_table(tb->sg, max_sg); return tb; } @@ -3788,13 +3797,11 @@ static void buf_to_sg(struct st_buffer *STbp, unsigned int length) sg = &(STbp->sg[0]); frp = STbp->frp; for (i=count=0; count < length; i++) { - sg[i].page = frp[i].page; if (length - count > frp[i].length) - sg[i].length = frp[i].length; + sg_set_page(&sg[i], frp[i].page, frp[i].length, 0); else - sg[i].length = length - count; + sg_set_page(&sg[i], frp[i].page, length - count, 0); count += sg[i].length; - sg[i].offset = 0; } STbp->sg_segs = i; STbp->frp_sg_current = length; @@ -3857,12 +3864,12 @@ __setup("st=", st_setup); #endif -static struct file_operations st_fops = +static const struct file_operations st_fops = { .owner = THIS_MODULE, .read = st_read, .write = st_write, - .ioctl = st_ioctl, + .unlocked_ioctl = st_ioctl, #ifdef CONFIG_COMPAT .compat_ioctl = st_compat_ioctl, #endif @@ -4020,7 +4027,7 @@ static int st_probe(struct device *dev) tpnt->density_changed = tpnt->compression_changed = tpnt->blksize_changed = 0; - init_MUTEX(&tpnt->lock); + mutex_init(&tpnt->lock); st_nr_dev++; write_unlock(&st_dev_arr_lock); @@ -4050,14 +4057,16 @@ static int st_probe(struct device *dev) STm->cdevs[j] = cdev; } - do_create_class_files(tpnt, dev_num, mode); + error = do_create_class_files(tpnt, dev_num, mode); + if (error) + goto out_free_tape; } - sdev_printk(KERN_WARNING, SDp, + sdev_printk(KERN_NOTICE, SDp, "Attached scsi tape %s\n", tape_name(tpnt)); - printk(KERN_WARNING "%s: try direct i/o: %s (alignment %d B)\n", - tape_name(tpnt), tpnt->try_dio ? "yes" : "no", - queue_dma_alignment(SDp->request_queue) + 1); + sdev_printk(KERN_INFO, SDp, "%s: try direct i/o: %s (alignment %d B)\n", + tape_name(tpnt), tpnt->try_dio ? "yes" : "no", + queue_dma_alignment(SDp->request_queue) + 1); return 0; @@ -4159,37 +4168,50 @@ static void scsi_tape_release(struct kref *kref) static int __init init_st(void) { + int err; + validate_options(); - printk(KERN_INFO - "st: Version %s, fixed bufsize %d, s/g segs %d\n", + printk(KERN_INFO "st: Version %s, fixed bufsize %d, s/g segs %d\n", verstr, st_fixed_buffer_size, st_max_sg_segs); st_sysfs_class = class_create(THIS_MODULE, "scsi_tape"); if (IS_ERR(st_sysfs_class)) { - st_sysfs_class = NULL; printk(KERN_ERR "Unable create sysfs class for SCSI tapes\n"); - return 1; + return PTR_ERR(st_sysfs_class); } - if (!register_chrdev_region(MKDEV(SCSI_TAPE_MAJOR, 0), - ST_MAX_TAPE_ENTRIES, "st")) { - if (scsi_register_driver(&st_template.gendrv) == 0) { - do_create_driverfs_files(); - return 0; - } - unregister_chrdev_region(MKDEV(SCSI_TAPE_MAJOR, 0), - ST_MAX_TAPE_ENTRIES); + err = register_chrdev_region(MKDEV(SCSI_TAPE_MAJOR, 0), + ST_MAX_TAPE_ENTRIES, "st"); + if (err) { + printk(KERN_ERR "Unable to get major %d for SCSI tapes\n", + SCSI_TAPE_MAJOR); + goto err_class; } - class_destroy(st_sysfs_class); - printk(KERN_ERR "Unable to get major %d for SCSI tapes\n", SCSI_TAPE_MAJOR); - return 1; + err = scsi_register_driver(&st_template.gendrv); + if (err) + goto err_chrdev; + + err = do_create_sysfs_files(); + if (err) + goto err_scsidrv; + + return 0; + +err_scsidrv: + scsi_unregister_driver(&st_template.gendrv); +err_chrdev: + unregister_chrdev_region(MKDEV(SCSI_TAPE_MAJOR, 0), + ST_MAX_TAPE_ENTRIES); +err_class: + class_destroy(st_sysfs_class); + return err; } static void __exit exit_st(void) { - do_remove_driverfs_files(); + do_remove_sysfs_files(); scsi_unregister_driver(&st_template.gendrv); unregister_chrdev_region(MKDEV(SCSI_TAPE_MAJOR, 0), ST_MAX_TAPE_ENTRIES); @@ -4227,24 +4249,43 @@ static ssize_t st_version_show(struct device_driver *ddd, char *buf) } static DRIVER_ATTR(version, S_IRUGO, st_version_show, NULL); -static void do_create_driverfs_files(void) +static int do_create_sysfs_files(void) { - struct device_driver *driverfs = &st_template.gendrv; + struct device_driver *sysfs = &st_template.gendrv; + int err; + + err = driver_create_file(sysfs, &driver_attr_try_direct_io); + if (err) + return err; + err = driver_create_file(sysfs, &driver_attr_fixed_buffer_size); + if (err) + goto err_try_direct_io; + err = driver_create_file(sysfs, &driver_attr_max_sg_segs); + if (err) + goto err_attr_fixed_buf; + err = driver_create_file(sysfs, &driver_attr_version); + if (err) + goto err_attr_max_sg; + + return 0; - driver_create_file(driverfs, &driver_attr_try_direct_io); - driver_create_file(driverfs, &driver_attr_fixed_buffer_size); - driver_create_file(driverfs, &driver_attr_max_sg_segs); - driver_create_file(driverfs, &driver_attr_version); +err_attr_max_sg: + driver_remove_file(sysfs, &driver_attr_max_sg_segs); +err_attr_fixed_buf: + driver_remove_file(sysfs, &driver_attr_fixed_buffer_size); +err_try_direct_io: + driver_remove_file(sysfs, &driver_attr_try_direct_io); + return err; } -static void do_remove_driverfs_files(void) +static void do_remove_sysfs_files(void) { - struct device_driver *driverfs = &st_template.gendrv; + struct device_driver *sysfs = &st_template.gendrv; - driver_remove_file(driverfs, &driver_attr_version); - driver_remove_file(driverfs, &driver_attr_max_sg_segs); - driver_remove_file(driverfs, &driver_attr_fixed_buffer_size); - driver_remove_file(driverfs, &driver_attr_try_direct_io); + driver_remove_file(sysfs, &driver_attr_version); + driver_remove_file(sysfs, &driver_attr_max_sg_segs); + driver_remove_file(sysfs, &driver_attr_fixed_buffer_size); + driver_remove_file(sysfs, &driver_attr_try_direct_io); } @@ -4295,15 +4336,12 @@ static ssize_t st_defcompression_show(struct class_device *class_dev, char *buf) CLASS_DEVICE_ATTR(default_compression, S_IRUGO, st_defcompression_show, NULL); -static void do_create_class_files(struct scsi_tape *STp, int dev_num, int mode) +static int do_create_class_files(struct scsi_tape *STp, int dev_num, int mode) { int i, rew, error; char name[10]; struct class_device *st_class_member; - if (!st_sysfs_class) - return; - for (rew=0; rew < 2; rew++) { /* Make sure that the minor numbers corresponding to the four first modes always get the same names */ @@ -4318,18 +4356,24 @@ static void do_create_class_files(struct scsi_tape *STp, int dev_num, int mode) if (IS_ERR(st_class_member)) { printk(KERN_WARNING "st%d: class_device_create failed\n", dev_num); + error = PTR_ERR(st_class_member); goto out; } class_set_devdata(st_class_member, &STp->modes[mode]); - class_device_create_file(st_class_member, - &class_device_attr_defined); - class_device_create_file(st_class_member, - &class_device_attr_default_blksize); - class_device_create_file(st_class_member, - &class_device_attr_default_density); - class_device_create_file(st_class_member, - &class_device_attr_default_compression); + error = class_device_create_file(st_class_member, + &class_device_attr_defined); + if (error) goto out; + error = class_device_create_file(st_class_member, + &class_device_attr_default_blksize); + if (error) goto out; + error = class_device_create_file(st_class_member, + &class_device_attr_default_density); + if (error) goto out; + error = class_device_create_file(st_class_member, + &class_device_attr_default_compression); + if (error) goto out; + if (mode == 0 && rew == 0) { error = sysfs_create_link(&STp->device->sdev_gendev.kobj, &st_class_member->kobj, @@ -4338,11 +4382,15 @@ static void do_create_class_files(struct scsi_tape *STp, int dev_num, int mode) printk(KERN_ERR "st%d: Can't create sysfs link from SCSI device.\n", dev_num); + goto out; } } } - out: - return; + + return 0; + +out: + return error; } /* The following functions may be useful for a larger audience. */ @@ -4396,15 +4444,13 @@ static int sgl_map_user_pages(struct scatterlist *sgl, const unsigned int max_pa } /* Populate the scatter/gather list */ - sgl[0].page = pages[0]; - sgl[0].offset = uaddr & ~PAGE_MASK; + sg_set_page(&sgl[0], pages[0], 0, uaddr & ~PAGE_MASK); if (nr_pages > 1) { sgl[0].length = PAGE_SIZE - sgl[0].offset; count -= sgl[0].length; for (i=1; i < nr_pages ; i++) { - sgl[i].offset = 0; - sgl[i].page = pages[i]; - sgl[i].length = count < PAGE_SIZE ? count : PAGE_SIZE; + sg_set_page(&sgl[i], pages[i], + count < PAGE_SIZE ? count : PAGE_SIZE, 0);; count -= PAGE_SIZE; } } @@ -4433,7 +4479,7 @@ static int sgl_unmap_user_pages(struct scatterlist *sgl, const unsigned int nr_p int i; for (i=0; i < nr_pages; i++) { - struct page *page = sgl[i].page; + struct page *page = sg_page(&sgl[i]); if (dirtied) SetPageDirty(page);