Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

scsi_dh_rdac: update 'access_state' field

Track attached SCSI devices and update the 'access_state' whenever the
path state of the device changes.

Signed-off-by: Hannes Reinecke <hare@suse.com>
Reviewed-by: Christoph Hellwig <hch@lst.de>
Reviewed-by: Johannes Thumshirn <jthumshirn@suse.de>
Signed-off-by: Martin K. Petersen <martin.petersen@oracle.com>

authored by

Hannes Reinecke and committed by
Martin K. Petersen
1a5dc166 cb0a168c

+31 -7
+31 -7
drivers/scsi/device_handler/scsi_dh_rdac.c
··· 165 165 struct work_struct ms_work; 166 166 struct scsi_device *ms_sdev; 167 167 struct list_head ms_head; 168 + struct list_head dh_list; 168 169 }; 169 170 170 171 struct c2_inquiry { ··· 182 181 }; 183 182 184 183 struct rdac_dh_data { 184 + struct list_head node; 185 185 struct rdac_controller *ctlr; 186 + struct scsi_device *sdev; 186 187 #define UNINITIALIZED_LUN (1 << 8) 187 188 unsigned lun; 188 189 ··· 395 392 INIT_WORK(&ctlr->ms_work, send_mode_select); 396 393 INIT_LIST_HEAD(&ctlr->ms_head); 397 394 list_add(&ctlr->node, &ctlr_list); 395 + INIT_LIST_HEAD(&ctlr->dh_list); 398 396 399 397 return ctlr; 400 398 } ··· 459 455 460 456 static int check_ownership(struct scsi_device *sdev, struct rdac_dh_data *h) 461 457 { 462 - int err; 458 + int err, access_state; 459 + struct rdac_dh_data *tmp; 463 460 struct c9_inquiry *inqp; 464 461 465 462 h->state = RDAC_STATE_ACTIVE; ··· 476 471 h->mode = RDAC_MODE; /* LUN in RDAC mode */ 477 472 478 473 /* Update ownership */ 479 - if (inqp->avte_cvp & 0x1) 474 + if (inqp->avte_cvp & 0x1) { 480 475 h->lun_state = RDAC_LUN_OWNED; 481 - else { 476 + access_state = SCSI_ACCESS_STATE_OPTIMAL; 477 + } else { 482 478 h->lun_state = RDAC_LUN_UNOWNED; 483 - if (h->mode == RDAC_MODE) 479 + if (h->mode == RDAC_MODE) { 484 480 h->state = RDAC_STATE_PASSIVE; 481 + access_state = SCSI_ACCESS_STATE_STANDBY; 482 + } else 483 + access_state = SCSI_ACCESS_STATE_ACTIVE; 485 484 } 486 485 487 486 /* Update path prio*/ 488 - if (inqp->path_prio & 0x1) 487 + if (inqp->path_prio & 0x1) { 489 488 h->preferred = RDAC_PREFERRED; 490 - else 489 + access_state |= SCSI_ACCESS_STATE_PREFERRED; 490 + } else 491 491 h->preferred = RDAC_NON_PREFERRED; 492 + rcu_read_lock(); 493 + list_for_each_entry_rcu(tmp, &h->ctlr->dh_list, node) { 494 + /* h->sdev should always be valid */ 495 + BUG_ON(!tmp->sdev); 496 + tmp->sdev->access_state = access_state; 497 + } 498 + rcu_read_unlock(); 492 499 } 493 500 494 501 return err; ··· 525 508 h->ctlr = get_controller(index, array_name, array_id, sdev); 526 509 if (!h->ctlr) 527 510 err = SCSI_DH_RES_TEMP_UNAVAIL; 511 + else { 512 + list_add_rcu(&h->node, &h->ctlr->dh_list); 513 + h->sdev = sdev; 514 + } 528 515 spin_unlock(&list_lock); 529 516 } 530 517 return err; ··· 850 829 flush_workqueue(kmpath_rdacd); 851 830 852 831 spin_lock(&list_lock); 853 - if (h->ctlr) 832 + if (h->ctlr) { 833 + list_del_rcu(&h->node); 834 + h->sdev = NULL; 854 835 kref_put(&h->ctlr->kref, release_controller); 836 + } 855 837 spin_unlock(&list_lock); 856 838 sdev->handler_data = NULL; 857 839 kfree(h);