* 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);
}
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;
/* 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
* 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) {
}
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 */
* 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) {