aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorJames Bottomley <JBottomley@Parallels.com>2013-10-25 05:21:57 -0400
committerJames Bottomley <JBottomley@Parallels.com>2013-10-25 05:58:07 -0400
commitc0d3b9c29ed22d449481bcfac267a879034a3a5b (patch)
treee1e67d3d50fab46ed53c3d021767a018ee38a2a9
parent10c580e4239df5c3344ca00322eca86ab2de880b (diff)
[SCSI] Revert "sg: push file descriptor list locking down to per-device locking"
This reverts commit 1f962ebcdfa15cede59e9edb299d1330949eec92. This is one of four patches that was causing this bug [ 205.372823] ================================================ [ 205.372901] [ BUG: lock held when returning to user space! ] [ 205.372979] 3.12.0-rc6-hw-debug-pagealloc+ #67 Not tainted [ 205.373055] ------------------------------------------------ [ 205.373132] megarc.bin/5283 is leaving the kernel with locks still held! [ 205.373212] 1 lock held by megarc.bin/5283: [ 205.373285] #0: (&sdp->o_sem){.+.+..}, at: [<ffffffff8161e650>] sg_open+0x3a0/0x4d0 Cc: Vaughan Cao <vaughan.cao@oracle.com> Acked-by: Douglas Gilbert <dgilbert@interlog.com> Signed-off-by: James Bottomley <JBottomley@Parallels.com>
-rw-r--r--drivers/scsi/sg.c62
1 files changed, 28 insertions, 34 deletions
diff --git a/drivers/scsi/sg.c b/drivers/scsi/sg.c
index 5cbc4bb1b395..64df1ab141e5 100644
--- a/drivers/scsi/sg.c
+++ b/drivers/scsi/sg.c
@@ -106,7 +106,8 @@ static int sg_add(struct device *, struct class_interface *);
106static void sg_remove(struct device *, struct class_interface *); 106static void sg_remove(struct device *, struct class_interface *);
107 107
108static DEFINE_IDR(sg_index_idr); 108static DEFINE_IDR(sg_index_idr);
109static DEFINE_RWLOCK(sg_index_lock); 109static DEFINE_RWLOCK(sg_index_lock); /* Also used to lock
110 file descriptor list for device */
110 111
111static struct class_interface sg_interface = { 112static struct class_interface sg_interface = {
112 .add_dev = sg_add, 113 .add_dev = sg_add,
@@ -143,7 +144,8 @@ typedef struct sg_request { /* SG_MAX_QUEUE requests outstanding per file */
143} Sg_request; 144} Sg_request;
144 145
145typedef struct sg_fd { /* holds the state of a file descriptor */ 146typedef struct sg_fd { /* holds the state of a file descriptor */
146 struct list_head sfd_siblings; /* protected by sfd_lock of device */ 147 /* sfd_siblings is protected by sg_index_lock */
148 struct list_head sfd_siblings;
147 struct sg_device *parentdp; /* owning device */ 149 struct sg_device *parentdp; /* owning device */
148 wait_queue_head_t read_wait; /* queue read until command done */ 150 wait_queue_head_t read_wait; /* queue read until command done */
149 rwlock_t rq_list_lock; /* protect access to list in req_arr */ 151 rwlock_t rq_list_lock; /* protect access to list in req_arr */
@@ -168,7 +170,7 @@ typedef struct sg_device { /* holds the state of each scsi generic device */
168 struct scsi_device *device; 170 struct scsi_device *device;
169 int sg_tablesize; /* adapter's max scatter-gather table size */ 171 int sg_tablesize; /* adapter's max scatter-gather table size */
170 u32 index; /* device index number */ 172 u32 index; /* device index number */
171 spinlock_t sfd_lock; /* protect file descriptor list for device */ 173 /* sfds is protected by sg_index_lock */
172 struct list_head sfds; 174 struct list_head sfds;
173 struct rw_semaphore o_sem; /* exclude open should hold this rwsem */ 175 struct rw_semaphore o_sem; /* exclude open should hold this rwsem */
174 volatile char detached; /* 0->attached, 1->detached pending removal */ 176 volatile char detached; /* 0->attached, 1->detached pending removal */
@@ -225,9 +227,9 @@ static int sfds_list_empty(Sg_device *sdp)
225 unsigned long flags; 227 unsigned long flags;
226 int ret; 228 int ret;
227 229
228 spin_lock_irqsave(&sdp->sfd_lock, flags); 230 read_lock_irqsave(&sg_index_lock, flags);
229 ret = list_empty(&sdp->sfds); 231 ret = list_empty(&sdp->sfds);
230 spin_unlock_irqrestore(&sdp->sfd_lock, flags); 232 read_unlock_irqrestore(&sg_index_lock, flags);
231 return ret; 233 return ret;
232} 234}
233 235
@@ -1391,7 +1393,6 @@ static Sg_device *sg_alloc(struct gendisk *disk, struct scsi_device *scsidp)
1391 disk->first_minor = k; 1393 disk->first_minor = k;
1392 sdp->disk = disk; 1394 sdp->disk = disk;
1393 sdp->device = scsidp; 1395 sdp->device = scsidp;
1394 spin_lock_init(&sdp->sfd_lock);
1395 INIT_LIST_HEAD(&sdp->sfds); 1396 INIT_LIST_HEAD(&sdp->sfds);
1396 init_rwsem(&sdp->o_sem); 1397 init_rwsem(&sdp->o_sem);
1397 sdp->sg_tablesize = queue_max_segments(q); 1398 sdp->sg_tablesize = queue_max_segments(q);
@@ -1526,13 +1527,11 @@ static void sg_remove(struct device *cl_dev, struct class_interface *cl_intf)
1526 1527
1527 /* Need a write lock to set sdp->detached. */ 1528 /* Need a write lock to set sdp->detached. */
1528 write_lock_irqsave(&sg_index_lock, iflags); 1529 write_lock_irqsave(&sg_index_lock, iflags);
1529 spin_lock(&sdp->sfd_lock);
1530 sdp->detached = 1; 1530 sdp->detached = 1;
1531 list_for_each_entry(sfp, &sdp->sfds, sfd_siblings) { 1531 list_for_each_entry(sfp, &sdp->sfds, sfd_siblings) {
1532 wake_up_interruptible(&sfp->read_wait); 1532 wake_up_interruptible(&sfp->read_wait);
1533 kill_fasync(&sfp->async_qp, SIGPOLL, POLL_HUP); 1533 kill_fasync(&sfp->async_qp, SIGPOLL, POLL_HUP);
1534 } 1534 }
1535 spin_unlock(&sdp->sfd_lock);
1536 write_unlock_irqrestore(&sg_index_lock, iflags); 1535 write_unlock_irqrestore(&sg_index_lock, iflags);
1537 1536
1538 sysfs_remove_link(&scsidp->sdev_gendev.kobj, "generic"); 1537 sysfs_remove_link(&scsidp->sdev_gendev.kobj, "generic");
@@ -2057,13 +2056,13 @@ sg_add_sfp(Sg_device * sdp, int dev)
2057 sfp->cmd_q = SG_DEF_COMMAND_Q; 2056 sfp->cmd_q = SG_DEF_COMMAND_Q;
2058 sfp->keep_orphan = SG_DEF_KEEP_ORPHAN; 2057 sfp->keep_orphan = SG_DEF_KEEP_ORPHAN;
2059 sfp->parentdp = sdp; 2058 sfp->parentdp = sdp;
2060 spin_lock_irqsave(&sdp->sfd_lock, iflags); 2059 write_lock_irqsave(&sg_index_lock, iflags);
2061 if (sdp->detached) { 2060 if (sdp->detached) {
2062 spin_unlock_irqrestore(&sdp->sfd_lock, iflags); 2061 write_unlock_irqrestore(&sg_index_lock, iflags);
2063 return ERR_PTR(-ENODEV); 2062 return ERR_PTR(-ENODEV);
2064 } 2063 }
2065 list_add_tail(&sfp->sfd_siblings, &sdp->sfds); 2064 list_add_tail(&sfp->sfd_siblings, &sdp->sfds);
2066 spin_unlock_irqrestore(&sdp->sfd_lock, iflags); 2065 write_unlock_irqrestore(&sg_index_lock, iflags);
2067 SCSI_LOG_TIMEOUT(3, printk("sg_add_sfp: sfp=0x%p\n", sfp)); 2066 SCSI_LOG_TIMEOUT(3, printk("sg_add_sfp: sfp=0x%p\n", sfp));
2068 if (unlikely(sg_big_buff != def_reserved_size)) 2067 if (unlikely(sg_big_buff != def_reserved_size))
2069 sg_big_buff = def_reserved_size; 2068 sg_big_buff = def_reserved_size;
@@ -2110,12 +2109,11 @@ static void sg_remove_sfp_usercontext(struct work_struct *work)
2110static void sg_remove_sfp(struct kref *kref) 2109static void sg_remove_sfp(struct kref *kref)
2111{ 2110{
2112 struct sg_fd *sfp = container_of(kref, struct sg_fd, f_ref); 2111 struct sg_fd *sfp = container_of(kref, struct sg_fd, f_ref);
2113 struct sg_device *sdp = sfp->parentdp;
2114 unsigned long iflags; 2112 unsigned long iflags;
2115 2113
2116 spin_lock_irqsave(&sdp->sfd_lock, iflags); 2114 write_lock_irqsave(&sg_index_lock, iflags);
2117 list_del(&sfp->sfd_siblings); 2115 list_del(&sfp->sfd_siblings);
2118 spin_unlock_irqrestore(&sdp->sfd_lock, iflags); 2116 write_unlock_irqrestore(&sg_index_lock, iflags);
2119 2117
2120 INIT_WORK(&sfp->ew.work, sg_remove_sfp_usercontext); 2118 INIT_WORK(&sfp->ew.work, sg_remove_sfp_usercontext);
2121 schedule_work(&sfp->ew.work); 2119 schedule_work(&sfp->ew.work);
@@ -2502,7 +2500,7 @@ static int sg_proc_seq_show_devstrs(struct seq_file *s, void *v)
2502 return 0; 2500 return 0;
2503} 2501}
2504 2502
2505/* must be called while holding sg_index_lock and sfd_lock */ 2503/* must be called while holding sg_index_lock */
2506static void sg_proc_debug_helper(struct seq_file *s, Sg_device * sdp) 2504static void sg_proc_debug_helper(struct seq_file *s, Sg_device * sdp)
2507{ 2505{
2508 int k, m, new_interface, blen, usg; 2506 int k, m, new_interface, blen, usg;
@@ -2587,26 +2585,22 @@ static int sg_proc_seq_show_debug(struct seq_file *s, void *v)
2587 2585
2588 read_lock_irqsave(&sg_index_lock, iflags); 2586 read_lock_irqsave(&sg_index_lock, iflags);
2589 sdp = it ? sg_lookup_dev(it->index) : NULL; 2587 sdp = it ? sg_lookup_dev(it->index) : NULL;
2590 if (sdp) { 2588 if (sdp && !list_empty(&sdp->sfds)) {
2591 spin_lock(&sdp->sfd_lock); 2589 struct scsi_device *scsidp = sdp->device;
2592 if (!list_empty(&sdp->sfds)) {
2593 struct scsi_device *scsidp = sdp->device;
2594 2590
2595 seq_printf(s, " >>> device=%s ", sdp->disk->disk_name); 2591 seq_printf(s, " >>> device=%s ", sdp->disk->disk_name);
2596 if (sdp->detached) 2592 if (sdp->detached)
2597 seq_printf(s, "detached pending close "); 2593 seq_printf(s, "detached pending close ");
2598 else 2594 else
2599 seq_printf 2595 seq_printf
2600 (s, "scsi%d chan=%d id=%d lun=%d em=%d", 2596 (s, "scsi%d chan=%d id=%d lun=%d em=%d",
2601 scsidp->host->host_no, 2597 scsidp->host->host_no,
2602 scsidp->channel, scsidp->id, 2598 scsidp->channel, scsidp->id,
2603 scsidp->lun, 2599 scsidp->lun,
2604 scsidp->host->hostt->emulated); 2600 scsidp->host->hostt->emulated);
2605 seq_printf(s, " sg_tablesize=%d excl=%d\n", 2601 seq_printf(s, " sg_tablesize=%d excl=%d\n",
2606 sdp->sg_tablesize, sdp->exclude); 2602 sdp->sg_tablesize, sdp->exclude);
2607 sg_proc_debug_helper(s, sdp); 2603 sg_proc_debug_helper(s, sdp);
2608 }
2609 spin_unlock(&sdp->sfd_lock);
2610 } 2604 }
2611 read_unlock_irqrestore(&sg_index_lock, iflags); 2605 read_unlock_irqrestore(&sg_index_lock, iflags);
2612 return 0; 2606 return 0;