patch-2.4.0-test6 linux/drivers/scsi/st.c
Next file: linux/drivers/sgi/Makefile
Previous file: linux/drivers/scsi/sg.c
Back to the patch index
Back to the overall index
- Lines: 232
- Date:
Mon Aug 7 22:52:10 2000
- Orig file:
v2.4.0-test5/linux/drivers/scsi/st.c
- Orig date:
Fri Jul 14 12:12:12 2000
diff -u --recursive --new-file v2.4.0-test5/linux/drivers/scsi/st.c linux/drivers/scsi/st.c
@@ -12,10 +12,13 @@
Copyright 1992 - 2000 Kai Makisara
email Kai.Makisara@metla.fi
- Last modified: Sat Jun 17 15:21:49 2000 by makisara@kai.makisara.local
+ Last modified: Sun Aug 6 23:02:13 2000 by makisara@kai.makisara.local
Some small formal changes - aeb, 950809
Last modified: 18-JAN-1998 Richard Gooch <rgooch@atnf.csiro.au> Devfs support
+
+ Reminder: write_lock_irqsave() can be replaced by write_lock() when the old SCSI
+ error handling will be discarded.
*/
#include <linux/module.h>
@@ -141,7 +144,7 @@
static int modes_defined;
-static ST_buffer *new_tape_buffer(int, int);
+static ST_buffer *new_tape_buffer(int, int, int);
static int enlarge_buffer(ST_buffer *, int, int);
static void normalize_buffer(ST_buffer *);
static int append_to_buffer(const char *, ST_buffer *, int);
@@ -587,10 +590,11 @@
}
-/* Open the device */
-static int scsi_tape_open(struct inode *inode, struct file *filp)
+/* Open the device. Needs to be called with BKL only because of incrementing the SCSI host
+ module count. */
+static int st_open(struct inode *inode, struct file *filp)
{
- unsigned short flags;
+ unsigned short st_flags;
int i, need_dma_buffer, new_session = FALSE;
int retval;
unsigned char cmd[MAX_COMMAND_SIZE];
@@ -600,28 +604,32 @@
ST_partstat *STps;
int dev = TAPE_NR(inode->i_rdev);
int mode = TAPE_MODE(inode->i_rdev);
+ unsigned long flags;
- read_lock(&st_dev_arr_lock);
+ write_lock_irqsave(&st_dev_arr_lock, flags);
STp = scsi_tapes[dev];
if (dev >= st_template.dev_max || STp == NULL) {
- read_unlock(&st_dev_arr_lock);
+ write_unlock_irqrestore(&st_dev_arr_lock, flags);
return (-ENXIO);
}
- read_unlock(&st_dev_arr_lock);
- if (!scsi_block_when_processing_errors(STp->device)) {
- return -ENXIO;
- }
if (STp->in_use) {
+ write_unlock_irqrestore(&st_dev_arr_lock, flags);
DEB( printk(ST_DEB_MSG "st%d: Device already in use.\n", dev); )
return (-EBUSY);
}
STp->in_use = 1;
+ write_unlock_irqrestore(&st_dev_arr_lock, flags);
STp->rew_at_close = STp->autorew_dev = (MINOR(inode->i_rdev) & 0x80) == 0;
if (STp->device->host->hostt->module)
__MOD_INC_USE_COUNT(STp->device->host->hostt->module);
+ if (!scsi_block_when_processing_errors(STp->device)) {
+ retval = (-ENXIO);
+ goto err_out;
+ }
+
if (mode != STp->current_mode) {
DEBC(printk(ST_DEB_MSG "st%d: Mode change from %d to %d.\n",
dev, STp->current_mode, mode));
@@ -632,16 +640,17 @@
/* Allocate a buffer for this user */
need_dma_buffer = STp->restr_dma;
- read_lock(&st_dev_arr_lock);
+ write_lock_irqsave(&st_dev_arr_lock, flags);
for (i = 0; i < st_nbr_buffers; i++)
if (!st_buffers[i]->in_use &&
(!need_dma_buffer || st_buffers[i]->dma)) {
STp->buffer = st_buffers[i];
+ (STp->buffer)->in_use = 1;
break;
}
- read_unlock(&st_dev_arr_lock);
+ write_unlock_irqrestore(&st_dev_arr_lock, flags);
if (i >= st_nbr_buffers) {
- STp->buffer = new_tape_buffer(FALSE, need_dma_buffer);
+ STp->buffer = new_tape_buffer(FALSE, need_dma_buffer, TRUE);
if (STp->buffer == NULL) {
printk(KERN_WARNING "st%d: Can't allocate tape buffer.\n", dev);
retval = (-EBUSY);
@@ -649,7 +658,6 @@
}
}
- (STp->buffer)->in_use = 1;
(STp->buffer)->writing = 0;
(STp->buffer)->syscall_result = 0;
(STp->buffer)->use_sg = STp->device->host->sg_tablesize;
@@ -663,8 +671,8 @@
(STp->buffer)->buffer_size += (STp->buffer)->sg[i].length;
}
- flags = filp->f_flags;
- STp->write_prot = ((flags & O_ACCMODE) == O_RDONLY);
+ st_flags = filp->f_flags;
+ STp->write_prot = ((st_flags & O_ACCMODE) == O_RDONLY);
STp->dirty = 0;
for (i = 0; i < ST_NBR_PARTITIONS; i++) {
@@ -813,7 +821,7 @@
DEBC(printk(ST_DEB_MSG "st%d: Write protected\n", dev));
- if ((flags & O_ACCMODE) == O_WRONLY || (flags & O_ACCMODE) == O_RDWR) {
+ if ((st_flags & O_ACCMODE) == O_WRONLY || (st_flags & O_ACCMODE) == O_RDWR) {
retval = (-EROFS);
goto err_out;
}
@@ -864,7 +872,7 @@
/* Flush the tape buffer before close */
-static int scsi_tape_flush(struct file *filp)
+static int st_flush(struct file *filp)
{
int result = 0, result2;
unsigned char cmd[MAX_COMMAND_SIZE];
@@ -982,17 +990,18 @@
}
-/* Close the device and release it */
-static int scsi_tape_close(struct inode *inode, struct file *filp)
+/* Close the device and release it. BKL is not needed: this is the only thread
+ accessing this tape. */
+static int st_release(struct inode *inode, struct file *filp)
{
int result = 0;
Scsi_Tape *STp;
+ unsigned long flags;
kdev_t devt = inode->i_rdev;
int dev;
dev = TAPE_NR(devt);
- lock_kernel();
read_lock(&st_dev_arr_lock);
STp = scsi_tapes[dev];
read_unlock(&st_dev_arr_lock);
@@ -1002,13 +1011,18 @@
if (STp->buffer != NULL) {
normalize_buffer(STp->buffer);
+ write_lock_irqsave(&st_dev_arr_lock, flags);
(STp->buffer)->in_use = 0;
+ STp->buffer = NULL;
+ }
+ else {
+ write_lock_irqsave(&st_dev_arr_lock, flags);
}
STp->in_use = 0;
+ write_unlock_irqrestore(&st_dev_arr_lock, flags);
if (STp->device->host->hostt->module)
__MOD_DEC_USE_COUNT(STp->device->host->hostt->module);
- unlock_kernel();
return result;
}
@@ -1452,8 +1466,11 @@
if (SRpnt->sr_sense_buffer[2] & 0x20) { /* ILI */
if (STp->block_size == 0) {
- if (transfer <= 0)
- transfer = 0;
+ if (transfer < 0) {
+ if (STps->drv_block >= 0)
+ STps->drv_block += 1;
+ return (-ENOMEM);
+ }
(STp->buffer)->buffer_bytes = bytes - transfer;
} else {
scsi_release_request(SRpnt);
@@ -3112,7 +3129,7 @@
/* Try to allocate a new tape buffer. Calling function must not hold
dev_arr_lock. */
static ST_buffer *
- new_tape_buffer(int from_initialization, int need_dma)
+ new_tape_buffer(int from_initialization, int need_dma, int in_use)
{
int i, priority, b_size, order, got = 0, segs = 0;
unsigned long flags;
@@ -3205,7 +3222,7 @@
"st: segment sizes: first %d, last %d bytes.\n",
tb->sg[0].length, tb->sg[segs - 1].length);
)
- tb->in_use = 0;
+ tb->in_use = in_use;
tb->dma = need_dma;
tb->buffer_size = got;
tb->writing = 0;
@@ -3429,9 +3446,9 @@
read: st_read,
write: st_write,
ioctl: st_ioctl,
- open: scsi_tape_open,
- flush: scsi_tape_flush,
- release: scsi_tape_close,
+ open: st_open,
+ flush: st_flush,
+ release: st_release,
};
static int st_attach(Scsi_Device * SDp)
@@ -3595,7 +3612,7 @@
if (target_nbr > st_max_buffers)
target_nbr = st_max_buffers;
for (i=st_nbr_buffers; i < target_nbr; i++)
- if (!new_tape_buffer(TRUE, TRUE)) {
+ if (!new_tape_buffer(TRUE, TRUE, FALSE)) {
printk(KERN_INFO "st: Unable to allocate new static buffer.\n");
break;
}
FUNET's LINUX-ADM group, linux-adm@nic.funet.fi
TCL-scripts by Sam Shen (who was at: slshen@lbl.gov)