aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorChristoph Hellwig <hch@lst.de>2015-08-27 08:17:00 -0400
committerJames Bottomley <JBottomley@Odin.com>2015-08-28 16:14:57 -0400
commite959ed9a44c5239863ca6db42cb37130bee3c7a3 (patch)
tree248382f514a1eb44b910886488ae94e056890957
parentee14c674e8fc57251223054fb52dc0ecfe711028 (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.c99
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}
284EXPORT_SYMBOL_GPL(scsi_unregister_device_handler); 284EXPORT_SYMBOL_GPL(scsi_unregister_device_handler);
285 285
286static 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 */
299int scsi_dh_activate(struct request_queue *q, activate_complete fn, void *data) 313int 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);
333out: 337
334 put_device(dev); 338out_put_device:
339 put_device(&sdev->sdev_gendev);
335 return err; 340 return err;
341
342out_fn:
343 if (fn)
344 fn(data, err);
345 goto out_put_device;
336} 346}
337EXPORT_SYMBOL_GPL(scsi_dh_activate); 347EXPORT_SYMBOL_GPL(scsi_dh_activate);
338 348
@@ -348,21 +358,15 @@ EXPORT_SYMBOL_GPL(scsi_dh_activate);
348 */ 358 */
349int scsi_dh_set_params(struct request_queue *q, const char *params) 359int 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 */
377int scsi_dh_attach(struct request_queue *q, const char *name) 381int 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 */
420const char *scsi_dh_attached_handler_name(struct request_queue *q, gfp_t gfp) 420const 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}