Last modified: 18-JAN-1998 Richard Gooch <rgooch@atnf.csiro.au> Devfs support
*/
-static const char *verstr = "20080224";
+static const char *verstr = "20080504";
#include <linux/module.h>
#include <linux/cdev.h>
#include <linux/delay.h>
#include <linux/mutex.h>
+#include <linux/smp_lock.h>
#include <asm/uaccess.h>
#include <asm/dma.h>
/* Flush the write buffer (never need to write if variable blocksize). */
static int st_flush_write_buffer(struct scsi_tape * STp)
{
- int offset, transfer, blks;
+ int transfer, blks;
int result;
unsigned char cmd[MAX_COMMAND_SIZE];
struct st_request *SRpnt;
result = 0;
if (STp->dirty == 1) {
- offset = (STp->buffer)->buffer_bytes;
- transfer = ((offset + STp->block_size - 1) /
- STp->block_size) * STp->block_size;
+ transfer = STp->buffer->buffer_bytes;
DEBC(printk(ST_DEB_MSG "%s: Flushing %d bytes.\n",
tape_name(STp), transfer));
- memset((STp->buffer)->b_data + offset, 0, transfer - offset);
-
memset(cmd, 0, MAX_COMMAND_SIZE);
cmd[0] = WRITE_6;
cmd[1] = 1;
}
-\f/* Open the device. Needs to be called with BKL only because of incrementing the SCSI host
+\f/* Open the device. Needs to take the BKL only because of incrementing the SCSI host
module count. */
static int st_open(struct inode *inode, struct file *filp)
{
int dev = TAPE_NR(inode);
char *name;
+ lock_kernel();
/*
* We really want to do nonseekable_open(inode, filp); here, but some
* versions of tar incorrectly call lseek on tapes and bail out if that
*/
filp->f_mode &= ~(FMODE_PREAD | FMODE_PWRITE);
- if (!(STp = scsi_tape_get(dev)))
+ if (!(STp = scsi_tape_get(dev))) {
+ unlock_kernel();
return -ENXIO;
+ }
write_lock(&st_dev_arr_lock);
filp->private_data = STp;
if (STp->in_use) {
write_unlock(&st_dev_arr_lock);
scsi_tape_put(STp);
+ unlock_kernel();
DEB( printk(ST_DEB_MSG "%s: Device already in use.\n", name); )
return (-EBUSY);
}
retval = (-EIO);
goto err_out;
}
+ unlock_kernel();
return 0;
err_out:
normalize_buffer(STp->buffer);
STp->in_use = 0;
scsi_tape_put(STp);
+ unlock_kernel();
return retval;
}
if (undone <= do_count) {
/* Only data from this write is not written */
count += undone;
+ b_point -= undone;
do_count -= undone;
if (STp->block_size)
blks = (transfer - undone) / STp->block_size;