aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--drivers/scsi/st.c11
1 files changed, 9 insertions, 2 deletions
diff --git a/drivers/scsi/st.c b/drivers/scsi/st.c
index e8db66ad0bde..e93544dd81bf 100644
--- a/drivers/scsi/st.c
+++ b/drivers/scsi/st.c
@@ -38,6 +38,7 @@ static const char *verstr = "20080224";
38#include <linux/cdev.h> 38#include <linux/cdev.h>
39#include <linux/delay.h> 39#include <linux/delay.h>
40#include <linux/mutex.h> 40#include <linux/mutex.h>
41#include <linux/smp_lock.h>
41 42
42#include <asm/uaccess.h> 43#include <asm/uaccess.h>
43#include <asm/dma.h> 44#include <asm/dma.h>
@@ -1113,7 +1114,7 @@ static int check_tape(struct scsi_tape *STp, struct file *filp)
1113} 1114}
1114 1115
1115 1116
1116 /* Open the device. Needs to be called with BKL only because of incrementing the SCSI host 1117 /* Open the device. Needs to take the BKL only because of incrementing the SCSI host
1117 module count. */ 1118 module count. */
1118static int st_open(struct inode *inode, struct file *filp) 1119static int st_open(struct inode *inode, struct file *filp)
1119{ 1120{
@@ -1123,6 +1124,7 @@ static int st_open(struct inode *inode, struct file *filp)
1123 int dev = TAPE_NR(inode); 1124 int dev = TAPE_NR(inode);
1124 char *name; 1125 char *name;
1125 1126
1127 lock_kernel();
1126 /* 1128 /*
1127 * We really want to do nonseekable_open(inode, filp); here, but some 1129 * We really want to do nonseekable_open(inode, filp); here, but some
1128 * versions of tar incorrectly call lseek on tapes and bail out if that 1130 * 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)
1130 */ 1132 */
1131 filp->f_mode &= ~(FMODE_PREAD | FMODE_PWRITE); 1133 filp->f_mode &= ~(FMODE_PREAD | FMODE_PWRITE);
1132 1134
1133 if (!(STp = scsi_tape_get(dev))) 1135 if (!(STp = scsi_tape_get(dev))) {
1136 unlock_kernel();
1134 return -ENXIO; 1137 return -ENXIO;
1138 }
1135 1139
1136 write_lock(&st_dev_arr_lock); 1140 write_lock(&st_dev_arr_lock);
1137 filp->private_data = STp; 1141 filp->private_data = STp;
@@ -1140,6 +1144,7 @@ static int st_open(struct inode *inode, struct file *filp)
1140 if (STp->in_use) { 1144 if (STp->in_use) {
1141 write_unlock(&st_dev_arr_lock); 1145 write_unlock(&st_dev_arr_lock);
1142 scsi_tape_put(STp); 1146 scsi_tape_put(STp);
1147 unlock_kernel();
1143 DEB( printk(ST_DEB_MSG "%s: Device already in use.\n", name); ) 1148 DEB( printk(ST_DEB_MSG "%s: Device already in use.\n", name); )
1144 return (-EBUSY); 1149 return (-EBUSY);
1145 } 1150 }
@@ -1188,12 +1193,14 @@ static int st_open(struct inode *inode, struct file *filp)
1188 retval = (-EIO); 1193 retval = (-EIO);
1189 goto err_out; 1194 goto err_out;
1190 } 1195 }
1196 unlock_kernel();
1191 return 0; 1197 return 0;
1192 1198
1193 err_out: 1199 err_out:
1194 normalize_buffer(STp->buffer); 1200 normalize_buffer(STp->buffer);
1195 STp->in_use = 0; 1201 STp->in_use = 0;
1196 scsi_tape_put(STp); 1202 scsi_tape_put(STp);
1203 unlock_kernel();
1197 return retval; 1204 return retval;
1198 1205
1199} 1206}