scsi: fix the {host,target,device}_blocked counter mess
Seems like these counters are missing any sort of synchronization for updates, as a over 10 year old comment from me noted. Fix this by using atomic counters, and while we're at it also make sure they are in the same cacheline as the _busy counters and not needlessly stored to in every I/O completion. With the new model the _busy counters can temporarily go negative, so all the readers are updated to check for > 0 values. Longer term every successful I/O completion will reset the counters to zero, so the temporarily negative values will not cause any harm. Signed-off-by: Christoph Hellwig <hch@lst.de> Reviewed-by: Martin K. Petersen <martin.petersen@oracle.com> Reviewed-by: Webb Scales <webbnh@hp.com> Acked-by: Jens Axboe <axboe@kernel.dk> Tested-by: Bart Van Assche <bvanassche@acm.org> Tested-by: Robert Elliott <elliott@hp.com>
此提交包含在:
@@ -583,6 +583,8 @@ struct Scsi_Host {
|
||||
struct blk_queue_tag *bqt;
|
||||
|
||||
atomic_t host_busy; /* commands actually active on low-level */
|
||||
atomic_t host_blocked;
|
||||
|
||||
unsigned int host_failed; /* commands that failed.
|
||||
protected by host_lock */
|
||||
unsigned int host_eh_scheduled; /* EH scheduled without command */
|
||||
@@ -681,11 +683,6 @@ struct Scsi_Host {
|
||||
*/
|
||||
struct workqueue_struct *tmf_work_q;
|
||||
|
||||
/*
|
||||
* Host has rejected a command because it was busy.
|
||||
*/
|
||||
unsigned int host_blocked;
|
||||
|
||||
/*
|
||||
* Value host_blocked counts down from
|
||||
*/
|
||||
|
新增問題並參考
封鎖使用者