From c3ced3e86c18ab5e457c090f2d2320802f7eb002 Mon Sep 17 00:00:00 2001
From: phil <phil>
Date: Fri, 19 Mar 2004 06:33:27 +0000
Subject: [PATCH] land b_cray_delivery on HEAD liblustre fixes and group lock
 support

---
 lustre/include/liblustre.h                    |   4 +
 lustre/include/linux/lustre_dlm.h             |   5 +-
 lustre/include/linux/lustre_idl.h             |   5 +-
 lustre/include/linux/lustre_user.h            |   3 +
 lustre/include/linux/obd_support.h            |   5 +
 .../kernel_patches/patches/bproc-patch-2.4.20 |   6 +-
 lustre/ldlm/ldlm_extent.c                     | 111 ++++++++++++++----
 lustre/ldlm/ldlm_flock.c                      |   6 +-
 lustre/ldlm/ldlm_internal.h                   |   4 +
 lustre/ldlm/ldlm_lock.c                       |   7 +-
 lustre/ldlm/ldlm_lockd.c                      |   9 +-
 lustre/ldlm/ldlm_request.c                    |  11 +-
 lustre/ldlm/ldlm_resource.c                   |  23 ++++
 lustre/liblustre/file.c                       |   9 ++
 lustre/liblustre/llite_lib.h                  |   3 +
 lustre/liblustre/rw.c                         |  73 ++++++------
 lustre/liblustre/super.c                      |  70 ++++++++++-
 lustre/llite/file.c                           |  91 +++++++++++++-
 lustre/llite/llite_internal.h                 |   4 +-
 lustre/llite/rw.c                             |  15 ++-
 lustre/lov/lov_obd.c                          |   2 +
 lustre/osc/osc_request.c                      |   5 +-
 lustre/ptlrpc/pack_generic.c                  |  34 +++---
 lustre/utils/wirecheck.c                      |   1 +
 lustre/utils/wiretest.c                       |  40 ++++---
 25 files changed, 427 insertions(+), 119 deletions(-)

diff --git a/lustre/include/liblustre.h b/lustre/include/liblustre.h
index 2133888400..460d86e641 100644
--- a/lustre/include/liblustre.h
+++ b/lustre/include/liblustre.h
@@ -578,6 +578,10 @@ extern struct task_struct *current;
 #define del_wait_queue(p) do { list_del(&(p)->sleeping); } while (0)
 #define remove_wait_queue(q,p) do { list_del(&(p)->sleeping); } while (0)
 
+#define DECLARE_WAIT_QUEUE_HEAD(HEAD)                           \
+        wait_queue_head_t HEAD = {                              \
+                .sleepers = LIST_HEAD_INIT(HEAD.sleepers)       \
+        }
 #define init_waitqueue_head(l) INIT_LIST_HEAD(&(l)->sleepers)
 #define wake_up(l) do { int a; a++; } while (0)
 #define TASK_INTERRUPTIBLE 0
diff --git a/lustre/include/linux/lustre_dlm.h b/lustre/include/linux/lustre_dlm.h
index 6736418dda..fe47d7f93a 100644
--- a/lustre/include/linux/lustre_dlm.h
+++ b/lustre/include/linux/lustre_dlm.h
@@ -68,6 +68,9 @@ typedef enum {
 #define LDLM_FL_WARN           0x008000 /* see ldlm_cli_cancel_unused */
 #define LDLM_FL_DISCARD_DATA   0x010000 /* discard (no writeback) on cancel */
 
+#define LDLM_FL_NO_TIMEOUT     0x020000 /* Blocked by group lock - wait
+                                         * indefinitely */
+
 /* file & record locking */
 #define LDLM_FL_BLOCK_NOWAIT   0x040000 // server told not to wait if blocked
 #define LDLM_FL_TEST_LOCK      0x080000 // return blocking lock
@@ -331,7 +334,7 @@ do {                                                                          \
         if (lock->l_resource->lr_type == LDLM_FLOCK) {                        \
                 CDEBUG(level, "### " format                                   \
                        " ns: %s lock: %p/"LPX64" lrc: %d/%d,%d mode: %s/%s "  \
-                       "res: "LPU64"/"LPU64" rrc: %d type: %s pid: %d "       \
+                       "res: "LPU64"/"LPU64" rrc: %d type: %s pid: "LPU64" "  \
                        "["LPU64"->"LPU64"] flags: %x remote: "LPX64           \
                        " expref: %d\n" , ## a,                                \
                        lock->l_resource->lr_namespace->ns_name, lock,         \
diff --git a/lustre/include/linux/lustre_idl.h b/lustre/include/linux/lustre_idl.h
index 72804d174d..669c079f45 100644
--- a/lustre/include/linux/lustre_idl.h
+++ b/lustre/include/linux/lustre_idl.h
@@ -729,14 +729,15 @@ typedef enum {
 struct ldlm_extent {
         __u64 start;
         __u64 end;
+        __u64 gid;
 };
 
 struct ldlm_flock {
         __u64 start;
         __u64 end;
+        __u64 pid;
+        __u64 blocking_pid;
         __u64 blocking_export;
-        pid_t blocking_pid;
-        pid_t pid;
 };
 
 /* it's important that the fields of the ldlm_extent structure match
diff --git a/lustre/include/linux/lustre_user.h b/lustre/include/linux/lustre_user.h
index 9866acf5c0..2c3e315ae4 100644
--- a/lustre/include/linux/lustre_user.h
+++ b/lustre/include/linux/lustre_user.h
@@ -35,10 +35,13 @@
 #define LL_IOC_LOV_GETSTRIPE            _IOW ('f', 155, long)
 #define LL_IOC_LOV_SETEA                _IOW ('f', 156, long)
 #define LL_IOC_RECREATE_OBJ             _IOW ('f', 157, long)
+#define LL_IOC_CW_LOCK                  _IOW ('f', 158, long)
+#define LL_IOC_CW_UNLOCK                _IOW ('f', 159, long)
 
 #define O_LOV_DELAY_CREATE 0100000000  /* hopefully this does not conflict */
 
 #define LL_FILE_IGNORE_LOCK             0x00000001
+#define LL_FILE_CW_LOCKED               0x00000002
 
 #define LOV_USER_MAGIC_V1 0x0BD10BD0
 #define LOV_USER_MAGIC    LOV_USER_MAGIC_V1
diff --git a/lustre/include/linux/obd_support.h b/lustre/include/linux/obd_support.h
index 2e2137336e..a186aa3582 100644
--- a/lustre/include/linux/obd_support.h
+++ b/lustre/include/linux/obd_support.h
@@ -178,6 +178,7 @@ do {                                                                         \
        }                                                                     \
 } while(0)
 
+#ifdef __KERNEL__
 /* The idea here is to synchronise two threads to force a race. The
  * first thread that calls this with a matching fail_loc is put to
  * sleep. The next thread that calls with the same fail_loc wakes up
@@ -193,6 +194,10 @@ do {                                                            \
                 wake_up(&obd_race_waitq);                       \
         }                                                       \
 } while(0)
+#else
+/* sigh.  an expedient fix until OBD_RACE is fixed up */
+#define OBD_RACE(foo) LBUG()
+#endif
 
 #define fixme() CDEBUG(D_OTHER, "FIXME\n");
 
diff --git a/lustre/kernel_patches/patches/bproc-patch-2.4.20 b/lustre/kernel_patches/patches/bproc-patch-2.4.20
index a13ecc97a8..3587bd88c8 100644
--- a/lustre/kernel_patches/patches/bproc-patch-2.4.20
+++ b/lustre/kernel_patches/patches/bproc-patch-2.4.20
@@ -1,4 +1,4 @@
-$Id: bproc-patch-2.4.20,v 1.6 2004/03/19 01:09:33 zab Exp $
+$Id: bproc-patch-2.4.20,v 1.7 2004/03/19 06:33:08 phil Exp $
 
 Index: linux/fs/exec.c
 ===================================================================
@@ -764,7 +764,7 @@ Index: linux/kernel/bproc_hook.c
 + *  along with this program; if not, write to the Free Software
 + *  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
 + *
-+ * $Id: bproc-patch-2.4.20,v 1.6 2004/03/19 01:09:33 zab Exp $
++ * $Id: bproc-patch-2.4.20,v 1.7 2004/03/19 06:33:08 phil Exp $
 + *-----------------------------------------------------------------------*/
 +#include <linux/kernel.h>
 +#include <linux/sched.h>
@@ -832,7 +832,7 @@ Index: linux/include/linux/bproc.h
 + *  along with this program; if not, write to the Free Software
 + *  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
 + *
-+ * $Id: bproc-patch-2.4.20,v 1.6 2004/03/19 01:09:33 zab Exp $
++ * $Id: bproc-patch-2.4.20,v 1.7 2004/03/19 06:33:08 phil Exp $
 + *-----------------------------------------------------------------------*/
 +#ifndef _LINUX_BPROC_H
 +#define _LINUX_BPROC_H
diff --git a/lustre/ldlm/ldlm_extent.c b/lustre/ldlm/ldlm_extent.c
index c2c1e256c9..dd04c1c0f3 100644
--- a/lustre/ldlm/ldlm_extent.c
+++ b/lustre/ldlm/ldlm_extent.c
@@ -130,10 +130,16 @@ static void ldlm_extent_policy(struct ldlm_resource *res,
 
 /* Determine if the lock is compatible with all locks on the queue.
  * We stop walking the queue if we hit ourselves so we don't take
- * conflicting locks enqueued after us into accound, or we'd wait forever. */
+ * conflicting locks enqueued after us into accound, or we'd wait forever.
+ *
+ * 0 if the lock is not compatible
+ * 1 if the lock is compatible
+ * 2 if this group lock is compatible and requires no further checking
+ * negative error, such as EWOULDBLOCK for group locks
+ */
 static int
 ldlm_extent_compat_queue(struct list_head *queue, struct ldlm_lock *req,
-                         int send_cbs)
+                         int send_cbs, int *flags, ldlm_error_t *err)
 {
         struct list_head *tmp;
         struct ldlm_lock *lock;
@@ -152,13 +158,54 @@ ldlm_extent_compat_queue(struct list_head *queue, struct ldlm_lock *req,
                         RETURN(compat);
 
                 /* locks are compatible, overlap doesn't matter */
-                if (lockmode_compat(lock->l_req_mode, req_mode))
-                        continue;
+                if (lockmode_compat(lock->l_req_mode, req_mode)) {
+                        /* nonCW locks are compatible, overlap doesn't matter */
+                        if (req_mode != LCK_CW)
+                                continue;
+                                
+                        /* If we are trying to get a CW lock and there is
+                           another one of this kind, we need to compare gid */
+                        if (req->l_policy_data.l_extent.gid ==
+                             lock->l_policy_data.l_extent.gid) {
+                                if (lock->l_req_mode == lock->l_granted_mode)
+                                        RETURN(2);
+
+                                /* If we are in nonblocking mode - return
+                                   immediately */
+                                if (*flags & LDLM_FL_BLOCK_NOWAIT) {
+                                        compat = -EWOULDBLOCK;
+                                        goto destroylock;
+                                }
+                                /* If this group lock is compatible with another
+                                 * group lock on the waiting list, they must be
+                                 * together in the list, so they can be granted
+                                 * at the same time.  Otherwise the later lock
+                                 * can get stuck behind another, incompatible,
+                                 * lock. */
+                                ldlm_resource_insert_lock_after(lock, req);
+                                /* Because 'lock' is not granted, we can stop
+                                 * processing this queue and return immediately.
+                                 * There is no need to check the rest of the
+                                 * list. */
+                                RETURN(0);
+                        }
+                }
 
-                /* if lock doesn't overlap skip it */
-                if (lock->l_policy_data.l_extent.end < req_start ||
-                    lock->l_policy_data.l_extent.start > req_end)
+                if (lock->l_req_mode == LCK_CW) {
+                        /* If compared lock is CW, then requested is PR/PW/ =>
+                         * this is not compatible; extent range does not
+                         * matter */
+                        if (*flags & LDLM_FL_BLOCK_NOWAIT) {
+                                compat = -EWOULDBLOCK;
+                                goto destroylock;
+                        } else {
+                                *flags |= LDLM_FL_NO_TIMEOUT;
+                        }
+                } else if (lock->l_policy_data.l_extent.end < req_start ||
+                           lock->l_policy_data.l_extent.start > req_end) {
+                        /* if a non-CW lock doesn't overlap skip it */
                         continue;
+                }
 
                 if (!send_cbs)
                         RETURN(0);
@@ -168,6 +215,11 @@ ldlm_extent_compat_queue(struct list_head *queue, struct ldlm_lock *req,
                         ldlm_add_ast_work_item(lock, req, NULL, 0);
         }
 
+        return(compat);
+destroylock:
+        list_del_init(&req->l_res_link);
+        ldlm_lock_destroy(req);
+        *err = compat;
         RETURN(compat);
 }
 
@@ -185,18 +237,27 @@ int ldlm_process_extent_lock(struct ldlm_lock *lock, int *flags, int first_enq,
 {
         struct ldlm_resource *res = lock->l_resource;
         struct list_head rpc_list = LIST_HEAD_INIT(rpc_list);
-        int rc;
+        int rc, rc2;
         ENTRY;
 
         LASSERT(list_empty(&res->lr_converting));
+        *err = ELDLM_OK;
 
         if (!first_enq) {
+                /* Careful observers will note that we don't handle -EWOULDBLOCK
+                 * here, but it's ok for a non-obvious reason -- compat_queue
+                 * can only return -EWOULDBLOCK if (flags & BLOCK_NOWAIT).
+                 * flags should always be zero here, and if that ever stops
+                 * being true, we want to find out. */
+                LASSERT(*flags == 0);
                 LASSERT(res->lr_tmp != NULL);
-                rc = ldlm_extent_compat_queue(&res->lr_granted, lock, 0);
-                if (!rc)
-                        RETURN(LDLM_ITER_STOP);
-                rc = ldlm_extent_compat_queue(&res->lr_waiting, lock, 0);
-                if (!rc)
+                rc = ldlm_extent_compat_queue(&res->lr_granted, lock, 0, flags,
+                                              err);
+                if (rc == 1) {
+                        rc = ldlm_extent_compat_queue(&res->lr_waiting, lock, 0,
+                                                      flags, err);
+                }
+                if (rc == 0)
                         RETURN(LDLM_ITER_STOP);
 
                 ldlm_resource_unlink_lock(lock);
@@ -209,12 +270,24 @@ int ldlm_process_extent_lock(struct ldlm_lock *lock, int *flags, int first_enq,
  restart:
         LASSERT(res->lr_tmp == NULL);
         res->lr_tmp = &rpc_list;
-        rc = ldlm_extent_compat_queue(&res->lr_granted, lock, 1);
-        rc += ldlm_extent_compat_queue(&res->lr_waiting, lock, 1);
+        rc = ldlm_extent_compat_queue(&res->lr_granted, lock, 1, flags, err);
+        if (rc < 0)
+                RETURN(rc); /* lock was destroyed */
+        if (rc == 2)
+                goto grant;
+
+        rc2 = ldlm_extent_compat_queue(&res->lr_waiting, lock, 1, flags, err);
+        if (rc2 < 0)
+                RETURN(rc2); /* lock was destroyed */
         res->lr_tmp = NULL;
 
-        if (rc != 2) {
-                /* If either of the compat_queue()s returned 0, then we
+        if (rc + rc2 == 2) {
+        grant:
+                ldlm_extent_policy(res, lock, flags);
+                ldlm_resource_unlink_lock(lock);
+                ldlm_grant_lock(lock, NULL, 0, 0);
+        } else {
+                /* If either of the compat_queue()s returned failure, then we
                  * have ASTs to send and must go onto the waiting list.
                  *
                  * bug 2322: we used to unlink and re-add here, which was a
@@ -228,10 +301,6 @@ int ldlm_process_extent_lock(struct ldlm_lock *lock, int *flags, int first_enq,
                 if (rc == -ERESTART)
                         GOTO(restart, -ERESTART);
                 *flags |= LDLM_FL_BLOCK_GRANTED;
-        } else {
-                ldlm_extent_policy(res, lock, flags);
-                ldlm_resource_unlink_lock(lock);
-                ldlm_grant_lock(lock, NULL, 0, 0);
         }
         RETURN(0);
 }
diff --git a/lustre/ldlm/ldlm_flock.c b/lustre/ldlm/ldlm_flock.c
index 148be59ddc..ea17da6d72 100644
--- a/lustre/ldlm/ldlm_flock.c
+++ b/lustre/ldlm/ldlm_flock.c
@@ -129,8 +129,8 @@ ldlm_process_flock_lock(struct ldlm_lock *req, int *flags, int first_enq,
         int overlaps = 0;
         ENTRY;
 
-        CDEBUG(D_DLMTRACE, "flags %#x pid %u mode %u start "LPU64" end "LPU64
-               "\n", *flags, new->l_policy_data.l_flock.pid, mode,
+        CDEBUG(D_DLMTRACE, "flags %#x pid "LPU64" mode %u start "LPU64" end "
+               LPU64"\n", *flags, new->l_policy_data.l_flock.pid, mode,
                req->l_policy_data.l_flock.start,
                req->l_policy_data.l_flock.end);
 
@@ -512,7 +512,7 @@ granted:
                 getlk->fl_end = lock->l_policy_data.l_flock.end;
         } else {
                 /* We need to reprocess the lock to do merges or splits
-                 * with existing locks owne by this process. */
+                 * with existing locks owned by this process. */
                 flags = LDLM_FL_WAIT_NOREPROC;
                 ldlm_process_flock_lock(lock, &flags, 1, &err);
         }
diff --git a/lustre/ldlm/ldlm_internal.h b/lustre/ldlm/ldlm_internal.h
index 4111cbe05a..735f77607f 100644
--- a/lustre/ldlm/ldlm_internal.h
+++ b/lustre/ldlm/ldlm_internal.h
@@ -1,6 +1,10 @@
 /* ldlm_request.c */
 int ldlm_cancel_lru(struct ldlm_namespace *ns);
 
+/* ldlm_resource.c */
+void ldlm_resource_insert_lock_after(struct ldlm_lock *original,
+                                     struct ldlm_lock *new);
+
 /* ldlm_lock.c */
 void ldlm_grant_lock(struct ldlm_lock *lock, void *data, int datalen,
 		     int run_ast);
diff --git a/lustre/ldlm/ldlm_lock.c b/lustre/ldlm/ldlm_lock.c
index 73f10eb1d8..e720e4cd17 100644
--- a/lustre/ldlm/ldlm_lock.c
+++ b/lustre/ldlm/ldlm_lock.c
@@ -590,6 +590,11 @@ static struct ldlm_lock *search_queue(struct list_head *queue, ldlm_mode_t mode,
                      lock->l_policy_data.l_extent.end < policy->l_extent.end))
                         continue;
 
+                if (lock->l_resource->lr_type == LDLM_EXTENT &&
+                    mode == LCK_CW &&
+                    lock->l_policy_data.l_extent.gid != policy->l_extent.gid)
+                        continue;
+
                 if (lock->l_destroyed)
                         continue;
 
@@ -1180,7 +1185,7 @@ void ldlm_lock_dump(int level, struct ldlm_lock *lock, int pos)
                        lock->l_policy_data.l_extent.end,
                        lock->l_req_extent.start, lock->l_req_extent.end);
         else if (lock->l_resource->lr_type == LDLM_FLOCK)
-                CDEBUG(level, "  Pid: %d Extent: "LPU64" -> "LPU64"\n",
+                CDEBUG(level, "  Pid: "LPU64" Extent: "LPU64" -> "LPU64"\n",
                        lock->l_policy_data.l_flock.pid,
                        lock->l_policy_data.l_flock.start,
                        lock->l_policy_data.l_flock.end);
diff --git a/lustre/ldlm/ldlm_lockd.c b/lustre/ldlm/ldlm_lockd.c
index 76a719f23f..a46dd73a3e 100644
--- a/lustre/ldlm/ldlm_lockd.c
+++ b/lustre/ldlm/ldlm_lockd.c
@@ -184,7 +184,8 @@ static void waiting_locks_callback(unsigned long unused)
                 lock = list_entry(waiting_locks_list.next, struct ldlm_lock,
                                   l_pending_chain);
 
-                if (lock->l_callback_timeout > jiffies)
+                if ((lock->l_callback_timeout > jiffies) ||
+                    (lock->l_req_mode == LCK_CW))
                         break;
 
                 LDLM_ERROR(lock, "lock callback timer expired: evicting client "
@@ -496,7 +497,8 @@ int ldlm_server_completion_ast(struct ldlm_lock *lock, int flags, void *data)
         l_unlock(&lock->l_resource->lr_namespace->ns_lock);
 
         rc = ptlrpc_queue_wait(req);
-        if (rc == -ETIMEDOUT || rc == -EINTR || rc == -ENOTCONN) {
+        if ((rc == -ETIMEDOUT || rc == -EINTR || rc == -ENOTCONN) &&
+             !lock->l_export->exp_libclient) {
                 ldlm_del_waiting_lock(lock);
                 ldlm_failed_ast(lock, rc, "completion");
         } else if (rc == -EINVAL) {
@@ -542,7 +544,8 @@ int ldlm_server_glimpse_ast(struct ldlm_lock *lock, void *data)
         req->rq_timeout = 2; /* 2 second timeout for initial AST reply */
 
         rc = ptlrpc_queue_wait(req);
-        if (rc == -ETIMEDOUT || rc == -EINTR || rc == -ENOTCONN) {
+        if ((rc == -ETIMEDOUT || rc == -EINTR || rc == -ENOTCONN) &&
+            !lock->l_export->exp_libclient) {
                 ldlm_del_waiting_lock(lock);
                 ldlm_failed_ast(lock, rc, "glimpse");
         } else if (rc == -EINVAL) {
diff --git a/lustre/ldlm/ldlm_request.c b/lustre/ldlm/ldlm_request.c
index 7d5000ed89..37868ca320 100644
--- a/lustre/ldlm/ldlm_request.c
+++ b/lustre/ldlm/ldlm_request.c
@@ -106,8 +106,15 @@ noreproc:
 
         lwd.lwd_lock = lock;
 
-        lwi = LWI_TIMEOUT_INTR(obd_timeout * HZ, ldlm_expired_completion_wait,
-                               interrupted_completion_wait, &lwd);
+        if (flags & LDLM_FL_NO_TIMEOUT) {
+                LDLM_DEBUG(lock, "waiting indefinitely for group lock\n");
+                lwi = LWI_INTR(interrupted_completion_wait, &lwd);
+        } else {
+                lwi = LWI_TIMEOUT_INTR(obd_timeout * HZ,
+                                       ldlm_expired_completion_wait,
+                                       interrupted_completion_wait, &lwd);
+        }
+
         if (imp != NULL) {
                 spin_lock_irqsave(&imp->imp_lock, irqflags);
                 lwd.lwd_generation = imp->imp_generation;
diff --git a/lustre/ldlm/ldlm_resource.c b/lustre/ldlm/ldlm_resource.c
index c04a14c318..52770e9094 100644
--- a/lustre/ldlm/ldlm_resource.c
+++ b/lustre/ldlm/ldlm_resource.c
@@ -625,6 +625,29 @@ void ldlm_resource_add_lock(struct ldlm_resource *res, struct list_head *head,
         l_unlock(&res->lr_namespace->ns_lock);
 }
 
+void ldlm_resource_insert_lock_after(struct ldlm_lock *original,
+                                     struct ldlm_lock *new)
+{
+        struct ldlm_resource *res = original->l_resource;
+
+        l_lock(&res->lr_namespace->ns_lock);
+
+        ldlm_resource_dump(res);
+        CDEBUG(D_OTHER, "About to insert this lock after %p:\n", original);
+        ldlm_lock_dump(D_OTHER, new, 0);
+
+        if (new->l_destroyed) {
+                CDEBUG(D_OTHER, "Lock destroyed, not adding to resource\n");
+                goto out;
+        }
+
+        LASSERT(list_empty(&new->l_res_link));
+
+        list_add(&new->l_res_link, &original->l_res_link);
+ out:
+        l_unlock(&res->lr_namespace->ns_lock);
+}
+
 void ldlm_resource_unlink_lock(struct ldlm_lock *lock)
 {
         l_lock(&lock->l_resource->lr_namespace->ns_lock);
diff --git a/lustre/liblustre/file.c b/lustre/liblustre/file.c
index 9a5162d0bb..f666cdcd4f 100644
--- a/lustre/liblustre/file.c
+++ b/lustre/liblustre/file.c
@@ -166,6 +166,8 @@ int llu_iop_open(struct pnode *pnode, int flags, mode_t mode)
         }
         fd->fd_flags &= ~O_LOV_DELAY_CREATE;
 
+        lli->lli_open_flags = flags;
+
  out_release:
         request = it->d.lustre.it_data;
         ptlrpc_req_finished(request);
@@ -256,6 +258,13 @@ int llu_mdc_close(struct obd_export *mdc_exp, struct inode *inode)
         int rc, valid;
         ENTRY;
 
+        /* clear group lock, if present */
+        if (fd->fd_flags & LL_FILE_CW_LOCKED) {
+                struct lov_stripe_md *lsm = llu_i2info(inode)->lli_smd;
+                fd->fd_flags &= ~(LL_FILE_CW_LOCKED|LL_FILE_IGNORE_LOCK);
+                rc = llu_extent_unlock(fd, inode, lsm, LCK_CW, &fd->fd_cwlockh);
+        }
+
         valid = OBD_MD_FLID;
         if (test_bit(LLI_F_HAVE_OST_SIZE_LOCK, &lli->lli_flags))
                 valid |= OBD_MD_FLSIZE | OBD_MD_FLBLOCKS;
diff --git a/lustre/liblustre/llite_lib.h b/lustre/liblustre/llite_lib.h
index 123bb5c2c8..27432c470f 100644
--- a/lustre/liblustre/llite_lib.h
+++ b/lustre/liblustre/llite_lib.h
@@ -38,6 +38,8 @@
 struct ll_file_data {
         struct obd_client_handle fd_mds_och;
         __u32 fd_flags;
+        struct lustre_handle fd_cwlockh;
+        unsigned long fd_gid;
 };
 
 struct llu_sb_info
@@ -86,6 +88,7 @@ struct llu_inode_info {
          * was opened several times without close, we track an
          * open_count here */
         struct ll_file_data    *lli_file_data;
+        int                     lli_open_flags;
         int                     lli_open_count;
 
         /* stat FIXME not 64 bit clean */
diff --git a/lustre/liblustre/rw.c b/lustre/liblustre/rw.c
index 6fe7431ccf..546ab73ff8 100644
--- a/lustre/liblustre/rw.c
+++ b/lustre/liblustre/rw.c
@@ -29,6 +29,7 @@
 #include <time.h>
 #include <sys/types.h>
 #include <sys/queue.h>
+#include <fcntl.h>
 
 #include <sysio.h>
 #include <fs.h>
@@ -89,12 +90,17 @@ static int llu_extent_lock_callback(struct ldlm_lock *lock,
                         CERROR("ldlm_cli_cancel failed: %d\n", rc);
                 break;
         case LDLM_CB_CANCELING: {
-                struct inode *inode = llu_inode_from_lock(lock);
+                struct inode *inode;
                 struct llu_inode_info *lli;
                 struct lov_stripe_md *lsm;
                 __u32 stripe;
                 __u64 kms;
                 
+                /* This lock wasn't granted, don't try to evict pages */
+                if (lock->l_req_mode != lock->l_granted_mode)
+                        RETURN(0);
+
+                inode = llu_inode_from_lock(lock);
                 if (!inode)
                         RETURN(0);
                 lli= llu_i2info(inode);
@@ -126,59 +132,44 @@ static int llu_glimpse_callback(struct ldlm_lock *lock, void *reqp)
 {
         struct ptlrpc_request *req = reqp;
         struct inode *inode = llu_inode_from_lock(lock);
-        struct obd_export *exp;
         struct llu_inode_info *lli;
         struct ost_lvb *lvb;
-        struct {
-                int stripe_number;
-                __u64 size;
-                struct lov_stripe_md *lsm;
-        } data;
-        __u32 vallen = sizeof(data);
-        int rc, size = sizeof(*lvb);
+        int rc, size = sizeof(*lvb), stripe = 0;
         ENTRY;
 
         if (inode == NULL)
-                RETURN(0);
+                GOTO(out, rc = -ELDLM_NO_LOCK_DATA);
         lli = llu_i2info(inode);
         if (lli == NULL)
-                goto iput;
+                GOTO(iput, rc = -ELDLM_NO_LOCK_DATA);
         if (lli->lli_smd == NULL)
-                goto iput;
-        exp = llu_i2obdexp(inode);
+                GOTO(iput, rc = -ELDLM_NO_LOCK_DATA);
 
         /* First, find out which stripe index this lock corresponds to. */
         if (lli->lli_smd->lsm_stripe_count > 1)
-                data.stripe_number = llu_lock_to_stripe_offset(inode, lock);
-        else
-                data.stripe_number = 0;
-
-        data.size = lli->lli_st_size;
-        data.lsm = lli->lli_smd;
-
-        rc = obd_get_info(exp, strlen("size_to_stripe"), "size_to_stripe",
-                          &vallen, &data);
-        if (rc != 0) {
-                CERROR("obd_get_info: rc = %d\n", rc);
-                LBUG();
-        }
-
-        LDLM_DEBUG(lock, "i_size: %Lu -> stripe number %d -> size %Lu",
-                   lli->lli_st_size, data.stripe_number, data.size);
+                stripe = llu_lock_to_stripe_offset(inode, lock);
 
         rc = lustre_pack_reply(req, 1, &size, NULL);
         if (rc) {
                 CERROR("lustre_pack_reply: %d\n", rc);
-                goto iput;
+                GOTO(iput, rc);
         }
 
         lvb = lustre_msg_buf(req->rq_repmsg, 0, sizeof(*lvb));
-        lvb->lvb_size = data.size;
-        ptlrpc_reply(req);
+        lvb->lvb_size = lli->lli_smd->lsm_oinfo[stripe].loi_kms;
 
+        LDLM_DEBUG(lock, "i_size: %llu -> stripe number %u -> kms "LPU64,
+                   lli->lli_st_size, stripe, lvb->lvb_size);
  iput:
         I_RELE(inode);
-        RETURN(0);
+ out:
+        /* These errors are normal races, so we don't want to fill the console
+         * with messages by calling ptlrpc_error() */
+        if (rc == -ELDLM_NO_LOCK_DATA)
+                lustre_pack_reply(req, 0, NULL, NULL);
+
+        req->rq_status = rc;
+        return rc;
 }
 
 __u64 lov_merge_size(struct lov_stripe_md *lsm, int kms);
@@ -287,16 +278,19 @@ int llu_extent_lock_no_validate(struct ll_file_data *fd,
  */
 int llu_extent_lock(struct ll_file_data *fd, struct inode *inode,
                     struct lov_stripe_md *lsm, int mode,
-                    struct ldlm_extent *extent, struct lustre_handle *lockh)
+                    struct ldlm_extent *extent, struct lustre_handle *lockh,
+                    int nonblock)
 {
         struct llu_inode_info *lli = llu_i2info(inode);
         struct obd_export *exp = llu_i2obdexp(inode);
         struct ldlm_extent size_lock;
         struct lustre_handle match_lockh = {0};
         int flags, rc, matched;
+        int astflags = nonblock ? LDLM_FL_BLOCK_NOWAIT : 0;
         ENTRY;
 
-        rc = llu_extent_lock_no_validate(fd, inode, lsm, mode, extent, lockh, 0);
+        rc = llu_extent_lock_no_validate(fd, inode, lsm, mode, extent,
+                                         lockh, astflags);
         if (rc != ELDLM_OK)
                 RETURN(rc);
 
@@ -708,6 +702,8 @@ llu_file_write(struct inode *inode, const struct iovec *iovec,
         ldlm_policy_data_t policy;
         struct llu_sysio_callback_args *lsca;
         struct llu_sysio_cookie *cookie;
+        int astflag = (lli->lli_open_flags & O_NONBLOCK) ?
+                       LDLM_FL_BLOCK_NOWAIT : 0;
         ldlm_error_t err;
         int iovidx;
         ENTRY;
@@ -742,7 +738,7 @@ llu_file_write(struct inode *inode, const struct iovec *iovec,
                 policy.l_extent.end = pos + count - 1;
 
                 err = llu_extent_lock(fd, inode, lsm, LCK_PW, &policy,
-                                      &lockh, 0);
+                                      &lockh, astflag);
                 if (err != ELDLM_OK)
                         GOTO(err_out, err = -ENOLCK);
 
@@ -816,6 +812,8 @@ llu_file_read(struct inode *inode, const struct iovec *iovec,
         ldlm_policy_data_t policy;
         struct llu_sysio_callback_args *lsca;
         struct llu_sysio_cookie *cookie;
+        int astflag = (lli->lli_open_flags & O_NONBLOCK) ?
+                       LDLM_FL_BLOCK_NOWAIT : 0;
         __u64 kms;
         int iovidx;
 
@@ -838,7 +836,8 @@ llu_file_read(struct inode *inode, const struct iovec *iovec,
                 policy.l_extent.start = pos;
                 policy.l_extent.end = pos + count - 1;
 
-                err = llu_extent_lock(fd, inode, lsm, LCK_PR, &policy, &lockh, 0);
+                err = llu_extent_lock(fd, inode, lsm, LCK_PR, &policy,
+                                      &lockh, astflag);
                 if (err != ELDLM_OK)
                         GOTO(err_out, err = -ENOLCK);
 
diff --git a/lustre/liblustre/super.c b/lustre/liblustre/super.c
index a03dc4a14a..25ffc0fc6e 100644
--- a/lustre/liblustre/super.c
+++ b/lustre/liblustre/super.c
@@ -1187,10 +1187,78 @@ static int llu_iop_fcntl(struct inode *ino, int cmd, va_list ap)
         return -ENOSYS;
 }
 
+static int llu_get_cwlock(struct inode *inode, unsigned long arg)
+{
+        struct llu_inode_info *lli = llu_i2info(inode);
+        struct ll_file_data *fd = lli->lli_file_data;
+        ldlm_policy_data_t policy = { .l_extent = { .start = 0,
+                                                    .end = OBD_OBJECT_EOF}};
+        struct lustre_handle lockh = { 0 };
+        struct lov_stripe_md *lsm = lli->lli_smd;
+        ldlm_error_t err;
+        int flags = 0;
+        ENTRY;
+
+        if (fd->fd_flags & LL_FILE_CW_LOCKED) {
+                RETURN(-EINVAL);
+        }
+
+        policy.l_extent.gid = arg;
+        if (lli->lli_open_flags & O_NONBLOCK)
+                flags = LDLM_FL_BLOCK_NOWAIT;
+
+        err = llu_extent_lock(fd, inode, lsm, LCK_CW, &policy, &lockh, flags);
+        if (err)
+                RETURN(err);
+
+        fd->fd_flags |= LL_FILE_CW_LOCKED|LL_FILE_IGNORE_LOCK;
+        fd->fd_gid = arg;
+        memcpy(&fd->fd_cwlockh, &lockh, sizeof(lockh));
+
+        RETURN(0);
+}
+
+static int llu_put_cwlock(struct inode *inode, unsigned long arg)
+{
+        struct llu_inode_info *lli = llu_i2info(inode);
+        struct ll_file_data *fd = lli->lli_file_data;
+        struct lov_stripe_md *lsm = lli->lli_smd;
+        ldlm_error_t err;
+        ENTRY;
+
+        if (!(fd->fd_flags & LL_FILE_CW_LOCKED))
+                RETURN(-EINVAL);
+
+        if (fd->fd_gid != arg)
+                RETURN(-EINVAL);
+
+        fd->fd_flags &= ~(LL_FILE_CW_LOCKED|LL_FILE_IGNORE_LOCK);
+
+        err = llu_extent_unlock(fd, inode, lsm, LCK_CW, &fd->fd_cwlockh);
+        if (err)
+                RETURN(err);
+
+        fd->fd_gid = 0;
+        memset(&fd->fd_cwlockh, 0, sizeof(fd->fd_cwlockh));
+
+        RETURN(0);
+}       
+
 static int llu_iop_ioctl(struct inode *ino, unsigned long int request,
                          va_list ap)
 {
-        CERROR("liblustre did not support ioctl\n");
+        unsigned long arg;
+
+        switch (request) {
+        case LL_IOC_CW_LOCK:
+                arg = va_arg(ap, unsigned long);
+                return llu_get_cwlock(ino, arg);
+        case LL_IOC_CW_UNLOCK:
+                arg = va_arg(ap, unsigned long);
+                return llu_put_cwlock(ino, arg);
+        }
+
+        CERROR("did not support ioctl cmd %lx\n", request);
         return -ENOSYS;
 }
 
diff --git a/lustre/llite/file.c b/lustre/llite/file.c
index 60c8304eee..7fbd8a585d 100644
--- a/lustre/llite/file.c
+++ b/lustre/llite/file.c
@@ -43,6 +43,13 @@ static int ll_mdc_close(struct obd_export *mdc_exp, struct inode *inode,
         int rc, valid;
         ENTRY;
 
+        /* clear group lock, if present */
+        if (fd->fd_flags & LL_FILE_CW_LOCKED) {
+                struct lov_stripe_md *lsm = ll_i2info(inode)->lli_smd;
+                fd->fd_flags &= ~(LL_FILE_CW_LOCKED|LL_FILE_IGNORE_LOCK);
+                rc = ll_extent_unlock(fd, inode, lsm, LCK_CW, &fd->fd_cwlockh);
+        }
+
         valid = OBD_MD_FLID;
 
         memset(&obdo, 0, sizeof(obdo));
@@ -721,7 +728,9 @@ static ssize_t ll_file_read(struct file *filp, char *buf, size_t count,
         policy.l_extent.start = *ppos;
         policy.l_extent.end = *ppos + count - 1;
 
-        err = ll_extent_lock(fd, inode, lsm, LCK_PR, &policy, &lockh, 0);
+        err = ll_extent_lock(fd, inode, lsm, LCK_PR, &policy, &lockh,
+                             (filp->f_flags & O_NONBLOCK)?LDLM_FL_BLOCK_NOWAIT:
+                                                          0);
         if (err != ELDLM_OK)
                 RETURN(err);
 
@@ -768,7 +777,10 @@ static ssize_t ll_file_write(struct file *file, const char *buf, size_t count,
         loff_t maxbytes = ll_file_maxbytes(inode);
         ldlm_error_t err;
         ssize_t retval;
+        int nonblock = 0;
         ENTRY;
+        if (file->f_flags & O_NONBLOCK)
+                nonblock = LDLM_FL_BLOCK_NOWAIT;
         CDEBUG(D_VFSTRACE, "VFS Op:inode=%lu/%u(%p),size="LPSZ",offset=%Ld\n",
                inode->i_ino, inode->i_generation, inode, count, *ppos);
 
@@ -793,7 +805,7 @@ static ssize_t ll_file_write(struct file *file, const char *buf, size_t count,
                 policy.l_extent.end = *ppos + count - 1;
         }
 
-        err = ll_extent_lock(fd, inode, lsm, LCK_PW, &policy, &lockh, 0);
+        err = ll_extent_lock(fd, inode, lsm, LCK_PW, &policy, &lockh, nonblock);
         if (err != ELDLM_OK)
                 RETURN(err);
 
@@ -1006,6 +1018,67 @@ static int ll_lov_getstripe(struct inode *inode, unsigned long arg)
                             (void *)arg);
 }
 
+static int ll_get_cwlock(struct inode *inode, struct file *file,
+                         unsigned long arg)
+{
+        struct ll_file_data *fd = file->private_data;
+        ldlm_policy_data_t policy = { .l_extent = { .start = 0,
+                                                    .end = OBD_OBJECT_EOF}};
+        struct lustre_handle lockh = { 0 };
+        struct ll_inode_info *lli = ll_i2info(inode);
+        struct lov_stripe_md *lsm = lli->lli_smd;
+        ldlm_error_t err;
+        int flags = 0;
+        ENTRY;
+
+        if (fd->fd_flags & LL_FILE_CW_LOCKED) {
+                RETURN(-EINVAL);
+        }
+
+        policy.l_extent.gid = arg;
+        if (file->f_flags & O_NONBLOCK)
+                flags = LDLM_FL_BLOCK_NOWAIT;
+
+        err = ll_extent_lock(fd, inode, lsm, LCK_CW, &policy, &lockh, flags);
+        if (err)
+                RETURN(err);
+
+        fd->fd_flags |= LL_FILE_CW_LOCKED|LL_FILE_IGNORE_LOCK;
+        fd->fd_gid = arg;
+        memcpy(&fd->fd_cwlockh, &lockh, sizeof(lockh));
+
+        RETURN(0);
+}
+
+static int ll_put_cwlock(struct inode *inode, struct file *file,
+                         unsigned long arg)
+{
+        struct ll_file_data *fd = file->private_data;
+        struct ll_inode_info *lli = ll_i2info(inode);
+        struct lov_stripe_md *lsm = lli->lli_smd;
+        ldlm_error_t err;
+        ENTRY;
+
+        if (!(fd->fd_flags & LL_FILE_CW_LOCKED)) {
+                /* Ugh, it's already unlocked. */
+                RETURN(-EINVAL);
+        }
+
+        if (fd->fd_gid != arg) /* Ugh? Unlocking with different gid? */
+                RETURN(-EINVAL);
+        
+        fd->fd_flags &= ~(LL_FILE_CW_LOCKED|LL_FILE_IGNORE_LOCK);
+
+        err = ll_extent_unlock(fd, inode, lsm, LCK_CW, &fd->fd_cwlockh);
+        if (err)
+                RETURN(err);
+
+        fd->fd_gid = 0;
+        memset(&fd->fd_cwlockh, 0, sizeof(fd->fd_cwlockh));
+
+        RETURN(0);
+}       
+
 int ll_file_ioctl(struct inode *inode, struct file *file, unsigned int cmd,
                   unsigned long arg)
 {
@@ -1049,6 +1122,10 @@ int ll_file_ioctl(struct inode *inode, struct file *file, unsigned int cmd,
         case EXT3_IOC_GETFLAGS:
         case EXT3_IOC_SETFLAGS:
                 RETURN( ll_iocontrol(inode, file, cmd, arg) );
+        case LL_IOC_CW_LOCK:
+                RETURN(ll_get_cwlock(inode, file, arg));
+        case LL_IOC_CW_UNLOCK:
+                RETURN(ll_put_cwlock(inode, file, arg));
         /* We need to special case any other ioctls we want to handle,
          * to send them to the MDS/OST as appropriate and to properly
          * network encode the arg field.
@@ -1078,8 +1155,14 @@ loff_t ll_file_seek(struct file *file, loff_t offset, int origin)
         lprocfs_counter_incr(ll_i2sbi(inode)->ll_stats, LPROC_LL_LLSEEK);
         if (origin == 2) { /* SEEK_END */
                 ldlm_error_t err;
+                int nonblock = 0;
                 ldlm_policy_data_t policy = { .l_extent = {0, OBD_OBJECT_EOF }};
-                err = ll_extent_lock(fd, inode, lsm, LCK_PR, &policy, &lockh,0);
+
+                if (file->f_flags & O_NONBLOCK)
+                        nonblock = LDLM_FL_BLOCK_NOWAIT;
+
+                err = ll_extent_lock(fd, inode, lsm, LCK_PR, &policy, &lockh,
+                                     nonblock);
                 if (err != ELDLM_OK)
                         RETURN(err);
 
@@ -1212,7 +1295,7 @@ int ll_file_flock(struct file *file, int cmd, struct file_lock *file_lock)
                 LBUG();
         }
 
-        CDEBUG(D_DLMTRACE, "inode=%lu, pid=%u, flags=%#x, mode=%u, "
+        CDEBUG(D_DLMTRACE, "inode=%lu, pid="LPU64", flags=%#x, mode=%u, "
                "start="LPU64", end="LPU64"\n", inode->i_ino, flock.l_flock.pid,
                flags, mode, flock.l_flock.start, flock.l_flock.end);
 
diff --git a/lustre/llite/llite_internal.h b/lustre/llite/llite_internal.h
index 80cac348b8..4f1277cfd7 100644
--- a/lustre/llite/llite_internal.h
+++ b/lustre/llite/llite_internal.h
@@ -49,13 +49,15 @@ struct ll_readahead_state {
 };
 
 extern kmem_cache_t *ll_file_data_slab;
+struct lustre_handle;
 struct ll_file_data {
         struct obd_client_handle fd_mds_och;
         struct ll_readahead_state fd_ras;
         __u32 fd_flags;
+        struct lustre_handle fd_cwlockh;
+        unsigned long fd_gid;
 };
 
-struct lustre_handle;
 struct lov_stripe_md;
 
 extern spinlock_t inode_lock;
diff --git a/lustre/llite/rw.c b/lustre/llite/rw.c
index 61c2b4b661..a1ed4d15c1 100644
--- a/lustre/llite/rw.c
+++ b/lustre/llite/rw.c
@@ -519,7 +519,7 @@ void ll_removepage(struct page *page)
         EXIT;
 }
 
-static int ll_page_matches(struct page *page)
+static int ll_page_matches(struct page *page, int fd_flags)
 {
         struct lustre_handle match_lockh = {0};
         struct inode *inode = page->mapping->host;
@@ -527,6 +527,9 @@ static int ll_page_matches(struct page *page)
         int flags, matches;
         ENTRY;
 
+        if (fd_flags & LL_FILE_CW_LOCKED)
+                RETURN(1);
+
         page_extent.l_extent.start = (__u64)page->index << PAGE_CACHE_SHIFT;
         page_extent.l_extent.end =
                 page_extent.l_extent.start + PAGE_CACHE_SIZE - 1;
@@ -563,7 +566,7 @@ static int ll_issue_page_read(struct obd_export *exp,
 
 static void ll_readahead(struct ll_readahead_state *ras,
                          struct obd_export *exp, struct address_space *mapping,
-                         struct obd_io_group *oig)
+                         struct obd_io_group *oig, int flags)
 {
         unsigned long i, start, end;
         struct ll_async_page *llap;
@@ -612,7 +615,7 @@ static void ll_readahead(struct ll_readahead_state *ras,
                 if (Page_Uptodate(page))
                         goto next_page;
 
-                if ((rc = ll_page_matches(page)) <= 0) {
+                if ((rc = ll_page_matches(page, flags)) <= 0) {
                         LL_CDEBUG_PAGE(D_READA | D_PAGE, page,
                                        "lock match failed: rc %d\n", rc);
                         goto next_page;
@@ -764,7 +767,7 @@ int ll_readpage(struct file *filp, struct page *page)
 
         if (llap->llap_defer_uptodate) {
                 ll_readahead_update(inode, &fd->fd_ras, page->index, 1);
-                ll_readahead(&fd->fd_ras, exp, page->mapping, oig);
+                ll_readahead(&fd->fd_ras, exp, page->mapping, oig,fd->fd_flags);
                 obd_trigger_group_io(exp, ll_i2info(inode)->lli_smd, NULL,
                                      oig);
                 LL_CDEBUG_PAGE(D_PAGE, page, "marking uptodate from defer\n");
@@ -775,7 +778,7 @@ int ll_readpage(struct file *filp, struct page *page)
 
         ll_readahead_update(inode, &fd->fd_ras, page->index, 0);
 
-        rc = ll_page_matches(page);
+        rc = ll_page_matches(page, fd->fd_flags);
         if (rc < 0) {
                 LL_CDEBUG_PAGE(D_ERROR, page, "lock match failed: rc %d\n", rc);
                 GOTO(out, rc);
@@ -806,7 +809,7 @@ int ll_readpage(struct file *filp, struct page *page)
 
         LL_CDEBUG_PAGE(D_PAGE, page, "queued readpage\n");
         if ((ll_i2sbi(inode)->ll_flags & LL_SBI_READAHEAD))
-                ll_readahead(&fd->fd_ras, exp, page->mapping, oig);
+                ll_readahead(&fd->fd_ras, exp, page->mapping, oig,fd->fd_flags);
 
         rc = obd_trigger_group_io(exp, ll_i2info(inode)->lli_smd, NULL, oig);
 
diff --git a/lustre/lov/lov_obd.c b/lustre/lov/lov_obd.c
index b0be68f248..a1400f752e 100644
--- a/lustre/lov/lov_obd.c
+++ b/lustre/lov/lov_obd.c
@@ -2048,6 +2048,8 @@ static int lov_enqueue(struct obd_export *exp, struct lov_stripe_md *lsm,
                                            &sub_ext.l_extent.end))
                         continue;
 
+                sub_ext.l_extent.gid = policy->l_extent.gid;
+
                 if (lov->tgts[loi->loi_ost_idx].active == 0) {
                         CDEBUG(D_HA, "lov idx %d inactive\n", loi->loi_ost_idx);
                         continue;
diff --git a/lustre/osc/osc_request.c b/lustre/osc/osc_request.c
index 005ebbd740..9e36be628d 100644
--- a/lustre/osc/osc_request.c
+++ b/lustre/osc/osc_request.c
@@ -2514,7 +2514,10 @@ static int osc_cancel(struct obd_export *exp, struct lov_stripe_md *md,
 {
         ENTRY;
 
-        ldlm_lock_decref(lockh, mode);
+        if (mode == LCK_CW)
+                ldlm_lock_decref_and_cancel(lockh, mode);
+        else
+                ldlm_lock_decref(lockh, mode);
 
         RETURN(0);
 }
diff --git a/lustre/ptlrpc/pack_generic.c b/lustre/ptlrpc/pack_generic.c
index f424e53c93..7e5ccefcdf 100644
--- a/lustre/ptlrpc/pack_generic.c
+++ b/lustre/ptlrpc/pack_generic.c
@@ -552,12 +552,12 @@ void lustre_swab_ldlm_res_id (struct ldlm_res_id *id)
 
 void lustre_swab_ldlm_policy_data (ldlm_policy_data_t *d)
 {
-        /* the lock data is a union and the first two fields are always an
-         * extent so it's ok to process an LDLM_EXTENT and LDLM_FLOCK lock
-         * data the same way. */
+        /* the lock data is a union and the first three fields of both EXTENT
+         * and FLOCK types are __u64, so it's ok to swab them in the same way */
         __swab64s (&d->l_flock.start);
         __swab64s (&d->l_flock.end);
-        __swab32s (&d->l_flock.pid);
+        __swab64s (&d->l_flock.pid);
+        __swab64s (&d->l_flock.blocking_pid);
 }
 
 void lustre_swab_ldlm_intent (struct ldlm_intent *i)
@@ -1619,7 +1619,7 @@ void lustre_assert_wire_constants(void)
                  (long long)(int)sizeof(((struct ldlm_res_id *)0)->name[4]));
 
         /* Checks for struct ldlm_extent */
-        LASSERTF((int)sizeof(struct ldlm_extent) == 16, " found %lld\n",
+        LASSERTF((int)sizeof(struct ldlm_extent) == 24, " found %lld\n",
                  (long long)(int)sizeof(struct ldlm_extent));
         LASSERTF(offsetof(struct ldlm_extent, start) == 0, " found %lld\n",
                  (long long)offsetof(struct ldlm_extent, start));
@@ -1629,9 +1629,13 @@ void lustre_assert_wire_constants(void)
                  (long long)offsetof(struct ldlm_extent, end));
         LASSERTF((int)sizeof(((struct ldlm_extent *)0)->end) == 8, " found %lld\n",
                  (long long)(int)sizeof(((struct ldlm_extent *)0)->end));
+        LASSERTF(offsetof(struct ldlm_extent, gid) == 16, " found %lld\n",
+                 (long long)offsetof(struct ldlm_extent, gid));
+        LASSERTF((int)sizeof(((struct ldlm_extent *)0)->gid) == 8, " found %lld\n",
+                 (long long)(int)sizeof(((struct ldlm_extent *)0)->gid));
 
         /* Checks for struct ldlm_flock */
-        LASSERTF((int)sizeof(struct ldlm_flock) == 32, " found %lld\n",
+        LASSERTF((int)sizeof(struct ldlm_flock) == 40, " found %lld\n",
                  (long long)(int)sizeof(struct ldlm_flock));
         LASSERTF(offsetof(struct ldlm_flock, start) == 0, " found %lld\n",
                  (long long)offsetof(struct ldlm_flock, start));
@@ -1641,18 +1645,18 @@ void lustre_assert_wire_constants(void)
                  (long long)offsetof(struct ldlm_flock, end));
         LASSERTF((int)sizeof(((struct ldlm_flock *)0)->end) == 8, " found %lld\n",
                  (long long)(int)sizeof(((struct ldlm_flock *)0)->end));
-        LASSERTF(offsetof(struct ldlm_flock, blocking_export) == 16, " found %lld\n",
-                 (long long)offsetof(struct ldlm_flock, blocking_export));
-        LASSERTF((int)sizeof(((struct ldlm_flock *)0)->blocking_export) == 8, " found %lld\n",
-                 (long long)(int)sizeof(((struct ldlm_flock *)0)->blocking_export));
+        LASSERTF(offsetof(struct ldlm_flock, pid) == 16, " found %lld\n",
+                 (long long)offsetof(struct ldlm_flock, pid));
+        LASSERTF((int)sizeof(((struct ldlm_flock *)0)->pid) == 8, " found %lld\n",
+                 (long long)(int)sizeof(((struct ldlm_flock *)0)->pid));
         LASSERTF(offsetof(struct ldlm_flock, blocking_pid) == 24, " found %lld\n",
                  (long long)offsetof(struct ldlm_flock, blocking_pid));
-        LASSERTF((int)sizeof(((struct ldlm_flock *)0)->blocking_pid) == 4, " found %lld\n",
+        LASSERTF((int)sizeof(((struct ldlm_flock *)0)->blocking_pid) == 8, " found %lld\n",
                  (long long)(int)sizeof(((struct ldlm_flock *)0)->blocking_pid));
-        LASSERTF(offsetof(struct ldlm_flock, pid) == 28, " found %lld\n",
-                 (long long)offsetof(struct ldlm_flock, pid));
-        LASSERTF((int)sizeof(((struct ldlm_flock *)0)->pid) == 4, " found %lld\n",
-                 (long long)(int)sizeof(((struct ldlm_flock *)0)->pid));
+        LASSERTF(offsetof(struct ldlm_flock, blocking_export) == 32, " found %lld\n",
+                 (long long)offsetof(struct ldlm_flock, blocking_export));
+        LASSERTF((int)sizeof(((struct ldlm_flock *)0)->blocking_export) == 8, " found %lld\n",
+                 (long long)(int)sizeof(((struct ldlm_flock *)0)->blocking_export));
 
         /* Checks for struct ldlm_intent */
         LASSERTF((int)sizeof(struct ldlm_intent) == 8, " found %lld\n",
diff --git a/lustre/utils/wirecheck.c b/lustre/utils/wirecheck.c
index 8fb5d2e985..f1f05f51b1 100644
--- a/lustre/utils/wirecheck.c
+++ b/lustre/utils/wirecheck.c
@@ -406,6 +406,7 @@ check_ldlm_extent(void)
         CHECK_STRUCT(ldlm_extent);
         CHECK_MEMBER(ldlm_extent, start);
         CHECK_MEMBER(ldlm_extent, end);
+        CHECK_MEMBER(ldlm_extent, gid);
 }
 
 void
diff --git a/lustre/utils/wiretest.c b/lustre/utils/wiretest.c
index ed317f9bc4..077601a56d 100644
--- a/lustre/utils/wiretest.c
+++ b/lustre/utils/wiretest.c
@@ -25,7 +25,7 @@ int main()
 void lustre_assert_wire_constants(void)
 {
         /* Wire protocol assertions generated by 'wirecheck'
-         * running on Linux schnapps.adilger.int 2.4.22-l32 #4 Thu Jan 8 14:32:57 MST 2004 i686 i686 
+         * running on Linux innova.tion.org 2.4.20-30.9-87k.37-b1_2.RC_1_2_0_3.200403111837 #1 Thu Ma
          * with gcc version 3.2.2 20030222 (Red Hat Linux 3.2.2-5) */
 
 
@@ -976,7 +976,7 @@ void lustre_assert_wire_constants(void)
                  (long long)(int)sizeof(((struct ldlm_res_id *)0)->name[4]));
 
         /* Checks for struct ldlm_extent */
-        LASSERTF((int)sizeof(struct ldlm_extent) == 16, " found %lld\n",
+        LASSERTF((int)sizeof(struct ldlm_extent) == 24, " found %lld\n",
                  (long long)(int)sizeof(struct ldlm_extent));
         LASSERTF(offsetof(struct ldlm_extent, start) == 0, " found %lld\n",
                  (long long)offsetof(struct ldlm_extent, start));
@@ -986,9 +986,13 @@ void lustre_assert_wire_constants(void)
                  (long long)offsetof(struct ldlm_extent, end));
         LASSERTF((int)sizeof(((struct ldlm_extent *)0)->end) == 8, " found %lld\n",
                  (long long)(int)sizeof(((struct ldlm_extent *)0)->end));
+        LASSERTF(offsetof(struct ldlm_extent, gid) == 16, " found %lld\n",
+                 (long long)offsetof(struct ldlm_extent, gid));
+        LASSERTF((int)sizeof(((struct ldlm_extent *)0)->gid) == 8, " found %lld\n",
+                 (long long)(int)sizeof(((struct ldlm_extent *)0)->gid));
 
         /* Checks for struct ldlm_flock */
-        LASSERTF((int)sizeof(struct ldlm_flock) == 32, " found %lld\n",
+        LASSERTF((int)sizeof(struct ldlm_flock) == 40, " found %lld\n",
                  (long long)(int)sizeof(struct ldlm_flock));
         LASSERTF(offsetof(struct ldlm_flock, start) == 0, " found %lld\n",
                  (long long)offsetof(struct ldlm_flock, start));
@@ -998,17 +1002,17 @@ void lustre_assert_wire_constants(void)
                  (long long)offsetof(struct ldlm_flock, end));
         LASSERTF((int)sizeof(((struct ldlm_flock *)0)->end) == 8, " found %lld\n",
                  (long long)(int)sizeof(((struct ldlm_flock *)0)->end));
-        LASSERTF(offsetof(struct ldlm_flock, blocking_export) == 16, " found %lld\n",
+        LASSERTF(offsetof(struct ldlm_flock, blocking_export) == 32, " found %lld\n",
                  (long long)offsetof(struct ldlm_flock, blocking_export));
         LASSERTF((int)sizeof(((struct ldlm_flock *)0)->blocking_export) == 8, " found %lld\n",
                  (long long)(int)sizeof(((struct ldlm_flock *)0)->blocking_export));
         LASSERTF(offsetof(struct ldlm_flock, blocking_pid) == 24, " found %lld\n",
                  (long long)offsetof(struct ldlm_flock, blocking_pid));
-        LASSERTF((int)sizeof(((struct ldlm_flock *)0)->blocking_pid) == 4, " found %lld\n",
+        LASSERTF((int)sizeof(((struct ldlm_flock *)0)->blocking_pid) == 8, " found %lld\n",
                  (long long)(int)sizeof(((struct ldlm_flock *)0)->blocking_pid));
-        LASSERTF(offsetof(struct ldlm_flock, pid) == 28, " found %lld\n",
+        LASSERTF(offsetof(struct ldlm_flock, pid) == 16, " found %lld\n",
                  (long long)offsetof(struct ldlm_flock, pid));
-        LASSERTF((int)sizeof(((struct ldlm_flock *)0)->pid) == 4, " found %lld\n",
+        LASSERTF((int)sizeof(((struct ldlm_flock *)0)->pid) == 8, " found %lld\n",
                  (long long)(int)sizeof(((struct ldlm_flock *)0)->pid));
 
         /* Checks for struct ldlm_intent */
@@ -1032,7 +1036,7 @@ void lustre_assert_wire_constants(void)
                  (long long)(int)sizeof(((struct ldlm_resource_desc *)0)->lr_name));
 
         /* Checks for struct ldlm_lock_desc */
-        LASSERTF((int)sizeof(struct ldlm_lock_desc) == 80, " found %lld\n",
+        LASSERTF((int)sizeof(struct ldlm_lock_desc) == 88, " found %lld\n",
                  (long long)(int)sizeof(struct ldlm_lock_desc));
         LASSERTF(offsetof(struct ldlm_lock_desc, l_resource) == 0, " found %lld\n",
                  (long long)offsetof(struct ldlm_lock_desc, l_resource));
@@ -1048,11 +1052,11 @@ void lustre_assert_wire_constants(void)
                  (long long)(int)sizeof(((struct ldlm_lock_desc *)0)->l_granted_mode));
         LASSERTF(offsetof(struct ldlm_lock_desc, l_policy_data) == 48, " found %lld\n",
                  (long long)offsetof(struct ldlm_lock_desc, l_policy_data));
-        LASSERTF((int)sizeof(((struct ldlm_lock_desc *)0)->l_policy_data) == 32, " found %lld\n",
+        LASSERTF((int)sizeof(((struct ldlm_lock_desc *)0)->l_policy_data) == 40, " found %lld\n",
                  (long long)(int)sizeof(((struct ldlm_lock_desc *)0)->l_policy_data));
 
         /* Checks for struct ldlm_request */
-        LASSERTF((int)sizeof(struct ldlm_request) == 104, " found %lld\n",
+        LASSERTF((int)sizeof(struct ldlm_request) == 112, " found %lld\n",
                  (long long)(int)sizeof(struct ldlm_request));
         LASSERTF(offsetof(struct ldlm_request, lock_flags) == 0, " found %lld\n",
                  (long long)offsetof(struct ldlm_request, lock_flags));
@@ -1060,19 +1064,19 @@ void lustre_assert_wire_constants(void)
                  (long long)(int)sizeof(((struct ldlm_request *)0)->lock_flags));
         LASSERTF(offsetof(struct ldlm_request, lock_desc) == 8, " found %lld\n",
                  (long long)offsetof(struct ldlm_request, lock_desc));
-        LASSERTF((int)sizeof(((struct ldlm_request *)0)->lock_desc) == 80, " found %lld\n",
+        LASSERTF((int)sizeof(((struct ldlm_request *)0)->lock_desc) == 88, " found %lld\n",
                  (long long)(int)sizeof(((struct ldlm_request *)0)->lock_desc));
-        LASSERTF(offsetof(struct ldlm_request, lock_handle1) == 88, " found %lld\n",
+        LASSERTF(offsetof(struct ldlm_request, lock_handle1) == 96, " found %lld\n",
                  (long long)offsetof(struct ldlm_request, lock_handle1));
         LASSERTF((int)sizeof(((struct ldlm_request *)0)->lock_handle1) == 8, " found %lld\n",
                  (long long)(int)sizeof(((struct ldlm_request *)0)->lock_handle1));
-        LASSERTF(offsetof(struct ldlm_request, lock_handle2) == 96, " found %lld\n",
+        LASSERTF(offsetof(struct ldlm_request, lock_handle2) == 104, " found %lld\n",
                  (long long)offsetof(struct ldlm_request, lock_handle2));
         LASSERTF((int)sizeof(((struct ldlm_request *)0)->lock_handle2) == 8, " found %lld\n",
                  (long long)(int)sizeof(((struct ldlm_request *)0)->lock_handle2));
 
         /* Checks for struct ldlm_reply */
-        LASSERTF((int)sizeof(struct ldlm_reply) == 112, " found %lld\n",
+        LASSERTF((int)sizeof(struct ldlm_reply) == 120, " found %lld\n",
                  (long long)(int)sizeof(struct ldlm_reply));
         LASSERTF(offsetof(struct ldlm_reply, lock_flags) == 0, " found %lld\n",
                  (long long)offsetof(struct ldlm_reply, lock_flags));
@@ -1080,17 +1084,17 @@ void lustre_assert_wire_constants(void)
                  (long long)(int)sizeof(((struct ldlm_reply *)0)->lock_flags));
         LASSERTF(offsetof(struct ldlm_request, lock_desc) == 8, " found %lld\n",
                  (long long)offsetof(struct ldlm_request, lock_desc));
-        LASSERTF((int)sizeof(((struct ldlm_request *)0)->lock_desc) == 80, " found %lld\n",
+        LASSERTF((int)sizeof(((struct ldlm_request *)0)->lock_desc) == 88, " found %lld\n",
                  (long long)(int)sizeof(((struct ldlm_request *)0)->lock_desc));
-        LASSERTF(offsetof(struct ldlm_reply, lock_handle) == 88, " found %lld\n",
+        LASSERTF(offsetof(struct ldlm_reply, lock_handle) == 96, " found %lld\n",
                  (long long)offsetof(struct ldlm_reply, lock_handle));
         LASSERTF((int)sizeof(((struct ldlm_reply *)0)->lock_handle) == 8, " found %lld\n",
                  (long long)(int)sizeof(((struct ldlm_reply *)0)->lock_handle));
-        LASSERTF(offsetof(struct ldlm_reply, lock_policy_res1) == 96, " found %lld\n",
+        LASSERTF(offsetof(struct ldlm_reply, lock_policy_res1) == 104, " found %lld\n",
                  (long long)offsetof(struct ldlm_reply, lock_policy_res1));
         LASSERTF((int)sizeof(((struct ldlm_reply *)0)->lock_policy_res1) == 8, " found %lld\n",
                  (long long)(int)sizeof(((struct ldlm_reply *)0)->lock_policy_res1));
-        LASSERTF(offsetof(struct ldlm_reply, lock_policy_res2) == 104, " found %lld\n",
+        LASSERTF(offsetof(struct ldlm_reply, lock_policy_res2) == 112, " found %lld\n",
                  (long long)offsetof(struct ldlm_reply, lock_policy_res2));
         LASSERTF((int)sizeof(((struct ldlm_reply *)0)->lock_policy_res2) == 8, " found %lld\n",
                  (long long)(int)sizeof(((struct ldlm_reply *)0)->lock_policy_res2));
-- 
GitLab