diff options
author | Jörn Engel <joern@logfs.org> | 2012-04-25 11:17:29 -0400 |
---|---|---|
committer | James Bottomley <JBottomley@Parallels.com> | 2012-05-17 05:08:56 -0400 |
commit | 035d12e658fba287a223361bc7dd442dd6737b68 (patch) | |
tree | 1017b20cd9432b9507c485098171c74ee478aeb1 /drivers/scsi/sg.c | |
parent | b499e5249eb80e4a7e71cfd04c6f628abdb27498 (diff) |
[SCSI] sg: completely protect sfds
sfds is protected by sg_index_lock - except for sg_open(), where it
isn't. Change that and add some documentation.
Signed-off-by: Joern Engel <joern@logfs.org>
Acked-by: Douglas Gilbert <dgilbert@interlog.com>
Signed-off-by: James Bottomley <JBottomley@Parallels.com>
Diffstat (limited to 'drivers/scsi/sg.c')
-rw-r--r-- | drivers/scsi/sg.c | 19 |
1 files changed, 16 insertions, 3 deletions
diff --git a/drivers/scsi/sg.c b/drivers/scsi/sg.c index 8e15c448a761..53af8089dcb9 100644 --- a/drivers/scsi/sg.c +++ b/drivers/scsi/sg.c | |||
@@ -146,6 +146,7 @@ typedef struct sg_request { /* SG_MAX_QUEUE requests outstanding per file */ | |||
146 | } Sg_request; | 146 | } Sg_request; |
147 | 147 | ||
148 | typedef struct sg_fd { /* holds the state of a file descriptor */ | 148 | typedef struct sg_fd { /* holds the state of a file descriptor */ |
149 | /* sfd_siblings is protected by sg_index_lock */ | ||
149 | struct list_head sfd_siblings; | 150 | struct list_head sfd_siblings; |
150 | struct sg_device *parentdp; /* owning device */ | 151 | struct sg_device *parentdp; /* owning device */ |
151 | wait_queue_head_t read_wait; /* queue read until command done */ | 152 | wait_queue_head_t read_wait; /* queue read until command done */ |
@@ -172,6 +173,7 @@ typedef struct sg_device { /* holds the state of each scsi generic device */ | |||
172 | wait_queue_head_t o_excl_wait; /* queue open() when O_EXCL in use */ | 173 | wait_queue_head_t o_excl_wait; /* queue open() when O_EXCL in use */ |
173 | int sg_tablesize; /* adapter's max scatter-gather table size */ | 174 | int sg_tablesize; /* adapter's max scatter-gather table size */ |
174 | u32 index; /* device index number */ | 175 | u32 index; /* device index number */ |
176 | /* sfds is protected by sg_index_lock */ | ||
175 | struct list_head sfds; | 177 | struct list_head sfds; |
176 | volatile char detached; /* 0->attached, 1->detached pending removal */ | 178 | volatile char detached; /* 0->attached, 1->detached pending removal */ |
177 | /* exclude protected by sg_open_exclusive_lock */ | 179 | /* exclude protected by sg_open_exclusive_lock */ |
@@ -244,6 +246,17 @@ static int set_exclude(Sg_device *sdp, char val) | |||
244 | return val; | 246 | return val; |
245 | } | 247 | } |
246 | 248 | ||
249 | static int sfds_list_empty(Sg_device *sdp) | ||
250 | { | ||
251 | unsigned long flags; | ||
252 | int ret; | ||
253 | |||
254 | read_lock_irqsave(&sg_index_lock, flags); | ||
255 | ret = list_empty(&sdp->sfds); | ||
256 | read_unlock_irqrestore(&sg_index_lock, flags); | ||
257 | return ret; | ||
258 | } | ||
259 | |||
247 | static int | 260 | static int |
248 | sg_open(struct inode *inode, struct file *filp) | 261 | sg_open(struct inode *inode, struct file *filp) |
249 | { | 262 | { |
@@ -287,12 +300,12 @@ sg_open(struct inode *inode, struct file *filp) | |||
287 | retval = -EPERM; /* Can't lock it with read only access */ | 300 | retval = -EPERM; /* Can't lock it with read only access */ |
288 | goto error_out; | 301 | goto error_out; |
289 | } | 302 | } |
290 | if (!list_empty(&sdp->sfds) && (flags & O_NONBLOCK)) { | 303 | if (!sfds_list_empty(sdp) && (flags & O_NONBLOCK)) { |
291 | retval = -EBUSY; | 304 | retval = -EBUSY; |
292 | goto error_out; | 305 | goto error_out; |
293 | } | 306 | } |
294 | res = wait_event_interruptible(sdp->o_excl_wait, | 307 | res = wait_event_interruptible(sdp->o_excl_wait, |
295 | ((!list_empty(&sdp->sfds) || get_exclude(sdp)) ? 0 : set_exclude(sdp, 1))); | 308 | ((!sfds_list_empty(sdp) || get_exclude(sdp)) ? 0 : set_exclude(sdp, 1))); |
296 | if (res) { | 309 | if (res) { |
297 | retval = res; /* -ERESTARTSYS because signal hit process */ | 310 | retval = res; /* -ERESTARTSYS because signal hit process */ |
298 | goto error_out; | 311 | goto error_out; |
@@ -312,7 +325,7 @@ sg_open(struct inode *inode, struct file *filp) | |||
312 | retval = -ENODEV; | 325 | retval = -ENODEV; |
313 | goto error_out; | 326 | goto error_out; |
314 | } | 327 | } |
315 | if (list_empty(&sdp->sfds)) { /* no existing opens on this device */ | 328 | if (sfds_list_empty(sdp)) { /* no existing opens on this device */ |
316 | sdp->sgdebug = 0; | 329 | sdp->sgdebug = 0; |
317 | q = sdp->device->request_queue; | 330 | q = sdp->device->request_queue; |
318 | sdp->sg_tablesize = queue_max_segments(q); | 331 | sdp->sg_tablesize = queue_max_segments(q); |