aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/scsi/st.c
diff options
context:
space:
mode:
authorJeff Mahoney <jeffm@suse.de>2012-08-18 15:20:39 -0400
committerJames Bottomley <JBottomley@Parallels.com>2012-09-14 12:59:28 -0400
commit6c648d95a6af4a79241a916871df17c84c68ea20 (patch)
tree9c658ea5964dea1ecdb029ce955587d17bea6d03 /drivers/scsi/st.c
parente3f2a9cc84d35fac73c906de57ad3b3f5ff82008 (diff)
[SCSI] st: get rid of scsi_tapes array
st currently allocates an array to store pointers to all of the scsi_tape objects. It's used to discover available indexes to use as the base for the minor number selection and later to look up scsi_tape devices for character devices. We switch to using an IDR for minor selection and a pointer from st_modedef back to scsi_tape for the lookups. Reviewed-by: Lee Duncan <lduncan@suse.com> Signed-off-by: Jeff Mahoney <jeffm@suse.com> Acked-by: Kai Mäkisara <kai.makisara@kolumbus.fi> Signed-off-by: James Bottomley <JBottomley@Parallels.com>
Diffstat (limited to 'drivers/scsi/st.c')
-rw-r--r--drivers/scsi/st.c178
1 files changed, 68 insertions, 110 deletions
diff --git a/drivers/scsi/st.c b/drivers/scsi/st.c
index 492b53b6e51d..052622fdba02 100644
--- a/drivers/scsi/st.c
+++ b/drivers/scsi/st.c
@@ -37,6 +37,7 @@ static const char *verstr = "20101219";
37#include <linux/blkdev.h> 37#include <linux/blkdev.h>
38#include <linux/moduleparam.h> 38#include <linux/moduleparam.h>
39#include <linux/cdev.h> 39#include <linux/cdev.h>
40#include <linux/idr.h>
40#include <linux/delay.h> 41#include <linux/delay.h>
41#include <linux/mutex.h> 42#include <linux/mutex.h>
42 43
@@ -81,9 +82,6 @@ static int try_direct_io = TRY_DIRECT_IO;
81static int try_rdio = 1; 82static int try_rdio = 1;
82static int try_wdio = 1; 83static int try_wdio = 1;
83 84
84static int st_dev_max;
85static int st_nr_dev;
86
87static struct class st_sysfs_class; 85static struct class st_sysfs_class;
88static struct device_attribute st_dev_attrs[]; 86static struct device_attribute st_dev_attrs[];
89 87
@@ -174,13 +172,9 @@ static int debugging = DEBUG;
174 24 bits) */ 172 24 bits) */
175#define SET_DENS_AND_BLK 0x10001 173#define SET_DENS_AND_BLK 0x10001
176 174
177static DEFINE_RWLOCK(st_dev_arr_lock);
178
179static int st_fixed_buffer_size = ST_FIXED_BUFFER_SIZE; 175static int st_fixed_buffer_size = ST_FIXED_BUFFER_SIZE;
180static int st_max_sg_segs = ST_MAX_SG; 176static int st_max_sg_segs = ST_MAX_SG;
181 177
182static struct scsi_tape **scsi_tapes = NULL;
183
184static int modes_defined; 178static int modes_defined;
185 179
186static int enlarge_buffer(struct st_buffer *, int, int); 180static int enlarge_buffer(struct st_buffer *, int, int);
@@ -222,6 +216,10 @@ static void scsi_tape_release(struct kref *);
222#define to_scsi_tape(obj) container_of(obj, struct scsi_tape, kref) 216#define to_scsi_tape(obj) container_of(obj, struct scsi_tape, kref)
223 217
224static DEFINE_MUTEX(st_ref_mutex); 218static DEFINE_MUTEX(st_ref_mutex);
219static DEFINE_SPINLOCK(st_index_lock);
220static DEFINE_SPINLOCK(st_use_lock);
221static DEFINE_IDR(st_index_idr);
222
225 223
226 224
227#include "osst_detect.h" 225#include "osst_detect.h"
@@ -239,10 +237,9 @@ static struct scsi_tape *scsi_tape_get(int dev)
239 struct scsi_tape *STp = NULL; 237 struct scsi_tape *STp = NULL;
240 238
241 mutex_lock(&st_ref_mutex); 239 mutex_lock(&st_ref_mutex);
242 write_lock(&st_dev_arr_lock); 240 spin_lock(&st_index_lock);
243 241
244 if (dev < st_dev_max && scsi_tapes != NULL) 242 STp = idr_find(&st_index_idr, dev);
245 STp = scsi_tapes[dev];
246 if (!STp) goto out; 243 if (!STp) goto out;
247 244
248 kref_get(&STp->kref); 245 kref_get(&STp->kref);
@@ -259,7 +256,7 @@ out_put:
259 kref_put(&STp->kref, scsi_tape_release); 256 kref_put(&STp->kref, scsi_tape_release);
260 STp = NULL; 257 STp = NULL;
261out: 258out:
262 write_unlock(&st_dev_arr_lock); 259 spin_unlock(&st_index_lock);
263 mutex_unlock(&st_ref_mutex); 260 mutex_unlock(&st_ref_mutex);
264 return STp; 261 return STp;
265} 262}
@@ -1202,12 +1199,12 @@ static int st_open(struct inode *inode, struct file *filp)
1202 return -ENXIO; 1199 return -ENXIO;
1203 } 1200 }
1204 1201
1205 write_lock(&st_dev_arr_lock);
1206 filp->private_data = STp; 1202 filp->private_data = STp;
1207 name = tape_name(STp); 1203 name = tape_name(STp);
1208 1204
1205 spin_lock(&st_use_lock);
1209 if (STp->in_use) { 1206 if (STp->in_use) {
1210 write_unlock(&st_dev_arr_lock); 1207 spin_unlock(&st_use_lock);
1211 scsi_tape_put(STp); 1208 scsi_tape_put(STp);
1212 mutex_unlock(&st_mutex); 1209 mutex_unlock(&st_mutex);
1213 DEB( printk(ST_DEB_MSG "%s: Device already in use.\n", name); ) 1210 DEB( printk(ST_DEB_MSG "%s: Device already in use.\n", name); )
@@ -1215,7 +1212,7 @@ static int st_open(struct inode *inode, struct file *filp)
1215 } 1212 }
1216 1213
1217 STp->in_use = 1; 1214 STp->in_use = 1;
1218 write_unlock(&st_dev_arr_lock); 1215 spin_unlock(&st_use_lock);
1219 STp->rew_at_close = STp->autorew_dev = (iminor(inode) & 0x80) == 0; 1216 STp->rew_at_close = STp->autorew_dev = (iminor(inode) & 0x80) == 0;
1220 1217
1221 if (scsi_autopm_get_device(STp->device) < 0) { 1218 if (scsi_autopm_get_device(STp->device) < 0) {
@@ -1404,9 +1401,9 @@ static int st_release(struct inode *inode, struct file *filp)
1404 do_door_lock(STp, 0); 1401 do_door_lock(STp, 0);
1405 1402
1406 normalize_buffer(STp->buffer); 1403 normalize_buffer(STp->buffer);
1407 write_lock(&st_dev_arr_lock); 1404 spin_lock(&st_use_lock);
1408 STp->in_use = 0; 1405 STp->in_use = 0;
1409 write_unlock(&st_dev_arr_lock); 1406 spin_unlock(&st_use_lock);
1410 scsi_autopm_put_device(STp->device); 1407 scsi_autopm_put_device(STp->device);
1411 scsi_tape_put(STp); 1408 scsi_tape_put(STp);
1412 1409
@@ -4029,58 +4026,16 @@ static int st_probe(struct device *dev)
4029 goto out_buffer_free; 4026 goto out_buffer_free;
4030 } 4027 }
4031 4028
4032 write_lock(&st_dev_arr_lock);
4033 if (st_nr_dev >= st_dev_max) {
4034 struct scsi_tape **tmp_da;
4035 int tmp_dev_max;
4036
4037 tmp_dev_max = max(st_nr_dev * 2, 8);
4038 if (tmp_dev_max > ST_MAX_TAPES)
4039 tmp_dev_max = ST_MAX_TAPES;
4040 if (tmp_dev_max <= st_nr_dev) {
4041 write_unlock(&st_dev_arr_lock);
4042 printk(KERN_ERR "st: Too many tape devices (max. %d).\n",
4043 ST_MAX_TAPES);
4044 goto out_put_disk;
4045 }
4046
4047 tmp_da = kzalloc(tmp_dev_max * sizeof(struct scsi_tape *), GFP_ATOMIC);
4048 if (tmp_da == NULL) {
4049 write_unlock(&st_dev_arr_lock);
4050 printk(KERN_ERR "st: Can't extend device array.\n");
4051 goto out_put_disk;
4052 }
4053
4054 if (scsi_tapes != NULL) {
4055 memcpy(tmp_da, scsi_tapes,
4056 st_dev_max * sizeof(struct scsi_tape *));
4057 kfree(scsi_tapes);
4058 }
4059 scsi_tapes = tmp_da;
4060
4061 st_dev_max = tmp_dev_max;
4062 }
4063
4064 for (i = 0; i < st_dev_max; i++)
4065 if (scsi_tapes[i] == NULL)
4066 break;
4067 if (i >= st_dev_max)
4068 panic("scsi_devices corrupt (st)");
4069
4070 tpnt = kzalloc(sizeof(struct scsi_tape), GFP_ATOMIC); 4029 tpnt = kzalloc(sizeof(struct scsi_tape), GFP_ATOMIC);
4071 if (tpnt == NULL) { 4030 if (tpnt == NULL) {
4072 write_unlock(&st_dev_arr_lock);
4073 printk(KERN_ERR "st: Can't allocate device descriptor.\n"); 4031 printk(KERN_ERR "st: Can't allocate device descriptor.\n");
4074 goto out_put_disk; 4032 goto out_put_disk;
4075 } 4033 }
4076 kref_init(&tpnt->kref); 4034 kref_init(&tpnt->kref);
4077 tpnt->disk = disk; 4035 tpnt->disk = disk;
4078 sprintf(disk->disk_name, "st%d", i);
4079 disk->private_data = &tpnt->driver; 4036 disk->private_data = &tpnt->driver;
4080 disk->queue = SDp->request_queue; 4037 disk->queue = SDp->request_queue;
4081 tpnt->driver = &st_template; 4038 tpnt->driver = &st_template;
4082 scsi_tapes[i] = tpnt;
4083 dev_num = i;
4084 4039
4085 tpnt->device = SDp; 4040 tpnt->device = SDp;
4086 if (SDp->scsi_level <= 2) 4041 if (SDp->scsi_level <= 2)
@@ -4126,6 +4081,7 @@ static int st_probe(struct device *dev)
4126 STm->default_compression = ST_DONT_TOUCH; 4081 STm->default_compression = ST_DONT_TOUCH;
4127 STm->default_blksize = (-1); /* No forced size */ 4082 STm->default_blksize = (-1); /* No forced size */
4128 STm->default_density = (-1); /* No forced density */ 4083 STm->default_density = (-1); /* No forced density */
4084 STm->tape = tpnt;
4129 } 4085 }
4130 4086
4131 for (i = 0; i < ST_NBR_PARTITIONS; i++) { 4087 for (i = 0; i < ST_NBR_PARTITIONS; i++) {
@@ -4145,8 +4101,29 @@ static int st_probe(struct device *dev)
4145 tpnt->blksize_changed = 0; 4101 tpnt->blksize_changed = 0;
4146 mutex_init(&tpnt->lock); 4102 mutex_init(&tpnt->lock);
4147 4103
4148 st_nr_dev++; 4104 if (!idr_pre_get(&st_index_idr, GFP_KERNEL)) {
4149 write_unlock(&st_dev_arr_lock); 4105 pr_warn("st: idr expansion failed\n");
4106 error = -ENOMEM;
4107 goto out_put_disk;
4108 }
4109
4110 spin_lock(&st_index_lock);
4111 error = idr_get_new(&st_index_idr, tpnt, &dev_num);
4112 spin_unlock(&st_index_lock);
4113 if (error) {
4114 pr_warn("st: idr allocation failed: %d\n", error);
4115 goto out_put_disk;
4116 }
4117
4118 if (dev_num > ST_MAX_TAPES) {
4119 pr_err("st: Too many tape devices (max. %d).\n", ST_MAX_TAPES);
4120 goto out_put_index;
4121 }
4122
4123 tpnt->index = dev_num;
4124 sprintf(disk->disk_name, "st%d", dev_num);
4125
4126 dev_set_drvdata(dev, tpnt);
4150 4127
4151 for (mode = 0; mode < ST_NBR_MODES; ++mode) { 4128 for (mode = 0; mode < ST_NBR_MODES; ++mode) {
4152 STm = &(tpnt->modes[mode]); 4129 STm = &(tpnt->modes[mode]);
@@ -4189,10 +4166,10 @@ static int st_probe(struct device *dev)
4189 return 0; 4166 return 0;
4190 4167
4191out_free_tape: 4168out_free_tape:
4169 sysfs_remove_link(&tpnt->device->sdev_gendev.kobj,
4170 "tape");
4192 for (mode=0; mode < ST_NBR_MODES; mode++) { 4171 for (mode=0; mode < ST_NBR_MODES; mode++) {
4193 STm = &(tpnt->modes[mode]); 4172 STm = &(tpnt->modes[mode]);
4194 sysfs_remove_link(&tpnt->device->sdev_gendev.kobj,
4195 "tape");
4196 for (j=0; j < 2; j++) { 4173 for (j=0; j < 2; j++) {
4197 if (STm->cdevs[j]) { 4174 if (STm->cdevs[j]) {
4198 device_destroy(&st_sysfs_class, 4175 device_destroy(&st_sysfs_class,
@@ -4202,10 +4179,10 @@ out_free_tape:
4202 } 4179 }
4203 } 4180 }
4204 } 4181 }
4205 write_lock(&st_dev_arr_lock); 4182out_put_index:
4206 scsi_tapes[dev_num] = NULL; 4183 spin_lock(&st_index_lock);
4207 st_nr_dev--; 4184 idr_remove(&st_index_idr, dev_num);
4208 write_unlock(&st_dev_arr_lock); 4185 spin_unlock(&st_index_lock);
4209out_put_disk: 4186out_put_disk:
4210 put_disk(disk); 4187 put_disk(disk);
4211 kfree(tpnt); 4188 kfree(tpnt);
@@ -4218,38 +4195,32 @@ out:
4218 4195
4219static int st_remove(struct device *dev) 4196static int st_remove(struct device *dev)
4220{ 4197{
4221 struct scsi_device *SDp = to_scsi_device(dev); 4198 struct scsi_tape *tpnt = dev_get_drvdata(dev);
4222 struct scsi_tape *tpnt; 4199 int rew, mode;
4223 int i, j, mode; 4200 dev_t cdev_devno;
4224 4201 struct cdev *cdev;
4225 scsi_autopm_get_device(SDp); 4202 int index = tpnt->index;
4226 write_lock(&st_dev_arr_lock); 4203
4227 for (i = 0; i < st_dev_max; i++) { 4204 scsi_autopm_get_device(to_scsi_device(dev));
4228 tpnt = scsi_tapes[i]; 4205 sysfs_remove_link(&tpnt->device->sdev_gendev.kobj, "tape");
4229 if (tpnt != NULL && tpnt->device == SDp) { 4206 for (mode = 0; mode < ST_NBR_MODES; ++mode) {
4230 scsi_tapes[i] = NULL; 4207 for (rew = 0; rew < 2; rew++) {
4231 st_nr_dev--; 4208 cdev = tpnt->modes[mode].cdevs[rew];
4232 write_unlock(&st_dev_arr_lock); 4209 if (!cdev)
4233 sysfs_remove_link(&tpnt->device->sdev_gendev.kobj, 4210 continue;
4234 "tape"); 4211 cdev_devno = cdev->dev;
4235 for (mode = 0; mode < ST_NBR_MODES; ++mode) { 4212 device_destroy(&st_sysfs_class, cdev_devno);
4236 for (j=0; j < 2; j++) { 4213 cdev_del(tpnt->modes[mode].cdevs[rew]);
4237 device_destroy(&st_sysfs_class, 4214 tpnt->modes[mode].cdevs[rew] = NULL;
4238 MKDEV(SCSI_TAPE_MAJOR,
4239 TAPE_MINOR(i, mode, j)));
4240 cdev_del(tpnt->modes[mode].cdevs[j]);
4241 tpnt->modes[mode].cdevs[j] = NULL;
4242 }
4243 }
4244
4245 mutex_lock(&st_ref_mutex);
4246 kref_put(&tpnt->kref, scsi_tape_release);
4247 mutex_unlock(&st_ref_mutex);
4248 return 0;
4249 } 4215 }
4250 } 4216 }
4251 4217
4252 write_unlock(&st_dev_arr_lock); 4218 mutex_lock(&st_ref_mutex);
4219 kref_put(&tpnt->kref, scsi_tape_release);
4220 mutex_unlock(&st_ref_mutex);
4221 spin_lock(&st_index_lock);
4222 idr_remove(&st_index_idr, index);
4223 spin_unlock(&st_index_lock);
4253 return 0; 4224 return 0;
4254} 4225}
4255 4226
@@ -4336,7 +4307,6 @@ static void __exit exit_st(void)
4336 unregister_chrdev_region(MKDEV(SCSI_TAPE_MAJOR, 0), 4307 unregister_chrdev_region(MKDEV(SCSI_TAPE_MAJOR, 0),
4337 ST_MAX_TAPE_ENTRIES); 4308 ST_MAX_TAPE_ENTRIES);
4338 class_unregister(&st_sysfs_class); 4309 class_unregister(&st_sysfs_class);
4339 kfree(scsi_tapes);
4340 printk(KERN_INFO "st: Unloaded.\n"); 4310 printk(KERN_INFO "st: Unloaded.\n");
4341} 4311}
4342 4312
@@ -4459,22 +4429,10 @@ static ssize_t
4459options_show(struct device *dev, struct device_attribute *attr, char *buf) 4429options_show(struct device *dev, struct device_attribute *attr, char *buf)
4460{ 4430{
4461 struct st_modedef *STm = dev_get_drvdata(dev); 4431 struct st_modedef *STm = dev_get_drvdata(dev);
4462 struct scsi_tape *STp; 4432 struct scsi_tape *STp = STm->tape;
4463 int i, j, options; 4433 int options;
4464 ssize_t l = 0; 4434 ssize_t l = 0;
4465 4435
4466 for (i=0; i < st_dev_max; i++) {
4467 for (j=0; j < ST_NBR_MODES; j++)
4468 if (&scsi_tapes[i]->modes[j] == STm)
4469 break;
4470 if (j < ST_NBR_MODES)
4471 break;
4472 }
4473 if (i == st_dev_max)
4474 return 0; /* should never happen */
4475
4476 STp = scsi_tapes[i];
4477
4478 options = STm->do_buffer_writes ? MT_ST_BUFFER_WRITES : 0; 4436 options = STm->do_buffer_writes ? MT_ST_BUFFER_WRITES : 0;
4479 options |= STm->do_async_writes ? MT_ST_ASYNC_WRITES : 0; 4437 options |= STm->do_async_writes ? MT_ST_ASYNC_WRITES : 0;
4480 options |= STm->do_read_ahead ? MT_ST_READ_AHEAD : 0; 4438 options |= STm->do_read_ahead ? MT_ST_READ_AHEAD : 0;