diff options
author | Christoph Hellwig <hch@lst.de> | 2015-08-27 08:17:00 -0400 |
---|---|---|
committer | James Bottomley <JBottomley@Odin.com> | 2015-08-28 16:14:57 -0400 |
commit | e959ed9a44c5239863ca6db42cb37130bee3c7a3 (patch) | |
tree | 248382f514a1eb44b910886488ae94e056890957 | |
parent | ee14c674e8fc57251223054fb52dc0ecfe711028 (diff) |
scsi_dh: add a common helper to get a scsi_device from a request_queue
And cleanup the various messy opencoded versions of this. Note that this
moves the sdev_state checks outside the queue_lock coverage, but as
we don't hold the lock over the activation they are only advisory anyway.
Signed-off-by: Christoph Hellwig <hch@lst.de>
Reviewed-by: Martin K. Petersen <martin.petersen@oracle.com>
Reviewed-by: Hannes Reinecke <hare@suse.de>
Signed-off-by: James Bottomley <JBottomley@Odin.com>
-rw-r--r-- | drivers/scsi/scsi_dh.c | 99 |
1 files changed, 46 insertions, 53 deletions
diff --git a/drivers/scsi/scsi_dh.c b/drivers/scsi/scsi_dh.c index 33c1148ff3b5..2e1db5738ae1 100644 --- a/drivers/scsi/scsi_dh.c +++ b/drivers/scsi/scsi_dh.c | |||
@@ -283,6 +283,20 @@ int scsi_unregister_device_handler(struct scsi_device_handler *scsi_dh) | |||
283 | } | 283 | } |
284 | EXPORT_SYMBOL_GPL(scsi_unregister_device_handler); | 284 | EXPORT_SYMBOL_GPL(scsi_unregister_device_handler); |
285 | 285 | ||
286 | static struct scsi_device *get_sdev_from_queue(struct request_queue *q) | ||
287 | { | ||
288 | struct scsi_device *sdev; | ||
289 | unsigned long flags; | ||
290 | |||
291 | spin_lock_irqsave(q->queue_lock, flags); | ||
292 | sdev = q->queuedata; | ||
293 | if (!sdev || !get_device(&sdev->sdev_gendev)) | ||
294 | sdev = NULL; | ||
295 | spin_unlock_irqrestore(q->queue_lock, flags); | ||
296 | |||
297 | return sdev; | ||
298 | } | ||
299 | |||
286 | /* | 300 | /* |
287 | * scsi_dh_activate - activate the path associated with the scsi_device | 301 | * scsi_dh_activate - activate the path associated with the scsi_device |
288 | * corresponding to the given request queue. | 302 | * corresponding to the given request queue. |
@@ -298,41 +312,37 @@ EXPORT_SYMBOL_GPL(scsi_unregister_device_handler); | |||
298 | */ | 312 | */ |
299 | int scsi_dh_activate(struct request_queue *q, activate_complete fn, void *data) | 313 | int scsi_dh_activate(struct request_queue *q, activate_complete fn, void *data) |
300 | { | 314 | { |
301 | int err = 0; | ||
302 | unsigned long flags; | ||
303 | struct scsi_device *sdev; | 315 | struct scsi_device *sdev; |
304 | struct device *dev = NULL; | 316 | int err = SCSI_DH_NOSYS; |
305 | 317 | ||
306 | spin_lock_irqsave(q->queue_lock, flags); | 318 | sdev = get_sdev_from_queue(q); |
307 | sdev = q->queuedata; | ||
308 | if (!sdev) { | 319 | if (!sdev) { |
309 | spin_unlock_irqrestore(q->queue_lock, flags); | ||
310 | err = SCSI_DH_NOSYS; | ||
311 | if (fn) | 320 | if (fn) |
312 | fn(data, err); | 321 | fn(data, err); |
313 | return err; | 322 | return err; |
314 | } | 323 | } |
315 | 324 | ||
316 | dev = get_device(&sdev->sdev_gendev); | 325 | if (!sdev->handler) |
317 | if (!sdev->handler || !dev || | 326 | goto out_fn; |
318 | sdev->sdev_state == SDEV_CANCEL || | 327 | if (sdev->sdev_state == SDEV_CANCEL || |
319 | sdev->sdev_state == SDEV_DEL) | 328 | sdev->sdev_state == SDEV_DEL) |
320 | err = SCSI_DH_NOSYS; | 329 | goto out_fn; |
321 | if (sdev->sdev_state == SDEV_OFFLINE) | ||
322 | err = SCSI_DH_DEV_OFFLINED; | ||
323 | spin_unlock_irqrestore(q->queue_lock, flags); | ||
324 | 330 | ||
325 | if (err) { | 331 | err = SCSI_DH_DEV_OFFLINED; |
326 | if (fn) | 332 | if (sdev->sdev_state == SDEV_OFFLINE) |
327 | fn(data, err); | 333 | goto out_fn; |
328 | goto out; | ||
329 | } | ||
330 | 334 | ||
331 | if (sdev->handler->activate) | 335 | if (sdev->handler->activate) |
332 | err = sdev->handler->activate(sdev, fn, data); | 336 | err = sdev->handler->activate(sdev, fn, data); |
333 | out: | 337 | |
334 | put_device(dev); | 338 | out_put_device: |
339 | put_device(&sdev->sdev_gendev); | ||
335 | return err; | 340 | return err; |
341 | |||
342 | out_fn: | ||
343 | if (fn) | ||
344 | fn(data, err); | ||
345 | goto out_put_device; | ||
336 | } | 346 | } |
337 | EXPORT_SYMBOL_GPL(scsi_dh_activate); | 347 | EXPORT_SYMBOL_GPL(scsi_dh_activate); |
338 | 348 | ||
@@ -348,21 +358,15 @@ EXPORT_SYMBOL_GPL(scsi_dh_activate); | |||
348 | */ | 358 | */ |
349 | int scsi_dh_set_params(struct request_queue *q, const char *params) | 359 | int scsi_dh_set_params(struct request_queue *q, const char *params) |
350 | { | 360 | { |
351 | int err = -SCSI_DH_NOSYS; | ||
352 | unsigned long flags; | ||
353 | struct scsi_device *sdev; | 361 | struct scsi_device *sdev; |
362 | int err = -SCSI_DH_NOSYS; | ||
354 | 363 | ||
355 | spin_lock_irqsave(q->queue_lock, flags); | 364 | sdev = get_sdev_from_queue(q); |
356 | sdev = q->queuedata; | 365 | if (!sdev) |
357 | if (sdev->handler && | ||
358 | sdev->handler->set_params && | ||
359 | get_device(&sdev->sdev_gendev)) | ||
360 | err = 0; | ||
361 | spin_unlock_irqrestore(q->queue_lock, flags); | ||
362 | |||
363 | if (err) | ||
364 | return err; | 366 | return err; |
365 | err = sdev->handler->set_params(sdev, params); | 367 | |
368 | if (sdev->handler && sdev->handler->set_params) | ||
369 | err = sdev->handler->set_params(sdev, params); | ||
366 | put_device(&sdev->sdev_gendev); | 370 | put_device(&sdev->sdev_gendev); |
367 | return err; | 371 | return err; |
368 | } | 372 | } |
@@ -376,23 +380,19 @@ EXPORT_SYMBOL_GPL(scsi_dh_set_params); | |||
376 | */ | 380 | */ |
377 | int scsi_dh_attach(struct request_queue *q, const char *name) | 381 | int scsi_dh_attach(struct request_queue *q, const char *name) |
378 | { | 382 | { |
379 | unsigned long flags; | ||
380 | struct scsi_device *sdev; | 383 | struct scsi_device *sdev; |
381 | struct scsi_device_handler *scsi_dh; | 384 | struct scsi_device_handler *scsi_dh; |
382 | int err = 0; | 385 | int err = 0; |
383 | 386 | ||
384 | scsi_dh = scsi_dh_lookup(name); | 387 | sdev = get_sdev_from_queue(q); |
385 | if (!scsi_dh) | 388 | if (!sdev) |
386 | return -EINVAL; | 389 | return -ENODEV; |
387 | |||
388 | spin_lock_irqsave(q->queue_lock, flags); | ||
389 | sdev = q->queuedata; | ||
390 | if (!sdev || !get_device(&sdev->sdev_gendev)) | ||
391 | err = -ENODEV; | ||
392 | spin_unlock_irqrestore(q->queue_lock, flags); | ||
393 | 390 | ||
394 | if (err) | 391 | scsi_dh = scsi_dh_lookup(name); |
395 | return err; | 392 | if (!scsi_dh) { |
393 | err = -EINVAL; | ||
394 | goto out_put_device; | ||
395 | } | ||
396 | 396 | ||
397 | if (sdev->handler) { | 397 | if (sdev->handler) { |
398 | if (sdev->handler != scsi_dh) | 398 | if (sdev->handler != scsi_dh) |
@@ -419,22 +419,15 @@ EXPORT_SYMBOL_GPL(scsi_dh_attach); | |||
419 | */ | 419 | */ |
420 | const char *scsi_dh_attached_handler_name(struct request_queue *q, gfp_t gfp) | 420 | const char *scsi_dh_attached_handler_name(struct request_queue *q, gfp_t gfp) |
421 | { | 421 | { |
422 | unsigned long flags; | ||
423 | struct scsi_device *sdev; | 422 | struct scsi_device *sdev; |
424 | const char *handler_name = NULL; | 423 | const char *handler_name = NULL; |
425 | 424 | ||
426 | spin_lock_irqsave(q->queue_lock, flags); | 425 | sdev = get_sdev_from_queue(q); |
427 | sdev = q->queuedata; | ||
428 | if (!sdev || !get_device(&sdev->sdev_gendev)) | ||
429 | sdev = NULL; | ||
430 | spin_unlock_irqrestore(q->queue_lock, flags); | ||
431 | |||
432 | if (!sdev) | 426 | if (!sdev) |
433 | return NULL; | 427 | return NULL; |
434 | 428 | ||
435 | if (sdev->handler) | 429 | if (sdev->handler) |
436 | handler_name = kstrdup(sdev->handler->name, gfp); | 430 | handler_name = kstrdup(sdev->handler->name, gfp); |
437 | |||
438 | put_device(&sdev->sdev_gendev); | 431 | put_device(&sdev->sdev_gendev); |
439 | return handler_name; | 432 | return handler_name; |
440 | } | 433 | } |