From d2b203692e24cde8e39266f91e9a150c5a287111 Mon Sep 17 00:00:00 2001 From: Fan Yong Date: Sun, 30 Nov 2014 08:26:29 +0800 Subject: [PATCH] LU-6301 llite: cleanup open handle for client open failure For open case, the client side open handling thread may hit error after the MDT grant the open. Under such case, the client should send close RPC to the MDT as cleanup; otherwise, the open handle on the MDT will be leaked there until the client umount or evicted. If the LFSCK marks LU_OBJECT_HEARD_BANSHEE on the MDT-object that is opened by others for repairing some inconsistency, such as repairing multiple-referenced OST-object, because the leaked open handle still references the MDT-object, then it will block the subsequent threads that want to locate such object via FID. Signed-off-by: Fan Yong Change-Id: I1fff2cde179b039e3bee562ef79d5cf3587fe3c8 Reviewed-on: http://review.whamcloud.com/13709 Reviewed-by: Andreas Dilger Tested-by: Jenkins Reviewed-by: Lai Siyao Reviewed-by: Alex Zhuravlev Tested-by: Maloo Reviewed-by: Oleg Drokin --- lustre/llite/llite_internal.h | 1 + lustre/llite/llite_lib.c | 65 ++++++++++++++++++++++++++++++++++++++----- lustre/llite/namei.c | 15 +++++++--- 3 files changed, 70 insertions(+), 11 deletions(-) diff --git a/lustre/llite/llite_internal.h b/lustre/llite/llite_internal.h index baa47ba..327cb36 100644 --- a/lustre/llite/llite_internal.h +++ b/lustre/llite/llite_internal.h @@ -934,6 +934,7 @@ char *ll_get_fsname(struct super_block *sb, char *buf, int buflen); void ll_compute_rootsquash_state(struct ll_sb_info *sbi); ssize_t ll_copy_user_md(const struct lov_user_md __user *md, struct lov_user_md **kbuf); +void ll_open_cleanup(struct super_block *sb, struct ptlrpc_request *open_req); /* Compute expected user md size when passing in a md from user space */ static inline ssize_t ll_lov_user_md_size(const struct lov_user_md *lum) diff --git a/lustre/llite/llite_lib.c b/lustre/llite/llite_lib.c index 7d332ab..d5d96e5 100644 --- a/lustre/llite/llite_lib.c +++ b/lustre/llite/llite_lib.c @@ -2388,6 +2388,50 @@ int ll_remount_fs(struct super_block *sb, int *flags, char *data) return 0; } +/** + * Cleanup the open handle that is cached on MDT-side. + * + * For open case, the client side open handling thread may hit error + * after the MDT grant the open. Under such case, the client should + * send close RPC to the MDT as cleanup; otherwise, the open handle + * on the MDT will be leaked there until the client umount or evicted. + * + * In further, if someone unlinked the file, because the open handle + * holds the reference on such file/object, then it will block the + * subsequent threads that want to locate such object via FID. + * + * \param[in] sb super block for this file-system + * \param[in] open_req pointer to the original open request + */ +void ll_open_cleanup(struct super_block *sb, struct ptlrpc_request *open_req) +{ + struct mdt_body *body; + struct md_op_data *op_data; + struct ptlrpc_request *close_req = NULL; + struct obd_export *exp = ll_s2sbi(sb)->ll_md_exp; + ENTRY; + + body = req_capsule_server_get(&open_req->rq_pill, &RMF_MDT_BODY); + OBD_ALLOC_PTR(op_data); + if (op_data == NULL) { + CWARN("%s: cannot allocate op_data to release open handle for " + DFID"\n", + ll_get_fsname(sb, NULL, 0), PFID(&body->mbo_fid1)); + + RETURN_EXIT; + } + + op_data->op_fid1 = body->mbo_fid1; + op_data->op_ioepoch = body->mbo_ioepoch; + op_data->op_handle = body->mbo_handle; + op_data->op_mod_time = cfs_time_current_sec(); + md_close(exp, op_data, NULL, &close_req); + ptlrpc_req_finished(close_req); + ll_finish_md_op_data(op_data); + + EXIT; +} + int ll_prep_inode(struct inode **inode, struct ptlrpc_request *req, struct super_block *sb, struct lookup_intent *it) { @@ -2396,12 +2440,12 @@ int ll_prep_inode(struct inode **inode, struct ptlrpc_request *req, int rc; ENTRY; - LASSERT(*inode || sb); - sbi = sb ? ll_s2sbi(sb) : ll_i2sbi(*inode); - rc = md_get_lustre_md(sbi->ll_md_exp, req, sbi->ll_dt_exp, - sbi->ll_md_exp, &md); - if (rc) - RETURN(rc); + LASSERT(*inode || sb); + sbi = sb ? ll_s2sbi(sb) : ll_i2sbi(*inode); + rc = md_get_lustre_md(sbi->ll_md_exp, req, sbi->ll_dt_exp, + sbi->ll_md_exp, &md); + if (rc != 0) + GOTO(cleanup, rc); if (*inode) { rc = ll_update_inode(*inode, &md); @@ -2461,11 +2505,18 @@ int ll_prep_inode(struct inode **inode, struct ptlrpc_request *req, LDLM_LOCK_PUT(lock); } + GOTO(out, rc = 0); + out: if (md.lsm != NULL) obd_free_memmd(sbi->ll_dt_exp, &md.lsm); md_free_lustre_md(sbi->ll_md_exp, &md); - RETURN(rc); + +cleanup: + if (rc != 0 && it != NULL && it->it_op & IT_OPEN) + ll_open_cleanup(sb != NULL ? sb : (*inode)->i_sb, req); + + return rc; } int ll_obd_statfs(struct inode *inode, void __user *arg) diff --git a/lustre/llite/namei.c b/lustre/llite/namei.c index 6329551..f5288a9 100644 --- a/lustre/llite/namei.c +++ b/lustre/llite/namei.c @@ -469,7 +469,8 @@ static int ll_lookup_it_finish(struct ptlrpc_request *request, alias = ll_splice_alias(inode, *de); if (IS_ERR(alias)) - RETURN(PTR_ERR(alias)); + GOTO(out, rc = PTR_ERR(alias)); + *de = alias; } else if (!it_disposition(it, DISP_LOOKUP_NEG) && !it_disposition(it, DISP_OPEN_CREATE)) { @@ -501,7 +502,7 @@ static int ll_lookup_it_finish(struct ptlrpc_request *request, (*de)->d_name.name, (*de)->d_name.len, &fid); if (rc != 0) - RETURN(rc); + GOTO(out, rc); } if (md_revalidate_lock(ll_i2mdexp(parent), &parent_it, &fid, @@ -509,9 +510,15 @@ static int ll_lookup_it_finish(struct ptlrpc_request *request, d_lustre_revalidate(*de); ll_intent_release(&parent_it); } - } + } + + GOTO(out, rc = 0); - RETURN(0); +out: + if (rc != 0 && it->it_op & IT_OPEN) + ll_open_cleanup((*de)->d_sb, request); + + return rc; } static struct dentry *ll_lookup_it(struct inode *parent, struct dentry *dentry, -- 1.8.3.1