]> git.karo-electronics.de Git - linux-beck.git/commitdiff
staging: lustre: mdt: race between open and migrate
authorwang di <di.wang@intel.com>
Sat, 3 Dec 2016 00:53:10 +0000 (19:53 -0500)
committerGreg Kroah-Hartman <gregkh@linuxfoundation.org>
Tue, 6 Dec 2016 09:47:55 +0000 (10:47 +0100)
During intent open, it was found that if the parent has
been migrated to another MDT, it should retry the open
request with the new object, so it needs to keep the
old object in the orphan list, which will be cleanup
during next recovery. Note: if the client still using
the old FID after next recovery, it will return -ENOENT
for the application. Also enqueue the lease lock of
the migrating file, then compare the lease before
migration to make sure no other clients open the file
at the same time.

Signed-off-by: wang di <di.wang@intel.com>
Intel-bug-id: https://jira.hpdd.intel.com/browse/LU-6475
Reviewed-on: http://review.whamcloud.com/14497
Reviewed-by: James Simmons <uja.ornl@yahoo.com>
Reviewed-by: Andreas Dilger <andreas.dilger@intel.com>
Reviewed-by: Oleg Drokin <oleg.drokin@intel.com>
Signed-off-by: James Simmons <jsimmons@infradead.org>
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
drivers/staging/lustre/lustre/include/lustre_req_layout.h
drivers/staging/lustre/lustre/llite/dir.c
drivers/staging/lustre/lustre/llite/file.c
drivers/staging/lustre/lustre/llite/llite_internal.h
drivers/staging/lustre/lustre/mdc/mdc_lib.c
drivers/staging/lustre/lustre/mdc/mdc_reint.c
drivers/staging/lustre/lustre/ptlrpc/layout.c

index 7657132b224ffcc5299de7ca2b1bef35d62bec9d..fbcd39572cd01e63c8dec07be8ce59cad752799f 100644 (file)
@@ -167,6 +167,7 @@ extern struct req_format RQF_MDS_REINT_SETATTR;
 extern struct req_format RQF_MDS_REINT_SETXATTR;
 extern struct req_format RQF_MDS_QUOTACTL;
 extern struct req_format RQF_MDS_SWAP_LAYOUTS;
+extern struct req_format RQF_MDS_REINT_MIGRATE;
 /* MDS hsm formats */
 extern struct req_format RQF_MDS_HSM_STATE_GET;
 extern struct req_format RQF_MDS_HSM_STATE_SET;
index fc291780a5189aae080f4b41fc3db5ad1fc6a9d9..7bdcbb46deaee6c1da0cd9abc1fcd5834d27371b 100644 (file)
@@ -1085,7 +1085,7 @@ static long ll_dir_ioctl(struct file *file, unsigned int cmd, unsigned long arg)
                        goto out_free;
                }
 
-               rc = ll_get_fid_by_name(inode, filename, namelen, NULL);
+               rc = ll_get_fid_by_name(inode, filename, namelen, NULL, NULL);
                if (rc < 0) {
                        CERROR("%s: lookup %.*s failed: rc = %d\n",
                               ll_get_fsname(inode->i_sb, NULL, 0), namelen,
index 12fff93b0a55ebc69667ab0003c2595ce6a6d8a5..f634c11216e641311191333064bd2c35fed33643 100644 (file)
@@ -2532,7 +2532,8 @@ ll_file_flock(struct file *file, int cmd, struct file_lock *file_lock)
 }
 
 int ll_get_fid_by_name(struct inode *parent, const char *name,
-                      int namelen, struct lu_fid *fid)
+                      int namelen, struct lu_fid *fid,
+                      struct inode **inode)
 {
        struct md_op_data *op_data = NULL;
        struct ptlrpc_request *req;
@@ -2544,7 +2545,7 @@ int ll_get_fid_by_name(struct inode *parent, const char *name,
        if (IS_ERR(op_data))
                return PTR_ERR(op_data);
 
-       op_data->op_valid = OBD_MD_FLID;
+       op_data->op_valid = OBD_MD_FLID | OBD_MD_FLTYPE;
        rc = md_getattr_name(ll_i2sbi(parent)->ll_md_exp, op_data, &req);
        ll_finish_md_op_data(op_data);
        if (rc < 0)
@@ -2557,6 +2558,9 @@ int ll_get_fid_by_name(struct inode *parent, const char *name,
        }
        if (fid)
                *fid = body->mbo_fid1;
+
+       if (inode)
+               rc = ll_prep_inode(inode, req, parent->i_sb, NULL);
 out_req:
        ptlrpc_req_finished(req);
        return rc;
@@ -2566,9 +2570,12 @@ int ll_migrate(struct inode *parent, struct file *file, int mdtidx,
               const char *name, int namelen)
 {
        struct ptlrpc_request *request = NULL;
+       struct obd_client_handle *och = NULL;
        struct inode *child_inode = NULL;
        struct dentry *dchild = NULL;
        struct md_op_data *op_data;
+       struct mdt_body *body;
+       u64 data_version = 0;
        struct qstr qstr;
        int rc;
 
@@ -2587,22 +2594,25 @@ int ll_migrate(struct inode *parent, struct file *file, int mdtidx,
        dchild = d_lookup(file_dentry(file), &qstr);
        if (dchild) {
                op_data->op_fid3 = *ll_inode2fid(dchild->d_inode);
-               if (dchild->d_inode) {
+               if (dchild->d_inode)
                        child_inode = igrab(dchild->d_inode);
-                       if (child_inode) {
-                               inode_lock(child_inode);
-                               op_data->op_fid3 = *ll_inode2fid(child_inode);
-                               ll_invalidate_aliases(child_inode);
-                       }
-               }
                dput(dchild);
-       } else {
+       }
+
+       if (!child_inode) {
                rc = ll_get_fid_by_name(parent, name, namelen,
-                                       &op_data->op_fid3);
+                                       &op_data->op_fid3, &child_inode);
                if (rc)
                        goto out_free;
        }
 
+       if (!child_inode) {
+               rc = -EINVAL;
+               goto out_free;
+       }
+
+       inode_lock(child_inode);
+       op_data->op_fid3 = *ll_inode2fid(child_inode);
        if (!fid_is_sane(&op_data->op_fid3)) {
                CERROR("%s: migrate %s, but fid "DFID" is insane\n",
                       ll_get_fsname(parent->i_sb, NULL, 0), name,
@@ -2621,6 +2631,26 @@ int ll_migrate(struct inode *parent, struct file *file, int mdtidx,
                rc = 0;
                goto out_free;
        }
+again:
+       if (S_ISREG(child_inode->i_mode)) {
+               och = ll_lease_open(child_inode, NULL, FMODE_WRITE, 0);
+               if (IS_ERR(och)) {
+                       rc = PTR_ERR(och);
+                       och = NULL;
+                       goto out_free;
+               }
+
+               rc = ll_data_version(child_inode, &data_version,
+                                    LL_DV_WR_FLUSH);
+               if (rc)
+                       goto out_free;
+
+               op_data->op_handle = och->och_fh;
+               op_data->op_data = och->och_mod;
+               op_data->op_data_version = data_version;
+               op_data->op_lease_handle = och->och_lease_handle;
+               op_data->op_bias |= MDS_RENAME_MIGRATE;
+       }
 
        op_data->op_mds = mdtidx;
        op_data->op_cli_flags = CLI_MIGRATE;
@@ -2629,10 +2659,32 @@ int ll_migrate(struct inode *parent, struct file *file, int mdtidx,
        if (!rc)
                ll_update_times(request, parent);
 
-       ptlrpc_req_finished(request);
+       body = req_capsule_server_get(&request->rq_pill, &RMF_MDT_BODY);
+       if (!body) {
+               rc = -EPROTO;
+               goto out_free;
+       }
+
+       /*
+        * If the server does release layout lock, then we cleanup
+        * the client och here, otherwise release it in out_free:
+        */
+       if (och && body->mbo_valid & OBD_MD_CLOSE_INTENT_EXECED) {
+               obd_mod_put(och->och_mod);
+               md_clear_open_replay_data(ll_i2sbi(parent)->ll_md_exp, och);
+               och->och_fh.cookie = DEAD_HANDLE_MAGIC;
+               kfree(och);
+               och = NULL;
+       }
 
+       ptlrpc_req_finished(request);
+       /* Try again if the file layout has changed. */
+       if (rc == -EAGAIN && S_ISREG(child_inode->i_mode))
+               goto again;
 out_free:
        if (child_inode) {
+               if (och) /* close the file */
+                       ll_lease_close(och, child_inode, NULL);
                clear_nlink(child_inode);
                inode_unlock(child_inode);
                iput(child_inode);
index ac4ce059bbc626ad23af3637991306a78994d545..ae0bb09796f422607e17bed895730b7d0edc7ed6 100644 (file)
@@ -745,7 +745,7 @@ struct posix_acl *ll_get_acl(struct inode *inode, int type);
 int ll_migrate(struct inode *parent, struct file *file, int mdtidx,
               const char *name, int namelen);
 int ll_get_fid_by_name(struct inode *parent, const char *name,
-                      int namelen, struct lu_fid *fid);
+                      int namelen, struct lu_fid *fid, struct inode **inode);
 int ll_inode_permission(struct inode *inode, int mask);
 
 int ll_lov_setstripe_ea_info(struct inode *inode, struct dentry *dentry,
index c1990f07ff6faf1027d30369f15fe9d79619e7b3..f35e1f9afdefb03102c5b5f4f7a4bff99045912d 100644 (file)
@@ -376,6 +376,31 @@ void mdc_link_pack(struct ptlrpc_request *req, struct md_op_data *op_data)
        mdc_pack_name(req, &RMF_NAME, op_data->op_name, op_data->op_namelen);
 }
 
+static void mdc_intent_close_pack(struct ptlrpc_request *req,
+                                 struct md_op_data *op_data)
+{
+       enum mds_op_bias bias = op_data->op_bias;
+       struct close_data *data;
+       struct ldlm_lock *lock;
+
+       if (!(bias & (MDS_HSM_RELEASE | MDS_CLOSE_LAYOUT_SWAP |
+                     MDS_RENAME_MIGRATE)))
+               return;
+
+       data = req_capsule_client_get(&req->rq_pill, &RMF_CLOSE_DATA);
+       LASSERT(data);
+
+       lock = ldlm_handle2lock(&op_data->op_lease_handle);
+       if (lock) {
+               data->cd_handle = lock->l_remote_handle;
+               LDLM_LOCK_PUT(lock);
+       }
+       ldlm_cli_cancel(&op_data->op_lease_handle, LCF_LOCAL);
+
+       data->cd_data_version = op_data->op_data_version;
+       data->cd_fid = op_data->op_fid2;
+}
+
 void mdc_rename_pack(struct ptlrpc_request *req, struct md_op_data *op_data,
                     const char *old, size_t oldlen,
                     const char *new, size_t newlen)
@@ -404,6 +429,15 @@ void mdc_rename_pack(struct ptlrpc_request *req, struct md_op_data *op_data,
 
        if (new)
                mdc_pack_name(req, &RMF_SYMTGT, new, newlen);
+
+       if (op_data->op_cli_flags & CLI_MIGRATE &&
+           op_data->op_bias & MDS_RENAME_MIGRATE) {
+               struct mdt_ioepoch *epoch;
+
+               mdc_intent_close_pack(req, op_data);
+               epoch = req_capsule_client_get(&req->rq_pill, &RMF_MDT_EPOCH);
+               mdc_ioepoch_pack(epoch, op_data);
+       }
 }
 
 void mdc_getattr_pack(struct ptlrpc_request *req, __u64 valid, u32 flags,
@@ -430,31 +464,6 @@ void mdc_getattr_pack(struct ptlrpc_request *req, __u64 valid, u32 flags,
                              op_data->op_namelen);
 }
 
-static void mdc_intent_close_pack(struct ptlrpc_request *req,
-                                 struct md_op_data *op_data)
-{
-       enum mds_op_bias bias = op_data->op_bias;
-       struct close_data *data;
-       struct ldlm_lock *lock;
-
-       if (!(bias & (MDS_HSM_RELEASE | MDS_CLOSE_LAYOUT_SWAP |
-                     MDS_RENAME_MIGRATE)))
-               return;
-
-       data = req_capsule_client_get(&req->rq_pill, &RMF_CLOSE_DATA);
-       LASSERT(data);
-
-       lock = ldlm_handle2lock(&op_data->op_lease_handle);
-       if (lock) {
-               data->cd_handle = lock->l_remote_handle;
-               LDLM_LOCK_PUT(lock);
-       }
-       ldlm_cli_cancel(&op_data->op_lease_handle, LCF_LOCAL);
-
-       data->cd_data_version = op_data->op_data_version;
-       data->cd_fid = op_data->op_fid2;
-}
-
 void mdc_close_pack(struct ptlrpc_request *req, struct md_op_data *op_data)
 {
        struct mdt_ioepoch *epoch;
index 51195884520aa28563006a82e741b71983988e55..07b168490f095184b1a6bce5c569b7e1a5710282 100644 (file)
@@ -366,7 +366,8 @@ int mdc_rename(struct obd_export *exp, struct md_op_data *op_data,
                                                 MDS_INODELOCK_FULL);
 
        req = ptlrpc_request_alloc(class_exp2cliimp(exp),
-                                  &RQF_MDS_REINT_RENAME);
+                                  op_data->op_cli_flags & CLI_MIGRATE ?
+                                  &RQF_MDS_REINT_MIGRATE : &RQF_MDS_REINT_RENAME);
        if (!req) {
                ldlm_lock_list_put(&cancels, l_bl_ast, count);
                return -ENOMEM;
@@ -382,6 +383,23 @@ int mdc_rename(struct obd_export *exp, struct md_op_data *op_data,
                return rc;
        }
 
+       if (op_data->op_cli_flags & CLI_MIGRATE && op_data->op_data) {
+               struct md_open_data *mod = op_data->op_data;
+
+               LASSERTF(mod->mod_open_req &&
+                        mod->mod_open_req->rq_type != LI_POISON,
+                        "POISONED open %p!\n", mod->mod_open_req);
+
+               DEBUG_REQ(D_HA, mod->mod_open_req, "matched open");
+               /*
+                * We no longer want to preserve this open for replay even
+                * though the open was committed. b=3632, b=3633
+                */
+               spin_lock(&mod->mod_open_req->rq_lock);
+               mod->mod_open_req->rq_replay = 0;
+               spin_unlock(&mod->mod_open_req->rq_lock);
+       }
+
        if (exp_connect_cancelset(exp) && req)
                ldlm_cli_cancel_list(&cancels, count, req, 0);
 
index cc95c094d1b3ebcc594f05507b75a03970bd11ef..99d7c667df284de7e244faacd76d26c34ea278f3 100644 (file)
@@ -257,6 +257,18 @@ static const struct req_msg_field *mds_reint_rename_client[] = {
        &RMF_DLM_REQ
 };
 
+static const struct req_msg_field *mds_reint_migrate_client[] = {
+       &RMF_PTLRPC_BODY,
+       &RMF_REC_REINT,
+       &RMF_CAPA1,
+       &RMF_CAPA2,
+       &RMF_NAME,
+       &RMF_SYMTGT,
+       &RMF_DLM_REQ,
+       &RMF_MDT_EPOCH,
+       &RMF_CLOSE_DATA
+};
+
 static const struct req_msg_field *mds_last_unlink_server[] = {
        &RMF_PTLRPC_BODY,
        &RMF_MDT_BODY,
@@ -678,6 +690,7 @@ static struct req_format *req_formats[] = {
        &RQF_MDS_REINT_UNLINK,
        &RQF_MDS_REINT_LINK,
        &RQF_MDS_REINT_RENAME,
+       &RQF_MDS_REINT_MIGRATE,
        &RQF_MDS_REINT_SETATTR,
        &RQF_MDS_REINT_SETXATTR,
        &RQF_MDS_QUOTACTL,
@@ -1254,6 +1267,11 @@ struct req_format RQF_MDS_REINT_RENAME =
                        mds_last_unlink_server);
 EXPORT_SYMBOL(RQF_MDS_REINT_RENAME);
 
+struct req_format RQF_MDS_REINT_MIGRATE =
+       DEFINE_REQ_FMT0("MDS_REINT_MIGRATE", mds_reint_migrate_client,
+                       mds_last_unlink_server);
+EXPORT_SYMBOL(RQF_MDS_REINT_MIGRATE);
+
 struct req_format RQF_MDS_REINT_SETATTR =
        DEFINE_REQ_FMT0("MDS_REINT_SETATTR",
                        mds_reint_setattr_client, mds_setattr_server);