Hello,
Attached is the first half of the patches for file record locking:
libfshelp_rlock.patch
libdiskfs_file_record_lock.patch
libtrivfs_file_record_lock.patch
The second part is following in a subsequent email:
libnetfs_file_record_lock.patch
pflocal_fs.c.patch
hurd_add_RPC.patch
libfshelp-tests_rlock.patch
fcntl.diff
The hurd patches are made against Debian version 0.9.git20181030-3 and
the glibc patch against 2.28-3. The patches should preferably be
applied in the same order as above.
All patches contains preliminary changelog entries.
Thanks!
libdiskfs/ChangeLog
2018-12-07 Svante Signell <svante.sign...@gmail.com>
* Update copyright years.
* dir-lookup.c(diskfs_S_dir_lookup): Call fshelp_rlock_tweak()
with new last argument rendezvous = MACH_PORT_NULL.
* file-lock.c(diskfs_S_file_lock): Likewise.
* file-record-lock.c(diskfs_S_file_record_lock): Likewise.
(diskfs_S_file_record_lock): Add new argument mach_port_t rendezvous.
2017-01-05 Svante Signell <svante.sign...@gmail.com>
* Update copyright years and headers.
2016-05-23 Svante Signell <svante.sign...@gmail.com>
* define temporary CPP_FLAGS until glibc is updated
* file-lock-stat.c: Port from cthreads to libpthread.
* file-lock.c: Likewise.
* file-record-lock: Likewise.
2001-04-11 Neal H Walfield <n...@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_rlock_tweak
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.
Index: hurd-0.9.git20181030-3.3/libdiskfs/Makefile
===================================================================
--- hurd-0.9.git20181030-3.3.orig/libdiskfs/Makefile
+++ hurd-0.9.git20181030-3.3/libdiskfs/Makefile
@@ -1,4 +1,4 @@
-# Copyright (C) 1994,95,96,97,98,99,2000,01,2006,2012
+# Copyright (C) 1994,95,96,97,98,99,2000,01,2006,2012,2016-2018
# Free Software Foundation, Inc.
#
# This program is free software; you can redistribute it and/or
@@ -12,8 +12,7 @@
# 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.
+# along with the GNU Hurd. If not, see <http://www.gnu.org/licenses/>.
dir := libdiskfs
makemode := library
@@ -26,7 +25,8 @@ FSSRCS= dir-chg.c dir-link.c dir-lookup.
file-get-trans.c file-get-transcntl.c file-getcontrol.c \
file-getfh.c file-getlinknode.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 \
@@ -72,4 +72,10 @@ ifsock-MIGSFLAGS = -imacros $(srcdir)/fs
exec_startup-MIGSFLAGS = -imacros $(srcdir)/fsmutations.h
MIGCOMSFLAGS = -prefix diskfs_
+# Define the 64 bit versions of the second argument to fcntl()
+# Can safely be removed when glibc is updated
+EXTRA_CPP_FLAGS= -DF_GETLK64=10 -DF_SETLK64=11 -DF_SETLKW64=12
+dir-lookup-CPPFLAGS += $(EXTRA_CPP_FLAGS)
+file-lock-CPPFLAGS += $(EXTRA_CPP_FLAGS)
+
include ../Makeconf
Index: hurd-0.9.git20181030-3.3/libdiskfs/diskfs.h
===================================================================
--- hurd-0.9.git20181030-3.3.orig/libdiskfs/diskfs.h
+++ hurd-0.9.git20181030-3.3/libdiskfs/diskfs.h
@@ -1,7 +1,7 @@
/* Definitions for fileserver helper functions
- Copyright (C) 1994, 1995, 1996, 1997, 1998, 1999, 2001, 2002, 2007, 2008,
- 2009, 2013 Free Software Foundation, Inc.
+ Copyright (C) 1994-1999, 2001, 2002, 2007-2009, 2013-2018
+ 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
@@ -14,8 +14,7 @@
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. */
+ along with the GNU Hurd. If not, see <http://www.gnu.org/licenses/>. */
#ifndef _HURD_DISKFS
#define _HURD_DISKFS
@@ -57,8 +56,8 @@ struct protid
/* One of these is created for each node opened by dir_lookup. */
struct peropen
{
- off_t filepointer;
- int lock_status;
+ loff_t filepointer;
+ struct rlock_peropen lock_status;
refcount_t refcnt;
int openstat;
@@ -113,7 +112,7 @@ struct node
struct transbox transbox;
- struct lock_box userlock;
+ struct rlock_box userlock;
struct conch conch;
Index: hurd-0.9.git20181030-3.3/libdiskfs/dir-lookup.c
===================================================================
--- hurd-0.9.git20181030-3.3.orig/libdiskfs/dir-lookup.c
+++ hurd-0.9.git20181030-3.3/libdiskfs/dir-lookup.c
@@ -1,6 +1,7 @@
/* libdiskfs implementation of fs.defs:dir_lookup
- Copyright (C) 1992, 1993, 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001,
- 2002, 2008, 2013, 2014 Free Software Foundation, Inc.
+
+ Copyright (C) 1992-2002, 2008, 2013-2018
+ 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
@@ -13,8 +14,7 @@
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. */
+ along with the GNU Hurd. If not, see <http://www.gnu.org/licenses/>. */
#include <stdio.h>
#include <fcntl.h>
@@ -499,12 +499,28 @@ diskfs_S_dir_lookup (struct protid *dirc
if (! err)
{
newpo = 0;
+ mach_port_t rendezvous = MACH_PORT_NULL;
+ struct flock64 lock =
+ {
+ l_start: 0,
+ l_len: 0,
+ l_whence: SEEK_SET
+ };
+
if (flags & O_EXLOCK)
- err = fshelp_acquire_lock (&np->userlock, &newpi->po->lock_status,
- &np->lock, LOCK_EX);
+ {
+ lock.l_type = F_WRLCK;
+ err = fshelp_rlock_tweak (&np->userlock, &np->lock,
+ &newpi->po->lock_status, flags, 0, 0,
+ F_SETLK64, &lock, rendezvous);
+ }
else if (flags & O_SHLOCK)
- err = fshelp_acquire_lock (&np->userlock, &newpi->po->lock_status,
- &np->lock, LOCK_SH);
+ {
+ lock.l_type = F_RDLCK;
+ err = fshelp_rlock_tweak (&np->userlock, &np->lock,
+ &newpi->po->lock_status, flags, 0, 0,
+ F_SETLK64, &lock, rendezvous);
+ }
}
if (! err)
Index: hurd-0.9.git20181030-3.3/libdiskfs/file-lock-stat.c
===================================================================
--- hurd-0.9.git20181030-3.3.orig/libdiskfs/file-lock-stat.c
+++ hurd-0.9.git20181030-3.3/libdiskfs/file-lock-stat.c
@@ -1,38 +1,42 @@
-/*
- Copyright (C) 1994, 1995 Free Software Foundation
+/* Copyright (C) 2001, 2014-2018 Free Software Foundation, Inc.
- This file is part of the GNU Hurd.
+ Written by Neal H Walfield <n...@cs.uml.edu>
- 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.
+ 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 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. */
+ along with the GNU Hurd. If not, see <http://www.gnu.org/licenses/>. */
#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;
-
- pthread_mutex_lock (&cred->po->np->lock);
- *mystatus = cred->po->lock_status;
- *otherstatus = cred->po->np->userlock.type;
- pthread_mutex_unlock (&cred->po->np->lock);
+
+ node = cred->po->np;
+
+ pthread_mutex_lock (&node->lock);
+ *mystatus = fshelp_rlock_peropen_status (&cred->po->lock_status);
+ *otherstatus = fshelp_rlock_node_status (&node->userlock);
+ pthread_mutex_unlock (&node->lock);
+
return 0;
}
Index: hurd-0.9.git20181030-3.3/libdiskfs/file-lock.c
===================================================================
--- hurd-0.9.git20181030-3.3.orig/libdiskfs/file-lock.c
+++ hurd-0.9.git20181030-3.3/libdiskfs/file-lock.c
@@ -1,36 +1,60 @@
-/*
- Copyright (C) 1993, 1994 Free Software Foundation
+/* Copyright (C) 2001, 2014-2017 Free Software Foundation, Inc.
- This file is part of the GNU Hurd.
+ Written by Neal H Walfield <n...@cs.uml.edu>
- 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.
+ 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 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. */
+ along with the GNU Hurd. If not, see <http://www.gnu.org/licenses/>. */
#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 flock64 lock;
+ struct node *node;
+ int openstat = cred->po->openstat;
+ mach_port_t rendezvous = MACH_PORT_NULL;
+
+ if (! cred)
return EOPNOTSUPP;
- pthread_mutex_lock (&cred->po->np->lock);
- err = fshelp_acquire_lock (&cred->po->np->userlock, &cred->po->lock_status,
- &cred->po->np->lock, flags);
- pthread_mutex_unlock (&cred->po->np->lock);
+
+ lock.l_whence = SEEK_SET;
+ lock.l_start = 0;
+ 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;
+ /* XXX: Fix for flock(2) calling fcntl(2) */
+ if ((openstat & O_RDONLY) && !(openstat & O_WRONLY)) openstat |= O_WRONLY;
+ if (!(openstat & O_RDONLY) && (openstat & O_WRONLY)) openstat |= O_RDONLY;
+ pthread_mutex_lock (&node->lock);
+ err = fshelp_rlock_tweak (&node->userlock, &node->lock,
+ &cred->po->lock_status, openstat,
+ 0, 0, flags & LOCK_NB ? F_SETLK64 : F_SETLKW64,
+ &lock, rendezvous);
+ pthread_mutex_unlock (&node->lock);
return err;
}
Index: hurd-0.9.git20181030-3.3/libdiskfs/file-record-lock.c
===================================================================
--- /dev/null
+++ hurd-0.9.git20181030-3.3/libdiskfs/file-record-lock.c
@@ -0,0 +1,48 @@
+/* Copyright (C) 2001, 2014-2018 Free Software Foundation, Inc.
+
+ Written by Neal H Walfield <n...@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 the GNU Hurd. If not, see <http://www.gnu.org/licenses/>. */
+
+#include "priv.h"
+#include "diskfs.h"
+#include "fs_S.h"
+
+#include <errno.h>
+#include <hurd/fshelp.h>
+
+error_t
+diskfs_S_file_record_lock (struct protid *cred,
+ int cmd,
+ struct flock64 *lock,
+ mach_port_t rendezvous)
+{
+ struct node *node;
+ error_t err;
+
+ if (! cred)
+ return EOPNOTSUPP;
+
+ /* XXX: Call with non-null for per process locking*/
+ rendezvous = MACH_PORT_NULL;
+
+ node = cred->po->np;
+ pthread_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, rendezvous);
+ pthread_mutex_unlock (&node->lock);
+ return err;
+}
Index: hurd-0.9.git20181030-3.3/libdiskfs/node-make.c
===================================================================
--- hurd-0.9.git20181030-3.3.orig/libdiskfs/node-make.c
+++ hurd-0.9.git20181030-3.3/libdiskfs/node-make.c
@@ -1,5 +1,5 @@
/*
- Copyright (C) 1994,95,96,2002 Free Software Foundation, Inc.
+ Copyright (C) 1994-1996, 2002, 2014-2018 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
@@ -12,8 +12,7 @@
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. */
+ along with the GNU Hurd. If not, see <http://www.gnu.org/licenses/>. */
#include "priv.h"
#include <fcntl.h>
@@ -41,7 +40,7 @@ init_node (struct node *np, struct diskn
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;
}
Index: hurd-0.9.git20181030-3.3/libdiskfs/peropen-make.c
===================================================================
--- hurd-0.9.git20181030-3.3.orig/libdiskfs/peropen-make.c
+++ hurd-0.9.git20181030-3.3/libdiskfs/peropen-make.c
@@ -1,5 +1,5 @@
/*
- Copyright (C) 1994,97,99,2001,02 Free Software Foundation
+ Copyright (C) 1994,97,99,2001,02,2014-2018 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
@@ -12,11 +12,13 @@
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. */
+ along with the GNU Hurd. If not, see <http://www.gnu.org/licenses/>. */
#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. */
@@ -24,13 +26,17 @@ error_t
diskfs_make_peropen (struct node *np, int flags, struct peropen *context,
struct peropen **ppo)
{
+ error_t err;
struct peropen *po = *ppo = malloc (sizeof (struct peropen));
if (! po)
return ENOMEM;
+ err = fshelp_rlock_po_init (&po->lock_status);
+ if (err)
+ return err;
+
po->filepointer = 0;
- po->lock_status = LOCK_UN;
refcount_init (&po->refcnt, 1);
po->openstat = flags;
po->np = np;
Index: hurd-0.9.git20181030-3.3/libdiskfs/peropen-rele.c
===================================================================
--- hurd-0.9.git20181030-3.3.orig/libdiskfs/peropen-rele.c
+++ hurd-0.9.git20181030-3.3/libdiskfs/peropen-rele.c
@@ -1,5 +1,5 @@
-/*
- Copyright (C) 1994, 1996, 1997 Free Software Foundation
+/*
+ Copyright (C) 1994, 1996, 1997, 2014-2018 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
@@ -12,8 +12,7 @@
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. */
+ along with the GNU Hurd. If not, see <http://www.gnu.org/licenses/>. */
#include <sys/file.h>
#include "priv.h"
@@ -33,14 +32,9 @@ diskfs_release_peropen (struct peropen *
if (po->shadow_root_parent)
mach_port_deallocate (mach_task_self (), po->shadow_root_parent);
-
- if (po->lock_status != LOCK_UN)
- {
- pthread_mutex_lock (&po->np->lock);
- fshelp_acquire_lock (&po->np->userlock, &po->lock_status,
- &po->np->lock, LOCK_UN);
- diskfs_nput (po->np);
- }
+ fshelp_rlock_drop_peropen (&po->lock_status);
+ if (fshelp_rlock_peropen_status(&po->lock_status) != LOCK_UN)
+ diskfs_nput (po->np);
else
diskfs_nrele (po->np);
libfshelp/ChangeLog
2018-12-07 Svante Signell <svante.sign...@gmail.com>
* Update copyright years.
* rlock-tweak.c(fshelp-rlock_tweak): Add new argument:
mach_port_t rendezvous. Calls using MACH_PORT_NULL indicates
per opened file locking. Calls with !MACH_PORT_NULL indicates
per process locking. l_pid is set to -1 when a conflicting
lock is taken by another process, like BSD does. This and per
process locking will be fixed by new proc RPCs implementing
proc_{server,user}_identify.
2017-01-05 Svante Signell <svante.sign...@gmail.com>
* Update copyright years and headers.
* rlock_tweak.c: l_pid is set to 0 when a conflicting lock
is taken by another process. Will be fixed by new proc RPCs.
2016-05-23 Svante Signell <svante.sign...@gmail.com>
* Makefile: Link with pthread
* define temporary CPP_FLAGS until glibc is updated
* rlock-drop-peropen.c: Port from cthreads to libpthread.
* rlock-tweak.c: Likewise
* fshelp.h: Likewise
* rlock.h: Likewise
2001-04-12 Neal H Walfield <n...@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.
Index: hurd-0.9.git20181030-3.3/libfshelp/Makefile
===================================================================
--- hurd-0.9.git20181030-3.3.orig/libfshelp/Makefile
+++ hurd-0.9.git20181030-3.3/libfshelp/Makefile
@@ -1,5 +1,5 @@
-# Copyright (C) 1994, 95, 96, 98, 1999, 2006, 2012 Free Software Foundation,
-# Inc.
+# Copyright (C) 1994, 95, 96, 98, 1999, 2006, 2012, 2016-2018
+# 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
@@ -12,8 +12,7 @@
# 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.
+# along with the GNU Hurd. If not, see <http://www.gnu.org/licenses/>.
dir := libfshelp
makemode := library
@@ -30,11 +29,19 @@ SRCS = lock-acquire.c lock-init.c \
get-identity.c \
perms-isowner.c perms-iscontroller.c perms-access.c \
perms-checkdirmod.c \
- touch.c
-installhdrs = fshelp.h
+ touch.c \
+ extern-inline.c \
+ rlock-drop-peropen.c rlock-tweak.c rlock-status.c
+
+installhdrs = fshelp.h rlock.h
HURDLIBS = shouldbeinlibc iohelp ports ihash
LDLIBS += -lpthread
OBJS = $(subst .c,.o,$(SRCS))
+# Define the 64 bit versions of the second argument to fcntl()
+# Can safely be removed when glibc is updated
+EXTRA_CPP_FLAGS= -DF_GETLK64=10 -DF_SETLK64=11 -DF_SETLKW64=12
+rlock-tweak-CPPFLAGS += $(EXTRA_CPP_FLAGS)
+
include ../Makeconf
Index: hurd-0.9.git20181030-3.3/libfshelp/fshelp.h
===================================================================
--- hurd-0.9.git20181030-3.3.orig/libfshelp/fshelp.h
+++ hurd-0.9.git20181030-3.3/libfshelp/fshelp.h
@@ -1,6 +1,6 @@
/* FS helper library definitions
- Copyright (C) 1994,95,96,97,98,99,2000,01,02,13,14
- Free Software Foundation, Inc.
+
+ Copyright (C) 1994-2002, 2013-2018 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
@@ -13,24 +13,29 @@
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. */
+ along with the GNU Hurd. If not, see <http://www.gnu.org/licenses/>. */
#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 <pthread.h>
#include <hurd/iohelp.h>
#include <sys/stat.h>
#include <maptime.h>
+#include <fcntl.h>
/* Keeping track of active translators */
@@ -228,7 +233,11 @@ struct lock_box
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
@@ -236,11 +245,71 @@ struct lock_box
error_t fshelp_acquire_lock (struct lock_box *box, int *user,
pthread_mutex_t *mut, int flags);
+
+/* Record locking. */
-/* 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);
+/* Unique to a node; initialize with fshelp_rlock_init. */
+struct rlock_box
+{
+ struct rlock_list *locks; /* List of locks on the file. */
+};
+
+/* 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_GETLK64,
+ F_SETLK64, F_SETLKW64. LOCK is passed by the user and is as defined by
+ <fcntl.h>. */
+error_t fshelp_rlock_tweak (struct rlock_box *box,
+ pthread_mutex_t *mutex,
+ struct rlock_peropen *po, int open_mode,
+ loff_t size, loff_t curpointer, int cmd,
+ struct flock64 *lock, mach_port_t rendezvous);
+
+/* 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
+ restrictive 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 */
Index: hurd-0.9.git20181030-3.3/libfshelp/rlock-drop-peropen.c
===================================================================
--- /dev/null
+++ hurd-0.9.git20181030-3.3/libfshelp/rlock-drop-peropen.c
@@ -0,0 +1,48 @@
+/*
+ Copyright (C) 2001, 2014-2018 Free Software Foundation
+
+ Written by Neal H Walfield <n...@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. If not, see <http://www.gnu.org/licenses/>. */
+
+#include "fshelp.h"
+#include "rlock.h"
+
+#include <stdlib.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;
+ pthread_cond_broadcast (&l->wait);
+ }
+
+ list_unlink (node, l);
+
+ t = l->po.next;
+ free (l);
+ }
+
+ return 0;
+}
Index: hurd-0.9.git20181030-3.3/libfshelp/rlock-status.c
===================================================================
--- /dev/null
+++ hurd-0.9.git20181030-3.3/libfshelp/rlock-status.c
@@ -0,0 +1,53 @@
+/* Copyright (C) 2001, 2014-2018 Free Software Foundation, Inc.
+
+ Written by Neal H Walfield <n...@cs.uml.edu>
+
+ This file is part of the GNU Hurd.
+
+ 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 the GNU Hurd. If not, see <http://www.gnu.org/licenses/>. */
+
+#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;
+}
+
Index: hurd-0.9.git20181030-3.3/libfshelp/rlock-tweak.c
===================================================================
--- /dev/null
+++ hurd-0.9.git20181030-3.3/libfshelp/rlock-tweak.c
@@ -0,0 +1,553 @@
+/*
+ Copyright (C) 2001, 2014-2018 Free Software Foundation
+
+ Written by Neal H Walfield <n...@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. If not, see <http://www.gnu.org/licenses/>. */
+
+#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 <hurd.h>
+#include <hurd/process.h>
+
+static inline long overlap (loff_t start, loff_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, pthread_mutex_t *mutex,
+ struct rlock_peropen *po, int open_mode,
+ loff_t obj_size, loff_t cur_pointer, int cmd,
+ struct flock64 *lock, mach_port_t rendezvous)
+{
+ inline struct rlock_list *
+ gen_lock (loff_t start, loff_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)
+ pthread_cond_broadcast (&l->wait);
+
+ free (l);
+ }
+
+ error_t
+ unlock_region (loff_t start, loff_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;
+ pthread_cond_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;
+ pthread_cond_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 (loff_t start, loff_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 (loff_t start, loff_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)
+ {
+ loff_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. */
+ {
+ loff_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;
+ loff_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;
+ loff_t start;
+ loff_t len;
+
+ if (rendezvous != MACH_PORT_NULL)
+ return EOPNOTSUPP;
+
+ if (cmd != F_GETLK64
+ && cmd != F_SETLK64
+ && cmd != F_SETLKW64)
+ 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_SETLKW64)
+ /* If we are unlocking a region, map F_SETLKW64 to F_SETLK64. */
+ cmd = F_SETLK64;
+ else if (cmd == F_GETLK64)
+ /* 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_SETLK64 && lock->l_type == F_UNLCK)
+ return unlock_region (start, len);
+
+retry:
+ e = find_conflict (start, len, lock->l_type);
+
+ if (cmd == F_GETLK64)
+ {
+ if (e)
+ {
+ lock->l_type = e->type;
+ lock->l_start = e->start;
+ lock->l_whence = SEEK_SET;
+ lock->l_len = e->len;
+ /* XXX: This will be fixed when the proc_{user,server}_identify
+ RPCs are implemented */
+ lock->l_pid = -1;
+ return 0;
+ }
+ else
+ {
+ lock->l_type = F_UNLCK;
+ return 0;
+ }
+ }
+ else
+ {
+ assert (cmd == F_SETLK64 || cmd == F_SETLKW64);
+
+ if (! e)
+ return merge_in (start, len, lock->l_type);
+ else
+ {
+ if (cmd == F_SETLKW64)
+ {
+ e->waiting = 1;
+ if (pthread_cond_wait (&e->wait, mutex))
+ return EINTR;
+ goto retry;
+ }
+ else
+ return EAGAIN;
+ }
+ }
+}
Index: hurd-0.9.git20181030-3.3/libfshelp/rlock.h
===================================================================
--- /dev/null
+++ hurd-0.9.git20181030-3.3/libfshelp/rlock.h
@@ -0,0 +1,111 @@
+/*
+ Copyright (C) 2001, 2014-2018 Free Software Foundation
+
+ Written by Neal H Walfield <n...@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. If not, see <http://www.gnu.org/licenses/>. */
+
+#ifndef FSHELP_RLOCK_H
+#define FSHELP_RLOCK_H
+
+#include <pthread.h>
+#include <string.h>
+
+struct rlock_linked_list
+{
+ struct rlock_list *next;
+ struct rlock_list **prevp;
+};
+
+/*
+libthreads/cthreads.h:
+typedef struct condition {
+ spin_lock_t lock;
+ struct cthread_queue queue;
+ const char *name; <-- differs
+ struct cond_imp *implications;
+} *condition_t;
+rlock.h:
+ struct condition wait;
+here replaced by
+ struct pthread_cond_t wait;
+/usr/include/pthread/pthreadtypes.h:typedef struct __pthread_cond pthread_cond_t;
+/usr/include/i386-gnu/bits/condition.h:struct __pthread_cond
+struct __pthread_cond
+{
+ __pthread_spinlock_t __lock;
+ struct __pthread *__queue;
+ struct __pthread_condattr *__attr; <-- differs
+ struct __pthread_condimpl *__impl;
+ void *__data; <-- differs
+};
+ */
+
+struct rlock_list
+{
+ loff_t start;
+ loff_t len;
+ int type;
+
+ struct rlock_linked_list node;
+ struct rlock_linked_list po;
+
+ pthread_cond_t 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));
+ pthread_cond_init (&l->wait, NULL);
+ 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 */
Index: hurd-0.9.git20181030-3.3/libfshelp/extern-inline.c
===================================================================
--- /dev/null
+++ hurd-0.9.git20181030-3.3/libfshelp/extern-inline.c
@@ -0,0 +1,24 @@
+/*
+ Copyright (C) 2001, 2014-2018 Free Software Foundation
+
+ Written by Neal H Walfield <n...@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. If not, see <http://www.gnu.org/licenses/>. */
+
+#define FSHELP_EXTERN_INLINE
+
+#include "fshelp.h"
+
libtrivfs/ChangeLog
2018-12-07 Svante Signell <svante.sign...@gmail.com>
* Update copyright years and headers.
* file-lock.c(netfs_S_dir_lookup): Call fshelp_rlock_tweak()
with new last argument rendezvous = MACH_PORT_NULL.
* file-record-lock.c(trivfs_S_file_record_lock): Likewise.
(trivfs_S_file_record_lock): Add new argument mach_port_t rendezvous.
2018-11-27 Svante Signell <svante.sign...@gmail.com>
* make-peropen.c (trivfs_make_peropen): Initialize po->cntl
* Update copyright years.
2015-12-17 Svante Signell <svante.sign...@gmail.com>
* Makefile (OTHERSRCS): Add make-node.c make-peropen.c
(FSSRCS): Add file-lock-stat.c
* trivfs.h (trivfs_peropen): Add struct rlock_peropen lock_status,
add struct trivfs_node *tp, include <hurd/fshelp.h>
* make-node.c: New file. Implement init_node and trivfs_make_node.
Call fshelp_transbox_init fshelp_rlock_init in init_node.
* make-peropen.c: New file. Implement trivfs_make_peropen.
Initialize trivfs_peropen lock_status with fshelp_rlock_po_init.
* open.c (trivfs_open): Trim off a trailing whitespace.
Update copyright header.
* Split out file-lock-stat.c (trivfs_S_file_lock_stat) from
file-lock.c to a separate file.
* file-lock.c (trivfs_S_file_lock): Call trivfs_make_peropen
and trivfs_make_node.
Implement locking using the new record locking functions.
* file-lock-stat.c (trivfs_S_file_lock_stat): Likewise
2001-04-11 Neal H Walfield <n...@cs.uml.edu>
* file-record-lock.c: New file. Implement
trivfs_S_file_record_lock.
* Makefile (FSSRCS): Add file-record-lock.c
Index: hurd-0.9.git20181030-3.3/libtrivfs/Makefile
===================================================================
--- hurd-0.9.git20181030-3.3.orig/libtrivfs/Makefile
+++ hurd-0.9.git20181030-3.3/libtrivfs/Makefile
@@ -1,4 +1,4 @@
-# Copyright (C) 1994, 1995, 1996, 1997, 1999, 2001, 2002, 2003, 2008, 2012
+# Copyright (C) 1994-1997, 1999, 2001-2003, 2008, 2012-2018
# Free Software Foundation, Inc.
#
# This program is free software; you can redistribute it and/or
@@ -12,8 +12,7 @@
# 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.
+# along with the GNU Hurd. If not, see <http://www.gnu.org/licenses/>.
dir := libtrivfs
makemode := library
@@ -22,7 +21,8 @@ FSSRCS= dir-link.c dir-mkdir.c dir-mkfil
dir-rename.c dir-rmdir.c dir-unlink.c file-chauthor.c \
file-chflags.c file-chmod.c file-chown.c file-get-trans.c \
file-get-transcntl.c file-getcontrol.c file-getfh.c \
- file-getlinknode.c file-lock.c file-set-trans.c file-statfs.c \
+ file-getlinknode.c file-lock.c file-lock-stat.c file-record-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-get-storage-info.c \
file-get-fs-options.c file-reparent.c \
@@ -38,7 +38,7 @@ FSYSSRCS=fsys-getroot.c fsys-goaway.c fs
fsys-get-children.c fsys-get-source.c \
OTHERSRCS=demuxer.c protid-clean.c protid-dup.c cntl-create.c \
- cntl-clean.c times.c startup.c open.c \
+ cntl-clean.c times.c startup.c make-node.c make-peropen.c open.c \
runtime-argp.c set-options.c append-args.c dyn-classes.c \
get-source.c
Index: hurd-0.9.git20181030-3.3/libtrivfs/trivfs.h
===================================================================
--- hurd-0.9.git20181030-3.3.orig/libtrivfs/trivfs.h
+++ hurd-0.9.git20181030-3.3/libtrivfs/trivfs.h
@@ -1,5 +1,5 @@
/*
- Copyright (C) 1994,95,96,97,99,2002,13 Free Software Foundation, Inc.
+ Copyright (C) 1994-1999,2002,2013-2018 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
@@ -12,8 +12,8 @@
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. */
+ along with the GNU Hurd. If not, see <http://www.gnu.org/licenses/>.
+*/
#ifndef __TRIVFS_H__
#define __TRIVFS_H__
@@ -24,6 +24,7 @@
#include <mach/mach.h>
#include <hurd/ports.h>
#include <hurd/iohelp.h>
+#include <hurd/fshelp.h>
#include <refcount.h>
struct trivfs_protid
@@ -45,6 +46,21 @@ struct trivfs_peropen
int openmodes;
refcount_t refcnt;
struct trivfs_control *cntl;
+
+ struct rlock_peropen lock_status;
+ struct trivfs_node *tp;
+};
+
+/* A unique one of these exists for each node currently in use. */
+struct trivfs_node
+{
+ pthread_mutex_t lock;
+
+ /* The number of references to this node. */
+ int references;
+
+ struct transbox transbox;
+ struct rlock_box credlock;
};
struct trivfs_control
@@ -170,9 +186,13 @@ trivfs_create_control (mach_port_t under
void trivfs_clean_protid (void *);
void trivfs_clean_cntl (void *);
-/* This demultiplees messages for trivfs ports. */
+/* This demultiplexes messages for trivfs ports. */
int trivfs_demuxer (mach_msg_header_t *, mach_msg_header_t *);
+/* FIXME: Add descriptions */
+struct trivfs_node *trivfs_make_node (struct trivfs_peropen *po);
+struct trivfs_peropen *trivfs_make_peropen (struct trivfs_protid *cred);
+
/* Return a new protid pointing to a new peropen in CRED, with REALNODE as
the underlying node reference, with the given identity, and open flags in
FLAGS. CNTL is the trivfs control object. */
Index: hurd-0.9.git20181030-3.3/libtrivfs/make-node.c
===================================================================
--- /dev/null
+++ hurd-0.9.git20181030-3.3/libtrivfs/make-node.c
@@ -0,0 +1,43 @@
+/*
+ Copyright (C) 2016-2018 Free Software Foundation, Inc.
+ Written by Svante Signell <svante.sign...@gmail.com>
+
+ 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. If not, see <http://www.gnu.org/licenses/>.
+*/
+
+#include "priv.h"
+
+static struct trivfs_node *
+init_node (struct trivfs_node *tp)
+{
+ tp->references = 1;
+ pthread_mutex_init (&tp->lock, NULL);
+ fshelp_transbox_init (&tp->transbox, &tp->lock, tp);
+ fshelp_rlock_init (&tp->credlock);
+
+ return tp;
+}
+
+struct trivfs_node *
+trivfs_make_node (struct trivfs_peropen *po)
+{
+ struct trivfs_node *tp = malloc (sizeof (struct trivfs_node));
+ if (! tp)
+ return NULL;
+
+ po->tp = tp;
+ return init_node (tp);
+}
Index: hurd-0.9.git20181030-3.3/libtrivfs/make-peropen.c
===================================================================
--- /dev/null
+++ hurd-0.9.git20181030-3.3/libtrivfs/make-peropen.c
@@ -0,0 +1,57 @@
+/*
+ Copyright (C) 2016-2018 Free Software Foundation, Inc.
+ Written by Svante Signell <svante.sign...@gmail.com>
+
+ 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. If not, see <http://www.gnu.org/licenses/>.
+*/
+
+#include "priv.h"
+#include <errno.h>
+#include <fcntl.h>
+
+struct trivfs_peropen *
+trivfs_make_peropen (struct trivfs_protid *cred)
+{
+ error_t err = 0;
+ struct trivfs_control *cntl;
+ struct port_class *control_class;
+ struct port_bucket *control_bucket;
+ struct port_class *protid_class;
+ struct port_bucket *protid_bucket;
+ struct trivfs_node *tp = NULL;
+ struct trivfs_peropen *po = malloc (sizeof (struct trivfs_peropen));
+ if (!po)
+ return NULL;
+
+ cred->po = po;
+ err = fshelp_rlock_po_init (&po->lock_status);
+ if (err)
+ return NULL;
+
+ err = trivfs_create_control (MACH_PORT_NULL,
+ control_class, control_bucket,
+ protid_class, protid_bucket,
+ &cntl);
+ if (err)
+ return NULL;
+ refcount_init (&po->refcnt, 1);
+ po->cntl = cntl;
+ po->openmodes = O_RDWR;
+ po->hook = 0;
+ po->tp = tp;
+
+ return po;
+}
Index: hurd-0.9.git20181030-3.3/libtrivfs/open.c
===================================================================
--- hurd-0.9.git20181030-3.3.orig/libtrivfs/open.c
+++ hurd-0.9.git20181030-3.3/libtrivfs/open.c
@@ -1,6 +1,6 @@
/* Make a new trivfs peropen/protid
- Copyright (C) 1993, 1994, 1995, 1996, 1999 Free Software Foundation, Inc.
+ Copyright (C) 1993-1996, 1999, 2018 Free Software Foundation, Inc.
This file is part of the GNU Hurd.
@@ -9,14 +9,13 @@
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,
+ 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. */
+ along with the GNU Hurd. If not, see <http://www.gnu.org/licenses/>. */
#include <string.h> /* For bcopy() */
Index: hurd-0.9.git20181030-3.3/libtrivfs/file-lock.c
===================================================================
--- hurd-0.9.git20181030-3.3.orig/libtrivfs/file-lock.c
+++ hurd-0.9.git20181030-3.3/libtrivfs/file-lock.c
@@ -1,5 +1,5 @@
/*
- Copyright (C) 1994,2002 Free Software Foundation, Inc.
+ Copyright (C) 1994, 2002, 2015-2018 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
@@ -12,24 +12,56 @@
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. */
+ along with the GNU Hurd. If not, see <http://www.gnu.org/licenses/>.
+*/
#include "priv.h"
#include "trivfs_fs_S.h"
+#include <fcntl.h>
+#include <sys/file.h>
+
kern_return_t
trivfs_S_file_lock (struct trivfs_protid *cred,
mach_port_t reply, mach_msg_type_name_t reply_type,
int flags)
{
- return EOPNOTSUPP;
-}
+ error_t err = 0;
+ struct flock64 lock;
+ struct trivfs_peropen *po;
+ struct trivfs_node *tp;
+ mach_port_t rendezvous = MACH_PORT_NULL;
+
+ if (!cred)
+ return EOPNOTSUPP;
+
+ lock.l_whence = SEEK_SET;
+ lock.l_start = 0;
+ 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;
+
+ po = trivfs_make_peropen(cred);
+ if (!po)
+ return ENOMEM;
+
+ tp = trivfs_make_node(po);
+ if (!tp)
+ return ENOMEM;
+
+ pthread_mutex_lock (&tp->lock);
+ err = fshelp_rlock_tweak (&tp->credlock, &tp->lock,
+ &cred->po->lock_status, cred->po->openmodes,
+ 0, 0, flags & LOCK_NB ? F_SETLK64 : F_SETLKW64,
+ &lock, rendezvous);
+ pthread_mutex_unlock (&tp->lock);
-kern_return_t
-trivfs_S_file_lock_stat (struct trivfs_protid *cred,
- mach_port_t reply, mach_msg_type_name_t reply_type,
- int *mystatus, int *otherstat)
-{
- return EOPNOTSUPP;
+ return err;
}
Index: hurd-0.9.git20181030-3.3/libtrivfs/file-lock-stat.c
===================================================================
--- /dev/null
+++ hurd-0.9.git20181030-3.3/libtrivfs/file-lock-stat.c
@@ -0,0 +1,56 @@
+/*
+ Copyright (C) 1994, 2002, 2015-2018 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 the GNU Hurd. If not, see <http://www.gnu.org/licenses/>.
+*/
+
+#include "priv.h"
+#include "trivfs_fs_S.h"
+
+#include <fcntl.h>
+#include <sys/file.h>
+
+kern_return_t
+trivfs_S_file_lock_stat (struct trivfs_protid *cred,
+ mach_port_t reply, mach_msg_type_name_t reply_type,
+ int *mystatus, int *otherstatus)
+{
+ struct trivfs_peropen *po;
+ struct trivfs_node *tp;
+
+ if (!cred)
+ return EOPNOTSUPP;
+
+ if (!po)
+ {
+ po = trivfs_make_peropen(cred);
+ if (!po)
+ return ENOMEM;
+ }
+
+ if (!tp)
+ {
+ tp = trivfs_make_node(po);
+ if (!tp)
+ return ENOMEM;
+ }
+
+ tp = cred->po->tp;
+ pthread_mutex_lock (&tp->lock);
+ *mystatus = fshelp_rlock_peropen_status (&cred->po->lock_status);
+ *otherstatus = fshelp_rlock_node_status (&tp->credlock);
+ pthread_mutex_unlock (&tp->lock);
+
+ return 0;
+}
Index: hurd-0.9.git20181030-3.3/libtrivfs/file-record-lock.c
===================================================================
--- /dev/null
+++ hurd-0.9.git20181030-3.3/libtrivfs/file-record-lock.c
@@ -0,0 +1,54 @@
+/*
+ Copyright (C) 2001, 2014-2018 Free Software Foundation
+ Written by Neal H Walfield <n...@cs.uml.edu>
+
+ This file is part of the GNU Hurd.
+
+ 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 the GNU Hurd. If not, see <http://www.gnu.org/licenses/>.
+*/
+
+#include "priv.h"
+/* #include "trivfs_fs_S.h" */
+#include <stdio.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 flock64 *lock,
+ mach_port_t rendezvous)
+{
+ struct trivfs_peropen *po;
+ struct trivfs_node *tp;
+ error_t err = 0;
+
+ if (! cred)
+ return EOPNOTSUPP;
+
+ po = trivfs_make_peropen(cred);
+ if (!po)
+ return ENOMEM;
+
+ tp = trivfs_make_node(po);
+ if (!tp)
+ return ENOMEM;
+
+ pthread_mutex_lock (&tp->lock);
+ err = fshelp_rlock_tweak (&tp->credlock, &tp->lock,
+ &cred->po->lock_status, cred->po->openmodes,
+ 0, 0, cmd, lock, rendezvous);
+ pthread_mutex_unlock (&tp->lock);
+
+ return err;
+}