diff -urpNX dontdiff linux-2.5.48/fs/lockd/clntproc.c linux-2.5.48-flock/fs/lockd/clntproc.c
--- linux-2.5.48/fs/lockd/clntproc.c    2002-11-17 23:29:21.000000000 -0500
+++ linux-2.5.48-flock/fs/lockd/clntproc.c      2002-11-19 18:38:39.000000000 -0500
@@ -462,8 +462,6 @@ nlmclnt_lock(struct nlm_rqst *req, struc
               fl->fl_u.nfs_fl.state = host->h_state;
               fl->fl_u.nfs_fl.flags |= NFS_LCK_GRANTED;
               fl->fl_u.nfs_fl.host = host;
-               fl->fl_insert = nlmclnt_insert_lock_callback;
-               fl->fl_remove = nlmclnt_remove_lock_callback;
       }

       return nlm_stat_to_errno(resp->status);
@@ -689,3 +687,30 @@ nlm_stat_to_errno(u32 status)
       printk(KERN_NOTICE "lockd: unexpected server status %d\n", status);
       return -ENOLCK;
}
+
+static int nlmclnt_set_lock(struct file *filp, struct file_lock *fl)
+{
+       if (fl->fl_flags & FL_SLEEP) {
+               nfs_lock(filp, F_SETLKW, fl);
+       } else {
+               nfs_lock(filp, F_SETLK, fl);
+       }
+}
+
+static int nlmclnt_get_lock(struct file *filp, struct file_lock *fl)
+{
+       nfs_lock(filp, F_GETLK, fl);
+}
+
+static int nlmclnt_remove_posix(struct file *filp, fl_owner_t id)
+{
+       printk("remove posix support not yet implemented\n");
+}
+
+struct lock_operations nfs_client_lops = {
+       .set_lock =     nlmclnt_set_lock,
+       .get_lock =     nlmclnt_get_lock,
+       .remove_posix = nlmclnt_remove_posix,
+       .lock_insert =  nlmclnt_insert_lock_callback,
+       .lock_remove =  nlmclnt_remove_lock_callback,
+};
diff -urpNX dontdiff linux-2.5.48/fs/locks.c linux-2.5.48-flock/fs/locks.c
--- linux-2.5.48/fs/locks.c     2002-11-17 23:29:56.000000000 -0500
+++ linux-2.5.48-flock/fs/locks.c       2002-11-19 19:31:23.000000000 -0500
@@ -187,8 +187,6 @@ void locks_init_lock(struct file_lock *f
       fl->fl_type = 0;
       fl->fl_start = fl->fl_end = 0;
       fl->fl_notify = NULL;
-       fl->fl_insert = NULL;
-       fl->fl_remove = NULL;
}

/*
@@ -219,8 +217,6 @@ void locks_copy_lock(struct file_lock *n
       new->fl_start = fl->fl_start;
       new->fl_end = fl->fl_end;
       new->fl_notify = fl->fl_notify;
-       new->fl_insert = fl->fl_insert;
-       new->fl_remove = fl->fl_remove;
       new->fl_u = fl->fl_u;
}

@@ -312,8 +308,6 @@ static int flock_to_posix_lock(struct fi
       fl->fl_file = filp;
       fl->fl_flags = FL_POSIX;
       fl->fl_notify = NULL;
-       fl->fl_insert = NULL;
-       fl->fl_remove = NULL;

       return assign_type(fl, l->l_type);
}
@@ -352,8 +346,6 @@ static int flock64_to_posix_lock(struct
       fl->fl_file = filp;
       fl->fl_flags = FL_POSIX;
       fl->fl_notify = NULL;
-       fl->fl_insert = NULL;
-       fl->fl_remove = NULL;

       switch (l->l_type) {
       case F_RDLCK:
@@ -388,8 +380,6 @@ static int lease_alloc(struct file *filp
       fl->fl_start = 0;
       fl->fl_end = OFFSET_MAX;
       fl->fl_notify = NULL;
-       fl->fl_insert = NULL;
-       fl->fl_remove = NULL;

       *flp = fl;
       return 0;
@@ -465,14 +455,17 @@ static void locks_wake_up_blocks(struct
 */
static void locks_insert_lock(struct file_lock **pos, struct file_lock *fl)
{
+       struct lock_operations *l_op = NULL;
       list_add(&fl->fl_link, &file_lock_list);

       /* insert into file's list */
       fl->fl_next = *pos;
       *pos = fl;

-       if (fl->fl_insert)
-               fl->fl_insert(fl);
+       if (fl->fl_file->f_op)
+               l_op = fl->fl_file->f_op->lock;
+       if (l_op && l_op->lock_insert)
+               l_op->lock_insert(fl);
}

/*
@@ -484,6 +477,7 @@ static void locks_insert_lock(struct fil
static void locks_delete_lock(struct file_lock **thisfl_p)
{
       struct file_lock *fl = *thisfl_p;
+       struct lock_operations *l_op = NULL;

       *thisfl_p = fl->fl_next;
       fl->fl_next = NULL;
@@ -495,8 +489,10 @@ static void locks_delete_lock(struct fil
               fl->fl_fasync = NULL;
       }

-       if (fl->fl_remove)
-               fl->fl_remove(fl);
+       if (fl->fl_file->f_op)
+               l_op = fl->fl_file->f_op->lock;
+       if (l_op && l_op->lock_remove)
+               l_op->lock_remove(fl);

       locks_wake_up_blocks(fl);
       locks_free_lock(fl);
@@ -1324,6 +1320,7 @@ asmlinkage long sys_flock(unsigned int f
int fcntl_getlk(struct file *filp, struct flock *l)
{
       struct file_lock *fl, file_lock;
+       struct lock_operations *l_op = NULL;
       struct flock flock;
       int error;

@@ -1338,15 +1335,13 @@ int fcntl_getlk(struct file *filp, struc
       if (error)
               goto out;

-       if (filp->f_op && filp->f_op->lock) {
-               error = filp->f_op->lock(filp, F_GETLK, &file_lock);
+       if (filp->f_op)
+               l_op = filp->f_op->lock;
+       if (l_op && l_op->get_lock) {
+               error = l_op->get_lock(filp, &file_lock);
               if (error < 0)
                       goto out;
-               else if (error == LOCK_USE_CLNT)
-                 /* Bypass for NFS with no locking - 2.0.36 compat */
-                 fl = posix_test_lock(filp, &file_lock);
-               else
-                 fl = (file_lock.fl_type == F_UNLCK ? NULL : &file_lock);
+               fl = (file_lock.fl_type == F_UNLCK ? NULL : &file_lock);
       } else {
               fl = posix_test_lock(filp, &file_lock);
       }
@@ -1380,19 +1375,48 @@ out:
       return error;
}

+int vfs_setlock_posix(struct file *filp, struct file_lock *fl)
+{
+       struct lock_operations *l_op = NULL;
+       int error;
+
+       error = security_ops->file_lock(filp, fl->fl_type);
+       if (error)
+               return error;
+
+       if (filp->f_op)
+               l_op = filp->f_op->lock;
+       if (l_op && l_op->set_lock)
+               return l_op->set_lock(filp, fl);
+
+       for (;;) {
+               error = posix_lock_file(filp, fl);
+               if ((error != -EAGAIN) || !(fl->fl_flags & FL_SLEEP))
+                       break;
+               error = wait_event_interruptible(fl->fl_wait,
+                               !fl->fl_next);
+               if (!error)
+                       continue;
+
+               lock_kernel();
+               locks_delete_block(fl);
+               unlock_kernel();
+               break;
+       }
+
+       return error;
+}
+
/* Apply the lock described by l to an open file descriptor.
 * This implements both the F_SETLK and F_SETLKW commands of fcntl().
 */
int fcntl_setlk(struct file *filp, unsigned int cmd, struct flock *l)
{
-       struct file_lock *file_lock = locks_alloc_lock(0);
+       struct file_lock file_lock;
       struct flock flock;
       struct inode *inode;
       int error;

-       if (file_lock == NULL)
-               return -ENOLCK;
-
       /*
        * This might block, so we do it before checking the inode.
        */
@@ -1417,11 +1441,12 @@ int fcntl_setlk(struct file *filp, unsig
       }
#endif

-       error = flock_to_posix_lock(filp, file_lock, &flock);
+       locks_init_lock(&file_lock);
+       error = flock_to_posix_lock(filp, &file_lock, &flock);
       if (error)
               goto out;
       if (cmd == F_SETLKW) {
-               file_lock->fl_flags |= FL_SLEEP;
+               file_lock.fl_flags |= FL_SLEEP;
       }

       error = -EBADF;
@@ -1441,33 +1466,9 @@ int fcntl_setlk(struct file *filp, unsig
               goto out;
       }

-       error = security_ops->file_lock(filp, file_lock->fl_type);
-       if (error)
-               goto out;
-
-       if (filp->f_op && filp->f_op->lock != NULL) {
-               error = filp->f_op->lock(filp, cmd, file_lock);
-               if (error < 0)
-                       goto out;
-       }
-
-       for (;;) {
-               error = posix_lock_file(filp, file_lock);
-               if ((error != -EAGAIN) || (cmd == F_SETLK))
-                       break;
-               error = wait_event_interruptible(file_lock->fl_wait,
-                               !file_lock->fl_next);
-               if (!error)
-                       continue;
-
-               lock_kernel();
-               locks_delete_block(file_lock);
-               unlock_kernel();
-               break;
-       }
+       error = vfs_setlock_posix(filp, &file_lock);

 out:
-       locks_free_lock(file_lock);
       return error;
}

@@ -1478,6 +1479,7 @@ int fcntl_setlk(struct file *filp, unsig
int fcntl_getlk64(struct file *filp, struct flock64 *l)
{
       struct file_lock *fl, file_lock;
+       struct lock_operations *l_op = NULL;
       struct flock64 flock;
       int error;

@@ -1492,15 +1494,13 @@ int fcntl_getlk64(struct file *filp, str
       if (error)
               goto out;

-       if (filp->f_op && filp->f_op->lock) {
-               error = filp->f_op->lock(filp, F_GETLK, &file_lock);
+       if (filp->f_op)
+               l_op = filp->f_op->lock;
+       if (l_op && l_op->get_lock) {
+               error = l_op->get_lock(filp, &file_lock);
               if (error < 0)
                       goto out;
-               else if (error == LOCK_USE_CLNT)
-                 /* Bypass for NFS with no locking - 2.0.36 compat */
-                 fl = posix_test_lock(filp, &file_lock);
-               else
-                 fl = (file_lock.fl_type == F_UNLCK ? NULL : &file_lock);
+               fl = (file_lock.fl_type == F_UNLCK ? NULL : &file_lock);
       } else {
               fl = posix_test_lock(filp, &file_lock);
       }
@@ -1527,14 +1527,11 @@ out:
 */
int fcntl_setlk64(struct file *filp, unsigned int cmd, struct flock64 *l)
{
-       struct file_lock *file_lock = locks_alloc_lock(0);
+       struct file_lock file_lock;
       struct flock64 flock;
       struct inode *inode;
       int error;

-       if (file_lock == NULL)
-               return -ENOLCK;
-
       /*
        * This might block, so we do it before checking the inode.
        */
@@ -1544,6 +1541,7 @@ int fcntl_setlk64(struct file *filp, uns

       inode = filp->f_dentry->d_inode;

+#ifdef CONFIG_MMU
       /* Don't allow mandatory locks on files that may be memory mapped
        * and shared.
        */
@@ -1556,12 +1554,13 @@ int fcntl_setlk64(struct file *filp, uns
                       goto out;
               }
       }
+#endif

-       error = flock64_to_posix_lock(filp, file_lock, &flock);
+       error = flock64_to_posix_lock(filp, &file_lock, &flock);
       if (error)
               goto out;
       if (cmd == F_SETLKW64) {
-               file_lock->fl_flags |= FL_SLEEP;
+               file_lock.fl_flags |= FL_SLEEP;
       }

       error = -EBADF;
@@ -1581,33 +1580,9 @@ int fcntl_setlk64(struct file *filp, uns
               goto out;
       }

-       error = security_ops->file_lock(filp, file_lock->fl_type);
-       if (error)
-               goto out;
-
-       if (filp->f_op && filp->f_op->lock != NULL) {
-               error = filp->f_op->lock(filp, cmd, file_lock);
-               if (error < 0)
-                       goto out;
-       }
-
-       for (;;) {
-               error = posix_lock_file(filp, file_lock);
-               if ((error != -EAGAIN) || (cmd == F_SETLK64))
-                       break;
-               error = wait_event_interruptible(file_lock->fl_wait,
-                               !file_lock->fl_next);
-               if (!error)
-                       continue;
-
-               lock_kernel();
-               locks_delete_block(file_lock);
-               unlock_kernel();
-               break;
-       }
+       error = vfs_setlock_posix(filp, &file_lock);

-out:
-       locks_free_lock(file_lock);
+ out:
       return error;
}
#endif /* BITS_PER_LONG == 32 */
@@ -1619,30 +1594,34 @@ out:
 */
void locks_remove_posix(struct file *filp, fl_owner_t owner)
{
-       struct file_lock lock;
+       struct file_lock *fl, **before;
+       struct lock_operations *l_op = NULL;
+       struct inode *inode = filp->f_dentry->d_inode;

       /*
-        * If there are no locks held on this file, we don't need to call
-        * posix_lock_file().  Another process could be setting a lock on this
-        * file at the same time, but we wouldn't remove that lock anyway.
+        * If there are no locks held on this file, we don't need to do
+        * anything.  Another thread could be setting a lock on this
+        * file at the same time, but it's a race we just won.
        */
-       if (!filp->f_dentry->d_inode->i_flock)
+       if (!inode->i_flock)
               return;

-       lock.fl_type = F_UNLCK;
-       lock.fl_flags = FL_POSIX;
-       lock.fl_start = 0;
-       lock.fl_end = OFFSET_MAX;
-       lock.fl_owner = owner;
-       lock.fl_pid = current->tgid;
-       lock.fl_file = filp;
-
-       if (filp->f_op && filp->f_op->lock != NULL) {
-               filp->f_op->lock(filp, F_SETLK, &lock);
-               /* Ignore any error -- we must remove the locks anyway */
+       if (filp->f_op)
+               l_op = filp->f_op->lock;
+       if (l_op && l_op->remove_posix) {
+               l_op->remove_posix(filp, owner);
+       } else {
+               lock_kernel();
+               before = &inode->i_flock;
+               while ((fl = *before) != NULL) {
+                       if (IS_POSIX(fl) && fl->fl_owner == owner) {
+                               locks_delete_lock(before);
+                               continue;
+                       }
+                       before = &fl->fl_next;
+               }
+               unlock_kernel();
       }
-
-       posix_lock_file(filp, &lock);
}

/*
diff -urpNX dontdiff linux-2.5.48/include/linux/fs.h linux-2.5.48-flock/include/linux/fs.h
--- linux-2.5.48/include/linux/fs.h     2002-11-17 23:29:29.000000000 -0500
+++ linux-2.5.48-flock/include/linux/fs.h       2002-11-19 19:24:41.000000000 -0500
@@ -540,8 +540,6 @@ struct file_lock {
       loff_t fl_end;

       void (*fl_notify)(struct file_lock *);  /* unblock callback */
-       void (*fl_insert)(struct file_lock *);  /* lock insertion callback */
-       void (*fl_remove)(struct file_lock *);  /* lock removal callback */

       struct fasync_struct *  fl_fasync; /* for lease break notifications */
       unsigned long fl_break_time;    /* for nonblocking lease breaks */
@@ -734,6 +732,42 @@ typedef struct {

typedef int (*read_actor_t)(read_descriptor_t *, struct page *, unsigned long, unsigned long);

+/**
+ * struct lock_operations - filesystem hooks for file locking
+ *
+ * This struct is a work in progress.  It is intended to be per-filesystem;
+ * indeed it could be part of f_ops were it not pure bloat for non-network
+ * filesystems.  I suspect lock_insert and lock_remove are now unnecessary,
+ * but need feedback from FS maintainers.
+ *
+ * @set_lock:
+ *     Attempt to set a new lock.  BKL not held, may sleep.
+ * @get_lock:
+ *     Return any lock which would conflict with the incoming lock.
+ *     No locks held, may sleep.
+ * @remove_posix:
+ *     A process closed a file descriptor.  Any locks on this @filp owned
+ *     by @owner should be removed.  BKL not held, may sleep.
+ * @remove_flock:
+ *     This @filp has been closed.  All locks owned by this process should
+ *     be removed.  BKL not held, may sleep.
+ * @lock_insert:
+ *     Notification that @fl, which was previously blocked, is now being
+ *     inserted.  BKL might not be held.  Must not sleep.
+ * @lock_remove:
+ *     Notification that @fl, which was an active lock, is now being
+ *     removed from the @filp.  BKL might not be held.  Must not sleep.
+ */
+
+struct lock_operations {
+       int (*set_lock) (struct file *filp, struct file_lock *fl);
+       int (*get_lock) (struct file *filp, struct file_lock *fl);
+       void (*remove_posix) (struct file *filp, fl_owner_t owner);
+       void (*remove_flock) (struct file *filp);
+       void (*lock_insert) (struct file_lock *fl);
+       void (*lock_remove) (struct file_lock *fl);
+};
+
/*
 * NOTE:
 * read, write, poll, fsync, readv, writev can be called
@@ -757,7 +791,7 @@ struct file_operations {
       int (*fsync) (struct file *, struct dentry *, int datasync);
       int (*aio_fsync) (struct kiocb *, int datasync);
       int (*fasync) (int, struct file *, int);
-       int (*lock) (struct file *, int, struct file_lock *);
+       struct lock_operations *lock;
       ssize_t (*readv) (struct file *, const struct iovec *, unsigned long, loff_t *);
       ssize_t (*writev) (struct file *, const struct iovec *, unsigned long, loff_t *);
       ssize_t (*sendfile) (struct file *, loff_t *, size_t, read_actor_t, void *);