Whamcloud - gitweb
LU-3200 mdc: layout lock rpc must not take rpc_lock
[fs/lustre-release.git] / lustre / mdc / mdc_locks.c
index d75508b..f2d666f 100644 (file)
@@ -1,6 +1,4 @@
-/* -*- mode: c; c-basic-offset: 8; indent-tabs-mode: nil; -*-
- * vim:expandtab:shiftwidth=8:tabstop=8:
- *
+/*
  * GPL HEADER START
  *
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
 /*
  * Copyright (c) 2003, 2010, Oracle and/or its affiliates. All rights reserved.
  * Use is subject to license terms.
+ *
+ * Copyright (c) 2011, 2013, Intel Corporation.
  */
 /*
  * This file is part of Lustre, http://www.lustre.org/
  * Lustre is a trademark of Sun Microsystems, Inc.
  */
 
-#ifndef EXPORT_SYMTAB
-# define EXPORT_SYMTAB
-#endif
 #define DEBUG_SUBSYSTEM S_MDC
 
 #ifdef __KERNEL__
@@ -120,7 +117,8 @@ EXPORT_SYMBOL(it_open_error);
 int mdc_set_lock_data(struct obd_export *exp, __u64 *lockh, void *data,
                       __u64 *bits)
 {
-        struct ldlm_lock *lock;
+       struct ldlm_lock *lock;
+       struct inode *new_inode = data;
         ENTRY;
 
         if(bits)
@@ -134,18 +132,18 @@ int mdc_set_lock_data(struct obd_export *exp, __u64 *lockh, void *data,
         LASSERT(lock != NULL);
         lock_res_and_lock(lock);
 #ifdef __KERNEL__
-        if (lock->l_ast_data && lock->l_ast_data != data) {
-                struct inode *new_inode = data;
-                struct inode *old_inode = lock->l_ast_data;
-                LASSERTF(old_inode->i_state & I_FREEING,
-                         "Found existing inode %p/%lu/%u state %lu in lock: "
-                         "setting data to %p/%lu/%u\n", old_inode,
-                         old_inode->i_ino, old_inode->i_generation,
-                         old_inode->i_state,
-                         new_inode, new_inode->i_ino, new_inode->i_generation);
-        }
+       if (lock->l_resource->lr_lvb_inode &&
+           lock->l_resource->lr_lvb_inode != data) {
+               struct inode *old_inode = lock->l_resource->lr_lvb_inode;
+               LASSERTF(old_inode->i_state & I_FREEING,
+                        "Found existing inode %p/%lu/%u state %lu in lock: "
+                        "setting data to %p/%lu/%u\n", old_inode,
+                        old_inode->i_ino, old_inode->i_generation,
+                        old_inode->i_state,
+                        new_inode, new_inode->i_ino, new_inode->i_generation);
+       }
 #endif
-        lock->l_ast_data = data;
+       lock->l_resource->lr_lvb_inode = new_inode;
         if (bits)
                 *bits = lock->l_policy_data.l_inodebits.bits;
 
@@ -155,7 +153,7 @@ int mdc_set_lock_data(struct obd_export *exp, __u64 *lockh, void *data,
         RETURN(0);
 }
 
-ldlm_mode_t mdc_lock_match(struct obd_export *exp, int flags,
+ldlm_mode_t mdc_lock_match(struct obd_export *exp, __u64 flags,
                            const struct lu_fid *fid, ldlm_type_t type,
                            ldlm_policy_data_t *policy, ldlm_mode_t mode,
                            struct lustre_handle *lockh)
@@ -189,19 +187,28 @@ int mdc_cancel_unused(struct obd_export *exp,
         RETURN(rc);
 }
 
-int mdc_change_cbdata(struct obd_export *exp,
-                      const struct lu_fid *fid,
-                      ldlm_iterator_t it, void *data)
+int mdc_null_inode(struct obd_export *exp,
+                  const struct lu_fid *fid)
 {
-        struct ldlm_res_id res_id;
-        ENTRY;
+       struct ldlm_res_id res_id;
+       struct ldlm_resource *res;
+       struct ldlm_namespace *ns = class_exp2obd(exp)->obd_namespace;
+       ENTRY;
 
-        fid_build_reg_res_name(fid, &res_id);
-        ldlm_resource_iterate(class_exp2obd(exp)->obd_namespace,
-                              &res_id, it, data);
+       LASSERTF(ns != NULL, "no namespace passed\n");
 
-        EXIT;
-        return 0;
+       fid_build_reg_res_name(fid, &res_id);
+
+       res = ldlm_resource_get(ns, NULL, &res_id, 0, 0);
+       if(res == NULL)
+               RETURN(0);
+
+       lock_res(res);
+       res->lr_lvb_inode = NULL;
+       unlock_res(res);
+
+       ldlm_resource_putref(res);
+       RETURN(0);
 }
 
 /* find any ldlm lock of the inode in mdc
@@ -228,11 +235,11 @@ int mdc_find_cbdata(struct obd_export *exp,
 
 static inline void mdc_clear_replay_flag(struct ptlrpc_request *req, int rc)
 {
-        /* Don't hold error requests for replay. */
-        if (req->rq_replay) {
-                cfs_spin_lock(&req->rq_lock);
-                req->rq_replay = 0;
-                cfs_spin_unlock(&req->rq_lock);
+       /* Don't hold error requests for replay. */
+       if (req->rq_replay) {
+               spin_lock(&req->rq_lock);
+               req->rq_replay = 0;
+               spin_unlock(&req->rq_lock);
         }
         if (rc && req->rq_transno != 0) {
                 DEBUG_REQ(D_ERROR, req, "transno returned on error rc %d", rc);
@@ -333,9 +340,9 @@ static struct ptlrpc_request *mdc_intent_open_pack(struct obd_export *exp,
                 return NULL;
         }
 
-        cfs_spin_lock(&req->rq_lock);
-        req->rq_replay = req->rq_import->imp_replayable;
-        cfs_spin_unlock(&req->rq_lock);
+       spin_lock(&req->rq_lock);
+       req->rq_replay = req->rq_import->imp_replayable;
+       spin_unlock(&req->rq_lock);
 
         /* pack the intent */
         lit = req_capsule_client_get(&req->rq_pill, &RMF_LDLM_INTENT);
@@ -440,7 +447,47 @@ static struct ptlrpc_request *mdc_intent_getattr_pack(struct obd_export *exp,
         RETURN(req);
 }
 
-static struct ptlrpc_request *ldlm_enqueue_pack(struct obd_export *exp)
+static struct ptlrpc_request *mdc_intent_layout_pack(struct obd_export *exp,
+                                                    struct lookup_intent *it,
+                                                    struct md_op_data *unused)
+{
+       struct obd_device     *obd = class_exp2obd(exp);
+       struct ptlrpc_request *req;
+       struct ldlm_intent    *lit;
+       struct layout_intent  *layout;
+       int rc;
+       ENTRY;
+
+       req = ptlrpc_request_alloc(class_exp2cliimp(exp),
+                               &RQF_LDLM_INTENT_LAYOUT);
+       if (req == NULL)
+               RETURN(ERR_PTR(-ENOMEM));
+
+       req_capsule_set_size(&req->rq_pill, &RMF_EADATA, RCL_CLIENT, 0);
+       rc = ldlm_prep_enqueue_req(exp, req, NULL, 0);
+       if (rc) {
+               ptlrpc_request_free(req);
+               RETURN(ERR_PTR(rc));
+       }
+
+       /* pack the intent */
+       lit = req_capsule_client_get(&req->rq_pill, &RMF_LDLM_INTENT);
+       lit->opc = (__u64)it->it_op;
+
+       /* pack the layout intent request */
+       layout = req_capsule_client_get(&req->rq_pill, &RMF_LAYOUT_INTENT);
+       /* LAYOUT_INTENT_ACCESS is generic, specific operation will be
+        * set for replication */
+       layout->li_opc = LAYOUT_INTENT_ACCESS;
+
+       req_capsule_set_size(&req->rq_pill, &RMF_DLM_LVB, RCL_SERVER,
+                       obd->u.cli.cl_max_mds_easize);
+       ptlrpc_request_set_replen(req);
+       RETURN(req);
+}
+
+static struct ptlrpc_request *
+mdc_enqueue_pack(struct obd_export *exp, int lvb_len)
 {
         struct ptlrpc_request *req;
         int rc;
@@ -456,6 +503,7 @@ static struct ptlrpc_request *ldlm_enqueue_pack(struct obd_export *exp)
                 RETURN(ERR_PTR(rc));
         }
 
+       req_capsule_set_size(&req->rq_pill, &RMF_DLM_LVB, RCL_SERVER, lvb_len);
         ptlrpc_request_set_replen(req);
         RETURN(req);
 }
@@ -467,9 +515,13 @@ static int mdc_finish_enqueue(struct obd_export *exp,
                               struct lustre_handle *lockh,
                               int rc)
 {
-        struct req_capsule  *pill = &req->rq_pill;
-        struct ldlm_request *lockreq;
-        struct ldlm_reply   *lockrep;
+       struct req_capsule  *pill = &req->rq_pill;
+       struct ldlm_request *lockreq;
+       struct ldlm_reply   *lockrep;
+       struct lustre_intent_data *intent = &it->d.lustre;
+       struct ldlm_lock    *lock;
+       void                *lvb_data = NULL;
+       int                  lvb_len = 0;
         ENTRY;
 
         LASSERT(rc >= 0);
@@ -477,7 +529,7 @@ static int mdc_finish_enqueue(struct obd_export *exp,
          * actually get a lock, just perform the intent. */
         if (req->rq_transno || req->rq_replay) {
                 lockreq = req_capsule_client_get(pill, &RMF_DLM_REQ);
-                lockreq->lock_flags |= LDLM_FL_INTENT_ONLY;
+               lockreq->lock_flags |= ldlm_flags_to_wire(LDLM_FL_INTENT_ONLY);
         }
 
         if (rc == ELDLM_LOCK_ABORTED) {
@@ -485,8 +537,8 @@ static int mdc_finish_enqueue(struct obd_export *exp,
                 memset(lockh, 0, sizeof(*lockh));
                 rc = 0;
         } else { /* rc = 0 */
-                struct ldlm_lock *lock = ldlm_handle2lock(lockh);
-                LASSERT(lock);
+               lock = ldlm_handle2lock(lockh);
+               LASSERT(lock != NULL);
 
                 /* If the server gave us back a different lock mode, we should
                  * fix up our variables. */
@@ -495,20 +547,22 @@ static int mdc_finish_enqueue(struct obd_export *exp,
                         ldlm_lock_decref(lockh, einfo->ei_mode);
                         einfo->ei_mode = lock->l_req_mode;
                 }
-                LDLM_LOCK_PUT(lock);
-        }
+               LDLM_LOCK_PUT(lock);
+       }
 
-        lockrep = req_capsule_server_get(pill, &RMF_DLM_REP);
-        LASSERT(lockrep != NULL);                 /* checked by ldlm_cli_enqueue() */
+       lockrep = req_capsule_server_get(pill, &RMF_DLM_REP);
+       LASSERT(lockrep != NULL); /* checked by ldlm_cli_enqueue() */
 
-        it->d.lustre.it_disposition = (int)lockrep->lock_policy_res1;
-        it->d.lustre.it_status = (int)lockrep->lock_policy_res2;
-        it->d.lustre.it_lock_mode = einfo->ei_mode;
-        it->d.lustre.it_lock_handle = lockh->cookie;
-        it->d.lustre.it_data = req;
+       intent->it_disposition = (int)lockrep->lock_policy_res1;
+       intent->it_status = (int)lockrep->lock_policy_res2;
+       intent->it_lock_mode = einfo->ei_mode;
+       intent->it_lock_handle = lockh->cookie;
+       intent->it_data = req;
 
-        if (it->d.lustre.it_status < 0 && req->rq_replay)
-                mdc_clear_replay_flag(req, it->d.lustre.it_status);
+       /* Technically speaking rq_transno must already be zero if
+        * it_status is in error, so the check is a bit redundant */
+       if ((!req->rq_transno || intent->it_status < 0) && req->rq_replay)
+               mdc_clear_replay_flag(req, intent->it_status);
 
         /* If we're doing an IT_OPEN which did not result in an actual
          * successful open, then we need to remove the bit which saves
@@ -518,11 +572,11 @@ static int mdc_finish_enqueue(struct obd_export *exp,
          * function without doing so, and try to replay a failed create
          * (bug 3440) */
         if (it->it_op & IT_OPEN && req->rq_replay &&
-            (!it_disposition(it, DISP_OPEN_OPEN) ||it->d.lustre.it_status != 0))
-                mdc_clear_replay_flag(req, it->d.lustre.it_status);
+           (!it_disposition(it, DISP_OPEN_OPEN) ||intent->it_status != 0))
+               mdc_clear_replay_flag(req, intent->it_status);
 
-        DEBUG_REQ(D_RPCTRACE, req, "op: %d disposition: %x, status: %d",
-                  it->it_op,it->d.lustre.it_disposition,it->d.lustre.it_status);
+       DEBUG_REQ(D_RPCTRACE, req, "op: %d disposition: %x, status: %d",
+                 it->it_op, intent->it_disposition, intent->it_status);
 
         /* We know what to expect, so we do any byte flipping required here */
         if (it->it_op & (IT_OPEN | IT_UNLINK | IT_LOOKUP | IT_GETATTR)) {
@@ -543,12 +597,12 @@ static int mdc_finish_enqueue(struct obd_export *exp,
                          * is swabbed by that handler correctly.
                          */
                         mdc_set_open_replay_data(NULL, NULL, req);
-                }
+               }
 
                 if ((body->valid & (OBD_MD_FLDIREA | OBD_MD_FLEASIZE)) != 0) {
                         void *eadata;
 
-                         mdc_update_max_ea_from_body(exp, body);
+                       mdc_update_max_ea_from_body(exp, body);
 
                         /*
                          * The eadata is opaque; just check that it is there.
@@ -559,6 +613,11 @@ static int mdc_finish_enqueue(struct obd_export *exp,
                         if (eadata == NULL)
                                 RETURN(-EPROTO);
 
+                       /* save lvb data and length in case this is for layout
+                        * lock */
+                       lvb_data = eadata;
+                       lvb_len = body->eadatasize;
+
                         /*
                          * We save the reply LOV EA in case we have to replay a
                          * create for recovery.  If we didn't allocate a large
@@ -619,9 +678,48 @@ static int mdc_finish_enqueue(struct obd_export *exp,
                         if (capa == NULL)
                                 RETURN(-EPROTO);
                 }
-        }
-
-        RETURN(rc);
+        } else if (it->it_op & IT_LAYOUT) {
+               /* maybe the lock was granted right away and layout
+                * is packed into RMF_DLM_LVB of req */
+               lvb_len = req_capsule_get_size(pill, &RMF_DLM_LVB, RCL_SERVER);
+               if (lvb_len > 0) {
+                       lvb_data = req_capsule_server_sized_get(pill,
+                                                       &RMF_DLM_LVB, lvb_len);
+                       if (lvb_data == NULL)
+                               RETURN(-EPROTO);
+               }
+       }
+
+       /* fill in stripe data for layout lock */
+       lock = ldlm_handle2lock(lockh);
+       if (lock != NULL && ldlm_has_layout(lock) && lvb_data != NULL) {
+               void *lmm;
+
+               LDLM_DEBUG(lock, "layout lock returned by: %s, lvb_len: %d\n",
+                       ldlm_it2str(it->it_op), lvb_len);
+
+               OBD_ALLOC_LARGE(lmm, lvb_len);
+               if (lmm == NULL) {
+                       LDLM_LOCK_PUT(lock);
+                       RETURN(-ENOMEM);
+               }
+               memcpy(lmm, lvb_data, lvb_len);
+
+               /* install lvb_data */
+               lock_res_and_lock(lock);
+               if (lock->l_lvb_data == NULL) {
+                       lock->l_lvb_data = lmm;
+                       lock->l_lvb_len = lvb_len;
+                       lmm = NULL;
+               }
+               unlock_res_and_lock(lock);
+               if (lmm != NULL)
+                       OBD_FREE_LARGE(lmm, lvb_len);
+       }
+       if (lock != NULL)
+               LDLM_LOCK_PUT(lock);
+
+       RETURN(rc);
 }
 
 /* We always reserve enough space in the reply packet for a stripe MD, because
@@ -629,19 +727,23 @@ static int mdc_finish_enqueue(struct obd_export *exp,
 int mdc_enqueue(struct obd_export *exp, struct ldlm_enqueue_info *einfo,
                 struct lookup_intent *it, struct md_op_data *op_data,
                 struct lustre_handle *lockh, void *lmm, int lmmsize,
-                struct ptlrpc_request **reqp, int extra_lock_flags)
+               struct ptlrpc_request **reqp, __u64 extra_lock_flags)
 {
         struct obd_device     *obddev = class_exp2obd(exp);
         struct ptlrpc_request *req = NULL;
-        struct req_capsule    *pill;
-        int                    flags = extra_lock_flags;
+       __u64                  flags, saved_flags = extra_lock_flags;
         int                    rc;
         struct ldlm_res_id res_id;
         static const ldlm_policy_data_t lookup_policy =
                             { .l_inodebits = { MDS_INODELOCK_LOOKUP } };
         static const ldlm_policy_data_t update_policy =
                             { .l_inodebits = { MDS_INODELOCK_UPDATE } };
+       static const ldlm_policy_data_t layout_policy =
+                           { .l_inodebits = { MDS_INODELOCK_LAYOUT } };
         ldlm_policy_data_t const *policy = &lookup_policy;
+        int                    generation, resends = 0;
+        struct ldlm_reply     *lockrep;
+       enum lvb_type          lvb_type = 0;
         ENTRY;
 
         LASSERTF(!it || einfo->ei_type == LDLM_IBITS, "lock type %d\n",
@@ -649,14 +751,19 @@ int mdc_enqueue(struct obd_export *exp, struct ldlm_enqueue_info *einfo,
 
         fid_build_reg_res_name(&op_data->op_fid1, &res_id);
 
-        if (it)
-                flags |= LDLM_FL_HAS_INTENT;
-        if (it && it->it_op & (IT_UNLINK | IT_GETATTR | IT_READDIR))
-                policy = &update_policy;
+       if (it) {
+               saved_flags |= LDLM_FL_HAS_INTENT;
+               if (it->it_op & (IT_UNLINK | IT_GETATTR | IT_READDIR))
+                       policy = &update_policy;
+               else if (it->it_op & IT_LAYOUT)
+                       policy = &layout_policy;
+       }
 
-        if (reqp)
-                req = *reqp;
+        LASSERT(reqp == NULL);
 
+        generation = obddev->u.cli.cl_import->imp_generation;
+resend:
+        flags = saved_flags;
         if (!it) {
                 /* The only way right now is FLOCK, in this case we hide flock
                    policy as lmm, but lmmsize is 0 */
@@ -671,20 +778,36 @@ int mdc_enqueue(struct obd_export *exp, struct ldlm_enqueue_info *einfo,
                 policy = &update_policy;
                 einfo->ei_cbdata = NULL;
                 lmm = NULL;
-        } else if (it->it_op & IT_UNLINK)
-                req = mdc_intent_unlink_pack(exp, it, op_data);
-        else if (it->it_op & (IT_GETATTR | IT_LOOKUP))
-                req = mdc_intent_getattr_pack(exp, it, op_data);
-        else if (it->it_op == IT_READDIR)
-                req = ldlm_enqueue_pack(exp);
-        else {
+       } else if (it->it_op & IT_UNLINK) {
+               req = mdc_intent_unlink_pack(exp, it, op_data);
+       } else if (it->it_op & (IT_GETATTR | IT_LOOKUP)) {
+               req = mdc_intent_getattr_pack(exp, it, op_data);
+       } else if (it->it_op & IT_READDIR) {
+               req = mdc_enqueue_pack(exp, 0);
+       } else if (it->it_op & IT_LAYOUT) {
+               if (!imp_connect_lvb_type(class_exp2cliimp(exp)))
+                       RETURN(-EOPNOTSUPP);
+
+               req = mdc_intent_layout_pack(exp, it, op_data);
+               lvb_type = LVB_T_LAYOUT;
+       } else {
                 LBUG();
                 RETURN(-EINVAL);
         }
 
         if (IS_ERR(req))
                 RETURN(PTR_ERR(req));
-        pill = &req->rq_pill;
+
+       if (req != NULL && it && it->it_op & IT_CREAT)
+               /* ask ptlrpc not to resend on EINPROGRESS since we have our own
+                * retry logic */
+               req->rq_no_retry_einprogress = 1;
+
+        if (resends) {
+                req->rq_generation_set = 1;
+                req->rq_import_generation = generation;
+                req->rq_sent = cfs_time_current_sec() + resends;
+        }
 
         /* It is important to obtain rpc_lock first (if applicable), so that
          * threads that are serialised with rpc_lock are not polluting our
@@ -694,20 +817,14 @@ int mdc_enqueue(struct obd_export *exp, struct ldlm_enqueue_info *einfo,
                 rc = mdc_enter_request(&obddev->u.cli);
                 if (rc != 0) {
                         mdc_put_rpc_lock(obddev->u.cli.cl_rpc_lock, it);
+                        mdc_clear_replay_flag(req, 0);
                         ptlrpc_req_finished(req);
                         RETURN(rc);
                 }
         }
 
         rc = ldlm_cli_enqueue(exp, &req, einfo, &res_id, policy, &flags, NULL,
-                              0, lockh, 0);
-        if (reqp)
-                *reqp = req;
-
-        if (it) {
-                mdc_exit_request(&obddev->u.cli);
-                mdc_put_rpc_lock(obddev->u.cli.cl_rpc_lock, it);
-        }
+                             0, lvb_type, lockh, 0);
         if (!it) {
                 /* For flock requests we immediatelly return without further
                    delay and let caller deal with the rest, since rest of
@@ -716,15 +833,51 @@ int mdc_enqueue(struct obd_export *exp, struct ldlm_enqueue_info *einfo,
                 RETURN(rc);
         }
 
+        mdc_exit_request(&obddev->u.cli);
+        mdc_put_rpc_lock(obddev->u.cli.cl_rpc_lock, it);
+
         if (rc < 0) {
                 CERROR("ldlm_cli_enqueue: %d\n", rc);
                 mdc_clear_replay_flag(req, rc);
                 ptlrpc_req_finished(req);
                 RETURN(rc);
         }
-        rc = mdc_finish_enqueue(exp, req, einfo, it, lockh, rc);
 
-        RETURN(rc);
+        lockrep = req_capsule_server_get(&req->rq_pill, &RMF_DLM_REP);
+        LASSERT(lockrep != NULL);
+
+       lockrep->lock_policy_res2 =
+               ptlrpc_status_ntoh(lockrep->lock_policy_res2);
+
+        /* Retry the create infinitely when we get -EINPROGRESS from
+         * server. This is required by the new quota design. */
+        if (it && it->it_op & IT_CREAT &&
+            (int)lockrep->lock_policy_res2 == -EINPROGRESS) {
+                mdc_clear_replay_flag(req, rc);
+                ptlrpc_req_finished(req);
+                resends++;
+
+                CDEBUG(D_HA, "%s: resend:%d op:%d "DFID"/"DFID"\n",
+                       obddev->obd_name, resends, it->it_op,
+                       PFID(&op_data->op_fid1), PFID(&op_data->op_fid2));
+
+                if (generation == obddev->u.cli.cl_import->imp_generation) {
+                        goto resend;
+                } else {
+                       CDEBUG(D_HA, "resend cross eviction\n");
+                        RETURN(-EIO);
+                }
+        }
+
+       rc = mdc_finish_enqueue(exp, req, einfo, it, lockh, rc);
+       if (rc < 0) {
+               if (lustre_handle_is_used(lockh)) {
+                       ldlm_lock_decref(lockh, einfo->ei_mode);
+                       memset(lockh, 0, sizeof(*lockh));
+               }
+               ptlrpc_req_finished(req);
+       }
+       RETURN(rc);
 }
 
 static int mdc_finish_intent_lock(struct obd_export *exp,
@@ -737,7 +890,7 @@ static int mdc_finish_intent_lock(struct obd_export *exp,
         struct mdt_body *mdt_body;
         struct ldlm_lock *lock;
         int rc;
-
+       ENTRY;
 
         LASSERT(request != NULL);
         LASSERT(request != LP_POISON);
@@ -804,7 +957,7 @@ static int mdc_finish_intent_lock(struct obd_export *exp,
         } else if (it->it_op == IT_OPEN) {
                 LASSERT(!it_disposition(it, DISP_OPEN_CREATE));
         } else {
-                LASSERT(it->it_op & (IT_GETATTR | IT_LOOKUP));
+                LASSERT(it->it_op & (IT_GETATTR | IT_LOOKUP | IT_LAYOUT));
         }
 
         /* If we already have a matching lock, then cancel the new
@@ -860,8 +1013,17 @@ int mdc_revalidate_lock(struct obd_export *exp, struct lookup_intent *it,
                 mode = ldlm_revalidate_lock_handle(&lockh, bits);
         } else {
                 fid_build_reg_res_name(fid, &res_id);
-                policy.l_inodebits.bits = (it->it_op == IT_GETATTR) ?
-                                  MDS_INODELOCK_UPDATE : MDS_INODELOCK_LOOKUP;
+                switch (it->it_op) {
+                case IT_GETATTR:
+                        policy.l_inodebits.bits = MDS_INODELOCK_UPDATE;
+                        break;
+                case IT_LAYOUT:
+                        policy.l_inodebits.bits = MDS_INODELOCK_LAYOUT;
+                        break;
+                default:
+                        policy.l_inodebits.bits = MDS_INODELOCK_LOOKUP;
+                        break;
+                }
                 mode = ldlm_lock_match(exp->exp_obd->obd_namespace,
                                        LDLM_FL_BLOCK_GRANTED, &res_id,
                                        LDLM_IBITS, &policy,
@@ -910,7 +1072,7 @@ int mdc_intent_lock(struct obd_export *exp, struct md_op_data *op_data,
                     void *lmm, int lmmsize, struct lookup_intent *it,
                     int lookup_flags, struct ptlrpc_request **reqp,
                     ldlm_blocking_callback cb_blocking,
-                    int extra_lock_flags)
+                   __u64 extra_lock_flags)
 {
         struct lustre_handle lockh;
         int rc = 0;
@@ -986,7 +1148,8 @@ static int mdc_intent_getattr_async_interpret(const struct lu_env *env,
         struct lookup_intent     *it;
         struct lustre_handle     *lockh;
         struct obd_device        *obddev;
-        int                       flags = LDLM_FL_HAS_INTENT;
+       struct ldlm_reply        *lockrep;
+       __u64                     flags = LDLM_FL_HAS_INTENT;
         ENTRY;
 
         it    = &minfo->mi_it;
@@ -1006,6 +1169,12 @@ static int mdc_intent_getattr_async_interpret(const struct lu_env *env,
                 GOTO(out, rc);
         }
 
+       lockrep = req_capsule_server_get(&req->rq_pill, &RMF_DLM_REP);
+       LASSERT(lockrep != NULL);
+
+       lockrep->lock_policy_res2 =
+               ptlrpc_status_ntoh(lockrep->lock_policy_res2);
+
         rc = mdc_finish_enqueue(exp, req, einfo, it, lockh, rc);
         if (rc)
                 GOTO(out, rc);
@@ -1037,7 +1206,7 @@ int mdc_intent_getattr_async(struct obd_export *exp,
                                                          MDS_INODELOCK_UPDATE }
                                  };
         int                      rc = 0;
-        int                      flags = LDLM_FL_HAS_INTENT;
+       __u64                    flags = LDLM_FL_HAS_INTENT;
         ENTRY;
 
         CDEBUG(D_DLMTRACE,"name: %.*s in inode "DFID", intent: %s flags %#o\n",
@@ -1056,7 +1225,7 @@ int mdc_intent_getattr_async(struct obd_export *exp,
         }
 
         rc = ldlm_cli_enqueue(exp, &req, einfo, &res_id, &policy, &flags, NULL,
-                              0, &minfo->mi_lockh, 1);
+                             0, LVB_T_NONE, &minfo->mi_lockh, 1);
         if (rc < 0) {
                 mdc_exit_request(&obddev->u.cli);
                 ptlrpc_req_finished(req);