From 44ecac688986e96d6654a1f71ce07032a8f6c278 Mon Sep 17 00:00:00 2001 From: Fan Yong Date: Mon, 14 Sep 2015 18:41:19 -0400 Subject: [PATCH] staging/lustre/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 Reviewed-on: http://review.whamcloud.com/13709 Intel-bug-id: https://jira.hpdd.intel.com/browse/LU-6301 Reviewed-by: Andreas Dilger Reviewed-by: Lai Siyao Reviewed-by: Alex Zhuravlev Signed-off-by: Oleg Drokin Signed-off-by: Greg Kroah-Hartman --- .../lustre/lustre/llite/llite_internal.h | 1 + .../staging/lustre/lustre/llite/llite_lib.c | 48 ++++++++++++++++++- drivers/staging/lustre/lustre/llite/namei.c | 14 ++++-- 3 files changed, 58 insertions(+), 5 deletions(-) diff --git a/drivers/staging/lustre/lustre/llite/llite_internal.h b/drivers/staging/lustre/lustre/llite/llite_internal.h index 2de64c23383b..8a3b03e36e3c 100644 --- a/drivers/staging/lustre/lustre/llite/llite_internal.h +++ b/drivers/staging/lustre/lustre/llite/llite_internal.h @@ -801,6 +801,7 @@ struct md_op_data *ll_prep_md_op_data(struct md_op_data *op_data, void ll_finish_md_op_data(struct md_op_data *op_data); int ll_get_obd_name(struct inode *inode, unsigned int cmd, unsigned long arg); char *ll_get_fsname(struct super_block *sb, char *buf, int buflen); +void ll_open_cleanup(struct super_block *sb, struct ptlrpc_request *open_req); /* llite/llite_nfs.c */ extern struct export_operations lustre_export_operations; diff --git a/drivers/staging/lustre/lustre/llite/llite_lib.c b/drivers/staging/lustre/lustre/llite/llite_lib.c index c60eb46e9c7e..725481d3916e 100644 --- a/drivers/staging/lustre/lustre/llite/llite_lib.c +++ b/drivers/staging/lustre/lustre/llite/llite_lib.c @@ -1973,6 +1973,47 @@ 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; + + body = req_capsule_server_get(&open_req->rq_pill, &RMF_MDT_BODY); + OBD_ALLOC_PTR(op_data); + if (!op_data) { + CWARN("%s: cannot allocate op_data to release open handle for " + DFID "\n", + ll_get_fsname(sb, NULL, 0), PFID(&body->fid1)); + + return; + } + + op_data->op_fid1 = body->fid1; + op_data->op_ioepoch = body->ioepoch; + op_data->op_handle = body->handle; + op_data->op_mod_time = get_seconds(); + md_close(exp, op_data, NULL, &close_req); + ptlrpc_req_finished(close_req); + ll_finish_md_op_data(op_data); +} + int ll_prep_inode(struct inode **inode, struct ptlrpc_request *req, struct super_block *sb, struct lookup_intent *it) { @@ -1985,7 +2026,7 @@ int ll_prep_inode(struct inode **inode, struct ptlrpc_request *req, rc = md_get_lustre_md(sbi->ll_md_exp, req, sbi->ll_dt_exp, sbi->ll_md_exp, &md); if (rc) - return rc; + goto cleanup; if (*inode) { ll_update_inode(*inode, &md); @@ -2047,6 +2088,11 @@ out: if (md.lsm != NULL) obd_free_memmd(sbi->ll_dt_exp, &md.lsm); md_free_lustre_md(sbi->ll_md_exp, &md); + +cleanup: + if (rc != 0 && it && it->it_op & IT_OPEN) + ll_open_cleanup(sb ? sb : (*inode)->i_sb, req); + return rc; } diff --git a/drivers/staging/lustre/lustre/llite/namei.c b/drivers/staging/lustre/lustre/llite/namei.c index 05e7dc85989e..2635678e3d60 100644 --- a/drivers/staging/lustre/lustre/llite/namei.c +++ b/drivers/staging/lustre/lustre/llite/namei.c @@ -409,7 +409,7 @@ static int ll_lookup_it_finish(struct ptlrpc_request *request, { struct inode *inode = NULL; __u64 bits = 0; - int rc; + int rc = 0; /* NB 1 request reference will be taken away by ll_intent_lock() * when I return */ @@ -439,8 +439,10 @@ static int ll_lookup_it_finish(struct ptlrpc_request *request, struct dentry *alias; alias = ll_splice_alias(inode, *de); - if (IS_ERR(alias)) - return PTR_ERR(alias); + if (IS_ERR(alias)) { + rc = PTR_ERR(alias); + goto out; + } *de = alias; } else if (!it_disposition(it, DISP_LOOKUP_NEG) && !it_disposition(it, DISP_OPEN_CREATE)) { @@ -471,7 +473,11 @@ static int ll_lookup_it_finish(struct ptlrpc_request *request, } } - 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, -- 2.34.1