mirror of
https://github.com/SCST-project/scst.git
synced 2026-10-22 14:12:33 +00:00
scst_user: yield cleanup while shared SGV remains checked out
With SGV sharing, device B can reuse a buffer whose allocation owner is a command from device A. If A's user handle closes while B still has the SGV checked out, A's command remains in its hash. The unjam pass sees that command, but there is no ready A command, so get_next_cmd() returns -EAGAIN. Once cleanup_done is set, the old inner loop keeps retrying A and prevents the single cleanup worker from reaching B. The post-unjam pool flush added by PR #378 frees SGV objects that have already returned to the recycling lists. It cannot free the object still checked out by B, so it cannot resolve this dependency. Yield A to the outer cleanup loop when no ready command exists but the unjam pass still reports commands. The worker can process B and retry A after its normal sleep. Signal A's cleanup completion only when its release is done and no commands remain. Link: https://github.com/SCST-project/scst/issues/279
This commit is contained in:
@@ -2738,7 +2738,8 @@ repeat:
|
||||
* The pre-unjam flush above misses these objects. Without this second
|
||||
* flush, dev_user_free_sg_entries() never fires, the alloc_pages
|
||||
* ucmd_get() ref is never balanced, and the ucmd stays in ucmd_hash
|
||||
* indefinitely — causing dev_user_process_cleanup() to loop forever.
|
||||
* indefinitely. A checked-out object cannot be flushed until its user
|
||||
* returns it; cleanup must allow that user to make progress.
|
||||
*/
|
||||
sgv_pool_flush(dev->pool);
|
||||
sgv_pool_flush(dev->pool_clust);
|
||||
@@ -3883,8 +3884,6 @@ static int dev_user_process_cleanup(struct scst_user_dev *dev)
|
||||
TRACE_DBG("Cleanuping dev %p", dev);
|
||||
|
||||
rc1 = dev_user_unjam_dev(dev);
|
||||
if (rc1 == 0 && rc == -EAGAIN && dev->cleanup_done)
|
||||
break;
|
||||
|
||||
spin_lock_irq(&dev->udev_cmd_threads.cmd_list_lock);
|
||||
|
||||
@@ -3895,10 +3894,16 @@ static int dev_user_process_cleanup(struct scst_user_dev *dev)
|
||||
spin_unlock_irq(&dev->udev_cmd_threads.cmd_list_lock);
|
||||
|
||||
if (rc == -EAGAIN) {
|
||||
if (!dev->cleanup_done) {
|
||||
TRACE_DBG("No more commands (dev %p)", dev);
|
||||
if (!dev->cleanup_done || rc1 != 0) {
|
||||
/*
|
||||
* An SGV object may still be checked out from a shared pool.
|
||||
* Let other devices finish cleanup before retrying this one.
|
||||
*/
|
||||
TRACE_DBG("Waiting for cleanup (dev %p, pending %d)",
|
||||
dev, rc1);
|
||||
goto out;
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user