- if (--oig->oig_pending <= 0)
- wake = &oig->oig_waitq;
-
- spin_unlock(&oig->oig_lock);
-
- CDEBUG(D_CACHE, "oig %p completed, rc %d -> %d via %d, %d now "
- "pending (racey)\n", oig, old_rc, oig->oig_rc, rc,
- oig->oig_pending);
- if (wake)
- cfs_waitq_signal(wake);
- oig_release(oig);
-}
-EXPORT_SYMBOL(oig_complete_one);
-
-static int oig_done(struct obd_io_group *oig)
-{
- int rc = 0;
- spin_lock(&oig->oig_lock);
- if (oig->oig_pending <= 0)
- rc = 1;
- spin_unlock(&oig->oig_lock);
- return rc;
-}
-
-static void interrupted_oig(void *data)
-{
- struct obd_io_group *oig = data;
- struct oig_callback_context *occ;
-
- spin_lock(&oig->oig_lock);
- /* We need to restart the processing each time we drop the lock, as
- * it is possible other threads called oig_complete_one() to remove
- * an entry elsewhere in the list while we dropped lock. We need to
- * drop the lock because osc_ap_completion() calls oig_complete_one()
- * which re-gets this lock ;-) as well as a lock ordering issue. */
-restart:
- list_for_each_entry(occ, &oig->oig_occ_list, occ_oig_item) {
- if (occ->interrupted)
- continue;
- occ->interrupted = 1;
- spin_unlock(&oig->oig_lock);
- occ->occ_interrupted(occ);
- spin_lock(&oig->oig_lock);
- goto restart;
- }
- spin_unlock(&oig->oig_lock);
-}
-
-int oig_wait(struct obd_io_group *oig)
-{
- struct l_wait_info lwi = LWI_INTR(interrupted_oig, oig);
- int rc;
-
- CDEBUG(D_CACHE, "waiting for oig %p\n", oig);
-
- do {
- rc = l_wait_event(oig->oig_waitq, oig_done(oig), &lwi);
- LASSERTF(rc == 0 || rc == -EINTR, "rc: %d\n", rc);
- /* we can't continue until the oig has emptied and stopped
- * referencing state that the caller will free upon return */
- if (rc == -EINTR)
- lwi = (struct l_wait_info){ 0, };
- } while (rc == -EINTR);
-
- LASSERTF(oig->oig_pending == 0,
- "exiting oig_wait(oig = %p) with %d pending\n", oig,
- oig->oig_pending);
-
- CDEBUG(D_CACHE, "done waiting on oig %p rc %d\n", oig, oig->oig_rc);
- return oig->oig_rc;