- /* server has seen req, we have reply: skip */
- if ((req->rq_flags & PTL_RPC_FL_REPLIED) &&
- req->rq_xid <= conn->c_last_xid) {
- CDEBUG(D_INODE,
- "req %Ld was complete: skip [last rcvd %Ld]\n",
- req->rq_xid, conn->c_last_xid);
- continue;
- }
+ /* It might have committed some after we last spoke, so make sure we
+ * get rid of them now.
+ */
+ spin_lock_irqsave(&imp->imp_lock, flags);
+ ptlrpc_free_committed(imp);
+ last_transno = imp->imp_last_replay_transno;
+ spin_unlock_irqrestore(&imp->imp_lock, flags);
+
+ CDEBUG(D_HA, "import %p from %s committed "LPU64" last "LPU64"\n",
+ imp, imp->imp_target_uuid.uuid, imp->imp_peer_committed_transno,
+ last_transno);
+
+ /* Do I need to hold a lock across this iteration? We shouldn't be
+ * racing with any additions to the list, because we're in recovery
+ * and are therefore not processing additional requests to add. Calls
+ * to ptlrpc_free_committed might commit requests, but nothing "newer"
+ * than the one we're replaying (it can't be committed until it's
+ * replayed, and we're doing that here). l_f_e_safe protects against
+ * problems with the current request being committed, in the unlikely
+ * event of that race. So, in conclusion, I think that it's safe to
+ * perform this list-walk without the imp_lock held.
+ *
+ * But, the {mdc,osc}_replay_open callbacks both iterate
+ * request lists, and have comments saying they assume the
+ * imp_lock is being held by ptlrpc_replay, but it's not. it's
+ * just a little race...
+ */
+ list_for_each_safe(tmp, pos, &imp->imp_replay_list) {
+ req = list_entry(tmp, struct ptlrpc_request, rq_replay_list);