void set_filepath(const filepath& fp);
void set_filepath2(const filepath& fp);
bool is_queued_for_replay() const;
+ bool get_queued_next_replay_op() const {
+ return queued_next_replay_op;
+ }
+ void set_queued_next_replay_op() {
+ queued_next_replay_op = true;
+ }
int compare_paths();
bool can_batch();
void _dump_op_descriptor_unlocked(std::ostream& stream) const override;
private:
mutable ceph::spinlock msg_lock;
+ bool queued_next_replay_op = false;
};
struct MDPeerUpdate {
return;
}
bool queue_replay = false;
+ dout(5) << "dispatch request in up:reconnect: " << *req << dendl;
if (req->is_replay() || req->is_async()) {
dout(3) << "queuing replayed op" << dendl;
queue_replay = true;
// process completed request in clientreplay stage. The completed request
// might have created new file/directorie. This guarantees MDS sends a reply
// to client before other request modifies the new file/directorie.
- if (session->have_completed_request(req->get_reqid().tid, NULL)) {
- dout(3) << "queuing completed op" << dendl;
+ bool r = session->have_completed_request(req->get_reqid().tid, NULL);
+ if (r) {
+ dout(3) << __func__ << ": queuing completed op" << dendl;
queue_replay = true;
- }
+ } else {
+ dout(20) << __func__ << ": request not complete" << dendl;
+ }
// this request was created before the cap reconnect message, drop any embedded
// cap releases.
req->releases.clear();
mdr->committing = true;
submit_mdlog_entry(le, fin, mdr, __func__);
-
- if (mdr->client_request && mdr->client_request->is_queued_for_replay()) {
- if (mds->queue_one_replay()) {
- dout(10) << " queued next replay op" << dendl;
- } else {
- dout(10) << " journaled last replay op" << dendl;
- }
+
+ if (mdr->is_queued_for_replay()) {
+
+ /* We want to queue the next replay op while waiting for the journaling, so
+ * do it now when the early (unsafe) replay is dispatched. Don't wait until
+ * this request is cleaned up in MDCache.cc.
+ */
+
+ mdr->set_queued_next_replay_op();
+ mds->queue_one_replay();
} else if (mdr->did_early_reply)
mds->locker->drop_rdlocks_for_early_reply(mdr.get());
else
mds->send_message_client(reply, session);
}
- if (req->is_queued_for_replay() &&
- (mdr->has_completed || reply->get_result() < 0)) {
- if (reply->get_result() < 0) {
- int r = reply->get_result();
+ if (req->is_queued_for_replay()) {
+ if (int r = reply->get_result(); r < 0) {
derr << "reply_client_request: failed to replay " << *req
- << " error " << r << " (" << cpp_strerror(r) << ")" << dendl;
+ << " error " << r << " (" << cpp_strerror(r) << ")" << dendl;
mds->clog->warn() << "failed to replay " << req->get_reqid() << " error " << r;
}
- mds->queue_one_replay();
}
// clean up request
// register + dispatch
MDRequestRef mdr = mdcache->request_start(req);
- if (!mdr.get())
+ if (!mdr.get()) {
+ dout(5) << __func__ << ": possibly duplicate op " << *req << dendl;
+ if (req->is_queued_for_replay())
+ mds->queue_one_replay();
return;
+ }
if (session) {
mdr->session = session;