staging/lustre/llite: cleanup open handle for client open failure
authorFan Yong <fan.yong@intel.com>
Mon, 14 Sep 2015 22:41:19 +0000 (18:41 -0400)
committerGreg Kroah-Hartman <gregkh@linuxfoundation.org>
Tue, 15 Sep 2015 13:26:52 +0000 (06:26 -0700)
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 <fan.yong@intel.com>
Reviewed-on: http://review.whamcloud.com/13709
Intel-bug-id: https://jira.hpdd.intel.com/browse/LU-6301
Reviewed-by: Andreas Dilger <andreas.dilger@intel.com>
Reviewed-by: Lai Siyao <lai.siyao@intel.com>
Reviewed-by: Alex Zhuravlev <alexey.zhuravlev@intel.com>
Signed-off-by: Oleg Drokin <oleg.drokin@intel.com>
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
drivers/staging/lustre/lustre/llite/llite_internal.h
drivers/staging/lustre/lustre/llite/llite_lib.c
drivers/staging/lustre/lustre/llite/namei.c

index 2de64c23383be848c3ca8c62c28327e07782a7bd..8a3b03e36e3cee97066481adb515ffc247a409b9 100644 (file)
@@ -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;
index c60eb46e9c7ef6168eb5ac8f3ca51740ed9fb392..725481d3916e625267565bdc01e1d01563f258cc 100644 (file)
@@ -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;
 }
 
index 05e7dc85989edde49566857d9fec19d6539b3f94..2635678e3d60357f2a5d1d765dc9d574beba5d57 100644 (file)
@@ -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,