aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/scsi
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/scsi')
-rw-r--r--drivers/scsi/3w-9xxx.c3
-rw-r--r--drivers/scsi/3w-xxxx.c3
-rw-r--r--drivers/scsi/aacraid/linit.c3
-rw-r--r--drivers/scsi/ch.c4
-rw-r--r--drivers/scsi/dpt_i2o.c5
-rw-r--r--drivers/scsi/esp_scsi.c22
-rw-r--r--drivers/scsi/gdth.c3
-rw-r--r--drivers/scsi/ipr.c6
-rw-r--r--drivers/scsi/megaraid.c5
-rw-r--r--drivers/scsi/megaraid/megaraid_mm.c2
-rw-r--r--drivers/scsi/megaraid/megaraid_sas.c2
-rw-r--r--drivers/scsi/osst.c15
-rw-r--r--drivers/scsi/scsi_lib.c9
-rw-r--r--drivers/scsi/scsi_tgt_if.c2
-rw-r--r--drivers/scsi/ses.c2
-rw-r--r--drivers/scsi/sg.c60
-rw-r--r--drivers/scsi/sr.c20
-rw-r--r--drivers/scsi/st.c11
18 files changed, 116 insertions, 61 deletions
diff --git a/drivers/scsi/3w-9xxx.c b/drivers/scsi/3w-9xxx.c
index 867f6fd5c2c0..7045511f9ad2 100644
--- a/drivers/scsi/3w-9xxx.c
+++ b/drivers/scsi/3w-9xxx.c
@@ -84,6 +84,7 @@
#include <linux/pci.h>
#include <linux/time.h>
#include <linux/mutex.h>
+#include <linux/smp_lock.h>
#include <asm/io.h>
#include <asm/irq.h>
#include <asm/uaccess.h>
@@ -862,11 +863,13 @@ out:
} /* End twa_chrdev_ioctl() */
/* This function handles open for the character device */
+/* NOTE that this function will race with remove. */
static int twa_chrdev_open(struct inode *inode, struct file *file)
{
unsigned int minor_number;
int retval = TW_IOCTL_ERROR_OS_ENODEV;
+ cycle_kernel_lock();
minor_number = iminor(inode);
if (minor_number >= twa_device_extension_count)
goto out;
diff --git a/drivers/scsi/3w-xxxx.c b/drivers/scsi/3w-xxxx.c
index 8c22329aa85e..a0537f09aa21 100644
--- a/drivers/scsi/3w-xxxx.c
+++ b/drivers/scsi/3w-xxxx.c
@@ -198,6 +198,7 @@
#include <linux/module.h>
#include <linux/reboot.h>
+#include <linux/smp_lock.h>
#include <linux/spinlock.h>
#include <linux/interrupt.h>
#include <linux/moduleparam.h>
@@ -1027,10 +1028,12 @@ out:
} /* End tw_chrdev_ioctl() */
/* This function handles open for the character device */
+/* NOTE that this function races with remove. */
static int tw_chrdev_open(struct inode *inode, struct file *file)
{
unsigned int minor_number;
+ cycle_kernel_lock();
dprintk(KERN_WARNING "3w-xxxx: tw_ioctl_open()\n");
minor_number = iminor(inode);
diff --git a/drivers/scsi/aacraid/linit.c b/drivers/scsi/aacraid/linit.c
index 1f7c83607f84..68c140e82673 100644
--- a/drivers/scsi/aacraid/linit.c
+++ b/drivers/scsi/aacraid/linit.c
@@ -38,6 +38,7 @@
#include <linux/moduleparam.h>
#include <linux/pci.h>
#include <linux/slab.h>
+#include <linux/smp_lock.h>
#include <linux/spinlock.h>
#include <linux/syscalls.h>
#include <linux/delay.h>
@@ -667,6 +668,7 @@ static int aac_cfg_open(struct inode *inode, struct file *file)
unsigned minor_number = iminor(inode);
int err = -ENODEV;
+ lock_kernel(); /* BKL pushdown: nothing else protects this list */
list_for_each_entry(aac, &aac_devices, entry) {
if (aac->id == minor_number) {
file->private_data = aac;
@@ -674,6 +676,7 @@ static int aac_cfg_open(struct inode *inode, struct file *file)
break;
}
}
+ unlock_kernel();
return err;
}
diff --git a/drivers/scsi/ch.c b/drivers/scsi/ch.c
index c4b938bc30d3..aa2011b64683 100644
--- a/drivers/scsi/ch.c
+++ b/drivers/scsi/ch.c
@@ -22,6 +22,7 @@
#include <linux/chio.h> /* here are all the ioctls */
#include <linux/mutex.h>
#include <linux/idr.h>
+#include <linux/smp_lock.h>
#include <scsi/scsi.h>
#include <scsi/scsi_cmnd.h>
@@ -571,16 +572,19 @@ ch_open(struct inode *inode, struct file *file)
scsi_changer *ch;
int minor = iminor(inode);
+ lock_kernel();
spin_lock(&ch_index_lock);
ch = idr_find(&ch_index_idr, minor);
if (NULL == ch || scsi_device_get(ch->device)) {
spin_unlock(&ch_index_lock);
+ unlock_kernel();
return -ENXIO;
}
spin_unlock(&ch_index_lock);
file->private_data = ch;
+ unlock_kernel();
return 0;
}
diff --git a/drivers/scsi/dpt_i2o.c b/drivers/scsi/dpt_i2o.c
index 8508816f303d..2bc30e32b67a 100644
--- a/drivers/scsi/dpt_i2o.c
+++ b/drivers/scsi/dpt_i2o.c
@@ -49,6 +49,7 @@ MODULE_DESCRIPTION("Adaptec I2O RAID Driver");
#include <linux/kernel.h> /* for printk */
#include <linux/sched.h>
#include <linux/reboot.h>
+#include <linux/smp_lock.h>
#include <linux/spinlock.h>
#include <linux/dma-mapping.h>
@@ -1727,10 +1728,12 @@ static int adpt_open(struct inode *inode, struct file *file)
int minor;
adpt_hba* pHba;
+ lock_kernel();
//TODO check for root access
//
minor = iminor(inode);
if (minor >= hba_count) {
+ unlock_kernel();
return -ENXIO;
}
mutex_lock(&adpt_configuration_lock);
@@ -1741,6 +1744,7 @@ static int adpt_open(struct inode *inode, struct file *file)
}
if (pHba == NULL) {
mutex_unlock(&adpt_configuration_lock);
+ unlock_kernel();
return -ENXIO;
}
@@ -1751,6 +1755,7 @@ static int adpt_open(struct inode *inode, struct file *file)
pHba->in_use = 1;
mutex_unlock(&adpt_configuration_lock);
+ unlock_kernel();
return 0;
}
diff --git a/drivers/scsi/esp_scsi.c b/drivers/scsi/esp_scsi.c
index a0b6d414953d..59fbef08d690 100644
--- a/drivers/scsi/esp_scsi.c
+++ b/drivers/scsi/esp_scsi.c
@@ -2359,6 +2359,24 @@ void scsi_esp_unregister(struct esp *esp)
}
EXPORT_SYMBOL(scsi_esp_unregister);
+static int esp_target_alloc(struct scsi_target *starget)
+{
+ struct esp *esp = shost_priv(dev_to_shost(&starget->dev));
+ struct esp_target_data *tp = &esp->target[starget->id];
+
+ tp->starget = starget;
+
+ return 0;
+}
+
+static void esp_target_destroy(struct scsi_target *starget)
+{
+ struct esp *esp = shost_priv(dev_to_shost(&starget->dev));
+ struct esp_target_data *tp = &esp->target[starget->id];
+
+ tp->starget = NULL;
+}
+
static int esp_slave_alloc(struct scsi_device *dev)
{
struct esp *esp = shost_priv(dev->host);
@@ -2370,8 +2388,6 @@ static int esp_slave_alloc(struct scsi_device *dev)
return -ENOMEM;
dev->hostdata = lp;
- tp->starget = dev->sdev_target;
-
spi_min_period(tp->starget) = esp->min_period;
spi_max_offset(tp->starget) = 15;
@@ -2608,6 +2624,8 @@ struct scsi_host_template scsi_esp_template = {
.name = "esp",
.info = esp_info,
.queuecommand = esp_queuecommand,
+ .target_alloc = esp_target_alloc,
+ .target_destroy = esp_target_destroy,
.slave_alloc = esp_slave_alloc,
.slave_configure = esp_slave_configure,
.slave_destroy = esp_slave_destroy,
diff --git a/drivers/scsi/gdth.c b/drivers/scsi/gdth.c
index 46771d4c81bd..822d5214692b 100644
--- a/drivers/scsi/gdth.c
+++ b/drivers/scsi/gdth.c
@@ -120,6 +120,7 @@
#include <linux/timer.h>
#include <linux/dma-mapping.h>
#include <linux/list.h>
+#include <linux/smp_lock.h>
#ifdef GDTH_RTC
#include <linux/mc146818rtc.h>
@@ -4019,10 +4020,12 @@ static int gdth_open(struct inode *inode, struct file *filep)
{
gdth_ha_str *ha;
+ lock_kernel();
list_for_each_entry(ha, &gdth_instances, list) {
if (!ha->sdev)
ha->sdev = scsi_get_host_dev(ha->shost);
}
+ unlock_kernel();
TRACE(("gdth_open()\n"));
return 0;
diff --git a/drivers/scsi/ipr.c b/drivers/scsi/ipr.c
index 999e91ea7451..e7a3a6554425 100644
--- a/drivers/scsi/ipr.c
+++ b/drivers/scsi/ipr.c
@@ -71,6 +71,7 @@
#include <linux/module.h>
#include <linux/moduleparam.h>
#include <linux/libata.h>
+#include <linux/hdreg.h>
#include <asm/io.h>
#include <asm/irq.h>
#include <asm/processor.h>
@@ -4913,8 +4914,11 @@ static int ipr_ioctl(struct scsi_device *sdev, int cmd, void __user *arg)
struct ipr_resource_entry *res;
res = (struct ipr_resource_entry *)sdev->hostdata;
- if (res && ipr_is_gata(res))
+ if (res && ipr_is_gata(res)) {
+ if (cmd == HDIO_GET_IDENTITY)
+ return -ENOTTY;
return ata_scsi_ioctl(sdev, cmd, arg);
+ }
return -EINVAL;
}
diff --git a/drivers/scsi/megaraid.c b/drivers/scsi/megaraid.c
index 18551aaf5e09..28c9da7d4a5c 100644
--- a/drivers/scsi/megaraid.c
+++ b/drivers/scsi/megaraid.c
@@ -46,6 +46,7 @@
#include <linux/pci.h>
#include <linux/init.h>
#include <linux/dma-mapping.h>
+#include <linux/smp_lock.h>
#include <scsi/scsicam.h>
#include "scsi.h"
@@ -3272,12 +3273,12 @@ mega_init_scb(adapter_t *adapter)
* @filep - unused
*
* Routines for the character/ioctl interface to the driver. Find out if this
- * is a valid open. If yes, increment the module use count so that it cannot
- * be unloaded.
+ * is a valid open.
*/
static int
megadev_open (struct inode *inode, struct file *filep)
{
+ cycle_kernel_lock();
/*
* Only allow superuser to access private ioctl interface
*/
diff --git a/drivers/scsi/megaraid/megaraid_mm.c b/drivers/scsi/megaraid/megaraid_mm.c
index 0ad215e27b83..ac3b280c2a72 100644
--- a/drivers/scsi/megaraid/megaraid_mm.c
+++ b/drivers/scsi/megaraid/megaraid_mm.c
@@ -15,6 +15,7 @@
* Common management module
*/
#include <linux/sched.h>
+#include <linux/smp_lock.h>
#include "megaraid_mm.h"
@@ -96,6 +97,7 @@ mraid_mm_open(struct inode *inode, struct file *filep)
*/
if (!capable(CAP_SYS_ADMIN)) return (-EACCES);
+ cycle_kernel_lock();
return 0;
}
diff --git a/drivers/scsi/megaraid/megaraid_sas.c b/drivers/scsi/megaraid/megaraid_sas.c
index 7d84c8bbcf3f..fc7ac158476c 100644
--- a/drivers/scsi/megaraid/megaraid_sas.c
+++ b/drivers/scsi/megaraid/megaraid_sas.c
@@ -33,6 +33,7 @@
#include <linux/spinlock.h>
#include <linux/interrupt.h>
#include <linux/delay.h>
+#include <linux/smp_lock.h>
#include <linux/uio.h>
#include <asm/uaccess.h>
#include <linux/fs.h>
@@ -2863,6 +2864,7 @@ static void megasas_shutdown(struct pci_dev *pdev)
*/
static int megasas_mgmt_open(struct inode *inode, struct file *filep)
{
+ cycle_kernel_lock();
/*
* Allow only those users with admin rights
*/
diff --git a/drivers/scsi/osst.c b/drivers/scsi/osst.c
index 243d8becd30f..1c79f9794f4e 100644
--- a/drivers/scsi/osst.c
+++ b/drivers/scsi/osst.c
@@ -50,6 +50,7 @@ static const char * osst_version = "0.99.4";
#include <linux/moduleparam.h>
#include <linux/delay.h>
#include <linux/jiffies.h>
+#include <linux/smp_lock.h>
#include <asm/uaccess.h>
#include <asm/dma.h>
#include <asm/system.h>
@@ -4359,7 +4360,7 @@ os_bypass:
/* Open the device */
-static int os_scsi_tape_open(struct inode * inode, struct file * filp)
+static int __os_scsi_tape_open(struct inode * inode, struct file * filp)
{
unsigned short flags;
int i, b_size, new_session = 0, retval = 0;
@@ -4725,6 +4726,18 @@ err_out:
return retval;
}
+/* BKL pushdown: spaghetti avoidance wrapper */
+static int os_scsi_tape_open(struct inode * inode, struct file * filp)
+{
+ int ret;
+
+ lock_kernel();
+ ret = __os_scsi_tape_open(inode, filp);
+ unlock_kernel();
+ return ret;
+}
+
+
/* Flush the tape buffer before close */
static int os_scsi_tape_flush(struct file * filp, fl_owner_t id)
diff --git a/drivers/scsi/scsi_lib.c b/drivers/scsi/scsi_lib.c
index a82d2fe80fb5..cbf55d59a54c 100644
--- a/drivers/scsi/scsi_lib.c
+++ b/drivers/scsi/scsi_lib.c
@@ -207,6 +207,15 @@ int scsi_execute(struct scsi_device *sdev, const unsigned char *cmd,
*/
blk_execute_rq(req->q, NULL, req, 1);
+ /*
+ * Some devices (USB mass-storage in particular) may transfer
+ * garbage data together with a residue indicating that the data
+ * is invalid. Prevent the garbage from being misinterpreted
+ * and prevent security leaks by zeroing out the excess data.
+ */
+ if (unlikely(req->data_len > 0 && req->data_len <= bufflen))
+ memset(buffer + (bufflen - req->data_len), 0, req->data_len);
+
ret = req->errors;
out:
blk_put_request(req);
diff --git a/drivers/scsi/scsi_tgt_if.c b/drivers/scsi/scsi_tgt_if.c
index d2557dbc2dc1..0e9533f7aabc 100644
--- a/drivers/scsi/scsi_tgt_if.c
+++ b/drivers/scsi/scsi_tgt_if.c
@@ -21,6 +21,7 @@
*/
#include <linux/miscdevice.h>
#include <linux/file.h>
+#include <linux/smp_lock.h>
#include <net/tcp.h>
#include <scsi/scsi.h>
#include <scsi/scsi_cmnd.h>
@@ -321,6 +322,7 @@ static int tgt_open(struct inode *inode, struct file *file)
{
tx_ring.tr_idx = rx_ring.tr_idx = 0;
+ cycle_kernel_lock();
return 0;
}
diff --git a/drivers/scsi/ses.c b/drivers/scsi/ses.c
index 45df83b9d847..0fe031f003e7 100644
--- a/drivers/scsi/ses.c
+++ b/drivers/scsi/ses.c
@@ -61,7 +61,7 @@ static int ses_probe(struct device *dev)
return err;
}
-#define SES_TIMEOUT 30
+#define SES_TIMEOUT (30 * HZ)
#define SES_RETRIES 3
static int ses_recv_diag(struct scsi_device *sdev, int page_code,
diff --git a/drivers/scsi/sg.c b/drivers/scsi/sg.c
index ea0edd1b2e76..fccd2e88d600 100644
--- a/drivers/scsi/sg.c
+++ b/drivers/scsi/sg.c
@@ -49,6 +49,7 @@ static int sg_version_num = 30534; /* 2 digits for each component */
#include <linux/delay.h>
#include <linux/scatterlist.h>
#include <linux/blktrace_api.h>
+#include <linux/smp_lock.h>
#include "scsi.h"
#include <scsi/scsi_dbg.h>
@@ -182,8 +183,9 @@ static int sg_build_sgat(Sg_scatter_hold * schp, const Sg_fd * sfp,
int tablesize);
static ssize_t sg_new_read(Sg_fd * sfp, char __user *buf, size_t count,
Sg_request * srp);
-static ssize_t sg_new_write(Sg_fd * sfp, const char __user *buf, size_t count,
- int blocking, int read_only, Sg_request ** o_srp);
+static ssize_t sg_new_write(Sg_fd *sfp, struct file *file,
+ const char __user *buf, size_t count, int blocking,
+ int read_only, Sg_request **o_srp);
static int sg_common_write(Sg_fd * sfp, Sg_request * srp,
unsigned char *cmnd, int timeout, int blocking);
static int sg_u_iovec(sg_io_hdr_t * hp, int sg_num, int ind,
@@ -204,7 +206,6 @@ static Sg_request *sg_get_rq_mark(Sg_fd * sfp, int pack_id);
static Sg_request *sg_add_request(Sg_fd * sfp);
static int sg_remove_request(Sg_fd * sfp, Sg_request * srp);
static int sg_res_in_use(Sg_fd * sfp);
-static int sg_allow_access(unsigned char opcode, char dev_type);
static int sg_build_direct(Sg_request * srp, Sg_fd * sfp, int dxfer_len);
static Sg_device *sg_get_dev(int dev);
#ifdef CONFIG_SCSI_PROC_FS
@@ -227,19 +228,26 @@ sg_open(struct inode *inode, struct file *filp)
int res;
int retval;
+ lock_kernel();
nonseekable_open(inode, filp);
SCSI_LOG_TIMEOUT(3, printk("sg_open: dev=%d, flags=0x%x\n", dev, flags));
sdp = sg_get_dev(dev);
- if ((!sdp) || (!sdp->device))
+ if ((!sdp) || (!sdp->device)) {
+ unlock_kernel();
return -ENXIO;
- if (sdp->detached)
+ }
+ if (sdp->detached) {
+ unlock_kernel();
return -ENODEV;
+ }
/* This driver's module count bumped by fops_get in <linux/fs.h> */
/* Prevent the device driver from vanishing while we sleep */
retval = scsi_device_get(sdp->device);
- if (retval)
+ if (retval) {
+ unlock_kernel();
return retval;
+ }
if (!((flags & O_NONBLOCK) ||
scsi_block_when_processing_errors(sdp->device))) {
@@ -295,10 +303,12 @@ sg_open(struct inode *inode, struct file *filp)
retval = -ENOMEM;
goto error_out;
}
+ unlock_kernel();
return 0;
error_out:
scsi_device_put(sdp->device);
+ unlock_kernel();
return retval;
}
@@ -544,7 +554,7 @@ sg_write(struct file *filp, const char __user *buf, size_t count, loff_t * ppos)
return -EFAULT;
blocking = !(filp->f_flags & O_NONBLOCK);
if (old_hdr.reply_len < 0)
- return sg_new_write(sfp, buf, count, blocking, 0, NULL);
+ return sg_new_write(sfp, filp, buf, count, blocking, 0, NULL);
if (count < (SZ_SG_HEADER + 6))
return -EIO; /* The minimum scsi command length is 6 bytes. */
@@ -621,8 +631,9 @@ sg_write(struct file *filp, const char __user *buf, size_t count, loff_t * ppos)
}
static ssize_t
-sg_new_write(Sg_fd * sfp, const char __user *buf, size_t count,
- int blocking, int read_only, Sg_request ** o_srp)
+sg_new_write(Sg_fd *sfp, struct file *file, const char __user *buf,
+ size_t count, int blocking, int read_only,
+ Sg_request **o_srp)
{
int k;
Sg_request *srp;
@@ -678,8 +689,7 @@ sg_new_write(Sg_fd * sfp, const char __user *buf, size_t count,
sg_remove_request(sfp, srp);
return -EFAULT;
}
- if (read_only &&
- (!sg_allow_access(cmnd[0], sfp->parentdp->device->type))) {
+ if (read_only && !blk_verify_command(file, cmnd)) {
sg_remove_request(sfp, srp);
return -EPERM;
}
@@ -799,7 +809,7 @@ sg_ioctl(struct inode *inode, struct file *filp,
if (!access_ok(VERIFY_WRITE, p, SZ_SG_IO_HDR))
return -EFAULT;
result =
- sg_new_write(sfp, p, SZ_SG_IO_HDR,
+ sg_new_write(sfp, filp, p, SZ_SG_IO_HDR,
blocking, read_only, &srp);
if (result < 0)
return result;
@@ -1048,7 +1058,7 @@ sg_ioctl(struct inode *inode, struct file *filp,
if (copy_from_user(&opcode, siocp->data, 1))
return -EFAULT;
- if (!sg_allow_access(opcode, sdp->device->type))
+ if (!blk_verify_command(filp, &opcode))
return -EPERM;
}
return sg_scsi_ioctl(filp, sdp->device->request_queue, NULL, p);
@@ -2502,30 +2512,6 @@ sg_page_free(struct page *page, int size)
__free_pages(page, order);
}
-#ifndef MAINTENANCE_IN_CMD
-#define MAINTENANCE_IN_CMD 0xa3
-#endif
-
-static unsigned char allow_ops[] = { TEST_UNIT_READY, REQUEST_SENSE,
- INQUIRY, READ_CAPACITY, READ_BUFFER, READ_6, READ_10, READ_12,
- READ_16, MODE_SENSE, MODE_SENSE_10, LOG_SENSE, REPORT_LUNS,
- SERVICE_ACTION_IN, RECEIVE_DIAGNOSTIC, READ_LONG, MAINTENANCE_IN_CMD
-};
-
-static int
-sg_allow_access(unsigned char opcode, char dev_type)
-{
- int k;
-
- if (TYPE_SCANNER == dev_type) /* TYPE_ROM maybe burner */
- return 1;
- for (k = 0; k < sizeof (allow_ops); ++k) {
- if (opcode == allow_ops[k])
- return 1;
- }
- return 0;
-}
-
#ifdef CONFIG_SCSI_PROC_FS
static int
sg_idr_max_id(int id, void *p, void *data)
diff --git a/drivers/scsi/sr.c b/drivers/scsi/sr.c
index c82df8bd4d89..27f5bfd1def3 100644
--- a/drivers/scsi/sr.c
+++ b/drivers/scsi/sr.c
@@ -673,24 +673,20 @@ fail:
static void get_sectorsize(struct scsi_cd *cd)
{
unsigned char cmd[10];
- unsigned char *buffer;
+ unsigned char buffer[8];
int the_result, retries = 3;
int sector_size;
struct request_queue *queue;
- buffer = kmalloc(512, GFP_KERNEL | GFP_DMA);
- if (!buffer)
- goto Enomem;
-
do {
cmd[0] = READ_CAPACITY;
memset((void *) &cmd[1], 0, 9);
- memset(buffer, 0, 8);
+ memset(buffer, 0, sizeof(buffer));
/* Do the command and wait.. */
the_result = scsi_execute_req(cd->device, cmd, DMA_FROM_DEVICE,
- buffer, 8, NULL, SR_TIMEOUT,
- MAX_RETRIES);
+ buffer, sizeof(buffer), NULL,
+ SR_TIMEOUT, MAX_RETRIES);
retries--;
@@ -745,14 +741,8 @@ static void get_sectorsize(struct scsi_cd *cd)
queue = cd->device->request_queue;
blk_queue_hardsect_size(queue, sector_size);
-out:
- kfree(buffer);
- return;
-Enomem:
- cd->capacity = 0x1fffff;
- cd->device->sector_size = 2048; /* A guess, just in case */
- goto out;
+ return;
}
static void get_capabilities(struct scsi_cd *cd)
diff --git a/drivers/scsi/st.c b/drivers/scsi/st.c
index 6e5a5bb31311..4684cc716aa4 100644
--- a/drivers/scsi/st.c
+++ b/drivers/scsi/st.c
@@ -38,6 +38,7 @@ static const char *verstr = "20080224";
#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>
@@ -1113,7 +1114,7 @@ static int check_tape(struct scsi_tape *STp, struct file *filp)
}
- /* Open the device. Needs to be called with BKL only because of incrementing the SCSI host
+ /* 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)
{
@@ -1123,6 +1124,7 @@ 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
@@ -1130,8 +1132,10 @@ static int st_open(struct inode *inode, struct file *filp)
*/
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;
@@ -1140,6 +1144,7 @@ static int st_open(struct inode *inode, struct file *filp)
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);
}
@@ -1188,12 +1193,14 @@ static int st_open(struct inode *inode, struct file *filp)
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;
}