Whamcloud - gitweb
LU-6301 llite: cleanup open handle for client open failure 09/13709/13
authorFan Yong <fan.yong@intel.com>
Sun, 30 Nov 2014 00:26:29 +0000 (08:26 +0800)
committerOleg Drokin <oleg.drokin@intel.com>
Tue, 3 Mar 2015 02:11:38 +0000 (02:11 +0000)
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>
Change-Id: I1fff2cde179b039e3bee562ef79d5cf3587fe3c8
Reviewed-on: http://review.whamcloud.com/13709
Reviewed-by: Andreas Dilger <andreas.dilger@intel.com>
Tested-by: Jenkins
Reviewed-by: Lai Siyao <lai.siyao@intel.com>
Reviewed-by: Alex Zhuravlev <alexey.zhuravlev@intel.com>
Tested-by: Maloo <hpdd-maloo@intel.com>
Reviewed-by: Oleg Drokin <oleg.drokin@intel.com>
lustre/llite/llite_internal.h
lustre/llite/llite_lib.c
lustre/llite/namei.c

index baa47ba..327cb36 100644 (file)
@@ -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)
index 7d332ab..d5d96e5 100644 (file)
@@ -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)
index 6329551..f5288a9 100644 (file)
@@ -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,