--- zzzz-none-000/linux-3.10.107/drivers/scsi/st.c 2017-06-27 09:49:32.000000000 +0000 +++ scorpion-7490-727/linux-3.10.107/drivers/scsi/st.c 2021-02-04 17:41:59.000000000 +0000 @@ -56,13 +56,14 @@ /* The driver prints some debugging information on the console if DEBUG is defined and non-zero. */ -#define DEBUG 0 +#define DEBUG 1 +#define NO_DEBUG 0 +#define ST_DEB_MSG KERN_NOTICE #if DEBUG /* The message level for the debug messages is currently set to KERN_NOTICE so that people can easily see the messages. Later when the debugging messages in the drivers are more widely classified, this may be changed to KERN_DEBUG. */ -#define ST_DEB_MSG KERN_NOTICE #define DEB(a) a #define DEBC(a) if (debugging) { a ; } #else @@ -80,9 +81,11 @@ static int try_direct_io = TRY_DIRECT_IO; static int try_rdio = 1; static int try_wdio = 1; +static int debug_flag; static struct class st_sysfs_class; -static struct device_attribute st_dev_attrs[]; +static const struct attribute_group *st_dev_groups[]; +static const struct attribute_group *st_drv_groups[]; MODULE_AUTHOR("Kai Makisara"); MODULE_DESCRIPTION("SCSI tape (st) driver"); @@ -100,6 +103,9 @@ MODULE_PARM_DESC(max_sg_segs, "Maximum number of scatter/gather segments to use (256)"); module_param_named(try_direct_io, try_direct_io, int, 0); MODULE_PARM_DESC(try_direct_io, "Try direct I/O between user buffer and tape drive (1)"); +module_param_named(debug_flag, debug_flag, int, 0); +MODULE_PARM_DESC(debug_flag, "Enable DEBUG, same as setting debugging=1"); + /* Extra parameters for testing */ module_param_named(try_rdio, try_rdio, int, 0); @@ -124,6 +130,9 @@ }, { "try_direct_io", &try_direct_io + }, + { + "debug_flag", &debug_flag } }; #endif @@ -190,15 +199,13 @@ static int st_probe(struct device *); static int st_remove(struct device *); -static int do_create_sysfs_files(void); -static void do_remove_sysfs_files(void); - static struct scsi_driver st_template = { - .owner = THIS_MODULE, .gendrv = { .name = "st", + .owner = THIS_MODULE, .probe = st_probe, .remove = st_remove, + .groups = st_drv_groups, }, }; @@ -305,6 +312,14 @@ return tape->disk->disk_name; } +#define st_printk(prefix, t, fmt, a...) \ + sdev_prefix_printk(prefix, (t)->device, tape_name(t), fmt, ##a) +#ifdef DEBUG +#define DEBC_printk(t, fmt, a...) \ + if (debugging) { st_printk(ST_DEB_MSG, t, fmt, ##a ); } +#else +#define DEBC_printk(t, fmt, a...) +#endif static void st_analyze_sense(struct st_request *SRpnt, struct st_cmdstatus *s) { @@ -358,21 +373,21 @@ else scode = 0; - DEB( - if (debugging) { - printk(ST_DEB_MSG "%s: Error: %x, cmd: %x %x %x %x %x %x\n", - name, result, - SRpnt->cmd[0], SRpnt->cmd[1], SRpnt->cmd[2], - SRpnt->cmd[3], SRpnt->cmd[4], SRpnt->cmd[5]); + DEB( + if (debugging) { + st_printk(ST_DEB_MSG, STp, + "Error: %x, cmd: %x %x %x %x %x %x\n", result, + 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(name, SRpnt->sense, SCSI_SENSE_BUFFERSIZE); + __scsi_print_sense(STp->device, name, + SRpnt->sense, SCSI_SENSE_BUFFERSIZE); } ) /* end DEB */ if (!debugging) { /* Abnormal conditions for tape */ if (!cmdstatp->have_sense) - printk(KERN_WARNING - "%s: Error %x (driver bt 0x%x, host bt 0x%x).\n", - name, result, driver_byte(result), - host_byte(result)); + st_printk(KERN_WARNING, STp, + "Error %x (driver bt 0x%x, host bt 0x%x).\n", + result, driver_byte(result), host_byte(result)); else if (cmdstatp->have_sense && scode != NO_SENSE && scode != RECOVERED_ERROR && @@ -382,7 +397,8 @@ SRpnt->cmd[0] != MODE_SENSE && SRpnt->cmd[0] != TEST_UNIT_READY) { - __scsi_print_sense(name, SRpnt->sense, SCSI_SENSE_BUFFERSIZE); + __scsi_print_sense(STp->device, name, + SRpnt->sense, SCSI_SENSE_BUFFERSIZE); } } @@ -411,7 +427,7 @@ STp->recover_count++; STp->recover_reg++; - DEB( + DEB( if (debugging) { if (SRpnt->cmd[0] == READ_6) stp = "read"; @@ -419,8 +435,9 @@ stp = "write"; else stp = "ioctl"; - printk(ST_DEB_MSG "%s: Recovered %s error (%d).\n", name, stp, - STp->recover_count); + st_printk(ST_DEB_MSG, STp, + "Recovered %s error (%d).\n", + stp, STp->recover_count); } ) /* end DEB */ if (cmdstatp->flags == 0) @@ -437,8 +454,8 @@ if (streq) streq->stp = stp; else { - DEBC(printk(KERN_ERR "%s: Can't get SCSI request.\n", - tape_name(stp));); + st_printk(KERN_ERR, stp, + "Can't get SCSI request.\n"); if (signal_pending(current)) stp->buffer->syscall_result = -EINTR; else @@ -453,6 +470,47 @@ kfree(streq); } +static void st_do_stats(struct scsi_tape *STp, struct request *req) +{ + ktime_t now; + + now = ktime_get(); + if (req->cmd[0] == WRITE_6) { + now = ktime_sub(now, STp->stats->write_time); + atomic64_add(ktime_to_ns(now), &STp->stats->tot_write_time); + atomic64_add(ktime_to_ns(now), &STp->stats->tot_io_time); + atomic64_inc(&STp->stats->write_cnt); + if (req->errors) { + atomic64_add(atomic_read(&STp->stats->last_write_size) + - STp->buffer->cmdstat.residual, + &STp->stats->write_byte_cnt); + if (STp->buffer->cmdstat.residual > 0) + atomic64_inc(&STp->stats->resid_cnt); + } else + atomic64_add(atomic_read(&STp->stats->last_write_size), + &STp->stats->write_byte_cnt); + } else if (req->cmd[0] == READ_6) { + now = ktime_sub(now, STp->stats->read_time); + atomic64_add(ktime_to_ns(now), &STp->stats->tot_read_time); + atomic64_add(ktime_to_ns(now), &STp->stats->tot_io_time); + atomic64_inc(&STp->stats->read_cnt); + if (req->errors) { + atomic64_add(atomic_read(&STp->stats->last_read_size) + - STp->buffer->cmdstat.residual, + &STp->stats->read_byte_cnt); + if (STp->buffer->cmdstat.residual > 0) + atomic64_inc(&STp->stats->resid_cnt); + } else + atomic64_add(atomic_read(&STp->stats->last_read_size), + &STp->stats->read_byte_cnt); + } else { + now = ktime_sub(now, STp->stats->other_time); + atomic64_add(ktime_to_ns(now), &STp->stats->tot_io_time); + atomic64_inc(&STp->stats->other_cnt); + } + atomic64_dec(&STp->stats->in_flight); +} + static void st_scsi_execute_end(struct request *req, int uptodate) { struct st_request *SRpnt = req->end_io_data; @@ -462,6 +520,8 @@ STp->buffer->cmdstat.midlevel_result = SRpnt->result = req->errors; STp->buffer->cmdstat.residual = req->resid_len; + st_do_stats(STp, req); + tmp = SRpnt->bio; if (SRpnt->waiting) complete(SRpnt->waiting); @@ -478,13 +538,14 @@ struct rq_map_data *mdata = &SRpnt->stp->buffer->map_data; int err = 0; int write = (data_direction == DMA_TO_DEVICE); + struct scsi_tape *STp = SRpnt->stp; req = blk_get_request(SRpnt->stp->device->request_queue, write, GFP_KERNEL); - if (!req) + if (IS_ERR(req)) return DRIVER_ERROR << 24; - req->cmd_type = REQ_TYPE_BLOCK_PC; + blk_rq_set_block_pc(req); req->cmd_flags |= REQ_QUIET; mdata->null_mapped = 1; @@ -498,6 +559,17 @@ } } + atomic64_inc(&STp->stats->in_flight); + if (cmd[0] == WRITE_6) { + atomic_set(&STp->stats->last_write_size, bufflen); + STp->stats->write_time = ktime_get(); + } else if (cmd[0] == READ_6) { + atomic_set(&STp->stats->last_read_size, bufflen); + STp->stats->read_time = ktime_get(); + } else { + STp->stats->other_time = ktime_get(); + } + SRpnt->bio = req->bio; req->cmd_len = COMMAND_SIZE(cmd[0]); memset(req->cmd, 0, BLK_MAX_CDB); @@ -525,8 +597,8 @@ /* if async, make sure there's no command outstanding */ if (!do_wait && ((STp->buffer)->last_SRpnt)) { - printk(KERN_ERR "%s: Async command already active.\n", - tape_name(STp)); + st_printk(KERN_ERR, STp, + "Async command already active.\n"); if (signal_pending(current)) (STp->buffer)->syscall_result = (-EINTR); else @@ -597,12 +669,12 @@ if (!STbuffer->writing) return 0; - DEB( + DEB( if (STp->write_pending) STp->nbr_waits++; else STp->nbr_finished++; - ) /* end DEB */ + ) /* end DEB */ wait_for_completion(&(STp->wait)); SRpnt = STbuffer->last_SRpnt; @@ -639,8 +711,9 @@ STbuffer->writing = 0; DEB(if (debugging && retval) - printk(ST_DEB_MSG "%s: Async write error %x, return value %d.\n", - tape_name(STp), STbuffer->cmdstat.midlevel_result, retval);) /* end DEB */ + st_printk(ST_DEB_MSG, STp, + "Async write error %x, return value %d.\n", + STbuffer->cmdstat.midlevel_result, retval);) /* end DEB */ return retval; } @@ -662,8 +735,8 @@ cmd[2] = cmd[3] = cmd[4] = 0xff; /* -1 filemarks */ cmd[5] = 0; - DEBC(printk(ST_DEB_MSG "%s: Stepping over filemark %s.\n", - tape_name(STp), forward ? "forward" : "backward")); + DEBC_printk(STp, "Stepping over filemark %s.\n", + forward ? "forward" : "backward"); SRpnt = st_do_scsi(NULL, STp, cmd, 0, DMA_NONE, STp->device->request_queue->rq_timeout, @@ -675,8 +748,9 @@ SRpnt = NULL; if ((STp->buffer)->cmdstat.midlevel_result != 0) - printk(KERN_ERR "%s: Stepping over filemark %s failed.\n", - tape_name(STp), forward ? "forward" : "backward"); + st_printk(KERN_ERR, STp, + "Stepping over filemark %s failed.\n", + forward ? "forward" : "backward"); return (STp->buffer)->syscall_result; } @@ -699,8 +773,7 @@ if (STp->dirty == 1) { transfer = STp->buffer->buffer_bytes; - DEBC(printk(ST_DEB_MSG "%s: Flushing %d bytes.\n", - tape_name(STp), transfer)); + DEBC_printk(STp, "Flushing %d bytes.\n", transfer); memset(cmd, 0, MAX_COMMAND_SIZE); cmd[0] = WRITE_6; @@ -732,8 +805,7 @@ STps->drv_block += blks; result = (-ENOSPC); } else { - printk(KERN_ERR "%s: Error on flush.\n", - tape_name(STp)); + st_printk(KERN_ERR, STp, "Error on flush.\n"); STps->drv_block = (-1); result = (-EIO); } @@ -811,7 +883,6 @@ { int set_it = 0; unsigned long arg; - char *name = tape_name(STp); if (!STp->density_changed && STm->default_density >= 0 && @@ -830,9 +901,10 @@ arg |= STp->block_size; if (set_it && st_int_ioctl(STp, SET_DENS_AND_BLK, arg)) { - printk(KERN_WARNING - "%s: Can't set default block size to %d bytes and density %x.\n", - name, STm->default_blksize, STm->default_density); + st_printk(KERN_WARNING, STp, + "Can't set default block size to %d bytes " + "and density %x.\n", + STm->default_blksize, STm->default_density); if (modes_defined) return (-EINVAL); } @@ -843,20 +915,16 @@ /* Lock or unlock the drive door. Don't use when st_request allocated. */ static int do_door_lock(struct scsi_tape * STp, int do_lock) { - int retval, cmd; - DEB(char *name = tape_name(STp);) + int retval; + DEBC_printk(STp, "%socking drive door.\n", do_lock ? "L" : "Unl"); - cmd = do_lock ? SCSI_IOCTL_DOORLOCK : SCSI_IOCTL_DOORUNLOCK; - DEBC(printk(ST_DEB_MSG "%s: %socking drive door.\n", name, - do_lock ? "L" : "Unl")); - retval = scsi_ioctl(STp->device, cmd, NULL); - if (!retval) { + retval = scsi_set_medium_removal(STp->device, + do_lock ? SCSI_REMOVAL_PREVENT : SCSI_REMOVAL_ALLOW); + if (!retval) STp->door_locked = do_lock ? ST_LOCKED_EXPLICIT : ST_UNLOCKED; - } - else { + else STp->door_locked = ST_LOCK_FAILS; - } return retval; } @@ -976,15 +1044,14 @@ struct st_request *SRpnt = NULL; struct st_modedef *STm; struct st_partstat *STps; - char *name = tape_name(STp); struct inode *inode = file_inode(filp); int mode = TAPE_MODE(inode); STp->ready = ST_READY; if (mode != STp->current_mode) { - DEBC(printk(ST_DEB_MSG "%s: Mode change from %d to %d.\n", - name, STp->current_mode, mode)); + DEBC_printk(STp, "Mode change from %d to %d.\n", + STp->current_mode, mode); new_session = 1; STp->current_mode = mode; } @@ -1055,13 +1122,12 @@ STp->min_block = ((STp->buffer)->b_data[4] << 8) | (STp->buffer)->b_data[5]; if ( DEB( debugging || ) !STp->inited) - printk(KERN_INFO - "%s: Block limits %d - %d bytes.\n", name, - STp->min_block, STp->max_block); + st_printk(KERN_INFO, STp, + "Block limits %d - %d bytes.\n", + STp->min_block, STp->max_block); } else { STp->min_block = STp->max_block = (-1); - DEBC(printk(ST_DEB_MSG "%s: Can't read block limits.\n", - name)); + DEBC_printk(STp, "Can't read block limits.\n"); } } @@ -1078,56 +1144,58 @@ } if ((STp->buffer)->syscall_result != 0) { - DEBC(printk(ST_DEB_MSG "%s: No Mode Sense.\n", name)); + DEBC_printk(STp, "No Mode Sense.\n"); STp->block_size = ST_DEFAULT_BLOCK; /* Educated guess (?) */ (STp->buffer)->syscall_result = 0; /* Prevent error propagation */ STp->drv_write_prot = 0; } else { - DEBC(printk(ST_DEB_MSG - "%s: Mode sense. Length %d, medium %x, WBS %x, BLL %d\n", - name, - (STp->buffer)->b_data[0], (STp->buffer)->b_data[1], - (STp->buffer)->b_data[2], (STp->buffer)->b_data[3])); + DEBC_printk(STp,"Mode sense. Length %d, " + "medium %x, WBS %x, BLL %d\n", + (STp->buffer)->b_data[0], + (STp->buffer)->b_data[1], + (STp->buffer)->b_data[2], + (STp->buffer)->b_data[3]); if ((STp->buffer)->b_data[3] >= 8) { STp->drv_buffer = ((STp->buffer)->b_data[2] >> 4) & 7; STp->density = (STp->buffer)->b_data[4]; STp->block_size = (STp->buffer)->b_data[9] * 65536 + (STp->buffer)->b_data[10] * 256 + (STp->buffer)->b_data[11]; - DEBC(printk(ST_DEB_MSG - "%s: Density %x, tape length: %x, drv buffer: %d\n", - name, STp->density, (STp->buffer)->b_data[5] * 65536 + - (STp->buffer)->b_data[6] * 256 + (STp->buffer)->b_data[7], - STp->drv_buffer)); + DEBC_printk(STp, "Density %x, tape length: %x, " + "drv buffer: %d\n", + STp->density, + (STp->buffer)->b_data[5] * 65536 + + (STp->buffer)->b_data[6] * 256 + + (STp->buffer)->b_data[7], + STp->drv_buffer); } STp->drv_write_prot = ((STp->buffer)->b_data[2] & 0x80) != 0; if (!STp->drv_buffer && STp->immediate_filemark) { - printk(KERN_WARNING - "%s: non-buffered tape: disabling writing immediate filemarks\n", - name); + st_printk(KERN_WARNING, STp, + "non-buffered tape: disabling " + "writing immediate filemarks\n"); STp->immediate_filemark = 0; } } st_release_request(SRpnt); SRpnt = NULL; - STp->inited = 1; + STp->inited = 1; if (STp->block_size > 0) (STp->buffer)->buffer_blocks = - (STp->buffer)->buffer_size / STp->block_size; + (STp->buffer)->buffer_size / STp->block_size; else (STp->buffer)->buffer_blocks = 1; (STp->buffer)->buffer_bytes = (STp->buffer)->read_pointer = 0; - DEBC(printk(ST_DEB_MSG - "%s: Block size: %d, buffer size: %d (%d blocks).\n", name, - STp->block_size, (STp->buffer)->buffer_size, - (STp->buffer)->buffer_blocks)); + DEBC_printk(STp, "Block size: %d, buffer size: %d (%d blocks).\n", + STp->block_size, (STp->buffer)->buffer_size, + (STp->buffer)->buffer_blocks); if (STp->drv_write_prot) { STp->write_prot = 1; - DEBC(printk(ST_DEB_MSG "%s: Write protected\n", name)); + DEBC_printk(STp, "Write protected\n"); if (do_wait && ((st_flags & O_ACCMODE) == O_WRONLY || @@ -1141,8 +1209,7 @@ /* This code is reached when the device is opened for the first time after the driver has been initialized with tape in the drive and the partition support has been enabled. */ - DEBC(printk(ST_DEB_MSG - "%s: Updating partition number in status.\n", name)); + DEBC_printk(STp, "Updating partition number in status.\n"); if ((STp->partition = find_partition(STp)) < 0) { retval = STp->partition; goto err_out; @@ -1160,9 +1227,10 @@ if (STp->default_drvbuffer != 0xff) { if (st_int_ioctl(STp, MTSETDRVBUFFER, STp->default_drvbuffer)) - printk(KERN_WARNING - "%s: Can't set default drive buffering to %d.\n", - name, STp->default_drvbuffer); + st_printk(KERN_WARNING, STp, + "Can't set default drive " + "buffering to %d.\n", + STp->default_drvbuffer); } } @@ -1182,7 +1250,6 @@ struct scsi_tape *STp; struct st_partstat *STps; int dev = TAPE_NR(inode); - char *name; /* * We really want to do nonseekable_open(inode, filp); here, but some @@ -1196,13 +1263,12 @@ } filp->private_data = STp; - name = tape_name(STp); spin_lock(&st_use_lock); if (STp->in_use) { spin_unlock(&st_use_lock); scsi_tape_put(STp); - DEB( printk(ST_DEB_MSG "%s: Device already in use.\n", name); ) + DEBC_printk(STp, "Device already in use.\n"); return (-EBUSY); } @@ -1222,8 +1288,8 @@ /* See that we have at least a one page buffer available */ if (!enlarge_buffer(STp->buffer, PAGE_SIZE, STp->restr_dma)) { - printk(KERN_WARNING "%s: Can't allocate one page tape buffer.\n", - name); + st_printk(KERN_WARNING, STp, + "Can't allocate one page tape buffer.\n"); retval = (-EOVERFLOW); goto err_out; } @@ -1279,7 +1345,6 @@ struct scsi_tape *STp = filp->private_data; struct st_modedef *STm = &(STp->modes[STp->current_mode]); struct st_partstat *STps = &(STp->ps[STp->partition]); - char *name = tape_name(STp); if (file_count(filp) > 1) return 0; @@ -1292,24 +1357,25 @@ if (STp->can_partitions && (result2 = switch_partition(STp)) < 0) { - DEBC(printk(ST_DEB_MSG - "%s: switch_partition at close failed.\n", name)); + DEBC_printk(STp, "switch_partition at close failed.\n"); if (result == 0) result = result2; goto out; } DEBC( if (STp->nbr_requests) - printk(KERN_DEBUG "%s: Number of r/w requests %d, dio used in %d, pages %d.\n", - name, STp->nbr_requests, STp->nbr_dio, STp->nbr_pages)); + st_printk(KERN_DEBUG, STp, + "Number of r/w requests %d, dio used in %d, " + "pages %d.\n", STp->nbr_requests, STp->nbr_dio, + STp->nbr_pages)); if (STps->rw == ST_WRITING && !STp->pos_unknown) { struct st_cmdstatus *cmdstatp = &STp->buffer->cmdstat; - DEBC(printk(ST_DEB_MSG "%s: Async write waits %d, finished %d.\n", - name, STp->nbr_waits, STp->nbr_finished); - ) - +#if DEBUG + DEBC_printk(STp, "Async write waits %d, finished %d.\n", + STp->nbr_waits, STp->nbr_finished); +#endif memset(cmd, 0, MAX_COMMAND_SIZE); cmd[0] = WRITE_FILEMARKS; if (STp->immediate_filemark) @@ -1343,13 +1409,13 @@ else { /* Write error */ st_release_request(SRpnt); SRpnt = NULL; - printk(KERN_ERR "%s: Error on write filemark.\n", name); + st_printk(KERN_ERR, STp, + "Error on write filemark.\n"); if (result == 0) result = (-EIO); } - DEBC(printk(ST_DEB_MSG "%s: Buffer flushed, %d EOF(s) written\n", - name, cmd[4])); + DEBC_printk(STp, "Buffer flushed, %d EOF(s) written\n", cmd[4]); } else if (!STp->rew_at_close) { STps = &(STp->ps[STp->partition]); if (!STm->sysv || STps->rw != ST_READING) { @@ -1447,9 +1513,10 @@ if (count == 0) goto out; - DEB( + DEB( if (!STp->in_use) { - printk(ST_DEB_MSG "%s: Incorrect device.\n", tape_name(STp)); + st_printk(ST_DEB_MSG, STp, + "Incorrect device.\n"); retval = (-EIO); goto out; } ) /* end DEB */ @@ -1519,8 +1586,9 @@ if (bufsize > STbp->buffer_size && !enlarge_buffer(STbp, bufsize, STp->restr_dma)) { - printk(KERN_WARNING "%s: Can't allocate %d byte tape buffer.\n", - tape_name(STp), bufsize); + st_printk(KERN_WARNING, STp, + "Can't allocate %d byte tape buffer.\n", + bufsize); retval = (-EOVERFLOW); goto out; } @@ -1563,7 +1631,6 @@ struct st_modedef *STm; struct st_partstat *STps; struct st_buffer *STbp; - char *name = tape_name(STp); if (mutex_lock_interruptible(&STp->lock)) return -ERESTARTSYS; @@ -1574,8 +1641,8 @@ /* Write must be integral number of blocks */ if (STp->block_size != 0 && (count % STp->block_size) != 0) { - printk(KERN_WARNING "%s: Write not multiple of tape block size.\n", - name); + st_printk(KERN_WARNING, STp, + "Write not multiple of tape block size.\n"); retval = (-EINVAL); goto out; } @@ -1601,8 +1668,8 @@ if (STm->default_compression != ST_DONT_TOUCH && !(STp->compression_changed)) { if (st_compression(STp, (STm->default_compression == ST_YES))) { - printk(KERN_WARNING "%s: Can't set default compression.\n", - name); + st_printk(KERN_WARNING, STp, + "Can't set default compression.\n"); if (modes_defined) { retval = (-EINVAL); goto out; @@ -1723,7 +1790,7 @@ if (STbp->syscall_result != 0) { struct st_cmdstatus *cmdstatp = &STp->buffer->cmdstat; - DEBC(printk(ST_DEB_MSG "%s: Error on write:\n", name)); + DEBC_printk(STp, "Error on write:\n"); if (cmdstatp->have_sense && (cmdstatp->flags & SENSE_EOM)) { scode = cmdstatp->sense_hdr.sense_key; if (cmdstatp->remainder_valid) @@ -1750,9 +1817,9 @@ if (STp->block_size == 0 || undone > 0 || count == 0) retval = (-ENOSPC); /* EOM within current request */ - DEBC(printk(ST_DEB_MSG - "%s: EOM with %d bytes unwritten.\n", - name, (int)count)); + DEBC_printk(STp, "EOM with %d " + "bytes unwritten.\n", + (int)count); } else { /* EOT within data buffered earlier (possible only in fixed block mode without direct i/o) */ @@ -1765,9 +1832,10 @@ STp->block_size; } STps->eof = ST_EOM_OK; - DEBC(printk(ST_DEB_MSG - "%s: Retry write of %d bytes at EOM.\n", - name, STp->buffer->buffer_bytes)); + DEBC_printk(STp, "Retry " + "write of %d " + "bytes at EOM.\n", + STp->buffer->buffer_bytes); goto retry_write; } else { @@ -1778,9 +1846,8 @@ STps->eof = ST_EOM_ERROR; STps->drv_block = (-1); /* Too cautious? */ retval = (-EIO); /* EOM for old data */ - DEBC(printk(ST_DEB_MSG - "%s: EOM with lost data.\n", - name)); + DEBC_printk(STp, "EOM with " + "lost data.\n"); } } } else { @@ -1839,7 +1906,6 @@ struct st_partstat *STps; struct st_buffer *STbp; int retval = 0; - char *name = tape_name(STp); if (count == 0) return 0; @@ -1891,12 +1957,12 @@ struct st_cmdstatus *cmdstatp = &STp->buffer->cmdstat; retval = 1; - DEBC(printk(ST_DEB_MSG "%s: Sense: %2x %2x %2x %2x %2x %2x %2x %2x\n", - name, - SRpnt->sense[0], SRpnt->sense[1], - SRpnt->sense[2], SRpnt->sense[3], - SRpnt->sense[4], SRpnt->sense[5], - SRpnt->sense[6], SRpnt->sense[7])); + DEBC_printk(STp, + "Sense: %2x %2x %2x %2x %2x %2x %2x %2x\n", + SRpnt->sense[0], SRpnt->sense[1], + SRpnt->sense[2], SRpnt->sense[3], + SRpnt->sense[4], SRpnt->sense[5], + SRpnt->sense[6], SRpnt->sense[7]); if (cmdstatp->have_sense) { if (cmdstatp->sense_hdr.sense_key == BLANK_CHECK) @@ -1913,23 +1979,27 @@ transfer = bytes; if (cmdstatp->flags & SENSE_ILI) { /* ILI */ - if (STp->block_size == 0) { - if (transfer <= 0) { - if (transfer < 0) - printk(KERN_NOTICE - "%s: Failed to read %d byte block with %d byte transfer.\n", - name, bytes - transfer, bytes); - if (STps->drv_block >= 0) - STps->drv_block += 1; - STbp->buffer_bytes = 0; - return (-ENOMEM); - } + if (STp->block_size == 0 && + transfer < 0) { + st_printk(KERN_NOTICE, STp, + "Failed to read %d " + "byte block with %d " + "byte transfer.\n", + bytes - transfer, + bytes); + if (STps->drv_block >= 0) + STps->drv_block += 1; + STbp->buffer_bytes = 0; + return (-ENOMEM); + } else if (STp->block_size == 0) { STbp->buffer_bytes = bytes - transfer; } else { st_release_request(SRpnt); SRpnt = *aSRpnt = NULL; if (transfer == blks) { /* We did not get anything, error */ - printk(KERN_NOTICE "%s: Incorrect block size.\n", name); + st_printk(KERN_NOTICE, STp, + "Incorrect " + "block size.\n"); if (STps->drv_block >= 0) STps->drv_block += blks - transfer + 1; st_int_ioctl(STp, MTBSR, 1); @@ -1938,9 +2008,11 @@ /* We have some data, deliver it */ STbp->buffer_bytes = (blks - transfer) * STp->block_size; - DEBC(printk(ST_DEB_MSG - "%s: ILI but enough data received %ld %d.\n", - name, count, STbp->buffer_bytes)); + DEBC_printk(STp, "ILI but " + "enough data " + "received %ld " + "%d.\n", count, + STbp->buffer_bytes); if (STps->drv_block >= 0) STps->drv_block += 1; if (st_int_ioctl(STp, MTBSR, 1)) @@ -1956,9 +2028,9 @@ else STbp->buffer_bytes = bytes - transfer * STp->block_size; - DEBC(printk(ST_DEB_MSG - "%s: EOF detected (%d bytes read).\n", - name, STbp->buffer_bytes)); + DEBC_printk(STp, "EOF detected (%d " + "bytes read).\n", + STbp->buffer_bytes); } else if (cmdstatp->flags & SENSE_EOM) { if (STps->eof == ST_FM) STps->eof = ST_EOD_1; @@ -1970,20 +2042,20 @@ STbp->buffer_bytes = bytes - transfer * STp->block_size; - DEBC(printk(ST_DEB_MSG "%s: EOM detected (%d bytes read).\n", - name, STbp->buffer_bytes)); + DEBC_printk(STp, "EOM detected (%d " + "bytes read).\n", + STbp->buffer_bytes); } } - /* end of EOF, EOM, ILI test */ + /* end of EOF, EOM, ILI test */ else { /* nonzero sense key */ - DEBC(printk(ST_DEB_MSG - "%s: Tape error while reading.\n", name)); + DEBC_printk(STp, "Tape error while reading.\n"); STps->drv_block = (-1); if (STps->eof == ST_FM && cmdstatp->sense_hdr.sense_key == BLANK_CHECK) { - DEBC(printk(ST_DEB_MSG - "%s: Zero returned for first BLANK CHECK after EOF.\n", - name)); + DEBC_printk(STp, "Zero returned for " + "first BLANK CHECK " + "after EOF.\n"); STps->eof = ST_EOD_2; /* First BLANK_CHECK after FM */ } else /* Some other extended sense code */ retval = (-EIO); @@ -1992,13 +2064,13 @@ if (STbp->buffer_bytes < 0) /* Caused by bogus sense data */ STbp->buffer_bytes = 0; } - /* End of extended sense test */ + /* End of extended sense test */ else { /* Non-extended sense */ retval = STbp->syscall_result; } } - /* End of error handling */ + /* End of error handling */ else { /* Read successful */ STbp->buffer_bytes = bytes; if (STp->sili) /* In fixed block mode residual is always zero here */ @@ -2028,7 +2100,6 @@ struct st_modedef *STm; struct st_partstat *STps; struct st_buffer *STbp = STp->buffer; - DEB( char *name = tape_name(STp); ) if (mutex_lock_interruptible(&STp->lock)) return -ERESTARTSYS; @@ -2053,11 +2124,12 @@ goto out; STps->rw = ST_READING; } - DEB( + DEB( if (debugging && STps->eof != ST_NOEOF) - printk(ST_DEB_MSG "%s: EOF/EOM flag up (%d). Bytes %d\n", name, - STps->eof, STbp->buffer_bytes); - ) /* end DEB */ + st_printk(ST_DEB_MSG, STp, + "EOF/EOM flag up (%d). Bytes %d\n", + STps->eof, STbp->buffer_bytes); + ) /* end DEB */ retval = setup_buffering(STp, buf, count, 1); if (retval) @@ -2104,13 +2176,13 @@ /* Move the data from driver buffer to user buffer */ if (STbp->buffer_bytes > 0) { - DEB( + DEB( if (debugging && STps->eof != ST_NOEOF) - printk(ST_DEB_MSG - "%s: EOF up (%d). Left %d, needed %d.\n", name, - STps->eof, STbp->buffer_bytes, - (int)(count - total)); - ) /* end DEB */ + st_printk(ST_DEB_MSG, STp, + "EOF up (%d). Left %d, needed %d.\n", + STps->eof, STbp->buffer_bytes, + (int)(count - total)); + ) /* end DEB */ transfer = STbp->buffer_bytes < count - total ? STbp->buffer_bytes : count - total; if (!do_dio) { @@ -2166,26 +2238,30 @@ DEB( /* Set the driver options */ -static void st_log_options(struct scsi_tape * STp, struct st_modedef * STm, char *name) +static void st_log_options(struct scsi_tape * STp, struct st_modedef * STm) { if (debugging) { - printk(KERN_INFO - "%s: Mode %d options: buffer writes: %d, async writes: %d, read ahead: %d\n", - name, STp->current_mode, STm->do_buffer_writes, STm->do_async_writes, - STm->do_read_ahead); - printk(KERN_INFO - "%s: can bsr: %d, two FMs: %d, fast mteom: %d, auto lock: %d,\n", - name, STp->can_bsr, STp->two_fm, STp->fast_mteom, STp->do_auto_lock); - printk(KERN_INFO - "%s: defs for wr: %d, no block limits: %d, partitions: %d, s2 log: %d\n", - name, STm->defaults_for_writes, STp->omit_blklims, STp->can_partitions, - STp->scsi2_logical); - printk(KERN_INFO - "%s: sysv: %d nowait: %d sili: %d nowait_filemark: %d\n", - name, STm->sysv, STp->immediate, STp->sili, - STp->immediate_filemark); - printk(KERN_INFO "%s: debugging: %d\n", - name, debugging); + st_printk(KERN_INFO, STp, + "Mode %d options: buffer writes: %d, " + "async writes: %d, read ahead: %d\n", + STp->current_mode, STm->do_buffer_writes, + STm->do_async_writes, STm->do_read_ahead); + st_printk(KERN_INFO, STp, + " can bsr: %d, two FMs: %d, " + "fast mteom: %d, auto lock: %d,\n", + STp->can_bsr, STp->two_fm, STp->fast_mteom, + STp->do_auto_lock); + st_printk(KERN_INFO, STp, + " defs for wr: %d, no block limits: %d, " + "partitions: %d, s2 log: %d\n", + STm->defaults_for_writes, STp->omit_blklims, + STp->can_partitions, STp->scsi2_logical); + st_printk(KERN_INFO, STp, + " sysv: %d nowait: %d sili: %d " + "nowait_filemark: %d\n", + STm->sysv, STp->immediate, STp->sili, + STp->immediate_filemark); + st_printk(KERN_INFO, STp, " debugging: %d\n", debugging); } } ) @@ -2196,18 +2272,23 @@ int value; long code; struct st_modedef *STm; - char *name = tape_name(STp); struct cdev *cd0, *cd1; + struct device *d0, *d1; STm = &(STp->modes[STp->current_mode]); if (!STm->defined) { - cd0 = STm->cdevs[0]; cd1 = STm->cdevs[1]; + cd0 = STm->cdevs[0]; + cd1 = STm->cdevs[1]; + d0 = STm->devs[0]; + d1 = STm->devs[1]; memcpy(STm, &(STp->modes[0]), sizeof(struct st_modedef)); - STm->cdevs[0] = cd0; STm->cdevs[1] = cd1; + STm->cdevs[0] = cd0; + STm->cdevs[1] = cd1; + STm->devs[0] = d0; + STm->devs[1] = d1; modes_defined = 1; - DEBC(printk(ST_DEB_MSG - "%s: Initialized mode %d definition from mode 0\n", - name, STp->current_mode)); + DEBC_printk(STp, "Initialized mode %d definition from mode 0\n", + STp->current_mode); } code = options & MT_ST_OPTIONS; @@ -2229,7 +2310,7 @@ STm->sysv = (options & MT_ST_SYSV) != 0; STp->sili = (options & MT_ST_SILI) != 0; DEB( debugging = (options & MT_ST_DEBUGGING) != 0; - st_log_options(STp, STm, name); ) + st_log_options(STp, STm); ) } else if (code == MT_ST_SETBOOLEANS || code == MT_ST_CLEARBOOLEANS) { value = (code == MT_ST_SETBOOLEANS); if ((options & MT_ST_BUFFER_WRITES) != 0) @@ -2263,21 +2344,21 @@ STm->sysv = value; if ((options & MT_ST_SILI) != 0) STp->sili = value; - DEB( + DEB( if ((options & MT_ST_DEBUGGING) != 0) debugging = value; - st_log_options(STp, STm, name); ) + st_log_options(STp, STm); ) } else if (code == MT_ST_WRITE_THRESHOLD) { /* Retained for compatibility */ } else if (code == MT_ST_DEF_BLKSIZE) { value = (options & ~MT_ST_OPTIONS); if (value == ~MT_ST_OPTIONS) { STm->default_blksize = (-1); - DEBC( printk(KERN_INFO "%s: Default block size disabled.\n", name)); + DEBC_printk(STp, "Default block size disabled.\n"); } else { STm->default_blksize = value; - DEBC( printk(KERN_INFO "%s: Default block size set to %d bytes.\n", - name, STm->default_blksize)); + DEBC_printk(STp,"Default block size set to " + "%d bytes.\n", STm->default_blksize); if (STp->ready == ST_READY) { STp->blksize_changed = 0; set_mode_densblk(STp, STm); @@ -2287,13 +2368,13 @@ value = (options & ~MT_ST_OPTIONS); if ((value & MT_ST_SET_LONG_TIMEOUT) != 0) { STp->long_timeout = (value & ~MT_ST_SET_LONG_TIMEOUT) * HZ; - DEBC( printk(KERN_INFO "%s: Long timeout set to %d seconds.\n", name, - (value & ~MT_ST_SET_LONG_TIMEOUT))); + DEBC_printk(STp, "Long timeout set to %d seconds.\n", + (value & ~MT_ST_SET_LONG_TIMEOUT)); } else { blk_queue_rq_timeout(STp->device->request_queue, value * HZ); - DEBC( printk(KERN_INFO "%s: Normal timeout set to %d seconds.\n", - name, value) ); + DEBC_printk(STp, "Normal timeout set to %d seconds.\n", + value); } } else if (code == MT_ST_SET_CLN) { value = (options & ~MT_ST_OPTIONS) & 0xff; @@ -2304,21 +2385,21 @@ STp->cln_mode = value; STp->cln_sense_mask = (options >> 8) & 0xff; STp->cln_sense_value = (options >> 16) & 0xff; - printk(KERN_INFO - "%s: Cleaning request mode %d, mask %02x, value %02x\n", - name, value, STp->cln_sense_mask, STp->cln_sense_value); + st_printk(KERN_INFO, STp, + "Cleaning request mode %d, mask %02x, value %02x\n", + value, STp->cln_sense_mask, STp->cln_sense_value); } else if (code == MT_ST_DEF_OPTIONS) { code = (options & ~MT_ST_CLEAR_DEFAULT); value = (options & MT_ST_CLEAR_DEFAULT); if (code == MT_ST_DEF_DENSITY) { if (value == MT_ST_CLEAR_DEFAULT) { STm->default_density = (-1); - DEBC( printk(KERN_INFO "%s: Density default disabled.\n", - name)); + DEBC_printk(STp, + "Density default disabled.\n"); } else { STm->default_density = value & 0xff; - DEBC( printk(KERN_INFO "%s: Density default set to %x\n", - name, STm->default_density)); + DEBC_printk(STp, "Density default set to %x\n", + STm->default_density); if (STp->ready == ST_READY) { STp->density_changed = 0; set_mode_densblk(STp, STm); @@ -2327,31 +2408,33 @@ } else if (code == MT_ST_DEF_DRVBUFFER) { if (value == MT_ST_CLEAR_DEFAULT) { STp->default_drvbuffer = 0xff; - DEBC( printk(KERN_INFO - "%s: Drive buffer default disabled.\n", name)); + DEBC_printk(STp, + "Drive buffer default disabled.\n"); } else { STp->default_drvbuffer = value & 7; - DEBC( printk(KERN_INFO - "%s: Drive buffer default set to %x\n", - name, STp->default_drvbuffer)); + DEBC_printk(STp, + "Drive buffer default set to %x\n", + STp->default_drvbuffer); if (STp->ready == ST_READY) st_int_ioctl(STp, MTSETDRVBUFFER, STp->default_drvbuffer); } } else if (code == MT_ST_DEF_COMPRESSION) { if (value == MT_ST_CLEAR_DEFAULT) { STm->default_compression = ST_DONT_TOUCH; - DEBC( printk(KERN_INFO - "%s: Compression default disabled.\n", name)); + DEBC_printk(STp, + "Compression default disabled.\n"); } else { if ((value & 0xff00) != 0) { STp->c_algo = (value & 0xff00) >> 8; - DEBC( printk(KERN_INFO "%s: Compression algorithm set to 0x%x.\n", - name, STp->c_algo)); + DEBC_printk(STp, "Compression " + "algorithm set to 0x%x.\n", + STp->c_algo); } if ((value & 0xff) != 0xff) { STm->default_compression = (value & 1 ? ST_YES : ST_NO); - DEBC( printk(KERN_INFO "%s: Compression default set to %x\n", - name, (value & 1))); + DEBC_printk(STp, "Compression default " + "set to %x\n", + (value & 1)); if (STp->ready == ST_READY) { STp->compression_changed = 0; st_compression(STp, (STm->default_compression == ST_YES)); @@ -2466,7 +2549,6 @@ int retval; int mpoffs; /* Offset to mode page start */ unsigned char *b_data = (STp->buffer)->b_data; - DEB( char *name = tape_name(STp); ) if (STp->ready != ST_READY) return (-EIO); @@ -2474,18 +2556,17 @@ /* Read the current page contents */ retval = read_mode_page(STp, COMPRESSION_PAGE, 0); if (retval) { - DEBC(printk(ST_DEB_MSG "%s: Compression mode page not supported.\n", - name)); + DEBC_printk(STp, "Compression mode page not supported.\n"); return (-EIO); } mpoffs = MODE_HEADER_LENGTH + b_data[MH_OFF_BDESCS_LENGTH]; - DEBC(printk(ST_DEB_MSG "%s: Compression state is %d.\n", name, - (b_data[mpoffs + CP_OFF_DCE_DCC] & DCE_MASK ? 1 : 0))); + DEBC_printk(STp, "Compression state is %d.\n", + (b_data[mpoffs + CP_OFF_DCE_DCC] & DCE_MASK ? 1 : 0)); /* Check if compression can be changed */ if ((b_data[mpoffs + CP_OFF_DCE_DCC] & DCC_MASK) == 0) { - DEBC(printk(ST_DEB_MSG "%s: Compression not supported.\n", name)); + DEBC_printk(STp, "Compression not supported.\n"); return (-EIO); } @@ -2503,11 +2584,10 @@ retval = write_mode_page(STp, COMPRESSION_PAGE, 0); if (retval) { - DEBC(printk(ST_DEB_MSG "%s: Compression change failed.\n", name)); + DEBC_printk(STp, "Compression change failed.\n"); return (-EIO); } - DEBC(printk(ST_DEB_MSG "%s: Compression state changed to %d.\n", - name, state)); + DEBC_printk(STp, "Compression state changed to %d.\n", state); STp->compression_changed = 1; return 0; @@ -2518,7 +2598,6 @@ static int do_load_unload(struct scsi_tape *STp, struct file *filp, int load_code) { int retval = (-EIO), timeout; - DEB( char *name = tape_name(STp); ) unsigned char cmd[MAX_COMMAND_SIZE]; struct st_partstat *STps; struct st_request *SRpnt; @@ -2539,9 +2618,9 @@ */ if (load_code >= 1 + MT_ST_HPLOADER_OFFSET && load_code <= 6 + MT_ST_HPLOADER_OFFSET) { - DEBC(printk(ST_DEB_MSG "%s: Enhanced %sload slot %2d.\n", - name, (cmd[4]) ? "" : "un", - load_code - MT_ST_HPLOADER_OFFSET)); + DEBC_printk(STp, " Enhanced %sload slot %2d.\n", + (cmd[4]) ? "" : "un", + load_code - MT_ST_HPLOADER_OFFSET); cmd[3] = load_code - MT_ST_HPLOADER_OFFSET; /* MediaID field of C1553A */ } if (STp->immediate) { @@ -2553,9 +2632,9 @@ DEBC( if (!load_code) - printk(ST_DEB_MSG "%s: Unloading tape.\n", name); + st_printk(ST_DEB_MSG, STp, "Unloading tape.\n"); else - printk(ST_DEB_MSG "%s: Loading tape.\n", name); + st_printk(ST_DEB_MSG, STp, "Loading tape.\n"); ); SRpnt = st_do_scsi(NULL, STp, cmd, 0, DMA_NONE, @@ -2590,17 +2669,24 @@ #if DEBUG #define ST_DEB_FORWARD 0 #define ST_DEB_BACKWARD 1 -static void deb_space_print(char *name, int direction, char *units, unsigned char *cmd) +static void deb_space_print(struct scsi_tape *STp, int direction, char *units, unsigned char *cmd) { s32 sc; + if (!debugging) + return; + sc = cmd[2] & 0x80 ? 0xff000000 : 0; sc |= (cmd[2] << 16) | (cmd[3] << 8) | cmd[4]; if (direction) sc = -sc; - printk(ST_DEB_MSG "%s: Spacing tape %s over %d %s.\n", name, - direction ? "backward" : "forward", sc, units); + st_printk(ST_DEB_MSG, STp, "Spacing tape %s over %d %s.\n", + direction ? "backward" : "forward", sc, units); } +#else +#define ST_DEB_FORWARD 0 +#define ST_DEB_BACKWARD 1 +static void deb_space_print(struct scsi_tape *STp, int direction, char *units, unsigned char *cmd) {} #endif @@ -2616,7 +2702,6 @@ struct st_partstat *STps; int fileno, blkno, at_sm, undone; int datalen = 0, direction = DMA_NONE; - char *name = tape_name(STp); WARN_ON(STp->buffer->do_dio != 0); if (STp->ready != ST_READY) { @@ -2641,7 +2726,7 @@ cmd[2] = (arg >> 16); cmd[3] = (arg >> 8); cmd[4] = arg; - DEBC(deb_space_print(name, ST_DEB_FORWARD, "filemarks", cmd);) + deb_space_print(STp, ST_DEB_FORWARD, "filemarks", cmd); if (fileno >= 0) fileno += arg; blkno = 0; @@ -2656,7 +2741,7 @@ cmd[2] = (ltmp >> 16); cmd[3] = (ltmp >> 8); cmd[4] = ltmp; - DEBC(deb_space_print(name, ST_DEB_BACKWARD, "filemarks", cmd);) + deb_space_print(STp, ST_DEB_BACKWARD, "filemarks", cmd); if (fileno >= 0) fileno -= arg; blkno = (-1); /* We can't know the block number */ @@ -2668,7 +2753,7 @@ cmd[2] = (arg >> 16); cmd[3] = (arg >> 8); cmd[4] = arg; - DEBC(deb_space_print(name, ST_DEB_FORWARD, "blocks", cmd);) + deb_space_print(STp, ST_DEB_FORWARD, "blocks", cmd); if (blkno >= 0) blkno += arg; at_sm &= (arg == 0); @@ -2680,7 +2765,7 @@ cmd[2] = (ltmp >> 16); cmd[3] = (ltmp >> 8); cmd[4] = ltmp; - DEBC(deb_space_print(name, ST_DEB_BACKWARD, "blocks", cmd);) + deb_space_print(STp, ST_DEB_BACKWARD, "blocks", cmd); if (blkno >= 0) blkno -= arg; at_sm &= (arg == 0); @@ -2691,7 +2776,7 @@ cmd[2] = (arg >> 16); cmd[3] = (arg >> 8); cmd[4] = arg; - DEBC(deb_space_print(name, ST_DEB_FORWARD, "setmarks", cmd);) + deb_space_print(STp, ST_DEB_FORWARD, "setmarks", cmd); if (arg != 0) { blkno = fileno = (-1); at_sm = 1; @@ -2704,7 +2789,7 @@ cmd[2] = (ltmp >> 16); cmd[3] = (ltmp >> 8); cmd[4] = ltmp; - DEBC(deb_space_print(name, ST_DEB_BACKWARD, "setmarks", cmd);) + deb_space_print(STp, ST_DEB_BACKWARD, "setmarks", cmd); if (arg != 0) { blkno = fileno = (-1); at_sm = 1; @@ -2725,13 +2810,19 @@ cmd[3] = (arg >> 8); cmd[4] = arg; timeout = STp->device->request_queue->rq_timeout; - DEBC( - if (cmd_in != MTWSM) - printk(ST_DEB_MSG "%s: Writing %d filemarks.\n", name, - cmd[2] * 65536 + cmd[3] * 256 + cmd[4]); - else - printk(ST_DEB_MSG "%s: Writing %d setmarks.\n", name, - cmd[2] * 65536 + cmd[3] * 256 + cmd[4]); + DEBC( + if (cmd_in != MTWSM) + st_printk(ST_DEB_MSG, STp, + "Writing %d filemarks.\n", + cmd[2] * 65536 + + cmd[3] * 256 + + cmd[4]); + else + st_printk(ST_DEB_MSG, STp, + "Writing %d setmarks.\n", + cmd[2] * 65536 + + cmd[3] * 256 + + cmd[4]); ) if (fileno >= 0) fileno += arg; @@ -2744,11 +2835,11 @@ cmd[1] = 1; /* Don't wait for completion */ timeout = STp->device->request_queue->rq_timeout; } - DEBC(printk(ST_DEB_MSG "%s: Rewinding tape.\n", name)); + DEBC_printk(STp, "Rewinding tape.\n"); fileno = blkno = at_sm = 0; break; case MTNOP: - DEBC(printk(ST_DEB_MSG "%s: No op on tape.\n", name)); + DEBC_printk(STp, "No op on tape.\n"); return 0; /* Should do something ? */ break; case MTRETEN: @@ -2758,7 +2849,7 @@ timeout = STp->device->request_queue->rq_timeout; } cmd[4] = 3; - DEBC(printk(ST_DEB_MSG "%s: Retensioning tape.\n", name)); + DEBC_printk(STp, "Retensioning tape.\n"); fileno = blkno = at_sm = 0; break; case MTEOM: @@ -2776,8 +2867,7 @@ fileno = (-1); cmd[0] = SPACE; cmd[1] = 3; - DEBC(printk(ST_DEB_MSG "%s: Spacing to end of recorded medium.\n", - name)); + DEBC_printk(STp, "Spacing to end of recorded medium.\n"); blkno = -1; at_sm = 0; break; @@ -2793,7 +2883,7 @@ else timeout = STp->long_timeout * 8; - DEBC(printk(ST_DEB_MSG "%s: Erasing tape.\n", name)); + DEBC_printk(STp, "Erasing tape.\n"); fileno = blkno = at_sm = 0; break; case MTSETBLK: /* Set block length */ @@ -2808,7 +2898,7 @@ STp->max_block > 0 && ((arg & MT_ST_BLKSIZE_MASK) < STp->min_block || (arg & MT_ST_BLKSIZE_MASK) > STp->max_block)) { - printk(KERN_WARNING "%s: Illegal block size.\n", name); + st_printk(KERN_WARNING, STp, "Illegal block size.\n"); return (-EINVAL); } cmd[0] = MODE_SELECT; @@ -2841,21 +2931,21 @@ (STp->buffer)->b_data[10] = (ltmp >> 8); (STp->buffer)->b_data[11] = ltmp; timeout = STp->device->request_queue->rq_timeout; - DEBC( + DEBC( if (cmd_in == MTSETBLK || cmd_in == SET_DENS_AND_BLK) - printk(ST_DEB_MSG - "%s: Setting block size to %d bytes.\n", name, - (STp->buffer)->b_data[9] * 65536 + - (STp->buffer)->b_data[10] * 256 + - (STp->buffer)->b_data[11]); + st_printk(ST_DEB_MSG, STp, + "Setting block size to %d bytes.\n", + (STp->buffer)->b_data[9] * 65536 + + (STp->buffer)->b_data[10] * 256 + + (STp->buffer)->b_data[11]); if (cmd_in == MTSETDENSITY || cmd_in == SET_DENS_AND_BLK) - printk(ST_DEB_MSG - "%s: Setting density code to %x.\n", name, - (STp->buffer)->b_data[4]); + st_printk(ST_DEB_MSG, STp, + "Setting density code to %x.\n", + (STp->buffer)->b_data[4]); if (cmd_in == MTSETDRVBUFFER) - printk(ST_DEB_MSG - "%s: Setting drive buffer code to %d.\n", name, - ((STp->buffer)->b_data[2] >> 4) & 7); + st_printk(ST_DEB_MSG, STp, + "Setting drive buffer code to %d.\n", + ((STp->buffer)->b_data[2] >> 4) & 7); ) break; default: @@ -3012,7 +3102,6 @@ int result; unsigned char scmd[MAX_COMMAND_SIZE]; struct st_request *SRpnt; - DEB( char *name = tape_name(STp); ) if (STp->ready != ST_READY) return (-EIO); @@ -3036,7 +3125,7 @@ (STp->device->scsi_level >= SCSI_2 && ((STp->buffer)->b_data[0] & 4) != 0)) { *block = *partition = 0; - DEBC(printk(ST_DEB_MSG "%s: Can't read tape position.\n", name)); + DEBC_printk(STp, " Can't read tape position.\n"); result = (-EIO); } else { result = 0; @@ -3055,8 +3144,8 @@ (STp->buffer)->b_data[1] == 0) /* BOP of partition 0 */ STp->ps[0].drv_block = STp->ps[0].drv_file = 0; } - DEBC(printk(ST_DEB_MSG "%s: Got tape pos. blk %d part %d.\n", name, - *block, *partition)); + DEBC_printk(STp, "Got tape pos. blk %d part %d.\n", + *block, *partition); } st_release_request(SRpnt); SRpnt = NULL; @@ -3076,15 +3165,14 @@ int timeout; unsigned char scmd[MAX_COMMAND_SIZE]; struct st_request *SRpnt; - DEB( char *name = tape_name(STp); ) if (STp->ready != ST_READY) return (-EIO); timeout = STp->long_timeout; STps = &(STp->ps[STp->partition]); - DEBC(printk(ST_DEB_MSG "%s: Setting block to %d and partition to %d.\n", - name, block, partition)); + DEBC_printk(STp, "Setting block to %d and partition to %d.\n", + block, partition); DEB(if (partition < 0) return (-EIO); ) @@ -3098,9 +3186,9 @@ else { STps->last_block_valid = 1; STps->last_block_visited = blk; - DEBC(printk(ST_DEB_MSG - "%s: Visited block %d for partition %d saved.\n", - name, blk, STp->partition)); + DEBC_printk(STp, "Visited block %d for " + "partition %d saved.\n", + blk, STp->partition); } } @@ -3122,9 +3210,9 @@ if (STp->partition != partition) { scmd[1] |= 2; scmd[8] = partition; - DEBC(printk(ST_DEB_MSG - "%s: Trying to change partition from %d to %d\n", - name, STp->partition, partition)); + DEBC_printk(STp, "Trying to change partition " + "from %d to %d\n", STp->partition, + partition); } } if (STp->immediate) { @@ -3215,7 +3303,6 @@ static int nbr_partitions(struct scsi_tape *STp) { int result; - DEB( char *name = tape_name(STp); ) if (STp->ready != ST_READY) return (-EIO); @@ -3223,13 +3310,12 @@ result = read_mode_page(STp, PART_PAGE, 1); if (result) { - DEBC(printk(ST_DEB_MSG "%s: Can't read medium partition page.\n", - name)); + DEBC_printk(STp, "Can't read medium partition page.\n"); result = (-EIO); } else { result = (STp->buffer)->b_data[MODE_HEADER_LENGTH + PP_OFF_NBR_ADD_PARTS] + 1; - DEBC(printk(ST_DEB_MSG "%s: Number of partitions %d.\n", name, result)); + DEBC_printk(STp, "Number of partitions %d.\n", result); } return result; @@ -3257,21 +3343,20 @@ */ static int partition_tape(struct scsi_tape *STp, int size) { - char *name = tape_name(STp); int result; int pgo, psd_cnt, psdo; unsigned char *bp; result = read_mode_page(STp, PART_PAGE, 0); if (result) { - DEBC(printk(ST_DEB_MSG "%s: Can't read partition mode page.\n", name)); + DEBC_printk(STp, "Can't read partition mode page.\n"); return result; } /* The mode page is in the buffer. Let's modify it and write it. */ bp = (STp->buffer)->b_data; pgo = MODE_HEADER_LENGTH + bp[MH_OFF_BDESCS_LENGTH]; - DEBC(printk(ST_DEB_MSG "%s: Partition page length is %d bytes.\n", - name, bp[pgo + MP_OFF_PAGE_LENGTH] + 2)); + DEBC_printk(STp, "Partition page length is %d bytes.\n", + bp[pgo + MP_OFF_PAGE_LENGTH] + 2); psd_cnt = (bp[pgo + MP_OFF_PAGE_LENGTH] + 2 - PART_PAGE_FIXED_LENGTH) / 2; psdo = pgo + PART_PAGE_FIXED_LENGTH; @@ -3281,25 +3366,23 @@ } memset(bp + psdo, 0, bp[pgo + PP_OFF_NBR_ADD_PARTS] * 2); - DEBC(printk("%s: psd_cnt %d, max.parts %d, nbr_parts %d\n", name, + DEBC_printk(STp, "psd_cnt %d, max.parts %d, nbr_parts %d\n", psd_cnt, bp[pgo + PP_OFF_MAX_ADD_PARTS], - bp[pgo + PP_OFF_NBR_ADD_PARTS])); + bp[pgo + PP_OFF_NBR_ADD_PARTS]); if (size <= 0) { bp[pgo + PP_OFF_NBR_ADD_PARTS] = 0; if (psd_cnt <= bp[pgo + PP_OFF_MAX_ADD_PARTS]) bp[pgo + MP_OFF_PAGE_LENGTH] = 6; - DEBC(printk(ST_DEB_MSG "%s: Formatting tape with one partition.\n", - name)); + DEBC_printk(STp, "Formatting tape with one partition.\n"); } else { bp[psdo] = (size >> 8) & 0xff; bp[psdo + 1] = size & 0xff; bp[pgo + 3] = 1; if (bp[pgo + MP_OFF_PAGE_LENGTH] < 8) bp[pgo + MP_OFF_PAGE_LENGTH] = 8; - DEBC(printk(ST_DEB_MSG - "%s: Formatting tape with two partitions (1 = %d MB).\n", - name, size)); + DEBC_printk(STp, "Formatting tape with two partitions " + "(1 = %d MB).\n", size); } bp[pgo + PP_OFF_PART_UNITS] = 0; bp[pgo + PP_OFF_RESERVED] = 0; @@ -3307,7 +3390,7 @@ result = write_mode_page(STp, PART_PAGE, 1); if (result) { - printk(KERN_INFO "%s: Partitioning of tape failed.\n", name); + st_printk(KERN_INFO, STp, "Partitioning of tape failed.\n"); result = (-EIO); } @@ -3325,15 +3408,14 @@ struct scsi_tape *STp = file->private_data; struct st_modedef *STm; struct st_partstat *STps; - char *name = tape_name(STp); void __user *p = (void __user *)arg; if (mutex_lock_interruptible(&STp->lock)) return -ERESTARTSYS; - DEB( + DEB( if (debugging && !STp->in_use) { - printk(ST_DEB_MSG "%s: Incorrect device.\n", name); + st_printk(ST_DEB_MSG, STp, "Incorrect device.\n"); retval = (-EIO); goto out; } ) /* end DEB */ @@ -3347,11 +3429,10 @@ * may try and take the device offline, in which case all further * access to the device is prohibited. */ - retval = scsi_nonblockable_ioctl(STp->device, cmd_in, p, - file->f_flags & O_NDELAY); - if (!scsi_block_when_processing_errors(STp->device) || retval != -ENODEV) + retval = scsi_ioctl_block_when_processing_errors(STp->device, cmd_in, + file->f_flags & O_NDELAY); + if (retval) goto out; - retval = 0; cmd_type = _IOC_TYPE(cmd_in); cmd_nr = _IOC_NR(cmd_in); @@ -3371,8 +3452,8 @@ } if (mtc.mt_op == MTSETDRVBUFFER && !capable(CAP_SYS_ADMIN)) { - printk(KERN_WARNING - "%s: MTSETDRVBUFFER only allowed for root.\n", name); + st_printk(KERN_WARNING, STp, + "MTSETDRVBUFFER only allowed for root.\n"); retval = (-EPERM); goto out; } @@ -3719,7 +3800,7 @@ static int enlarge_buffer(struct st_buffer * STbuffer, int new_size, int need_dma) { - int segs, nbr, max_segs, b_size, order, got; + int segs, max_segs, b_size, order, got; gfp_t priority; if (new_size <= STbuffer->buffer_size) @@ -3729,9 +3810,6 @@ normalize_buffer(STbuffer); /* Avoid extra segment */ max_segs = STbuffer->use_sg; - nbr = max_segs - STbuffer->frp_segs; - if (nbr <= 0) - return 0; priority = GFP_KERNEL | __GFP_NOWARN; if (need_dma) @@ -4005,6 +4083,7 @@ } cdev->owner = THIS_MODULE; cdev->ops = &st_fops; + STm->cdevs[rew] = cdev; error = cdev_add(cdev, cdev_devno, 1); if (error) { @@ -4013,7 +4092,6 @@ pr_err("st%d: Device not attached.\n", dev_num); goto out_free; } - STm->cdevs[rew] = cdev; i = mode << (4 - ST_NBR_MODE_BITS); snprintf(name, 10, "%s%s%s", rew ? "n" : "", @@ -4032,8 +4110,9 @@ return 0; out_free: cdev_del(STm->cdevs[rew]); - STm->cdevs[rew] = NULL; out: + STm->cdevs[rew] = NULL; + STm->devs[rew] = NULL; return error; } @@ -4083,29 +4162,34 @@ return -ENODEV; if ((stp = st_incompatible(SDp))) { sdev_printk(KERN_INFO, SDp, "Found incompatible tape\n"); - printk(KERN_INFO "st: The suggested driver is %s.\n", stp); + sdev_printk(KERN_INFO, SDp, + "st: The suggested driver is %s.\n", stp); return -ENODEV; } + scsi_autopm_get_device(SDp); i = queue_max_segments(SDp->request_queue); if (st_max_sg_segs < i) i = st_max_sg_segs; buffer = new_tape_buffer((SDp->host)->unchecked_isa_dma, i); if (buffer == NULL) { - printk(KERN_ERR - "st: Can't allocate new tape buffer. Device not attached.\n"); + sdev_printk(KERN_ERR, SDp, + "st: Can't allocate new tape buffer. " + "Device not attached.\n"); goto out; } disk = alloc_disk(1); if (!disk) { - printk(KERN_ERR "st: out of memory. Device not attached.\n"); + sdev_printk(KERN_ERR, SDp, + "st: out of memory. Device not attached.\n"); goto out_buffer_free; } tpnt = kzalloc(sizeof(struct scsi_tape), GFP_ATOMIC); if (tpnt == NULL) { - printk(KERN_ERR "st: Can't allocate device descriptor.\n"); + sdev_printk(KERN_ERR, SDp, + "st: Can't allocate device descriptor.\n"); goto out_put_disk; } kref_init(&tpnt->kref); @@ -4193,6 +4277,12 @@ } tpnt->index = error; sprintf(disk->disk_name, "st%d", tpnt->index); + tpnt->stats = kzalloc(sizeof(struct scsi_tape_stats), GFP_KERNEL); + if (tpnt->stats == NULL) { + sdev_printk(KERN_ERR, SDp, + "st: Can't allocate statistics.\n"); + goto out_idr_remove; + } dev_set_drvdata(dev, tpnt); @@ -4212,6 +4302,8 @@ out_remove_devs: remove_cdevs(tpnt); + kfree(tpnt->stats); +out_idr_remove: spin_lock(&st_index_lock); idr_remove(&st_index_idr, tpnt->index); spin_unlock(&st_index_lock); @@ -4223,6 +4315,7 @@ out_buffer_free: kfree(buffer); out: + scsi_autopm_put_device(SDp); return -ENODEV; }; @@ -4268,13 +4361,14 @@ disk->private_data = NULL; put_disk(disk); + kfree(tpnt->stats); kfree(tpnt); return; } static struct class st_sysfs_class = { .name = "scsi_tape", - .dev_attrs = st_dev_attrs, + .dev_groups = st_dev_groups, }; static int __init init_st(void) @@ -4286,6 +4380,12 @@ printk(KERN_INFO "st: Version %s, fixed bufsize %d, s/g segs %d\n", verstr, st_fixed_buffer_size, st_max_sg_segs); + debugging = (debug_flag > 0) ? debug_flag : NO_DEBUG; + if (debugging) { + printk(KERN_INFO "st: Debugging enabled debug_flag = %d\n", + debugging); + } + err = class_register(&st_sysfs_class); if (err) { pr_err("Unable register sysfs class for SCSI tapes\n"); @@ -4304,14 +4404,8 @@ 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); @@ -4322,11 +4416,11 @@ static void __exit exit_st(void) { - do_remove_sysfs_files(); scsi_unregister_driver(&st_template.gendrv); unregister_chrdev_region(MKDEV(SCSI_TAPE_MAJOR, 0), ST_MAX_TAPE_ENTRIES); class_unregister(&st_sysfs_class); + idr_destroy(&st_index_idr); printk(KERN_INFO "st: Unloaded.\n"); } @@ -4335,68 +4429,68 @@ /* The sysfs driver interface. Read-only at the moment */ -static ssize_t st_try_direct_io_show(struct device_driver *ddp, char *buf) +static ssize_t try_direct_io_show(struct device_driver *ddp, char *buf) { - return snprintf(buf, PAGE_SIZE, "%d\n", try_direct_io); + return scnprintf(buf, PAGE_SIZE, "%d\n", try_direct_io); } -static DRIVER_ATTR(try_direct_io, S_IRUGO, st_try_direct_io_show, NULL); +static DRIVER_ATTR_RO(try_direct_io); -static ssize_t st_fixed_buffer_size_show(struct device_driver *ddp, char *buf) +static ssize_t fixed_buffer_size_show(struct device_driver *ddp, char *buf) { - return snprintf(buf, PAGE_SIZE, "%d\n", st_fixed_buffer_size); + return scnprintf(buf, PAGE_SIZE, "%d\n", st_fixed_buffer_size); } -static DRIVER_ATTR(fixed_buffer_size, S_IRUGO, st_fixed_buffer_size_show, NULL); +static DRIVER_ATTR_RO(fixed_buffer_size); -static ssize_t st_max_sg_segs_show(struct device_driver *ddp, char *buf) +static ssize_t max_sg_segs_show(struct device_driver *ddp, char *buf) { - return snprintf(buf, PAGE_SIZE, "%d\n", st_max_sg_segs); + return scnprintf(buf, PAGE_SIZE, "%d\n", st_max_sg_segs); } -static DRIVER_ATTR(max_sg_segs, S_IRUGO, st_max_sg_segs_show, NULL); +static DRIVER_ATTR_RO(max_sg_segs); -static ssize_t st_version_show(struct device_driver *ddd, char *buf) +static ssize_t version_show(struct device_driver *ddd, char *buf) { - return snprintf(buf, PAGE_SIZE, "[%s]\n", verstr); + return scnprintf(buf, PAGE_SIZE, "[%s]\n", verstr); } -static DRIVER_ATTR(version, S_IRUGO, st_version_show, NULL); +static DRIVER_ATTR_RO(version); -static int do_create_sysfs_files(void) +#if DEBUG +static ssize_t debug_flag_store(struct device_driver *ddp, + const char *buf, size_t count) { - 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; - -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; +/* We only care what the first byte of the data is the rest is unused. + * if it's a '1' we turn on debug and if it's a '0' we disable it. All + * other values have -EINVAL returned if they are passed in. + */ + if (count > 0) { + if (buf[0] == '0') { + debugging = NO_DEBUG; + return count; + } else if (buf[0] == '1') { + debugging = 1; + return count; + } + } + return -EINVAL; } -static void do_remove_sysfs_files(void) +static ssize_t debug_flag_show(struct device_driver *ddp, char *buf) { - struct device_driver *sysfs = &st_template.gendrv; - - 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); + return scnprintf(buf, PAGE_SIZE, "%d\n", debugging); } +static DRIVER_ATTR_RW(debug_flag); +#endif + +static struct attribute *st_drv_attrs[] = { + &driver_attr_try_direct_io.attr, + &driver_attr_fixed_buffer_size.attr, + &driver_attr_max_sg_segs.attr, + &driver_attr_version.attr, +#if DEBUG + &driver_attr_debug_flag.attr, +#endif + NULL, +}; +ATTRIBUTE_GROUPS(st_drv); /* The sysfs simple class interface */ static ssize_t @@ -4408,6 +4502,7 @@ l = snprintf(buf, PAGE_SIZE, "%d\n", STm->defined); return l; } +static DEVICE_ATTR_RO(defined); static ssize_t default_blksize_show(struct device *dev, struct device_attribute *attr, @@ -4419,7 +4514,7 @@ l = snprintf(buf, PAGE_SIZE, "%d\n", STm->default_blksize); return l; } - +static DEVICE_ATTR_RO(default_blksize); static ssize_t default_density_show(struct device *dev, struct device_attribute *attr, @@ -4433,6 +4528,7 @@ l = snprintf(buf, PAGE_SIZE, fmt, STm->default_density); return l; } +static DEVICE_ATTR_RO(default_density); static ssize_t default_compression_show(struct device *dev, struct device_attribute *attr, @@ -4444,6 +4540,7 @@ l = snprintf(buf, PAGE_SIZE, "%d\n", STm->default_compression - 1); return l; } +static DEVICE_ATTR_RO(default_compression); static ssize_t options_show(struct device *dev, struct device_attribute *attr, char *buf) @@ -4472,14 +4569,222 @@ l = snprintf(buf, PAGE_SIZE, "0x%08x\n", options); return l; } +static DEVICE_ATTR_RO(options); + +/* Support for tape stats */ + +/** + * read_cnt_show - return read count - count of reads made from tape drive + * @dev: struct device + * @attr: attribute structure + * @buf: buffer to return formatted data in + */ +static ssize_t read_cnt_show(struct device *dev, + struct device_attribute *attr, char *buf) +{ + struct st_modedef *STm = dev_get_drvdata(dev); + + return sprintf(buf, "%lld", + (long long)atomic64_read(&STm->tape->stats->read_cnt)); +} +static DEVICE_ATTR_RO(read_cnt); + +/** + * read_byte_cnt_show - return read byte count - tape drives + * may use blocks less than 512 bytes this gives the raw byte count of + * of data read from the tape drive. + * @dev: struct device + * @attr: attribute structure + * @buf: buffer to return formatted data in + */ +static ssize_t read_byte_cnt_show(struct device *dev, + struct device_attribute *attr, char *buf) +{ + struct st_modedef *STm = dev_get_drvdata(dev); + + return sprintf(buf, "%lld", + (long long)atomic64_read(&STm->tape->stats->read_byte_cnt)); +} +static DEVICE_ATTR_RO(read_byte_cnt); + +/** + * read_us_show - return read us - overall time spent waiting on reads in ns. + * @dev: struct device + * @attr: attribute structure + * @buf: buffer to return formatted data in + */ +static ssize_t read_ns_show(struct device *dev, + struct device_attribute *attr, char *buf) +{ + struct st_modedef *STm = dev_get_drvdata(dev); + + return sprintf(buf, "%lld", + (long long)atomic64_read(&STm->tape->stats->tot_read_time)); +} +static DEVICE_ATTR_RO(read_ns); + +/** + * write_cnt_show - write count - number of user calls + * to write(2) that have written data to tape. + * @dev: struct device + * @attr: attribute structure + * @buf: buffer to return formatted data in + */ +static ssize_t write_cnt_show(struct device *dev, + struct device_attribute *attr, char *buf) +{ + struct st_modedef *STm = dev_get_drvdata(dev); + + return sprintf(buf, "%lld", + (long long)atomic64_read(&STm->tape->stats->write_cnt)); +} +static DEVICE_ATTR_RO(write_cnt); + +/** + * write_byte_cnt_show - write byte count - raw count of + * bytes written to tape. + * @dev: struct device + * @attr: attribute structure + * @buf: buffer to return formatted data in + */ +static ssize_t write_byte_cnt_show(struct device *dev, + struct device_attribute *attr, char *buf) +{ + struct st_modedef *STm = dev_get_drvdata(dev); + + return sprintf(buf, "%lld", + (long long)atomic64_read(&STm->tape->stats->write_byte_cnt)); +} +static DEVICE_ATTR_RO(write_byte_cnt); + +/** + * write_ns_show - write ns - number of nanoseconds waiting on write + * requests to complete. + * @dev: struct device + * @attr: attribute structure + * @buf: buffer to return formatted data in + */ +static ssize_t write_ns_show(struct device *dev, + struct device_attribute *attr, char *buf) +{ + struct st_modedef *STm = dev_get_drvdata(dev); + + return sprintf(buf, "%lld", + (long long)atomic64_read(&STm->tape->stats->tot_write_time)); +} +static DEVICE_ATTR_RO(write_ns); + +/** + * in_flight_show - number of I/Os currently in flight - + * in most cases this will be either 0 or 1. It may be higher if someone + * has also issued other SCSI commands such as via an ioctl. + * @dev: struct device + * @attr: attribute structure + * @buf: buffer to return formatted data in + */ +static ssize_t in_flight_show(struct device *dev, + struct device_attribute *attr, char *buf) +{ + struct st_modedef *STm = dev_get_drvdata(dev); + + return sprintf(buf, "%lld", + (long long)atomic64_read(&STm->tape->stats->in_flight)); +} +static DEVICE_ATTR_RO(in_flight); + +/** + * io_ns_show - io wait ns - this is the number of ns spent + * waiting on all I/O to complete. This includes tape movement commands + * such as rewinding, seeking to end of file or tape, it also includes + * read and write. To determine the time spent on tape movement + * subtract the read and write ns from this value. + * @dev: struct device + * @attr: attribute structure + * @buf: buffer to return formatted data in + */ +static ssize_t io_ns_show(struct device *dev, + struct device_attribute *attr, char *buf) +{ + struct st_modedef *STm = dev_get_drvdata(dev); + + return sprintf(buf, "%lld", + (long long)atomic64_read(&STm->tape->stats->tot_io_time)); +} +static DEVICE_ATTR_RO(io_ns); + +/** + * other_cnt_show - other io count - this is the number of + * I/O requests other than read and write requests. + * Typically these are tape movement requests but will include driver + * tape movement. This includes only requests issued by the st driver. + * @dev: struct device + * @attr: attribute structure + * @buf: buffer to return formatted data in + */ +static ssize_t other_cnt_show(struct device *dev, + struct device_attribute *attr, char *buf) +{ + struct st_modedef *STm = dev_get_drvdata(dev); + + return sprintf(buf, "%lld", + (long long)atomic64_read(&STm->tape->stats->other_cnt)); +} +static DEVICE_ATTR_RO(other_cnt); + +/** + * resid_cnt_show - A count of the number of times we get a residual + * count - this should indicate someone issuing reads larger than the + * block size on tape. + * @dev: struct device + * @attr: attribute structure + * @buf: buffer to return formatted data in + */ +static ssize_t resid_cnt_show(struct device *dev, + struct device_attribute *attr, char *buf) +{ + struct st_modedef *STm = dev_get_drvdata(dev); + + return sprintf(buf, "%lld", + (long long)atomic64_read(&STm->tape->stats->resid_cnt)); +} +static DEVICE_ATTR_RO(resid_cnt); + +static struct attribute *st_dev_attrs[] = { + &dev_attr_defined.attr, + &dev_attr_default_blksize.attr, + &dev_attr_default_density.attr, + &dev_attr_default_compression.attr, + &dev_attr_options.attr, + NULL, +}; + +static struct attribute *st_stats_attrs[] = { + &dev_attr_read_cnt.attr, + &dev_attr_read_byte_cnt.attr, + &dev_attr_read_ns.attr, + &dev_attr_write_cnt.attr, + &dev_attr_write_byte_cnt.attr, + &dev_attr_write_ns.attr, + &dev_attr_in_flight.attr, + &dev_attr_io_ns.attr, + &dev_attr_other_cnt.attr, + &dev_attr_resid_cnt.attr, + NULL, +}; + +static struct attribute_group stats_group = { + .name = "stats", + .attrs = st_stats_attrs, +}; + +static struct attribute_group st_group = { + .attrs = st_dev_attrs, +}; -static struct device_attribute st_dev_attrs[] = { - __ATTR_RO(defined), - __ATTR_RO(default_blksize), - __ATTR_RO(default_density), - __ATTR_RO(default_compression), - __ATTR_RO(options), - __ATTR_NULL, +static const struct attribute_group *st_dev_groups[] = { + &st_group, + &stats_group, + NULL, }; /* The following functions may be useful for a larger audience. */ @@ -4510,18 +4815,15 @@ return -ENOMEM; /* Try to fault in all of the necessary pages */ - down_read(¤t->mm->mmap_sem); /* rw==READ means read from drive, write into memory area */ - res = get_user_pages( + res = get_user_pages_unlocked( current, current->mm, uaddr, nr_pages, rw == READ, 0, /* don't force */ - pages, - NULL); - up_read(¤t->mm->mmap_sem); + pages); /* Errors and no page mapped should return here */ if (res < nr_pages)