bug-hurd
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

[PATCH] POSIX file locking


From: Neal H Walfield
Subject: [PATCH] POSIX file locking
Date: Fri, 13 Apr 2001 18:08:55 +0200
User-agent: Mutt/1.3.15i

This patch adds support for POSIX file locking to the Hurd.  As I do not
have a POSIX manual, this is a best effort at conformance.  What does
that mean?  As far as I can tell, the behavior, with the exceptions
listed below, matches that exhibited by GNU/Linux and the descriptions
which I have found in Stevens' ``Advanced Programming in the UNIX
Environment'' and Gay's ``Advanced Unix.''

* F_GETLK is only half implement.  Currently, we have no way to
  determine the sender of a message (it is not sufficient to know
  the owner of a protid, as a process can fork), therefore, in the
  case where we need to return the pid, we fail returning EOPNOTSUPP.
  This should not be a road block in advertising to applications that
  we support POSIX file locking as the F_GETLK operation is rarely
  used.  This is, however, an important problem as other facilities
  also require this support, e.g. System V IPC.

* According to POSIX, when a process forks, the child should not inherit
  any of the parent's locks.  Currently, we merely add a reference to the
  send right associated with each file descriptor.
  libc/hurd/dtable.c:fork_child_dtable could get new protids, however,
  this implies that they no longer share the same file pointer.  Thus,
  this re-emphasizes the importance of determining the sender of a
  message.

* When a file descriptor is closed, the locks associated with the protid
  need to be dropped.  At the moment, we only dereference the send right
  (Cf.  libc/hurd/fs-close.c:_hurd_fd_close and
  libc/hurd/hurd/port.h:_hurd_port_locked_set), i.e.  the locks are
  dropped when all of the references to the protid are released.
  Consider:

        fd1 = open ("foo", ...);
        fd2 = dup (fd1);
        fcntl (fd1, F_SETLKW, &lock);
        close (fd2);
        /* LOCK should now be dropped.  */

  Thus, _hurd_fd_close should free any locks.

* The definition of flock_t is sketchy.  If we take a look at
  <hurd/hurd_types.defs>, we find:

        type flock_t = struct[5] of int;

  And looking at <bits/fcntl.h> shows:

        struct flock
          {
            int l_type;
            int l_whence;
        #ifndef __USE_FILE_OFFSET64
            __off_t l_start;
            __off_t l_len;
        #else
            __off64_t l_start;
            __off64_t l_len;
        #endif
            __pid_t l_pid;
          };

  Thus, when l_start and l_len are 64 bits, we overflow.

* We have no way to associate multiple opens of the same file.
  Consider:

        fd1 = open ("foo", ...);
        fd2 = open ("foo", ...);
        fcntl (fd1, F_SETLKW, &lock);
        close (fd2);
        /* LOCK should now be dropped.  */

  I imagine this being extremely difficult to implement correctly.

* In libdiskfs, I have reimplemented file_lock and file_lock_stat using
  fcntl.  This is a transparent change.

* A test suite is included in this patch and shows up in
  hurd/libfshelp-tests.

  `race' locks a file, reads an integer, increments it, writes the result
  to the file and then unlocks the file -- 10,000 times.  It is intended
  that multiple instances of this program be run at the same time.  Race
  takes three arguments:  the file to use, the start of the lock and the
  length.  For obvious reasons, it is important that all instances of
  race have locks that overlap.

  For example:

        # rm -f foo && ( ./race foo 2 0 & ./race foo 2 3 & \
        > ./race foo 0 3 )
        Was blocked 5482 times
        Was blocked 5485 times
        Was blocked 5479 times
        # cat foo
        30000

  We see here that each process was blocked several thousand times
  and that the result in the file foo is 30000.  Perfect.

  Locks is an interactive shell that has one ``file'' and ten open
  file descriptors.  Using some simple commands, one can test to see
  if locks are established, cleared, and enforced.  The principal
  command is `lock,' which takes four parameters.  The first is the
  file descriptor to lock, the second is the start of the lock, the
  third is the length of the lock (0 = until EOF) and the last is
  the type of lock to establish from the set {0: F_UNLCK, 1: F_RDLCK,
  2: F_WRLCK}.  Help on the other commands can be gotten using the
  `help' command.

  A small run:

        # ./locks
        > lock 0 10 0 1
          0:    Start =   10; Length =    0; Type = F_RDLCK

  Lock from byte 10 through the EOF.

        > lock 0 20 0 0
          0:    Start =   10; Length =   10; Type = F_RDLCK

  Unlock from byte 20 through the EOF.

        > lock 0 11 8 2
          0:    Start =   10; Length =    1; Type = F_RDLCK
                Start =   11; Length =    8; Type = F_WRLCK
                Start =   19; Length =    1; Type = F_RDLCK

  Upgrade bytes 11 through 19 to a write lock.

        > lock 0 9 10 1
          0:    Start =    9; Length =    2; Type = F_RDLCK
                Start =   11; Length =    8; Type = F_WRLCK
                Start =   19; Length =    1; Type = F_RDLCK

  Add a read lock to byte 9.

        > lock 1 0 10 1
        1:    Start =    0; Length =   10; Type = F_RDLCK

  Read lock the first ten bytes of the file through file
  descriptor 1.

        > lock 1 10 0 1
        Resource temporarily unavailable

  Attempts to read lock the rest of the file.  This, however,
  fails as there are outstanding write locks held through file
  descriptor 1.

        > lock 1 10 0 0
        1:    Start =    0; Length =   10; Type = F_RDLCK

  What happens when file descriptor tries to unlock the blocked
  range?

        > lock 1 10 0 2
        Resource temporarily unavailable

  Nothing.

  A bunch of tests live in hurd/libfshelp-tests/locks-test.  One can
  run them through the test program using:
  `./locks < locks-test 2>&1 | less'.  If it core dumps or triggers an
  assertion, that is a bug.  Report it.

diff --exclude configure --exclude CVS -urN 
hurd-20010412-snapshot/hurd/ChangeLog hurd-20010412/hurd/ChangeLog
--- hurd-20010412-snapshot/hurd/ChangeLog       Wed Feb 28 09:33:15 2001
+++ hurd-20010412/hurd/ChangeLog        Fri Apr 13 16:06:34 2001
@@ -1,3 +1,8 @@
+2001-04-10  Neal H Walfield  <neal@cs.uml.edu>
+
+       * fs.defs: New rpc file_record_lock.
+       * hurd_typed.defs: Import <fcntl.h>.
+
 2001-01-11  Marcus Brinkmann  <marcus@gnu.org>
 
        * default_pager_types.h: New file.
diff --exclude configure --exclude CVS -urN hurd-20010412-snapshot/hurd/fs.defs 
hurd-20010412/hurd/fs.defs
--- hurd-20010412-snapshot/hurd/fs.defs Mon Oct 11 11:02:37 1999
+++ hurd-20010412/hurd/fs.defs  Thu Apr 12 20:41:03 2001
@@ -352,3 +352,11 @@
        RPT
        parent: mach_port_t;
        out new_file: mach_port_send_t);
+
+/* Do fcntl type locking.  Cf.  <fcntl.h>.  */
+routine file_record_lock (
+       file: file_t;
+       RPT
+       cmd: int;
+       inout flock: flock_t);
+
diff --exclude configure --exclude CVS -urN 
hurd-20010412-snapshot/hurd/hurd_types.defs hurd-20010412/hurd/hurd_types.defs
--- hurd-20010412-snapshot/hurd/hurd_types.defs Mon Nov 30 04:18:44 1998
+++ hurd-20010412/hurd/hurd_types.defs  Thu Apr 12 20:43:06 2001
@@ -223,3 +223,5 @@
 import <sys/resource.h>;
 import <sys/utsname.h>;
 import <hurd/hurd_types.h>;
+import <fcntl.h>;
+
diff --exclude configure --exclude CVS -urN 
hurd-20010412-snapshot/libdiskfs/ChangeLog hurd-20010412/libdiskfs/ChangeLog
--- hurd-20010412-snapshot/libdiskfs/ChangeLog  Sun Apr  1 23:32:11 2001
+++ hurd-20010412/libdiskfs/ChangeLog   Fri Apr 13 16:02:52 2001
@@ -1,3 +1,25 @@
+2001-04-11  Neal H Walfield  <neal@cs.uml.edu>
+
+       * Makefile (FSSRCS): Add file-record-lock.c.
+       * diskfs.h (struct peropen): Change the type of lock_status
+       from an int to a struct rlock_peropen.
+       (struct node): Change the type of userbox from a struct lock_box
+       to a struct rlock_box.
+       * dir-lookup.c (diskfs_S_dir_lookup): Use fshelp_tweak_rlock
+       as fshelp_acquire_lock is now depreciated.
+       * file-lock-stat.c (diskfs_S_file_lock_stat): Total rewrite
+       around the new record locking functions.
+       * file-lock.c (diskfs_S_file_lock): Total rewrite around the
+       new record locking functions.
+       * file-record-lock.c: New file.  Implement
+       diskfs_S_file_record_lock.
+       * node-make.c (diskfs_make_node):  Initialize userbox with
+       fshelp_rlock_init.
+       * peropen-make.c (diskfs_make_peropen): Initialize lock_status
+       using fshelp_rlock_po_init.
+       * peropen-rele.c (diskfs_release_peropen): Release lock_status
+       using fshelp_rlock_drop_peropen.
+       
 2001-04-01  Roland McGrath  <roland@frob.com>
 
        * io-interrupt.c: Obsolete file removed.
diff --exclude configure --exclude CVS -urN 
hurd-20010412-snapshot/libdiskfs/Makefile hurd-20010412/libdiskfs/Makefile
--- hurd-20010412-snapshot/libdiskfs/Makefile   Sun Apr  1 23:31:44 2001
+++ hurd-20010412/libdiskfs/Makefile    Fri Apr 13 00:35:16 2001
@@ -1,5 +1,5 @@
 #
-#   Copyright (C) 1994,95,96,97,98,99,2000, 2001 Free Software Foundation, Inc.
+#   Copyright (C) 1994,95,96,97,98,99,2000,01 Free Software Foundation, Inc.
 #
 #   This program is free software; you can redistribute it and/or
 #   modify it under the terms of the GNU General Public License as
@@ -26,7 +26,8 @@
        file-get-trans.c file-get-transcntl.c file-getcontrol.c \
        file-getfh.c file-getlinknode.c file-inv-trans.c file-lock-stat.c \
        file-lock.c file-set-size.c file-set-trans.c file-statfs.c \
-       file-sync.c file-syncfs.c file-utimes.c file-reparent.c
+       file-sync.c file-syncfs.c file-utimes.c file-record-lock.c \
+       file-reparent.c 
 IOSRCS= io-async-icky.c io-async.c io-duplicate.c io-get-conch.c io-revoke.c \
        io-map-cntl.c io-map.c io-modes-get.c io-modes-off.c \
        io-modes-on.c io-modes-set.c io-owner-mod.c io-owner-get.c \
diff --exclude configure --exclude CVS -urN 
hurd-20010412-snapshot/libdiskfs/dir-lookup.c 
hurd-20010412/libdiskfs/dir-lookup.c
--- hurd-20010412-snapshot/libdiskfs/dir-lookup.c       Wed Mar 28 20:06:38 2001
+++ hurd-20010412/libdiskfs/dir-lookup.c        Thu Apr 12 19:48:10 2001
@@ -1,5 +1,5 @@
 /* libdiskfs implementation of fs.defs:dir_lookup
-   Copyright (C) 1992,93,94,95,96,97,98,99,2000 Free Software Foundation, Inc.
+   Copyright (C) 1992,93,94,95,96,97,98,99,2000,01 Free Software Foundation, 
Inc.
 
    This program is free software; you can redistribute it and/or
    modify it under the terms of the GNU General Public License as
@@ -434,12 +434,27 @@
 
   if (! error)
     {
+      struct flock lock =
+        {
+         l_start: 0,
+         l_len: 0,
+         l_whence: SEEK_SET
+       };
+
       if (flags & O_EXLOCK)
-       error = fshelp_acquire_lock (&np->userlock, &newpi->po->lock_status,
-                                    &np->lock, LOCK_EX);
+        {
+         lock.l_type = F_WRLCK;
+         error = fshelp_rlock_tweak (&np->userlock, &np->lock,
+                                     &newpi->po->lock_status, flags, 0, 0,
+                                     F_SETLK, &lock);
+       }
       else if (flags & O_SHLOCK)
-       error = fshelp_acquire_lock (&np->userlock, &newpi->po->lock_status,
-                                    &np->lock, LOCK_SH);
+        {
+         lock.l_type = F_RDLCK;
+         error = fshelp_rlock_tweak (&np->userlock, &np->lock,
+                                     &newpi->po->lock_status, flags, 0, 0,
+                                     F_SETLK, &lock);
+       }
       if (error)
        ports_port_deref (newpi); /* Get rid of NEWPI.  */
     }
diff --exclude configure --exclude CVS -urN 
hurd-20010412-snapshot/libdiskfs/diskfs.h hurd-20010412/libdiskfs/diskfs.h
--- hurd-20010412-snapshot/libdiskfs/diskfs.h   Tue Jan 30 02:12:51 2001
+++ hurd-20010412/libdiskfs/diskfs.h    Thu Apr 12 20:10:08 2001
@@ -1,5 +1,5 @@
 /* Definitions for fileserver helper functions
-   Copyright (C) 1994, 95, 96, 97, 98, 99 Free Software Foundation, Inc.
+   Copyright (C) 1994,95,96,97,98,99,2001 Free Software Foundation, Inc.
 
    This program is free software; you can redistribute it and/or
    modify it under the terms of the GNU General Public License as
@@ -46,8 +46,8 @@
 /* One of these is created for each node opened by dir_pathtrans. */
 struct peropen
 {
-  int filepointer;
-  int lock_status;
+  off_t filepointer;
+  struct rlock_peropen lock_status;
   int refcnt;
   int openstat;
 
@@ -92,7 +92,7 @@
 
   struct transbox transbox;
 
-  struct lock_box userlock;
+  struct rlock_box userlock;
 
   struct conch conch;
 
diff --exclude configure --exclude CVS -urN 
hurd-20010412-snapshot/libdiskfs/file-lock-stat.c 
hurd-20010412/libdiskfs/file-lock-stat.c
--- hurd-20010412-snapshot/libdiskfs/file-lock-stat.c   Mon Nov 13 22:51:06 1995
+++ hurd-20010412/libdiskfs/file-lock-stat.c    Thu Apr 12 19:49:31 2001
@@ -1,38 +1,43 @@
-/*
-   Copyright (C) 1994, 1995 Free Software Foundation
-
-This file is part of the GNU Hurd.
-
-The GNU Hurd is free software; you can redistribute it and/or modify
-it under the terms of the GNU General Public License as published by
-the Free Software Foundation; either version 2, or (at your option)
-any later version.
-
-The GNU Hurd is distributed in the hope that it will be useful, 
-but WITHOUT ANY WARRANTY; without even the implied warranty of
-MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
-GNU General Public License for more details.
-
-You should have received a copy of the GNU General Public License
-along with the GNU Hurd; see the file COPYING.  If not, write to
-the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.  */
-
-/* Written by Michael I. Bushnell.  */
+/* Copyright (C) 2001 Free Software Foundation, Inc.
+ 
+   Written by Neal H Walfield <neal@cs.uml.edu>
+
+   This program is free software; you can redistribute it and/or
+   modify it under the terms of the GNU General Public License as
+   published by the Free Software Foundation; either version 2, or (at
+   your option) any later version.
+
+   This program is distributed in the hope that it will be useful, but
+   WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+   General Public License for more details.
+
+   You should have received a copy of the GNU General Public License
+   along with this program; if not, write to the Free Software
+   Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */
 
 #include "priv.h"
 #include "fs_S.h"
 
+#include <fcntl.h>
+#include <sys/file.h>
+
 kern_return_t
 diskfs_S_file_lock_stat (struct protid *cred,
                         int *mystatus,
                         int *otherstatus)
 {
+  struct node *node;
+
   if (!cred)
     return EOPNOTSUPP;
-  
-  mutex_lock (&cred->po->np->lock);
-  *mystatus = cred->po->lock_status;
-  *otherstatus = cred->po->np->userlock.type;
-  mutex_unlock (&cred->po->np->lock);
+
+  node = cred->po->np;
+
+  mutex_lock (&node->lock);
+  *mystatus = fshelp_rlock_peropen_status (&cred->po->lock_status);
+  *otherstatus = fshelp_rlock_node_status (&node->userlock);
+  mutex_unlock (&node->lock);
+
   return 0;
 }
diff --exclude configure --exclude CVS -urN 
hurd-20010412-snapshot/libdiskfs/file-lock.c hurd-20010412/libdiskfs/file-lock.c
--- hurd-20010412-snapshot/libdiskfs/file-lock.c        Thu May  5 15:14:29 1994
+++ hurd-20010412/libdiskfs/file-lock.c Thu Apr 12 19:50:20 2001
@@ -1,38 +1,56 @@
-/*
-   Copyright (C) 1993, 1994 Free Software Foundation
-
-This file is part of the GNU Hurd.
-
-The GNU Hurd is free software; you can redistribute it and/or modify
-it under the terms of the GNU General Public License as published by
-the Free Software Foundation; either version 2, or (at your option)
-any later version.
-
-The GNU Hurd is distributed in the hope that it will be useful, 
-but WITHOUT ANY WARRANTY; without even the implied warranty of
-MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
-GNU General Public License for more details.
-
-You should have received a copy of the GNU General Public License
-along with the GNU Hurd; see the file COPYING.  If not, write to
-the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.  */
-
-/* Written by Michael I. Bushnell.  */
+/* Copyright (C) 2001 Free Software Foundation, Inc.
+ 
+   Written by Neal H Walfield <neal@cs.uml.edu>
+
+   This program is free software; you can redistribute it and/or
+   modify it under the terms of the GNU General Public License as
+   published by the Free Software Foundation; either version 2, or (at
+   your option) any later version.
+
+   This program is distributed in the hope that it will be useful, but
+   WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+   General Public License for more details.
+
+   You should have received a copy of the GNU General Public License
+   along with this program; if not, write to the Free Software
+   Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */
 
 #include "priv.h"
 #include "fs_S.h"
 
+#include <fcntl.h>
+#include <sys/file.h>
+
 kern_return_t
 diskfs_S_file_lock (struct protid *cred, int flags)
 {
   error_t err;
-  if (!cred)
+  struct flock lock;
+  struct node *node;
+
+  if (! cred)
     return EOPNOTSUPP;
-  mutex_lock (&cred->po->np->lock);
-  err = fshelp_acquire_lock (&cred->po->np->userlock, &cred->po->lock_status,
-                            &cred->po->np->lock, flags);
-  mutex_unlock (&cred->po->np->lock);
+
+  lock.l_start = 0;
+  lock.l_whence = SEEK_SET;
+  lock.l_len = 0;
+
+  if (flags & LOCK_UN)
+    lock.l_type = F_UNLCK;
+  else if (flags & LOCK_SH)
+    lock.l_type = F_RDLCK;
+  else if (flags & LOCK_EX)
+    lock.l_type = F_WRLCK;
+  else
+    return EINVAL;
+
+  node = cred->po->np;
+  mutex_lock (&node->lock);
+  err = fshelp_rlock_tweak (&node->userlock, &node->lock,
+                           &cred->po->lock_status, cred->po->openstat,
+                           0, 0, flags & LOCK_NB ? F_SETLK : F_SETLKW,
+                           &lock);
+  mutex_unlock (&node->lock);
   return err;
 }
-
-    
diff --exclude configure --exclude CVS -urN 
hurd-20010412-snapshot/libdiskfs/file-record-lock.c 
hurd-20010412/libdiskfs/file-record-lock.c
--- hurd-20010412-snapshot/libdiskfs/file-record-lock.c Thu Jan  1 01:00:00 1970
+++ hurd-20010412/libdiskfs/file-record-lock.c  Thu Apr 12 19:50:25 2001
@@ -0,0 +1,43 @@
+/* Copyright (C) 2001 Free Software Foundation, Inc.
+ 
+   Written by Neal H Walfield <neal@cs.uml.edu>
+
+   This program is free software; you can redistribute it and/or
+   modify it under the terms of the GNU General Public License as
+   published by the Free Software Foundation; either version 2, or (at
+   your option) any later version.
+
+   This program is distributed in the hope that it will be useful, but
+   WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+   General Public License for more details.
+
+   You should have received a copy of the GNU General Public License
+   along with this program; if not, write to the Free Software
+   Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */
+
+#include "priv.h"
+#include "diskfs.h"
+
+#include <errno.h>
+#include <hurd/fshelp.h>
+
+error_t
+diskfs_S_file_record_lock (struct protid *cred, int cmd, struct flock *lock)
+{
+  struct node *node;
+  error_t err;
+
+  if (! cred)
+    return EOPNOTSUPP;
+
+  node = cred->po->np;
+
+  mutex_lock (&node->lock);
+  err = fshelp_rlock_tweak (&node->userlock, &node->lock,
+                           &cred->po->lock_status, cred->po->openstat,
+                           node->dn_stat.st_size, cred->po->filepointer,
+                           cmd, lock);
+  mutex_unlock (&node->lock);
+  return err;
+}
diff --exclude configure --exclude CVS -urN 
hurd-20010412-snapshot/libdiskfs/node-make.c hurd-20010412/libdiskfs/node-make.c
--- hurd-20010412-snapshot/libdiskfs/node-make.c        Mon Aug 10 19:42:39 1998
+++ hurd-20010412/libdiskfs/node-make.c Thu Apr 12 19:51:52 2001
@@ -1,5 +1,5 @@
 /* 
-   Copyright (C) 1994, 1995, 1996 Free Software Foundation
+   Copyright (C) 1994,95,96,2001 Free Software Foundation
 
    This program is free software; you can redistribute it and/or
    modify it under the terms of the GNU General Public License as
@@ -43,8 +43,7 @@
   
   fshelp_transbox_init (&np->transbox, &np->lock, np);
   iohelp_initialize_conch (&np->conch, &np->lock);
-  fshelp_lock_init (&np->userlock);
-  
+  fshelp_rlock_init (&np->userlock);
 
   return np;
 }
diff --exclude configure --exclude CVS -urN 
hurd-20010412-snapshot/libdiskfs/peropen-make.c 
hurd-20010412/libdiskfs/peropen-make.c
--- hurd-20010412-snapshot/libdiskfs/peropen-make.c     Sun Apr  1 03:39:47 2001
+++ hurd-20010412/libdiskfs/peropen-make.c      Fri Apr 13 15:59:52 2001
@@ -1,5 +1,5 @@
 /* 
-   Copyright (C) 1994, 1997, 1999, 2001 Free Software Foundation
+   Copyright (C) 1994, 1997, 1999 Free Software Foundation
 
    This program is free software; you can redistribute it and/or
    modify it under the terms of the GNU General Public License as
@@ -16,20 +16,26 @@
    Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */
 
 #include "priv.h"
+#include <errno.h>
+#include <stdlib.h>
 #include <sys/file.h>
+#include <hurd/fshelp.h>
 
 /* Create and return a new peropen structure on node NP with open
    flags FLAGS.  */
 struct peropen *
 diskfs_make_peropen (struct node *np, int flags, struct peropen *context)
 {
+  error_t err;
   struct peropen *po = malloc (sizeof (struct peropen));
-
   if (! po)
     return NULL;
 
+  err = fshelp_rlock_po_init (&po->lock_status);
+  if (err)
+    return NULL;
+
   po->filepointer = 0;
-  po->lock_status = LOCK_UN;
   po->refcnt = 0;
   po->openstat = flags;
   po->np = np;
diff --exclude configure --exclude CVS -urN 
hurd-20010412-snapshot/libdiskfs/peropen-rele.c 
hurd-20010412/libdiskfs/peropen-rele.c
--- hurd-20010412-snapshot/libdiskfs/peropen-rele.c     Mon Apr 13 21:36:24 1998
+++ hurd-20010412/libdiskfs/peropen-rele.c      Thu Apr 12 19:52:03 2001
@@ -1,5 +1,5 @@
 /* 
-   Copyright (C) 1994, 1996, 1997 Free Software Foundation
+   Copyright (C) 1994,96,97,2001 Free Software Foundation
 
    This program is free software; you can redistribute it and/or
    modify it under the terms of the GNU General Public License as
@@ -39,9 +39,7 @@
   if (po->shadow_root_parent)
     mach_port_deallocate (mach_task_self (), po->shadow_root_parent);
 
-  if (po->lock_status != LOCK_UN)
-    fshelp_acquire_lock (&po->np->userlock, &po->lock_status,
-                        &po->np->lock, LOCK_UN);
+  fshelp_rlock_drop_peropen (&po->lock_status);
 
   diskfs_nput (po->np);
 
diff --exclude configure --exclude CVS -urN 
hurd-20010412-snapshot/libfshelp/ChangeLog hurd-20010412/libfshelp/ChangeLog
--- hurd-20010412-snapshot/libfshelp/ChangeLog  Wed Jan 31 00:45:32 2001
+++ hurd-20010412/libfshelp/ChangeLog   Fri Apr 13 15:48:01 2001
@@ -1,3 +1,24 @@
+2001-04-12  Neal H Walfield  <neal@cs.uml.edu>
+
+       * fshelp.h (struct rlock_box): New structure.
+       (struct rlock_peropen): Likewise.
+       (fshelp_rlock_init): New funtion.
+       (fshelp_rlock_po_init): Likewise.
+       (fshelp_rlock_drop_peropen): Likewise.
+       (fshelp_rlock_tweak): Likewise.
+       (fshelp_rlock_peropen_status): Likewise.
+       (fshelp_rlock_node_status): Likewise.
+       * rlock-drop-peropen.c: New file.  Implement
+       fshelp_rlock_drop_peropen.
+       * rlock-status.c: New file.  Implement
+       fshelp_rlock_peropen_status and fshelp_rlock_node_status.
+       * rlock-tweak.c: New file.  Implement fshelp_rlock_tweak.
+       * rlock.h: New file.
+       * extern-inline.c: New file.
+       * Makefile (LCLHDRS): Add rlock.h.
+       (SRCS): Add extern-inline.c, rlock-drop-peropen.c, rlock-tweak.c
+       and rlock-status.c.
+
 2001-01-17  Neal H Walfield  <neal@cs.uml.edu>
 
        * fshelp.h: Add two new parameters to fshelp_open_fn_t:
diff --exclude configure --exclude CVS -urN 
hurd-20010412-snapshot/libfshelp/Makefile hurd-20010412/libfshelp/Makefile
--- hurd-20010412-snapshot/libfshelp/Makefile   Thu Jul  1 23:04:24 1999
+++ hurd-20010412/libfshelp/Makefile    Fri Apr 13 15:36:19 2001
@@ -1,5 +1,5 @@
 #
-#   Copyright (C) 1994, 95, 96, 98, 1999 Free Software Foundation, Inc.
+#   Copyright (C) 1994,95,96,98,99,2001 Free Software Foundation, Inc.
 #
 #   This program is free software; you can redistribute it and/or
 #   modify it under the terms of the GNU General Public License as
@@ -28,8 +28,11 @@
        set-options.c \
        get-identity.c \
        perms-isowner.c perms-access.c perms-checkdirmod.c \
-       touch.c
-LCLHDRS = fshelp.h locks.h trans.h
+       touch.c \
+       extern-inline.c \
+       rlock-drop-peropen.c rlock-tweak.c rlock-status.c
+
+LCLHDRS = fshelp.h locks.h trans.h rlock.h
 installhdrs = fshelp.h
 
 HURDLIBS=shouldbeinlibc threads
diff --exclude configure --exclude CVS -urN 
hurd-20010412-snapshot/libfshelp/extern-inline.c 
hurd-20010412/libfshelp/extern-inline.c
--- hurd-20010412-snapshot/libfshelp/extern-inline.c    Thu Jan  1 01:00:00 1970
+++ hurd-20010412/libfshelp/extern-inline.c     Thu Apr 12 20:21:56 2001
@@ -0,0 +1,25 @@
+/*
+   Copyright (C) 2001 Free Software Foundation
+
+   Written by Neal H Walfield <neal@cs.uml.edu>
+
+   This file is part of the GNU Hurd.
+
+   The GNU Hurd is free software; you can redistribute it and/or modify
+   it under the terms of the GNU General Public License as published by
+   the Free Software Foundation; either version 2, or (at your option)
+   any later version.
+
+   The GNU Hurd is distributed in the hope that it will be useful, 
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+   GNU General Public License for more details.
+
+   You should have received a copy of the GNU General Public License
+   along with the GNU Hurd; see the file COPYING.  If not, write to
+   the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.  */
+
+#define FSHELP_EXTERN_INLINE
+
+#include "fshelp.h"
+
diff --exclude configure --exclude CVS -urN 
hurd-20010412-snapshot/libfshelp/fshelp.h hurd-20010412/libfshelp/fshelp.h
--- hurd-20010412-snapshot/libfshelp/fshelp.h   Wed Jan 31 00:45:32 2001
+++ hurd-20010412/libfshelp/fshelp.h    Thu Apr 12 20:21:56 2001
@@ -1,5 +1,5 @@
 /* FS helper library definitions
-   Copyright (C) 1994,95,96,97,98,99,2000 Free Software Foundation, Inc.
+   Copyright (C) 1994,95,96,97,98,99,2000,01 Free Software Foundation, Inc.
 
    This program is free software; you can redistribute it and/or
    modify it under the terms of the GNU General Public License as
@@ -18,18 +18,24 @@
 #ifndef _HURD_FSHELP_
 #define _HURD_FSHELP_
 
+#ifndef FSHELP_EXTERN_INLINE
+#define FSHELP_EXTERN_INLINE extern inline
+#endif
+
 /* This library implements various things that are generic to
    all or most implementors of the filesystem protocol.  It
    presumes that you are using the iohelp library as well.  It
    is divided into separate facilities which may be used independently.  */
 
 #include <errno.h>
+#include <stdlib.h>
 #include <mach.h>
 #include <hurd/hurd_types.h>
 #include <cthreads.h>
 #include <hurd/iohelp.h>
 #include <sys/stat.h>
 #include <maptime.h>
+#include <fcntl.h>
 
 
 /* Passive translator linkage */
@@ -168,19 +174,81 @@
   int shcount;
 };
 
-/* Call when a user makes a request to acquire an lock via file_lock.
+/* Initialize lock_box BOX.  (The user int passed to fshelp_acquire_lock
+   should be initialized with LOCK_UN.).  */
+void fshelp_lock_init (struct lock_box *box);
+
+/* Call when a user makes a request to acquire a lock via file_lock.
    There should be one lock box per object and one int per open; these
    are passed as arguments BOX and USER respectively.  FLAGS are as
    per file_lock.  MUT is a mutex which will be held whenever this
    routine is called, to lock BOX->wait.  */
 error_t fshelp_acquire_lock (struct lock_box *box, int *user,
                             struct mutex *mut, int flags);
+
+/* Record locking.  */
 
+/* Unique to a node; initialize with fshelp_rlock_init.  */
+struct rlock_box
+{
+  struct rlock_list *locks;    /* List of locks on the file.  */
+};
 
-/* Initialize lock_box BOX.  (The user int passed to fshelp_acquire_lock
-   should be initialized with LOCK_UN.).  */
-void fshelp_lock_init (struct lock_box *box);
+/* Initialize the rlock_box BOX.  */
+FSHELP_EXTERN_INLINE
+error_t fshelp_rlock_init (struct rlock_box *box)
+{
+  box->locks = NULL;
+  return 0;
+}
+
+/* Unique to a peropen.  */
+struct rlock_peropen
+{
+  /* This is a pointer to a pointer to a rlock_lock (and not a pointer
+     to a rlock_list) as it really serves two functions:
+       o the list of locks owned by this peropen
+       o the unique peropen identifier that all locks on this peropen share.  
*/
+  struct rlock_list **locks;
+};
+
+FSHELP_EXTERN_INLINE
+error_t fshelp_rlock_po_init (struct rlock_peropen *po)
+{
+  po->locks = malloc (sizeof (struct rlock_list *));
+  if (! po->locks)
+    return ENOMEM;
+
+  *po->locks = NULL;
+  return 0;
+}
+
+/* Release all of the locks held by a given peropen.  */
+error_t fshelp_rlock_drop_peropen (struct rlock_peropen *po);
+
+/* Call when a user makes a request to tweak a lock as via fcntl.  There
+   should be one rlock box per object.  BOX is the rlock box associated
+   with the object.  MUT is a mutex which should be held whenever this
+   routine is called; it should be unique on a pernode basis.  PO is the
+   peropen identifier.  OPEN_MODE is how the file was opened (from the O_*
+   set).  SIZE is the size of the object in question.  CURPOINTER is the
+   current position of the file pointer.  CMD is from the set F_GETLK,
+   F_SETLK, F_SETLKW.  LOCK is passed by the user and is as defined by
+   <fcntl.h>.  */
+error_t fshelp_rlock_tweak (struct rlock_box *box, struct mutex *mutex,
+                           struct rlock_peropen *po, int open_mode,
+                           off_t size, off_t curpointer, int cmd,
+                           struct flock *lock);
+
+/* These functions allow for easy emulation of file_lock and
+   file_lock_stat.  */
+
+/* Returns the type (from the set LOCK_UN, LOCK_SH, LOCK_EX) of the most
+   restictive lock held by the PEROPEN.  */
+int fshelp_rlock_peropen_status (struct rlock_peropen *po);
 
+/* Like fshelp_rlock_peropen_status except for all users of BOX.  */
+int fshelp_rlock_node_status (struct rlock_box *box);
 
 
 struct port_bucket;            /* shut up C compiler */
diff --exclude configure --exclude CVS -urN 
hurd-20010412-snapshot/libfshelp/rlock-drop-peropen.c 
hurd-20010412/libfshelp/rlock-drop-peropen.c
--- hurd-20010412-snapshot/libfshelp/rlock-drop-peropen.c       Thu Jan  1 
01:00:00 1970
+++ hurd-20010412/libfshelp/rlock-drop-peropen.c        Thu Apr 12 20:21:56 2001
@@ -0,0 +1,51 @@
+/*
+   Copyright (C) 2001 Free Software Foundation
+
+   Written by Neal H Walfield <neal@cs.uml.edu>
+
+   This file is part of the GNU Hurd.
+
+   The GNU Hurd is free software; you can redistribute it and/or modify
+   it under the terms of the GNU General Public License as published by
+   the Free Software Foundation; either version 2, or (at your option)
+   any later version.
+
+   The GNU Hurd is distributed in the hope that it will be useful, 
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+   GNU General Public License for more details.
+
+   You should have received a copy of the GNU General Public License
+   along with the GNU Hurd; see the file COPYING.  If not, write to
+   the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.  */
+
+#include "fshelp.h"
+#include "rlock.h"
+
+#include <stdlib.h>
+#include <cthreads.h>
+#include <fcntl.h>
+#include <unistd.h>
+
+error_t
+fshelp_rlock_drop_peropen (struct rlock_peropen *po)
+{
+  struct rlock_list *l;
+  struct rlock_list *t;
+
+  for (l = *po->locks; l; l = t)
+    {
+      if (l->waiting)
+       {
+         l->waiting = 0;
+         condition_broadcast (&l->wait);
+       }
+
+      list_unlink (node, l);
+
+      t = l->po.next;
+      free (l);
+    }
+
+  return 0;
+}
diff --exclude configure --exclude CVS -urN 
hurd-20010412-snapshot/libfshelp/rlock-status.c 
hurd-20010412/libfshelp/rlock-status.c
--- hurd-20010412-snapshot/libfshelp/rlock-status.c     Thu Jan  1 01:00:00 1970
+++ hurd-20010412/libfshelp/rlock-status.c      Thu Apr 12 20:21:56 2001
@@ -0,0 +1,52 @@
+/* Copyright (C) 2001 Free Software Foundation, Inc.
+
+   Written by Neal H Walfield <neal@cs.uml.edu>
+
+   This program is free software; you can redistribute it and/or
+   modify it under the terms of the GNU General Public License as
+   published by the Free Software Foundation; either version 2, or (at
+   your option) any later version.
+
+   This program is distributed in the hope that it will be useful, but
+   WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+   General Public License for more details.
+
+   You should have received a copy of the GNU General Public License
+   along with this program; if not, write to the Free Software
+   Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */
+
+#include "fshelp.h"
+#include "rlock.h"
+#include <fcntl.h>
+#include <sys/file.h>
+
+int fshelp_rlock_peropen_status (struct rlock_peropen *po)
+{
+  struct rlock_list *l;
+
+  if (! *po->locks)
+    return LOCK_UN;
+
+  for (l = *po->locks; l; l = l->po.next)
+    if (l->type == F_WRLCK)
+      return LOCK_EX;
+
+  return LOCK_SH;
+}
+
+/* Like fshelp_rlock_peropen_status except for all users of NODE.  */
+int fshelp_rlock_node_status (struct rlock_box *box)
+{
+  struct rlock_list *l;
+
+  if (! box->locks)
+    return LOCK_UN;
+
+  for (l = box->locks; l; l = l->node.next)
+    if (l->type == F_WRLCK)
+      return LOCK_EX;
+
+  return LOCK_SH;
+}
+
diff --exclude configure --exclude CVS -urN 
hurd-20010412-snapshot/libfshelp/rlock-tweak.c 
hurd-20010412/libfshelp/rlock-tweak.c
--- hurd-20010412-snapshot/libfshelp/rlock-tweak.c      Thu Jan  1 01:00:00 1970
+++ hurd-20010412/libfshelp/rlock-tweak.c       Fri Apr 13 15:32:08 2001
@@ -0,0 +1,552 @@
+/*
+   Copyright (C) 2001 Free Software Foundation
+
+   Written by Neal H Walfield <neal@cs.uml.edu>
+
+   This file is part of the GNU Hurd.
+
+   The GNU Hurd is free software; you can redistribute it and/or modify
+   it under the terms of the GNU General Public License as published by
+   the Free Software Foundation; either version 2, or (at your option)
+   any later version.
+
+   The GNU Hurd is distributed in the hope that it will be useful, 
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+   GNU General Public License for more details.
+
+   You should have received a copy of the GNU General Public License
+   along with the GNU Hurd; see the file COPYING.  If not, write to
+   the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.  */
+
+#include "fshelp.h"
+#include "rlock.h"
+
+#include <assert.h>
+#include <stdlib.h>
+#include <errno.h>
+#include <fcntl.h>
+#include <unistd.h>
+#include <sys/types.h>
+#include <cthreads.h>
+
+static inline int overlap (off_t start, off_t len, struct rlock_list *l)
+{
+  return ((len == 0 && l->len == 0)
+         || (len == 0 && l->start + l->len > start)
+         || (l->len == 0 && start + len > l->start)
+         || (l->start + l->len > start && start + len > l->start));
+}
+
+error_t
+fshelp_rlock_tweak (struct rlock_box *box, struct mutex *mutex,
+                   struct rlock_peropen *po, int open_mode,
+                   off_t obj_size, off_t cur_pointer, int cmd,
+                   struct flock *lock)
+{
+  inline struct rlock_list *
+  gen_lock (off_t start, off_t len, int type)
+    {
+      struct rlock_list *l = malloc (sizeof (struct rlock_list));
+      if (! l)
+        return NULL;
+
+      rlock_list_init (po, l);
+      l->start = start;
+      l->len = len;
+      l->type = type;
+
+      list_link (po, po->locks, l);
+      list_link (node, &box->locks, l);
+      return l;
+    }
+
+  inline void
+  rele_lock (struct rlock_list *l, int wake_waiters)
+    {
+      list_unlink (po, l);
+      list_unlink (node, l);
+
+      if (wake_waiters && l->waiting)
+       condition_broadcast (&l->wait);
+
+      free (l);
+    }
+
+  error_t
+  unlock_region (off_t start, off_t len)
+    {
+      struct rlock_list *l;
+
+      for (l = *po->locks; l; l = l->po.next)
+       {
+         if (l->len != 0 && l->start + l->len <= start)
+           /* We start after the locked region ends.  */
+           {
+             continue;
+           }
+         else if (len != 0 && start + len <= l->start)
+           /* We end before this region starts.  Since we are sorted,
+              we are done.  */
+           {
+             return 0;
+           }
+         else if (start <= l->start
+                  && (len == 0
+                      || (l->len != 0
+                          && l->start + l->len <= start + len)))
+           /* We wrap the locked region; consume it.  */
+           {
+             rele_lock (l, 1);
+             continue;
+           }
+         else if (start <= l->start
+                  && (l->len == 0
+                      || (l->start < start + len)))
+           /* The locked region is having its head unlocked.  */
+           {
+             assert (len != 0);
+             assert (l->len == 0 || start + len < l->start + l->len);
+
+             if (l->len != 0)
+               l->len -= start + len - l->start;
+             l->start = start + len;
+
+             if (l->waiting)
+               {
+                 l->waiting = 0;
+                 condition_broadcast (&l->wait);
+               }
+           }
+         else if (l->start < start
+                  && ((start < l->start + l->len
+                       && (len == 0 || l->start + l->len <= start + len))
+                      || (len == 0 && l->len == 0)))
+           /* The locked region needs its tail unlocked.  */
+           {
+             assert (len == 0
+                     || (l->len != 0 && l->start + l->len <= start + len));
+
+             l->len = start - l->start;
+
+             if (l->waiting)
+               {
+                 l->waiting = 0;
+                 condition_broadcast (&l->wait);
+               }
+
+             continue;
+           }
+         else if (l->start < start
+                  && (l->len == 0
+                      || (len != 0
+                          && start + len < l->start + l->len)))
+           /* The locked region wraps us (absolutely); crave out the
+              middle.  */
+           {
+             struct rlock_list *upper_half;
+
+             assert (len != 0);
+             
+             upper_half = gen_lock (start + len,
+                                    l->len 
+                                      ? l->start + l->len - (start + len)
+                                      : 0,
+                                    l->type);
+             if (! upper_half)
+               return ENOMEM;
+
+             l->len = start - l->start;
+
+             return 0;
+           }
+         else if (start < l->start
+                  && len != 0
+                  && start + len <= l->start)
+           /* The locked region starts after our end.  */
+           {
+             return 0;
+           }
+         else
+           assert (! "Impossible!");
+       }
+
+      return 0;
+    }
+
+  inline struct rlock_list *
+  find_conflict (off_t start, off_t len, int type)
+    {
+      struct rlock_list *l;
+
+      for (l = box->locks; l; l = l->node.next)
+       {
+         if (po->locks == l->po_id)
+           continue;
+
+         if ((l->type == F_WRLCK || type == F_WRLCK)
+             && overlap (start, len, l))
+           return l;
+       }
+
+      return NULL;
+    }
+
+  inline error_t
+  merge_in (off_t start, off_t len, int type)
+    {
+      struct rlock_list *l;
+
+      for (l = *po->locks; l; l = l->po.next)
+       {
+         if (l->start <= start
+             && (l->len == 0
+                 || (len != 0
+                     && start + len <= l->start + l->len)))
+           /* Our start and end fall between the locked region
+              (i.e. we are wrapped).  */
+           {
+             struct rlock_list *head = NULL;
+             struct rlock_list *tail = NULL;
+
+             if (type == l->type || type == F_RDLCK)
+               return 0;
+
+             assert (type == F_WRLCK && l->type == F_RDLCK);
+
+             if (l->start < start)
+               /* We need to split the head off.  */
+               {
+                 head = gen_lock (l->start, start - l->start, F_RDLCK);
+                 if (! head)
+                   return ENOMEM;
+               }
+
+             if ((l->len == 0 && len != 0)
+                 || start + len < l->start + l->len)
+               /* We need to split the tail off.  */
+               {
+                 tail = gen_lock (start + len,
+                                  l->len
+                                    ? l->start + l->len - (start + len)
+                                    : 0,
+                                  F_RDLCK);
+                 if (! tail)
+                   {
+                     if (head)
+                       rele_lock (head, 0);
+                     return ENOMEM;
+                   }
+               }
+
+             if (head)
+               {
+                 off_t shift = start - l->start;
+
+                 if (l->len != 0)
+                   l->len -= shift;
+                 l->start += shift;
+               }
+
+             if (tail)
+               l->len = tail->start - l->start;
+
+             if (! tail)
+               /* There is a chance we can merge some more.  */
+               {
+                 start = l->start;
+                 len = l->len;
+
+                 rele_lock (l, 1);
+                 continue;
+               }
+             else
+               {
+                 l->type = F_WRLCK;
+                 return 0;
+               }
+           }
+         else if (start <= l->start
+                  && (len == 0
+                      || (l->len != 0
+                          && l->start + l->len <= start + len)))
+           /* We fully wrap the locked region.  */
+           {
+             struct rlock_list *head;
+
+             if (type == l->type || type == F_WRLCK)
+               {
+                 rele_lock (l, 1);
+                 /* Try to merge more.  */
+                 continue;
+               }
+
+             assert (type == F_RDLCK && l->type == F_WRLCK);
+
+             if (start < l->start)
+               /* Generate our head.  */
+               {
+                 head = gen_lock (start, l->start - start, F_RDLCK);
+                 if (! head)
+                   return ENOMEM;
+               }
+             else
+               head = NULL;
+
+             if (l->len != 0
+                 && (len == 0 || l->start + l->len < start + len))
+               /* We have a tail, try to merge it also.  */
+               {
+                 if (len != 0)
+                   len = start + len - (l->start + l->len);
+                 start = l->start + l->len;
+
+                 continue;
+               }
+             else
+               /* Our end is silently consumed.  */
+               {
+                 /* If we do not have a tail, we must have had a head
+                    (if not, the first case would have caught us).  */
+                 assert (head);
+                 return 0;
+               }
+           }
+         else if (l->start < start
+                  && (len == 0
+                      || (start <= l->start + l->len
+                          && start + len > l->start + l->len)))
+           /* Our start falls within the locked region or exactly one
+              byte after it and our end falls beyond it.  We know that
+              we cannot consume the entire region.  */
+           {
+             assert (l->len != 0);
+
+             if (type == l->type)
+               /* Merge the two areas.  */
+               {
+                 if (len != 0)
+                   len += start - l->start;
+                 start = l->start;
+
+                 rele_lock (l, 1);
+
+                 /* Try to merge in more.  */
+                 continue;
+               }
+             else if (start == l->start + l->len)
+                 /* We fall just after the locked region (there is no
+                    intersection) and we are not the same type.  */
+               {
+                 /* The is nothing to do except continue the search.  */
+                 continue;
+               }
+             else if (type == F_WRLCK)
+               /* We comsume the intersection.  */
+               {
+                 assert (l->type == F_RDLCK);
+
+                 l->len -= l->start + l->len - start;
+
+                 /* Don't create the lock now; we might be able to
+                    consume more locks.  */
+                 continue;
+               }
+             else
+               /* We are dominated; the locked region comsumes the
+                  intersection.  */
+               {
+                 off_t common = l->start + l->len - start;
+
+                 assert (type == F_RDLCK);
+                 assert (l->type == F_WRLCK);
+
+                 start += common;
+                 if (len != 0)
+                   len -= common;
+
+                 /* There is still a chance that we can consume more
+                    locks.  */
+                 continue;
+               }
+           }
+         else if (start < l->start
+                  && (l->len == 0
+                      || l->start <= start + len))
+           /* Our start falls before the locked region and our
+              end falls (inclusively) between it or one byte before it.
+              Note, we know that we do not consume the entire locked
+              area.  */
+           {
+             assert (len != 0);
+             assert (l->len == 0 || start + len < l->start + l->len);
+
+             if (type == l->type)
+               /* Merge the two areas.  */
+               {
+                 if (l->len)
+                   l->len += l->start - start;
+                 l->start = start;
+                 return 0;
+               }
+             else if (l->start == start + len)
+               /* Our end falls just before the start of the locked
+                  region, however, we are not the same type.  Just
+                  insert it.  */
+               {
+                 continue;
+               }
+             else if (type == F_WRLCK)
+               /* We consume the intersection.  */
+               {
+                 struct rlock_list *e;
+                 off_t common = start + len - l->start;
+
+                 assert (l->type == F_RDLCK);
+
+                 e = gen_lock (start, len, F_WRLCK);
+                 if (! e)
+                   return ENOMEM;
+
+                 if (l->len)
+                   l->len -= common;
+                 l->start += common;
+
+                 return 0;
+               }
+             else
+               /* The locked region comsumes the intersection.  */
+               {
+                 struct rlock_list *e;
+
+                 assert (l->type == F_WRLCK);
+                 assert (type == F_RDLCK);
+
+                 e = gen_lock (start, l->start - start, F_RDLCK);
+                 if (! e)
+                   return ENOMEM;
+
+                 return 0;
+               }
+           }
+         else if (start < l->start
+                  && len != 0
+                  && start + len <= l->start)
+           /* We start and end before this locked region.  Therefore,
+              knowing that the list is sorted, the merge is done.  */
+           {
+             break;
+           }
+         else
+           /* We start beyond the end of this locked region.  */
+           {
+             assert (start >= l->start + l->len);
+             assert (l->len != 0);
+             continue;
+           }
+       }
+
+      return (gen_lock (start, len, type) ? 0 : ENOMEM);
+    }
+
+  struct rlock_list *e;
+  off_t start;
+  off_t len;
+
+  if (cmd != F_GETLK
+      && cmd != F_SETLK
+      && cmd != F_SETLKW)
+    return EOPNOTSUPP;
+
+  if (lock->l_type != F_UNLCK
+      && lock->l_type != F_RDLCK
+      && lock->l_type != F_WRLCK)
+    return EINVAL;
+
+  if (lock->l_type == F_UNLCK)
+    {
+      if (cmd == F_SETLKW)
+        /* If we are unlocking a region, map F_SETLKW to F_SETLK.  */
+        cmd = F_SETLK;
+      else if (cmd == F_GETLK)
+       /* Impossible!  */
+       return EINVAL;
+    }
+
+  if (lock->l_type == F_RDLCK && !(open_mode & O_READ))
+    return EACCES;
+  if (lock->l_type == F_WRLCK && !(open_mode & O_WRITE))
+    return EACCES;
+
+  switch (lock->l_whence)
+    {
+    case SEEK_SET: 
+      start = lock->l_start;
+      break;
+
+    case SEEK_CUR:
+      start = cur_pointer + lock->l_start;
+      break;
+
+    case SEEK_END:
+      start = obj_size + lock->l_start;
+      break;
+
+    default:
+      return EINVAL;
+    }
+
+  if (start < 0)
+    return EINVAL;
+
+  len = lock->l_len;
+  if (len < 0)
+    return EINVAL;
+
+  if (cmd == F_SETLK && lock->l_type == F_UNLCK)
+    return unlock_region (start, len);
+
+retry:
+  e = find_conflict (start, len, lock->l_type);
+
+  if (cmd == F_GETLK)
+    {
+      if (e)
+       {
+#if 0
+         lock->l_type = e->l_type;
+         lock->l_start = e->start;
+         lock->l_whence = SEEK_SET;
+         lock->l_len = e->len;
+         lock->l_pid = -1;  /* XXX: This is so wrong it makes me puke.  */
+         return 0;
+#else
+         return EOPNOTSUPP;
+#endif
+       }
+      else
+       {
+         lock->l_type = F_UNLCK;
+         return 0;
+       }
+    }
+  else
+    {
+      assert (cmd == F_SETLK || cmd == F_SETLKW);
+
+      if (! e)
+       return merge_in (start, len, lock->l_type);
+      else
+        {
+         if (cmd == F_SETLKW)
+           {
+             e->waiting = 1;
+             if (hurd_condition_wait (&e->wait, mutex))
+               return EINTR;
+             goto retry;
+           }
+         else
+           return EAGAIN;
+       }
+    }
+}
diff --exclude configure --exclude CVS -urN 
hurd-20010412-snapshot/libfshelp/rlock.h hurd-20010412/libfshelp/rlock.h
--- hurd-20010412-snapshot/libfshelp/rlock.h    Thu Jan  1 01:00:00 1970
+++ hurd-20010412/libfshelp/rlock.h     Thu Apr 12 20:21:56 2001
@@ -0,0 +1,88 @@
+/*
+   Copyright (C) 2001 Free Software Foundation
+
+   Written by Neal H Walfield <neal@cs.uml.edu>
+
+   This file is part of the GNU Hurd.
+
+   The GNU Hurd is free software; you can redistribute it and/or modify
+   it under the terms of the GNU General Public License as published by
+   the Free Software Foundation; either version 2, or (at your option)
+   any later version.
+
+   The GNU Hurd is distributed in the hope that it will be useful, 
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+   GNU General Public License for more details.
+
+   You should have received a copy of the GNU General Public License
+   along with the GNU Hurd; see the file COPYING.  If not, write to
+   the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.  */
+
+#ifndef FSHELP_RLOCK_H
+#define FSHELP_RLOCK_H
+
+#include <cthreads.h>
+#include <string.h>
+
+struct rlock_linked_list
+{
+  struct rlock_list *next;
+  struct rlock_list **prevp;
+};
+
+struct rlock_list
+{
+  off_t start;
+  off_t len;
+  int type;
+
+  struct rlock_linked_list node;
+  struct rlock_linked_list po;
+
+  struct condition wait;
+  int waiting;
+
+  void *po_id;
+};
+
+extern inline error_t
+rlock_list_init (struct rlock_peropen *po, struct rlock_list *l)
+{
+  memset (l, 0, sizeof (struct rlock_list));
+  condition_init (&l->wait);
+  l->po_id = po->locks;
+  return 0;
+}
+
+/* void list_list (X ={po,node}, struct rlock_list **head,
+                  struct rlock_list *node)
+ 
+   Insert a node in the given list, X, in sorted order.  */
+#define list_link(X, head, node)                               \
+       do                                                      \
+         {                                                     \
+           struct rlock_list **e;                              \
+           for (e = head;                                      \
+                *e && ((*e)->start < node->start);             \
+                e = &(*e)->X.next)                             \
+             ;                                                 \
+           node->X.next = *e;                                  \
+           if (node->X.next)                                   \
+             node->X.next->X.prevp = &node->X.next;            \
+           node->X.prevp = e;                                  \
+           *e = node;                                          \
+         }                                                     \
+       while (0)
+
+/* void list_unlock (X = {po,node}, struct rlock_list *node)  */
+#define list_unlink(X, node)                                   \
+       do                                                      \
+         {                                                     \
+           *node->X.prevp = node->X.next;                      \
+           if (node->X.next)                                   \
+             node->X.next->X.prevp = node->X.prevp;            \
+         }                                                     \
+       while (0)
+
+#endif /* FSHELP_RLOCK_H */
diff --exclude configure --exclude CVS -urN 
hurd-20010412-snapshot/libfshelp-tests/ChangeLog 
hurd-20010412/libfshelp-tests/ChangeLog
--- hurd-20010412-snapshot/libfshelp-tests/ChangeLog    Thu Jan  1 01:00:00 1970
+++ hurd-20010412/libfshelp-tests/ChangeLog     Fri Apr 13 16:11:50 2001
@@ -0,0 +1,11 @@
+2001-04-11  Neal H Walfield  <neal@cs.uml.edu>
+
+       * ChangeLog: New file, mentioning itself in this sentence.
+       * Makefile: New file.
+       * README: Likewise.
+       * fork.c: Likewise.
+       * locks: Likewise.
+       * locks-test: Likewise.
+       * locks.c: Likewise.
+       * race.c: Likewise.
+
diff --exclude configure --exclude CVS -urN 
hurd-20010412-snapshot/libfshelp-tests/Makefile 
hurd-20010412/libfshelp-tests/Makefile
--- hurd-20010412-snapshot/libfshelp-tests/Makefile     Thu Jan  1 01:00:00 1970
+++ hurd-20010412/libfshelp-tests/Makefile      Thu Apr 12 20:23:19 2001
@@ -0,0 +1,36 @@
+# Makefile libfshelp test cases
+#
+#   Copyright (C) 2001 Free Software Foundation, Inc.
+#
+#   This program is free software; you can redistribute it and/or
+#   modify it under the terms of the GNU General Public License as
+#   published by the Free Software Foundation; either version 2, or (at
+#   your option) any later version.
+#
+#   This program is distributed in the hope that it will be useful, but
+#   WITHOUT ANY WARRANTY; without even the implied warranty of
+#   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+#   General Public License for more details.
+#
+#   You should have received a copy of the GNU General Public License
+#   along with this program; if not, write to the Free Software
+#   Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+
+dir := libfshelp-tests
+makemode := utilities
+
+targets = race locks fork
+SRCS = race.c locks.c fork.c
+
+MIGSTUBS = fsUser.o ioUser.o
+OBJS = $(SRCS:.c=.o) $(MIGSTUBS)
+HURDLIBS =
+
+include ../Makeconf
+
+race: race.o fsUser.o ioUser.o
+fork: fork.o fsUser.o
+locks: locks.o
+
+race locks: ../libfshelp/libfshelp.a ../libports/libports.a \
+           ../libthreads/libthreads.a
diff --exclude configure --exclude CVS -urN 
hurd-20010412-snapshot/libfshelp-tests/README 
hurd-20010412/libfshelp-tests/README
--- hurd-20010412-snapshot/libfshelp-tests/README       Thu Jan  1 01:00:00 1970
+++ hurd-20010412/libfshelp-tests/README        Fri Apr 13 17:47:56 2001
@@ -0,0 +1,102 @@
+These programs are used to help test the algorithms in the libfshelp
+library.
+
+Record Locking
+==============
+
+Race
+----
+
+Race locks a file, reads an integer, increments it, writes the result to
+the file and then unlocks the file -- 10,000 times.  It is intended that
+multiple instances of this program be run at the same time.  Race takes
+three arguments:  the file to use, the start of the lock and the length.
+For obvious reasons, it is important that all instances of race have
+locks that overlap.  For example:
+
+       # rm -f foo && ( ./race foo 2 0 & ./race foo 2 3 & \
+       > ./race foo 0 3 )
+       Was blocked 5482 times
+       Was blocked 5485 times
+       Was blocked 5479 times
+       # cat foo
+       30000
+
+We see here that each process was blocked several thousand times and that
+the result in the file foo is 30000.  Perfect.
+
+Locks
+-----
+
+Locks is an interactive shell that has one ``file'' and ten open file
+descriptors.  Using some simple commands, one can test to see if locks
+are established, cleared, and enforced.  The principal command is
+`lock,' which takes four parameters.  The first is the file descriptor
+to lock, the second is the start of the lock, the third is the length of
+the lock (0 = until EOF) and the last is the type of lock to establish
+from the set {0: F_UNLCK, 1: F_RDLCK, 2: F_WRLCK}.  Help on the other
+commands can be gotten using the `help' command.
+
+A small run:
+
+       # ./locks
+       > lock 0 10 0 1
+         0:    Start =   10; Length =    0; Type = F_RDLCK
+
+Lock from byte 10 through the EOF.
+
+       > lock 0 20 0 0
+         0:    Start =   10; Length =   10; Type = F_RDLCK
+
+Unlock from byte 20 through the EOF.
+
+       > lock 0 11 8 2
+         0:    Start =   10; Length =    1; Type = F_RDLCK
+               Start =   11; Length =    8; Type = F_WRLCK
+               Start =   19; Length =    1; Type = F_RDLCK
+
+Upgrade bytes 11 through 19 to a write lock.
+
+       > lock 0 9 10 1
+         0:    Start =    9; Length =    2; Type = F_RDLCK
+               Start =   11; Length =    8; Type = F_WRLCK
+               Start =   19; Length =    1; Type = F_RDLCK
+
+Add a read lock to byte 9.
+
+       > lock 1 0 10 1
+         1:    Start =    0; Length =   10; Type = F_RDLCK
+
+Read lock the first ten bytes of the file through file descriptor 1.
+
+       > lock 1 10 0 1
+       Resource temporarily unavailable
+
+Attempts to read lock the rest of the file.  This, however, fails as
+there are outstanding write locks held through file descriptor 1.
+
+       > lock 1 10 0 0
+         1:    Start =    0; Length =   10; Type = F_RDLCK
+
+What happens when file descriptor tries to unlock the blocked range?
+
+       > lock 1 10 0 2
+       Resource temporarily unavailable
+
+Nothing.
+
+A bunch of tests live in locks-test.  One can run them through the test
+program using: `./locks < locks-test 2>&1 | less'.  If it core dumps or
+triggers an assertion, that is a bug.  Report it.
+
+Fork
+----
+
+Tests to see if the a child inherits the locks across a fork.  According
+to POSIX, the child should not.
+
+       # ./fork foo
+       Parent has a write lock; Others have a write lock.
+       Child has a write lock; Others have a write lock.
+
+We are not POSIX compliant.
diff --exclude configure --exclude CVS -urN 
hurd-20010412-snapshot/libfshelp-tests/fork.c 
hurd-20010412/libfshelp-tests/fork.c
--- hurd-20010412-snapshot/libfshelp-tests/fork.c       Thu Jan  1 01:00:00 1970
+++ hurd-20010412/libfshelp-tests/fork.c        Fri Apr 13 11:10:31 2001
@@ -0,0 +1,79 @@
+/* Test is a process inherits locks after a fork.
+   Copyright (C) 2001 Free Software Foundation, Inc.
+
+   Written by Neal H Walfield <neal@cs.uml.edu>
+
+   This program is free software; you can redistribute it and/or
+   modify it under the terms of the GNU General Public License as
+   published by the Free Software Foundation; either version 2, or (at
+   your option) any later version.
+
+   This program is distributed in the hope that it will be useful, but
+   WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+   General Public License for more details.
+
+   You should have received a copy of the GNU General Public License
+   along with this program; if not, write to the Free Software
+   Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */
+
+#include <assert.h>
+#include <stdio.h>
+#include <error.h>
+#include <fcntl.h>
+#include <unistd.h>
+#include <sys/file.h>
+#include <hurd.h>
+#include "fs_U.h"
+
+char *lock2str (int type)
+{
+  if (type & LOCK_SH)
+    return "read";
+  if (type & LOCK_EX)
+    return "write";
+  if (type & LOCK_UN)
+    return "unlocked";
+ assert (! "Invalid");
+ return NULL;
+}
+
+int main (int argc, char **argv)
+{
+  error_t err;
+  struct flock lock;
+  int fd;
+  pid_t pid;
+  int mine, others;
+
+  if (argc != 2)
+    error (1, 0, "Usage: %s file", argv[0]);
+
+  lock.l_whence = SEEK_SET;
+  lock.l_start = 0;
+  lock.l_len = 0;
+  lock.l_type = F_WRLCK;
+  
+  fd = file_name_lookup (argv[1], O_READ | O_WRITE | O_CREAT, 0666);
+  if (fd == MACH_PORT_NULL)
+    error (1, errno, "file_name_lookup");
+
+  err = file_record_lock (fd, F_SETLK, &lock);
+  if (err)
+    error (1, err, "file_record_lock");
+
+  pid = fork ();
+  if (pid == -1)
+    error (1, errno, "fork");
+
+  err = file_lock_stat (fd, &mine, &others);
+  if (err)
+    error (1, err, "file_lock_stat");
+
+  printf ("%s has a %s lock; Others have a %s lock.\n",
+         pid ? "Parent" : "Child", lock2str (mine), lock2str (others));
+
+  mach_port_deallocate (mach_task_self (), fd);
+
+  return 0;
+}
diff --exclude configure --exclude CVS -urN 
hurd-20010412-snapshot/libfshelp-tests/locks-tests 
hurd-20010412/libfshelp-tests/locks-tests
--- hurd-20010412-snapshot/libfshelp-tests/locks-tests  Thu Jan  1 01:00:00 1970
+++ hurd-20010412/libfshelp-tests/locks-tests   Fri Apr 13 15:25:52 2001
@@ -0,0 +1,585 @@
+echo Legend:
+echo +   => Shared region
+echo x   => Exclusive region
+echo ' ' => Unlocked region
+echo .   => Clearing region
+echo []  => Start/End of a region
+echo After each lock command, the proposed region is shown followed
+echo by the result of applying it.
+echo * Established region wraps new region
+echo ** Both boundaries align
+echo [
+exec lock 0 1 10 1
+echo   [+++++++++++++]
+echo [ [+++++++++++++]
+exec lock 0 1 10 1
+echo   [+++++++++++++]
+echo [ [+++++++++++++]
+exec lock 0 1 10 2
+echo   [xxxxxxxxxxxxx]
+echo [ [xxxxxxxxxxxxx]
+exec lock 0 1 10 1
+echo   [+++++++++++++]
+echo [ [xxxxxxxxxxxxx]
+exec lock 0 1 10 2
+echo   [xxxxxxxxxxxxx]
+echo [ [xxxxxxxxxxxxx]
+exec lock 0 1 10 0
+echo   [.............]
+echo [
+exec lock 0 10 0 1
+echo         [++++++++
+echo [       [++++++++
+exec lock 0 10 0 1
+echo         [++++++++
+echo [       [++++++++
+exec lock 0 10 0 2
+echo         [xxxxxxxx
+echo [       [xxxxxxxx
+exec lock 0 10 0 2
+echo         [xxxxxxxx
+echo [       [xxxxxxxx
+exec lock 0 10 0 1
+echo         [++++++++
+echo [       [xxxxxxxx
+exec lock 0 10 0 0
+echo         [........
+echo [
+echo ** Left boundaries align
+exec lock 0 1 10 1
+echo   [+++++++++++]
+echo [ [+++++++++++]
+exec lock 0 1 5 1
+echo   [+++++]
+echo [ [+++++++++++]
+exec lock 0 1 5 2
+echo   [xxxxx]
+echo [ [xxxxx][++++]
+exec lock 0 1 3 1
+echo   [++]
+echo [ [xxxxx][++++]
+exec lock 0 1 10 0
+echo   [............
+echo [
+exec lock 0 1 10 1
+echo   [+++++++++++]
+echo [ [+++++++++++]
+exec lock 0 1 9 2
+echo   [xxxxxxxx]
+echo [ [xxxxxxxx][+]
+exec lock 0 1 5 0
+echo   [...]
+echo [      [***][+]
+exec lock 0 6 3 0
+echo        [.]
+echo [         [*][+]
+exec lock 0 9 1 0
+echo          [.]
+echo [           [+]
+exec lock 0 10 1 0
+echo             [.]
+echo [
+exec lock 0 1 0 1
+echo   [++++++++++++
+echo [ [++++++++++++
+exec lock 0 1 5 1
+echo   [++++]
+echo [ [++++++++++++
+exec lock 0 1 5 2
+echo   [xxxx]
+echo [ [xxxx][++++++
+exec lock 0 1 0 0
+echo   [............
+echo [
+exec lock 0 5 0 2
+echo     [xxxxxxxxxx
+echo [   [xxxxxxxxxx
+exec lock 0 5 5 1
+echo     [++++]
+echo [   [xxxxxxxxxx
+exec lock 0 5 0 1
+echo     [++++++++++
+echo [   [xxxxxxxxxx
+exec lock 0 0 0 0
+echo [..............
+echo [
+echo ** Common right side
+exec lock 0 5 5 1
+echo       [+++++]
+echo [     [+++++]
+exec lock 0 9 1 1
+echo           [+]
+echo [     [+++++]
+exec lock 0 9 1 2
+echo           [x]
+echo [     [++][x]
+exec lock 0 5 4 2
+echo       [xx]
+echo [     [xxxxx]
+exec lock 0 8 2 2
+echo           [x]
+echo [     [xxxxx]
+exec lock 0 9 1 0
+echo           [.]
+echo [     [xxx]
+exec lock 0 5 4 0
+echo       [...]
+echo [
+exec lock 0 5 0 1
+echo     [++++++++++
+echo [   [++++++++++
+exec lock 0 10 0 1
+echo          [+++++
+echo [   [++++++++++
+exec lock 0 10 0 2
+echo          [xxxxx
+echo [   [+++][xxxxx
+exec lock 0 5 0 0
+echo     [..........
+echo [
+echo ** Completely interior
+exec lock 0 5 10 1
+echo      [++++++++]
+echo [    [++++++++]
+exec lock 0 6 8 1
+echo       [++++++]
+echo [    [++++++++]
+exec lock 0 8 3 1
+echo         [+]
+echo [    [++++++++]
+exec lock 0 8 3 2
+echo         [x]
+echo [    [+][x][++]
+exec lock 0 12 1 2
+echo             x
+echo [    [++xxx+x+]
+exec lock 0 6 8 0
+echo       [......]
+echo [    [+]    [+]
+exec lock 0 0 0 0
+echo [..............
+echo [
+exec lock 0 5 0 1
+echo      [+++++++++
+echo [    [+++++++++
+exec lock 0 10 0 1
+echo           [++++
+echo [    [+++++++++
+exec lock 0 10 0 2
+echo           [xxxx
+echo [    [+++][xxxx
+exec lock 0 11 0 0
+echo             [..
+echo [    [+++][x]
+exec lock 0 6 0 0
+echo        [.......
+echo [    [+]
+exec lock 0 5 0 0
+echo      [.........
+echo [
+exec lock 0 10 0 1
+echo          [+++++
+echo [        [+++++
+exec lock 0 11 0 1
+echo           [+]
+echo [        [+++++
+exec lock 0 11 0 1
+echo           [+]
+echo [        [+++++
+exec lock 0 11 1 2
+echo           [x]
+echo [        [+x+++
+exec lock 0 13 0 1
+echo             [+]
+echo [        [+x+++
+exec lock 0 10 0 0
+echo          [.....
+echo [
+echo * We wrap the locked region
+echo ** Left boundaries align
+exec lock 0 1 10 1
+echo  [++++]
+echo [[++++]
+exec lock 0 1 15 1
+echo  [++++++++]
+echo [[++++++++]
+exec lock 0 1 16 1
+echo  [+++++++++]
+echo [[+++++++++]
+exec lock 0 1 20 2
+echo  [xxxxxxxxxxxxx]
+echo [[xxxxxxxxxxxxx]
+exec lock 0 1 30 1
+echo  [+++++++++++++++++++]
+echo [[xxxxxxxxxxxxx][++++]
+exec lock 0 22 11 2
+echo                   [xxx]
+echo [[xxxxxxxxxxxxx][+][xx]
+exec lock 0 1 40 0
+echo  [.........................]
+echo [
+exec lock 0 1 0 1
+echo  [++++++++++
+echo [[++++++++++
+exec lock 0 1 0 1
+echo  [++++++++++
+echo [[++++++++++
+exec lock 0 1 0 2
+echo  [xxxxxxxxxx
+echo [[xxxxxxxxxx
+exec lock 0 0 0 0
+echo [...........
+echo [
+exec lock 0 1 0 1
+echo  [++++++++++
+echo [[++++++++++
+exec lock 0 10 0 1
+echo       [+++++
+echo [[++++++++++
+exec lock 0 10 0 2
+echo       [xxxxx
+echo [[+++][xxxxx
+exec lock 0 0 0 0
+echo [...........
+echo [
+echo ** Right boundaries align
+exec lock 0 5 10 1
+echo     [++++++++]
+echo [   [++++++++]
+exec lock 0 4 11 1
+echo    [+++++++++]
+echo [  [+++++++++]
+exec lock 0 3 12 2
+echo   [xxxxxxxxxx]
+echo [ [xxxxxxxxxx]
+exec lock 0 0 15 2
+echo [xxxxxxxxxxxx]
+echo [xxxxxxxxxxxx]
+exec lock 0 0 0 0
+echo [.............
+echo [
+exec lock 0 5 0 1
+echo      [++++++++
+echo [    [++++++++
+exec lock 0 4 0 1
+echo     [+++++++++
+echo [   [+++++++++
+exec lock 0 3 0 2
+echo    [xxxxxxxxxx
+echo [  [xxxxxxxxxx
+exec lock 0 2 0 2
+echo   [xxxxxxxxxxx
+echo [ [xxxxxxxxxxx
+exec lock 0 0 0 2
+echo [xxxxxxxxxxxxx
+echo [xxxxxxxxxxxxx
+exec lock 0 0 0 0
+echo [.............
+echo [
+echo ** Consume locked region
+exec lock 0 5 10 1
+echo      [++++++++]
+echo [    [++++++++]
+exec lock 0 4 12 1
+echo     [++++++++++]
+echo [   [++++++++++]
+exec lock 0 2 16 1
+echo   [++++++++++++++]
+echo [ [++++++++++++++]
+exec lock 0 1 18 2
+echo  [xxxxxxxxxxxxxxxx]
+echo [[xxxxxxxxxxxxxxxx]
+exec lock 0 0 24 2
+echo [xxxxxxxxxxxxxxxxxxxxx]
+echo [xxxxxxxxxxxxxxxxxxxxx]
+exec lock 0 0 30 0
+echo [.........................]
+echo [
+exec lock 0 5 3 1
+echo      [++]
+echo [    [++]
+exec lock 0 10 5 1
+echo            [++++]
+echo [    [++]  [++++]
+exec lock 0 20 5 2
+echo                      [xxxx]
+echo [    [++]  [++++]    [xxxx]
+exec lock 0 4 30 2
+echo     [xxxxxxxxxxxxxxxxxxxxxxxxxx]
+echo [   [xxxxxxxxxxxxxxxxxxxxxxxxxx]
+exec lock 0 1 35 1
+echo   [++++++++++++++++++++++++++++++]
+echo [ [+[xxxxxxxxxxxxxxxxxxxxxxxxxx]+]
+exec lock 0 0 40 1
+echo [+++++++++++++++++++++++++++++++++++]
+echo [++][xxxxxxxxxxxxxxxxxxxxxxxxxx][+++]
+exec lock 0 0 0 0
+echo [....................................
+echo [
+exec lock 0 5 5 1
+echo      [+++]
+echo [    [+++]
+exec lock 0 4 0 1
+echo     [++++++]
+echo [   [++++++]
+exec lock 0 4 0 0
+echo     [..........
+echo [
+exec lock 0 5 3 1
+echo      [++]
+echo [    [++]
+exec lock 0 10 5 1
+echo              [++++]
+echo [    [++]    [++++]
+exec lock 0 0 0 1
+echo [++++++++++++++++++++
+echo [++++++++++++++++++++
+exec lock 0 0 0 0
+echo [....................
+echo [
+exec lock 0 5 3 1
+echo      [++]
+echo [    [++]
+exec lock 0 10 3 1
+echo             [++]
+echo [    [++]   [++]
+exec lock 0 4 0 1
+echo     [++++++++++++++
+echo [   [++++++++++++++
+exec lock 0 10 3 2
+echo             [**]
+echo [   [++++++][**][++
+exec lock 0 0 0 2
+echo [xxxxxxxxxxxxxxxxxx
+echo [xxxxxxxxxxxxxxxxxx
+exec lock 0 0 0 0
+echo [..................
+echo [
+echo * Our start is within the locked region or one byte after and our
+echo   end is after the end of the locked region.
+echo ** The regions are the same type: Merge into a single large region
+exec lock 0 5 5 1
+echo      [+++]
+echo [    [+++]
+exec lock 0 6 5 1
+echo       [+++]
+echo [    [++++]
+exec lock 0 8 8 1
+echo         [++++++]
+echo [    [+++++++++]
+exec lock 0 16 4 1
+echo                 [++]
+echo [    [+++++++++++++]
+exec lock 0 20 0 1
+echo                     [+++
+echo [    [++++++++++++++++++
+exec lock 0 5 16 0
+echo      [..............]
+echo [                    [+++
+exec lock 0 20 0 0
+echo                      [...
+echo [
+exec lock 0 6 6 2
+echo       [xxxx]
+echo [     [xxxx]
+exec lock 0 7 7 2
+echo        [xxxxx]
+echo [     [xxxxxx]
+exec lock 0 14 7 2
+echo               [xxxxx]
+echo [     [xxxxxxxxxxxxx]
+exec lock 0 21 0 2
+echo                      [xx
+echo [     [xxxxxxxxxxxxxxxxx
+exec lock 0 6 0 0
+echo       [.................
+echo [
+echo ** Different types just after the end of the locked region
+exec lock 0 1 3 1
+echo  [++]
+echo [[++]
+exec lock 0 4 3 2
+echo      [xx]
+echo [[++][xx]
+exec lock 0 7 3 1
+echo          [++]
+echo [[++][xx][++]
+exec lock 0 10 0 2
+echo              [xxx
+echo [[++][xx][++][xxx
+exec lock 0 5 0 0
+echo       [.........
+echo [[++]x
+exec lock 0 5 0 1
+echo       [+++
+echo [[++]x[+++
+exec lock 0 1 0 0
+echo  [...
+echo [
+echo ** New region consumes the intersection.
+exec lock 0 5 5 1
+echo      [+++]
+echo [    [+++]
+exec lock 0 8 6 2
+echo          [xxx]
+echo [    [++][xxx]
+exec lock 0 6 0 2
+echo         [xxxxxx
+echo [    [+][xxxxxx
+exec lock 0 5 0 0
+echo      [.........
+echo [
+echo ** New region is dominated
+exec lock 0 5 5 2
+echo      [xxx]
+echo [    [xxx]
+exec lock 0 8 6 1
+echo         [++++]
+echo [    [xxx][++]
+exec lock 0 6 0 1
+echo        [++++++
+echo [    [xxx][+++
+exec lock 0 5 0 0 
+echo      [........
+echo [
+echo * Our start falls before the locked region.  Our end falls just
+echo   before or with in the region (although we do not consume it)
+echo ** The regions are the same type: Merge into a single large region
+exec lock 0 10 5 1
+echo           [+++]
+echo [         [+++]
+exec lock 0 5 5 1
+echo      [+++]
+echo [    [++++++++]
+exec lock 0 4 4 1
+echo     [++]
+echo [   [+++++++++]
+exec lock 0 0 10 1
+echo [+++++++++]
+echo [+++++++++++++]
+exec lock 0 0 15 0
+echo [...............]
+echo [
+exec lock 0 10 0 1
+echo           [++++
+echo [         [++++
+exec lock 0 5 5 1
+echo      [+++]
+echo [    [+++++++++
+exec lock 0 4 1 1
+echo     +
+echo [   [++++++++++
+exec lock 0 0 0 1
+echo [++++++++++++++
+echo [++++++++++++++
+exec lock 0 0 0 0
+echo [....
+echo [
+exec lock 0 10 5 2
+echo           [xxx]
+echo [         [xxx]
+exec lock 0 5 5 2
+echo      [xxx]
+echo [    [xxxxxxxx]
+exec lock 0 4 4 2
+echo     [xx]
+echo [   [xxxxxxxxx]
+exec lock 0 0 10 2
+echo [xxxxxxxxx]
+echo [xxxxxxxxxxxxx]
+exec lock 0 0 15 0
+echo [...............]
+echo [
+exec lock 0 10 0 2
+echo           [xxxx
+echo [         [xxxx
+exec lock 0 5 5 2
+echo      [xxx]
+echo [    [xxxxxxxxx
+exec lock 0 4 1 2
+echo     x
+echo [   [xxxxxxxxxx
+exec lock 0 0 0 2
+echo [xxxxxxxxxxxxxx
+echo [xxxxxxxxxxxxxx
+exec lock 0 0 0 0
+echo [....
+echo [
+echo ** Different types just before the start of the locked region
+exec lock 0 5 5 1
+echo       [+++]
+echo [     [+++]
+exec lock 0 3 2 2
+echo    [x]
+echo [  [x][+++]
+exec lock 0 2 1 1
+echo   +
+echo [ +[x][+++]
+exec lock 0 1 0 2
+echo  [xxxx
+echo [[xxxx
+exec lock 0 0 1 1
+echo +
+echo +[xxxx
+exec lock 0 0 0 0
+echo [....
+echo [....
+exec lock 0 5 0 1
+echo      [++++
+echo [    [++++
+exec lock 0 0 5 2
+echo [xxxxxxxxx
+echo [xxxxxxxxx
+exec lock 0 0 0 0
+echo [....
+echo [
+echo ** New region consumes the intersection.
+exec lock 0 5 5 1
+echo      [+++]
+echo [    [+++]
+exec lock 0 4 3 2
+echo     [x]
+echo [   [x][+]
+exec lock 0 2 0 2
+echo    [xxxxxx
+echo [  [xxxxxx
+exec lock 0 0 0 0
+echo [....
+echo [
+exec lock 0 5 0 1
+echo      [++++++
+echo [    [++++++
+exec lock 0 4 5 2
+echo     [xxx]
+echo [   [xxx][++
+exec lock 0 4 0 0
+echo     [....
+echo [
+exec lock 0 5 0 1
+echo      [++++
+echo [    [++++
+exec lock 0 0 0 2
+echo [xxxxxxxxxx
+echo [xxxxxxxxxx
+exec lock 0 0 0 0
+echo [....
+echo [
+echo ** New region is dominated
+exec lock 0 5 5 2
+echo      [xxx]
+echo [    [xxx]
+exec lock 0 4 5 1
+echo     [+++]
+echo [   +[xxx]
+exec lock 0 0 0 0
+echo [...
+echo [
+exec lock 0 5 0 2
+echo     [xxxx
+echo [   [xxxx
+exec lock 0 0 0 1
+echo [++++++++
+echo [+++[xxxx
+exec lock 0 0 0 0
+echo [....
+echo [
diff --exclude configure --exclude CVS -urN 
hurd-20010412-snapshot/libfshelp-tests/locks.c 
hurd-20010412/libfshelp-tests/locks.c
--- hurd-20010412-snapshot/libfshelp-tests/locks.c      Thu Jan  1 01:00:00 1970
+++ hurd-20010412/libfshelp-tests/locks.c       Thu Apr 12 20:23:19 2001
@@ -0,0 +1,325 @@
+/* Test record locking.
+   Copyright (C) 2001 Free Software Foundation, Inc.
+
+   Written by Neal H Walfield <neal@cs.uml.edu>
+
+   This program is free software; you can redistribute it and/or
+   modify it under the terms of the GNU General Public License as
+   published by the Free Software Foundation; either version 2, or (at
+   your option) any later version.
+
+   This program is distributed in the hope that it will be useful, but
+   WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+   General Public License for more details.
+
+   You should have received a copy of the GNU General Public License
+   along with this program; if not, write to the Free Software
+   Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */
+
+#include "../libfshelp/fshelp.h"
+#include "../libfshelp/rlock.h"
+#include <errno.h>
+#include <error.h>
+#include <stdio.h>
+#include <string.h>
+
+#ifndef PEROPENS
+#define PEROPENS 10
+#endif
+
+struct rlock_box box;
+struct rlock_peropen peropens[PEROPENS];
+off_t pointers[PEROPENS];
+off_t file_size;
+
+struct command
+{
+  char *name;
+  int (*func)(char *cmds);
+  char *doc;
+};
+
+error_t cmd_help (char *);
+error_t cmd_comment (char *);
+error_t cmd_echo (char *);
+error_t cmd_lock (char *);
+error_t cmd_list (char *);
+error_t cmd_seek (char *);
+error_t cmd_exec (char *);
+
+struct command commands [] =
+  {
+    { "help", cmd_help, "Print this screen" },
+    { "#", cmd_comment, "Comment (Must _start_ the line)." },
+    { "echo", cmd_echo, "Echo the line." },
+    { "lock", cmd_lock, 
+         "po start length type\n"
+         "\ttype = { F_UNLCK=0, F_RDLCK,=1, F_WRLCK=2 }" },
+    { "list", cmd_list, "list all locks' status" },
+    { "seek", cmd_seek, "PO1 ... Print the position of the given po.\n"
+                       "\tPO1=N ... Seek a given po." },
+    { "exec", cmd_exec, "Execute a built in echoing the command."}
+  };
+
+error_t
+cmd_help (char *args)
+{
+  int i;
+  printf ("Commands:\n");
+  for (i = 0; i < sizeof (commands) / sizeof (struct command); i ++)
+    printf ("%s\t%s\n", commands[i].name, commands[i].doc);
+  return 0;
+}
+
+error_t
+cmd_comment (char *args)
+{
+  return 0;
+}
+
+error_t
+cmd_echo (char *args)
+{
+  printf ("%s", args);
+  return 0;
+}
+
+error_t
+cmd_lock (char *args)
+{
+  int po, type;
+  off_t start, len;
+  struct flock lock;
+  error_t err;
+
+  if (4 != sscanf (args, "%d %ld %ld %d", &po, &start, &len, &type))
+    {
+      printf ("Syntax error.\n");
+      return 0;
+    }
+
+  lock.l_type = type;
+  lock.l_whence = SEEK_CUR;
+  lock.l_start = start;
+  lock.l_len = len;
+
+  if (po < 0 || po >= PEROPENS)
+    {
+      printf ("Unknown peropen: %d.\n", po);
+      return 0;
+    }
+
+  switch (type)
+    {
+    case 0: lock.l_type = F_UNLCK; break;
+    case 1: lock.l_type = F_RDLCK; break;
+    case 2: lock.l_type = F_WRLCK; break;
+    default: printf ("Unknown type.\n"); return 0;
+    }
+
+  err= fshelp_rlock_tweak (&box, NULL, &peropens[po], O_RDWR,
+                          file_size, pointers[po], F_SETLK,
+                          &lock);
+  if (! err)
+    {
+      char buf[10];
+      sprintf (buf, "%d\n", po);
+      cmd_list (buf);
+    }
+  return err;
+}
+
+error_t
+cmd_list (char *args)
+{
+  char *end;
+
+  void dump (int i)
+    {
+      struct rlock_list *l;
+
+      printf ("%3d:", i);
+      for (l = *peropens[i].locks; l; l = l->po.next)
+        {
+         printf ("\tStart = %4ld; Length = %4ld; Type = ", l->start, l->len);
+         switch (l->type)
+           {
+           case F_RDLCK: printf ("F_RDLCK"); break;
+           case F_WRLCK: printf ("F_WRLCK"); break;
+           case F_UNLCK: printf ("F_UNLCK"); break;
+           default: printf ("UNKNOWN"); break;
+           }
+         printf ("\n");
+       }
+
+      if (*peropens[i].locks == NULL)
+       printf ("\n");
+    }
+
+  while (*args == ' ')
+    args ++;
+
+  if (*args == '\n' || *args == '\0')
+    {
+      int i;
+
+      for (i = 0; i < PEROPENS; i ++)
+       dump (i);
+      return 0;
+    }
+
+  while (1)
+    {
+      int p = strtol (args, &end, 0);
+      if (end == args)
+        {
+         printf ("Syntax error.\n");
+         return 0;
+       }
+
+      if (p < 0 || p > PEROPENS)
+       printf ("%3d:\tOut of range.", p);
+      else
+       dump (p);
+
+      while (*end == ' ')
+       end ++;
+
+      if (*end == '\n' || *end == '\0')
+       return 0;
+      args = end;
+    }
+}
+
+error_t
+cmd_seek (char *args)
+{
+  char *end;
+  int p;
+
+  while (*args == ' ')
+    args ++;
+
+  if (*args == '\n' || *args == '\0')
+    {
+      int i;
+      for (i = 0; i < PEROPENS; i ++)
+        printf ("%3d: %ld\n", i, pointers[i]);
+      return 0;
+    }
+
+  while (1)
+    {
+      int set = 0;
+      int seek_to = 0;
+
+      p = strtol (args, &end, 0);
+      if (end == args)
+        {
+         printf ("Syntax error.\n");
+         return 0;
+       }
+
+      if (*end == '=')
+        {
+         set = 1;
+         args = end + 1;
+         seek_to = strtol (args, &end, 0);
+         if (end == args)
+           {
+             printf ("Syntax error.\n");
+             return 0;
+           }
+       }
+
+      if (p < 0 || p > PEROPENS)
+       printf ("%3d: unknown peropen\n", p);
+      else
+        {
+          printf ("%3d: %ld", p, pointers[p]);
+         if (set)
+           printf (" => %ld\n", pointers[p] = seek_to);
+         else
+           printf ("\n");
+       }
+
+      while (*end == ' ')
+       end ++;
+      if (*end == '\0' || *end == '\n')
+        return 0;
+      args = end;
+    }
+}
+
+error_t
+interpret (char *buffer)
+{
+  int i;
+
+  while (*buffer == ' ')
+    buffer ++;
+
+  if (*buffer == '\n')
+    return 0;
+
+  for (i = 0; i < sizeof (commands) / sizeof (struct command); i ++)
+  if (strncmp (commands[i].name, buffer, strlen (commands[i].name)) == 0)
+    {
+      error_t err;
+      err = commands[i].func (buffer + strlen (commands[i].name) + 1);
+      if (err)
+       printf ("%s\n", strerror (err));
+      return err;
+    }
+
+  printf ("Unknown command.\n");
+  return 0;
+}
+
+error_t
+cmd_exec (char *arg)
+{
+  printf ("%s", arg);
+  interpret (arg);
+  return 0;
+}
+
+int main (int argc, char *argv[])
+{
+  int i;
+
+  if (argc != 1)
+    {
+      printf ("Usage: %s\n"
+             "\tType `help' at the prompt.\n"
+             "\tUsed to test the record locking functions in libfshelp\n",
+             argv[0]);
+      return 1;
+    }
+
+  fshelp_rlock_init (&box);
+  for (i = 0; i < PEROPENS; i ++)
+    fshelp_rlock_po_init (&peropens[i]);
+
+  while (! feof (stdin))
+    {
+      char b[1024];
+
+      printf ("> ");
+      fflush (stdout);
+
+      if (! fgets (b, sizeof (b), stdin))
+       {
+         if (feof (stdin))
+           break;
+         else
+           continue;
+       }
+
+      interpret (b);
+    }
+
+  printf ("\n");
+  return 0;
+}
diff --exclude configure --exclude CVS -urN 
hurd-20010412-snapshot/libfshelp-tests/race.c 
hurd-20010412/libfshelp-tests/race.c
--- hurd-20010412-snapshot/libfshelp-tests/race.c       Thu Jan  1 01:00:00 1970
+++ hurd-20010412/libfshelp-tests/race.c        Thu Apr 12 20:23:19 2001
@@ -0,0 +1,82 @@
+/* Test races in the record locking code.
+   Copyright (C) 2001 Free Software Foundation, Inc.
+
+   Written by Neal H Walfield <neal@cs.uml.edu>
+
+   This program is free software; you can redistribute it and/or
+   modify it under the terms of the GNU General Public License as
+   published by the Free Software Foundation; either version 2, or (at
+   your option) any later version.
+
+   This program is distributed in the hope that it will be useful, but
+   WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+   General Public License for more details.
+
+   You should have received a copy of the GNU General Public License
+   along with this program; if not, write to the Free Software
+   Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */
+
+#include <stdio.h>
+#include <error.h>
+#include <fcntl.h>
+#include <unistd.h>
+#include <hurd.h>
+#include "fs_U.h"
+#include "io_U.h"
+
+int main (int argc, char **argv)
+{
+  error_t err;
+  struct flock lock;
+  int fd;
+  int i;
+  int v;
+  int blocked = 0;
+  char buf[10] = "";
+  char *bufp;
+
+  if (argc != 4)
+    error (1, 0, "Usage: %s file start len", argv[0]);
+
+  lock.l_whence = SEEK_SET;
+  lock.l_start = atoi (argv[2]);
+  lock.l_len = atoi (argv[3]);
+  
+  fd = file_name_lookup (argv[1], O_READ | O_WRITE | O_CREAT, 0666);
+  if (fd == MACH_PORT_NULL)
+    error (1, errno, "file_name_lookup");
+
+  for (i = 0; i < 10000; i ++)
+    {
+      lock.l_type = F_WRLCK;
+      err = file_record_lock (fd, F_SETLK, &lock);
+      if (err)
+        {
+         blocked ++;
+          err = file_record_lock (fd, F_SETLKW, &lock);
+       }
+      if (err)
+        error (1, err, "file_record_lock");
+
+      v = sizeof (buf);
+      bufp = buf;
+      io_read (fd, &bufp, &v, 0, v);
+
+      v = atoi (bufp);
+      sprintf (buf, "%d\n", v + 1);
+
+      v = 10;
+      io_write (fd, buf, sizeof (buf), 0, &v);
+      if (v == 0)
+        error (1, errno, "write (%d)", i);
+
+      lock.l_type = F_UNLCK;
+      file_record_lock (fd, F_SETLK, &lock);
+    }
+
+  mach_port_deallocate (mach_task_self (), fd);
+
+  printf ("Was blocked %d times\n", blocked);
+  return 0;
+}
diff --exclude configure --exclude CVS -urN 
hurd-20010412-snapshot/libnetfs/ChangeLog hurd-20010412/libnetfs/ChangeLog
--- hurd-20010412-snapshot/libnetfs/ChangeLog   Sun Apr  1 23:33:03 2001
+++ hurd-20010412/libnetfs/ChangeLog    Thu Apr 12 20:27:24 2001
@@ -1,3 +1,9 @@
+2001-04-11  Neal H Walfield  <neal@cs.uml.edu>
+
+       * file-record-lock.c: New file.  Implement
+       netfs_S_file_record_lock.
+       * Makefile (SRCS): Add file-record-lock.c
+
 2001-04-01  Roland McGrath  <roland@frob.com>
 
        * Makefile (FSYSSRCS): Add fsys-goaway.c.
diff --exclude configure --exclude CVS -urN 
hurd-20010412-snapshot/libnetfs/Makefile hurd-20010412/libnetfs/Makefile
--- hurd-20010412-snapshot/libnetfs/Makefile    Sun Apr  1 23:32:25 2001
+++ hurd-20010412/libnetfs/Makefile     Fri Apr 13 16:03:42 2001
@@ -1,5 +1,5 @@
 # 
-#   Copyright (C) 1995, 1996, 1997, 1999, 2001 Free Software Foundation
+#   Copyright (C) 1995,96,97,99,2001 Free Software Foundation
 #   Written by Michael I. Bushnell.
 #
 #   This file is part of the GNU Hurd.
@@ -30,7 +30,7 @@
        file-get-translator.c file-getcontrol.c file-getlinknode.c \
        file-lock-stat.c file-lock.c file-set-size.c \
        file-set-translator.c file-statfs.c file-sync.c file-syncfs.c \
-       file-utimes.c file-reparent.c fsstubs.c
+       file-utimes.c file-record-lock.c file-reparent.c fsstubs.c
 
 IOSRCS=        io-read.c io-readable.c io-seek.c io-write.c io-stat.c 
io-async.c     \
        io-set-all-openmodes.c io-get-openmodes.c io-set-some-openmodes.c     \
diff --exclude configure --exclude CVS -urN 
hurd-20010412-snapshot/libnetfs/file-record-lock.c 
hurd-20010412/libnetfs/file-record-lock.c
--- hurd-20010412-snapshot/libnetfs/file-record-lock.c  Thu Jan  1 01:00:00 1970
+++ hurd-20010412/libnetfs/file-record-lock.c   Thu Apr 12 20:14:31 2001
@@ -0,0 +1,31 @@
+/* 
+   Copyright (C) 2001 Free Software Foundation, Inc.
+
+   Written by Neal H Walfield <neal@cs.uml.edu>
+
+   This file is part of the GNU Hurd.
+
+   The GNU Hurd is free software; you can redistribute it and/or
+   modify it under the terms of the GNU General Public License as
+   published by the Free Software Foundation; either version 2, or (at
+   your option) any later version.
+
+   The GNU Hurd is distributed in the hope that it will be useful, but
+   WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+   General Public License for more details.
+
+   You should have received a copy of the GNU General Public License
+   along with this program; if not, write to the Free Software
+   Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111, USA. */
+
+#include "netfs.h"
+#include "fs_S.h"
+
+error_t
+netfs_S_file_record_lock (struct protid *cred,
+                         int cmd,
+                         struct flock *flock)
+{
+  return EOPNOTSUPP;
+}
diff --exclude configure --exclude CVS -urN 
hurd-20010412-snapshot/libtrivfs/ChangeLog hurd-20010412/libtrivfs/ChangeLog
--- hurd-20010412-snapshot/libtrivfs/ChangeLog  Fri Mar 17 18:22:56 2000
+++ hurd-20010412/libtrivfs/ChangeLog   Thu Apr 12 20:25:59 2001
@@ -1,3 +1,9 @@
+2001-04-11  Neal H Walfield  <neal@cs.uml.edu>
+
+       * file-record-lock.c: New file.  Implement
+       trivfs_S_file_record_lock.
+       * Makefile (SRCS): Add file-record-lock.c
+
 2000-03-17  Thomas Bushnell, BSG  <tb@mit.edu>
 
        * startup.c (trivfs_startup): Don't use MAKE_SEND in Hurd RPC.
diff --exclude configure --exclude CVS -urN 
hurd-20010412-snapshot/libtrivfs/Makefile hurd-20010412/libtrivfs/Makefile
--- hurd-20010412-snapshot/libtrivfs/Makefile   Mon Sep 13 08:34:06 1999
+++ hurd-20010412/libtrivfs/Makefile    Fri Apr 13 16:03:23 2001
@@ -1,5 +1,5 @@
 # 
-#   Copyright (C) 1994, 1995, 1996, 1997, 1999 Free Software Foundation
+#   Copyright (C) 1994,95,96,97,99,2001 Free Software Foundation
 #
 #   This program is free software; you can redistribute it and/or
 #   modify it under the terms of the GNU General Public License as
@@ -25,7 +25,7 @@
        file-getlinknode.c file-lock.c file-set-trans.c file-statfs.c \
        file-sync.c file-syncfs.c file-set-size.c file-utimes.c file-exec.c \
        file-access.c dir-chg.c file-chg.c file-inv.c file-get-storage-info.c \
-       file-get-fs-options.c file-reparent.c
+       file-get-fs-options.c file-record-lock.c file-reparent.c
 
 IOSRCS=io-async-icky.c io-async.c io-duplicate.c io-map.c io-modes-get.c \
        io-modes-off.c io-modes-on.c io-modes-set.c io-owner-get.c \
diff --exclude configure --exclude CVS -urN 
hurd-20010412-snapshot/libtrivfs/file-record-lock.c 
hurd-20010412/libtrivfs/file-record-lock.c
--- hurd-20010412-snapshot/libtrivfs/file-record-lock.c Thu Jan  1 01:00:00 1970
+++ hurd-20010412/libtrivfs/file-record-lock.c  Thu Apr 12 20:19:12 2001
@@ -0,0 +1,28 @@
+/* 
+   Copyright (C) 2001 Free Software Foundation
+
+   This program is free software; you can redistribute it and/or
+   modify it under the terms of the GNU General Public License as
+   published by the Free Software Foundation; either version 2, or (at
+   your option) any later version.
+
+   This program is distributed in the hope that it will be useful, but
+   WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+   General Public License for more details.
+
+   You should have received a copy of the GNU General Public License
+   along with this program; if not, write to the Free Software
+   Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */
+
+#include "priv.h"
+#include "fs_S.h"
+
+kern_return_t
+trivfs_S_file_record_lock (struct trivfs_protid *cred,
+                          mach_port_t reply,
+                          mach_msg_type_name_t reply_type,
+                          int cmd, struct flock *lock)
+{
+  return EOPNOTSUPP;
+}

Attachment: pgpSMsBf8F_KK.pgp
Description: PGP signature


reply via email to

[Prev in Thread] Current Thread [Next in Thread]