diff --git a/lustre/ChangeLog b/lustre/ChangeLog index f4f8c00b951c6edaf93c930bee0296f4c2632042..7cf8c4d3894729d577be1ccbeb7cdfb66ff0c3b3 100644 --- a/lustre/ChangeLog +++ b/lustre/ChangeLog @@ -75,6 +75,13 @@ Bugzilla : 15278 Description: fix build on ppc32 Details : compile code with -m64 flag produce wrong object file for ppc32. +Severity : normal +Bugzilla : 15774 +Description: MDS LBUG: ASSERTION(!IS_ERR(dchild)) +Details : In reconstruct_* functions, LASSERTs on both the data supplied by + a client, and the data on disk are dangerous and incorrect. Change + them with client eviction. + ------------------------------------------------------------------------------- diff --git a/lustre/mds/handler.c b/lustre/mds/handler.c index 334208becd928ba41409eebe01a6be9420a25441..0e7c005aa8e52be2285f8e218f350d1baea5b21b 100644 --- a/lustre/mds/handler.c +++ b/lustre/mds/handler.c @@ -954,6 +954,8 @@ static int mds_getattr_lock(struct ptlrpc_request *req, int offset, } #endif + /* child_lockh() is only set in fixup_handle_for_resent_req() + * if MSG_RESENT is set */ if (lustre_handle_is_used(child_lockh)) { LASSERT(lustre_msg_get_flags(req->rq_reqmsg) & MSG_RESENT); resent_req = 1; @@ -987,6 +989,8 @@ static int mds_getattr_lock(struct ptlrpc_request *req, int offset, struct ldlm_resource *res; DEBUG_REQ(D_DLMTRACE, req, "resent, not enqueuing new locks"); granted_lock = ldlm_handle2lock(child_lockh); + /* lock was granted in fixup_handle_for_resent_req() if + * MSG_RESENT is set */ LASSERTF(granted_lock != NULL, LPU64"/%u lockh "LPX64"\n", body->fid1.id, body->fid1.generation, child_lockh->cookie); @@ -996,7 +1000,12 @@ static int mds_getattr_lock(struct ptlrpc_request *req, int offset, child_fid.id = res->lr_name.name[0]; child_fid.generation = res->lr_name.name[1]; dchild = mds_fid2dentry(&obd->u.mds, &child_fid, NULL); - LASSERT(!IS_ERR(dchild)); + if (IS_ERR(dchild)) { + rc = PTR_ERR(dchild); + LCONSOLE_WARN("Child "LPU64"/%u lookup error %d.", + child_fid.id, child_fid.generation, rc); + GOTO(cleanup, rc); + } LDLM_LOCK_PUT(granted_lock); } diff --git a/lustre/mds/mds_internal.h b/lustre/mds/mds_internal.h index f0817ef771d764b4e7ac86a743bf31e4a4b2325b..b13619309d7817d77941df4c8cbe16603d7a50f9 100644 --- a/lustre/mds/mds_internal.h +++ b/lustre/mds/mds_internal.h @@ -41,6 +41,12 @@ static inline struct mds_obd *mds_req2mds(struct ptlrpc_request *req) return &req->rq_export->exp_obd->u.mds; } +static inline void mds_export_evict(struct obd_export *exp) +{ + class_fail_export(exp); + class_export_put(exp); +} + #ifdef __KERNEL__ /* Open counts for files. No longer atomic, must hold inode->i_sem */ #if (LINUX_VERSION_CODE >= KERNEL_VERSION(2,5,0)) diff --git a/lustre/mds/mds_open.c b/lustre/mds/mds_open.c index b8c771aeb99805276214540f1049535e73614d74..e652c7e5ca92d258e09c163868ab2cd99a0df041 100644 --- a/lustre/mds/mds_open.c +++ b/lustre/mds/mds_open.c @@ -501,7 +501,8 @@ static void reconstruct_open(struct mds_update_record *rec, int offset, struct mds_client_data *mcd = med->med_mcd; struct mds_obd *mds = mds_req2mds(req); struct mds_file_data *mfd; - struct obd_device *obd = req->rq_export->exp_obd; + struct obd_export *exp = req->rq_export; + struct obd_device *obd = exp->exp_obd; struct dentry *parent, *dchild; struct ldlm_reply *rep; struct mds_body *body; @@ -525,10 +526,30 @@ static void reconstruct_open(struct mds_update_record *rec, int offset, } parent = mds_fid2dentry(mds, rec->ur_fid1, NULL); - LASSERT(!IS_ERR(parent)); + if (IS_ERR(parent)) { + rc = PTR_ERR(parent); + LCONSOLE_WARN("Parent "LPU64"/%u lookup error %d." + " Evicting client %s with export %s.\n", + rec->ur_fid1->id, rec->ur_fid1->generation, rc, + obd_uuid2str(&exp->exp_client_uuid), + obd_export_nid2str(exp)); + mds_export_evict(exp); + EXIT; + return; + } dchild = ll_lookup_one_len(rec->ur_name, parent, rec->ur_namelen - 1); - LASSERT(!IS_ERR(dchild)); + if (IS_ERR(dchild)) { + rc = PTR_ERR(dchild); + LCONSOLE_WARN("Child "LPU64"/%u lookup error %d." + " Evicting client %s with export %s.\n", + rec->ur_fid1->id, rec->ur_fid1->generation, rc, + obd_uuid2str(&exp->exp_client_uuid), + obd_export_nid2str(exp)); + mds_export_evict(exp); + EXIT; + return; + } if (!dchild->d_inode) GOTO(out_dput, 0); /* child not present to open */ diff --git a/lustre/mds/mds_reint.c b/lustre/mds/mds_reint.c index f366f1282d95c5569ee1c4cd9512b2148419335b..61e010881405a2ebea832ff587b3cf5f206306ac 100644 --- a/lustre/mds/mds_reint.c +++ b/lustre/mds/mds_reint.c @@ -402,8 +402,9 @@ void mds_req_from_mcd(struct ptlrpc_request *req, struct mds_client_data *mcd) static void reconstruct_reint_setattr(struct mds_update_record *rec, int offset, struct ptlrpc_request *req) { - struct mds_export_data *med = &req->rq_export->exp_mds_data; - struct mds_obd *obd = &req->rq_export->exp_obd->u.mds; + struct obd_export *exp = req->rq_export; + struct mds_export_data *med = &exp->exp_mds_data; + struct mds_obd *obd = &exp->exp_obd->u.mds; struct dentry *de; struct mds_body *body; @@ -411,7 +412,15 @@ static void reconstruct_reint_setattr(struct mds_update_record *rec, de = mds_fid2dentry(obd, rec->ur_fid1, NULL); if (IS_ERR(de)) { - LASSERT(PTR_ERR(de) == req->rq_status); + int rc; + rc = PTR_ERR(de); + LCONSOLE_WARN("FID "LPU64"/%u lookup error %d." + " Evicting client %s with export %s.\n", + rec->ur_fid1->id, rec->ur_fid1->generation, rc, + obd_uuid2str(&exp->exp_client_uuid), + obd_export_nid2str(exp)); + mds_export_evict(exp); + EXIT; return; } @@ -737,10 +746,12 @@ static int mds_reint_setattr(struct mds_update_record *rec, int offset, static void reconstruct_reint_create(struct mds_update_record *rec, int offset, struct ptlrpc_request *req) { - struct mds_export_data *med = &req->rq_export->exp_mds_data; - struct mds_obd *obd = &req->rq_export->exp_obd->u.mds; + struct obd_export *exp = req->rq_export; + struct mds_export_data *med = &exp->exp_mds_data; + struct mds_obd *obd = &exp->exp_obd->u.mds; struct dentry *parent, *child; struct mds_body *body; + int rc; mds_req_from_mcd(req, med->med_mcd); @@ -748,9 +759,29 @@ static void reconstruct_reint_create(struct mds_update_record *rec, int offset, return; parent = mds_fid2dentry(obd, rec->ur_fid1, NULL); - LASSERT(!IS_ERR(parent)); + if (IS_ERR(parent)) { + rc = PTR_ERR(parent); + LCONSOLE_WARN("Parent "LPU64"/%u lookup error %d." + " Evicting client %s with export %s.\n", + rec->ur_fid1->id, rec->ur_fid1->generation, rc, + obd_uuid2str(&exp->exp_client_uuid), + obd_export_nid2str(exp)); + mds_export_evict(exp); + EXIT; + return; + } child = ll_lookup_one_len(rec->ur_name, parent, rec->ur_namelen - 1); - LASSERT(!IS_ERR(child)); + if (IS_ERR(child)) { + rc = PTR_ERR(child); + LCONSOLE_WARN("Child "LPU64"/%u lookup error %d." + " Evicting client %s with export %s.\n", + rec->ur_fid1->id, rec->ur_fid1->generation, rc, + obd_uuid2str(&exp->exp_client_uuid), + obd_export_nid2str(exp)); + mds_export_evict(exp); + EXIT; + return; + } body = lustre_msg_buf(req->rq_repmsg, offset, sizeof(*body)); mds_pack_inode2fid(&body->fid1, child->d_inode);