* RHEL 4 and RHEL 5/SLES 10 clients behaves differently on 'cd' to a
removed cwd "./" (refer to Bugzilla 14399).
+Severity : normal
+Frequency : occasional
+Bugzilla : 13537
+Description: Correctly check stale fid, not start epoch if ost not support SOM
+Details : open with flag O_CREATE need set old fid in op_fid3 because op_fid2
+ overwrited with new generated fid, but mds can anwer with one of these
+ two fids and both is not stale. setattr incorectly start epoch and
+ assume will be called done_writeting, but without SOM done_writing
+ never called.
+
Severity : major
Frequency : rare, depends on device drivers and load
Bugzilla : 14529
export->exp_lock_replay_needed = 1;
spin_unlock(&export->exp_lock);
if ((lustre_msg_get_op_flags(req->rq_reqmsg) & MSG_CONNECT_TRANSNO)
+ && (data->ocd_transno == 0))
+ CWARN("Connect with zero transno!\n");
+
+ if ((lustre_msg_get_op_flags(req->rq_reqmsg) & MSG_CONNECT_TRANSNO)
&& data->ocd_transno < target->obd_next_recovery_transno)
target->obd_next_recovery_transno = data->ocd_transno;
target->obd_connected_clients++;
it->it_op_release = 0;
#endif
/* We are still holding extra reference on a request, need to free it */
- if (it_disposition(it, DISP_ENQ_OPEN_REF)) /* open req for llfile_open*/
- ptlrpc_req_finished(it->d.lustre.it_data);
+ if (it_disposition(it, DISP_ENQ_OPEN_REF))
+ ptlrpc_req_finished(it->d.lustre.it_data); /* ll_file_open */
if (it_disposition(it, DISP_ENQ_CREATE_REF)) /* create rec */
ptlrpc_req_finished(it->d.lustre.it_data);
if (it_disposition(it, DISP_ENQ_COMPLETE)) /* saved req from revalidate
rc = ll_have_md_lock(de->d_parent->d_inode,
MDS_INODELOCK_UPDATE);
-
RETURN(rc);
}
OBD_FAIL_TIMEOUT(OBD_FAIL_MDC_REVALIDATE_PAUSE, 5);
ll_frob_intent(&it, &lookup_it);
LASSERT(it);
-
parent = de->d_parent->d_inode;
- if (it->it_op & IT_CREAT) {
- op_data = ll_prep_md_op_data(NULL, parent, NULL,
- de->d_name.name, de->d_name.len,
- 0, LUSTRE_OPC_CREATE, NULL);
- } else {
- op_data = ll_prep_md_op_data(NULL, parent, de->d_inode,
- de->d_name.name, de->d_name.len,
- 0, LUSTRE_OPC_ANY, NULL);
- }
+ op_data = ll_prep_md_op_data(NULL, parent, de->d_inode,
+ de->d_name.name, de->d_name.len,
+ 0, LUSTRE_OPC_ANY, NULL);
if (IS_ERR(op_data))
RETURN(PTR_ERR(op_data));
struct ll_inode_info *lli = ll_i2info(inode);
struct obd_client_handle **och_p;
__u64 *och_usecount;
-
+
/*
* We used to check for MDS_INODELOCK_OPEN here, but in fact
* just having LOOKUP lock is enough to justify inode is the
struct mdt_body *mdt_body;
struct lu_fid fid = {.f_seq = 0, .f_oid = 0, .f_ver = 0};
mdt_body = req_capsule_server_get(&req->rq_pill, &RMF_MDT_BODY);
-
+
if (de->d_inode)
fid = *ll_inode2fid(de->d_inode);
OBD_ALLOC_PTR(op_data);
if (op_data == NULL)
RETURN(-ENOMEM);
-
+
memcpy(&op_data->op_attr, attr, sizeof(*attr));
/* Open epoch for truncate. */
- if (ia_valid & ATTR_SIZE)
+ if ((ll_i2mdexp(inode)->exp_connect_flags & OBD_CONNECT_SOM) &&
+ (ia_valid & ATTR_SIZE))
op_data->op_flags = MF_EPOCH_OPEN;
-
+
rc = ll_md_setattr(inode, op_data, &mod);
if (rc)
GOTO(out, rc);
* For open with IT_CREATE and for IT_CREATE cases allocate new
* fid and setup FLD for it.
*/
+ /* save old child fid for correctly check stale data*/
+ sop_data->op_fid3 = sop_data->op_fid2;
rc = lmv_fid_alloc(exp, &sop_data->op_fid2, sop_data);
if (rc)
GOTO(out_free_sop_data, rc);
it_set_disposition(it, DISP_ENQ_COMPLETE);
/* Also: did we find the same inode? */
- if (!lu_fid_eq(&op_data->op_fid2, &mdt_body->fid1))
+ /* sever can return one of two fids:
+ * op_fid2 - new allocated fid - if file is created.
+ * op_fid3 - existent fid - if file only open.
+ * op_fid3 is saved in lmv_intent_open */
+ if ((!lu_fid_eq(&op_data->op_fid2, &mdt_body->fid1)) &&
+ (!lu_fid_eq(&op_data->op_fid3, &mdt_body->fid1))) {
+ CDEBUG(D_DENTRY, "Found stale data "DFID"("DFID")/"DFID
+ "\n", PFID(&op_data->op_fid2),
+ PFID(&op_data->op_fid2), PFID(&mdt_body->fid1));
RETURN(-ESTALE);
+ }
}
rc = it_open_error(DISP_LOOKUP_EXECD, it);
{
struct ptlrpc_request *req;
struct list_head *tmp;
-
+
if (list_empty(&imp->imp_replay_list))
return 0;
tmp = imp->imp_replay_list.next;
req = list_entry(tmp, struct ptlrpc_request, rq_replay_list);
*transno = req->rq_transno;
+ if (req->rq_transno == 0) {
+ DEBUG_REQ(D_ERROR, req, "zero transno in replay");
+ LBUG();
+ }
+
return 1;
}