From b7cd297a6825ac955ff93ffdf0dd6519fc96ce32 Mon Sep 17 00:00:00 2001 From: vitaly Date: Tue, 20 Oct 2009 12:37:38 +0000 Subject: [PATCH] Branch HEAD b=20098 i=green i=tappro pin open rpc properly in memory --- lustre/include/lustre_net.h | 3 ++- lustre/include/obd.h | 13 ++++++++----- lustre/mdc/mdc_reint.c | 12 +++++++++++- lustre/mdc/mdc_request.c | 45 +++++++++++++++++++++++++++++++++++---------- 4 files changed, 56 insertions(+), 17 deletions(-) diff --git a/lustre/include/lustre_net.h b/lustre/include/lustre_net.h index 5f5e840..52587e2 100644 --- a/lustre/include/lustre_net.h +++ b/lustre/include/lustre_net.h @@ -371,7 +371,8 @@ struct ptlrpc_request { rq_packed_final:1, /* packed final reply */ rq_hp:1, /* high priority RPC */ rq_at_linked:1, /* link into service's srv_at_array */ - rq_reply_truncate:1; + rq_reply_truncate:1, + rq_committed:1; enum rq_phase rq_phase; /* one of RQ_PHASE_* */ enum rq_phase rq_next_phase; /* one of RQ_PHASE_* to be used next */ diff --git a/lustre/include/obd.h b/lustre/include/obd.h index 73a01f0..f4251c2 100644 --- a/lustre/include/obd.h +++ b/lustre/include/obd.h @@ -1682,11 +1682,14 @@ static inline struct md_open_data *obd_mod_alloc(void) return mod; } -#define obd_mod_get(mod) atomic_inc(&mod->mod_refcount) -#define obd_mod_put(mod) \ -({ \ - if (atomic_dec_and_test(&mod->mod_refcount)) \ - OBD_FREE_PTR(mod); \ +#define obd_mod_get(mod) atomic_inc(&(mod)->mod_refcount) +#define obd_mod_put(mod) \ +({ \ + if (atomic_dec_and_test(&(mod)->mod_refcount)) { \ + if ((mod)->mod_open_req) \ + ptlrpc_req_finished((mod)->mod_open_req); \ + OBD_FREE_PTR(mod); \ + } \ }) #endif /* __OBD_H */ diff --git a/lustre/mdc/mdc_reint.c b/lustre/mdc/mdc_reint.c index 8354bcc..ecab6c5 100644 --- a/lustre/mdc/mdc_reint.c +++ b/lustre/mdc/mdc_reint.c @@ -185,6 +185,13 @@ int mdc_setattr(struct obd_export *exp, struct md_op_data *op_data, req->rq_cb_data = *mod; (*mod)->mod_open_req = req; req->rq_commit_cb = mdc_commit_open; + /** + * Take an extra reference on \var mod, it protects \var + * mod from being freed on eviction (commit callback is + * called despite rq_replay flag). + * Will be put on mdc_done_writing(). + */ + obd_mod_get(*mod); } } @@ -209,8 +216,11 @@ int mdc_setattr(struct obd_export *exp, struct md_op_data *op_data, rc = 0; } *request = req; - if (rc && req->rq_commit_cb) + if (rc && req->rq_commit_cb) { + /* Put an extra reference on \var mod on error case. */ + obd_mod_put(*mod); req->rq_commit_cb(req); + } RETURN(rc); } diff --git a/lustre/mdc/mdc_request.c b/lustre/mdc/mdc_request.c index 0708d1d..a7a1bb4 100644 --- a/lustre/mdc/mdc_request.c +++ b/lustre/mdc/mdc_request.c @@ -684,8 +684,19 @@ void mdc_commit_open(struct ptlrpc_request *req) * freed after that when md_open_data::mod_och will put the reference. */ + /** + * Do not let open request to disappear as it still may be needed + * for close rpc to happen (it may happen on evict only, otherwise + * ptlrpc_request::rq_replay does not let mdc_commit_open() to be + * called), just mark this rpc as committed to distinguish these 2 + * cases, see mdc_close() for details. The open request reference will + * be put along with freeing \var mod. + */ + ptlrpc_request_addref(req); + spin_lock(&req->rq_lock); + req->rq_committed = 1; + spin_unlock(&req->rq_lock); req->rq_cb_data = NULL; - mod->mod_open_req = NULL; obd_mod_put(mod); } @@ -718,10 +729,18 @@ int mdc_set_open_replay_data(struct obd_export *exp, RETURN(0); } + /** + * Take a reference on \var mod, to be freed on mdc_close(). + * It protects \var mod from being freed on eviction (commit + * callback is called despite rq_replay flag). + * Another reference for \var och. + */ + obd_mod_get(mod); + obd_mod_get(mod); + spin_lock(&open_req->rq_lock); och->och_mod = mod; mod->mod_och = och; - obd_mod_get(mod); mod->mod_open_req = open_req; open_req->rq_cb_data = mod; open_req->rq_commit_cb = mdc_commit_open; @@ -786,11 +805,11 @@ int mdc_close(struct obd_export *exp, struct md_op_data *op_data, /* Ensure that this close's handle is fixed up during replay. */ if (likely(mod != NULL)) { - LASSERTF(mod->mod_open_req->rq_type != LI_POISON, + LASSERTF(mod->mod_open_req != NULL && + mod->mod_open_req->rq_type != LI_POISON, "POISONED open %p!\n", mod->mod_open_req); mod->mod_close_req = req; - obd_mod_get(mod); DEBUG_REQ(D_HA, mod->mod_open_req, "matched open"); /* We no longer want to preserve this open for replay even @@ -839,8 +858,11 @@ int mdc_close(struct obd_export *exp, struct md_op_data *op_data, * server failed before close was sent. Let's check if mod * exists and return no error in that case */ - if (mod && (mod->mod_open_req == NULL)) - rc = 0; + if (mod) { + LASSERT(mod->mod_open_req != NULL); + if (mod->mod_open_req->rq_committed) + rc = 0; + } } if (mod) { @@ -875,11 +897,11 @@ int mdc_done_writing(struct obd_export *exp, struct md_op_data *op_data, } if (mod != NULL) { - LASSERTF(mod->mod_open_req->rq_type != LI_POISON, + LASSERTF(mod->mod_open_req != NULL && + mod->mod_open_req->rq_type != LI_POISON, "POISONED setattr %p!\n", mod->mod_open_req); mod->mod_close_req = req; - obd_mod_get(mod); DEBUG_REQ(D_HA, mod->mod_open_req, "matched setattr"); /* We no longer want to preserve this setattr for replay even * though the open was committed. b=3632, b=3633 */ @@ -901,8 +923,11 @@ int mdc_done_writing(struct obd_export *exp, struct md_op_data *op_data, * committed and server failed before close was sent. * Let's check if mod exists and return no error in that case */ - if (mod && (mod->mod_open_req == NULL)) - rc = 0; + if (mod) { + LASSERT(mod->mod_open_req != NULL); + if (mod->mod_open_req->rq_committed) + rc = 0; + } } if (mod) { -- 1.8.3.1