taskThe GNU Hurd - Tasks: task #1022, POSIX record locking

 
 

task #1022: POSIX record locking

Submitter:  Marcus Brinkmann <marcus>
Submitted:  -
   
 
Category:  The GNU Hurd Should Start On:  Sun 26 May 2002 10:00:00 PM UTC
Should be Finished on:  Sun 26 May 2002 10:00:00 PM UTC Priority:  * 6
Status:  None Privacy:  Public
Assigned to:  None Percent Complete:  30%
Open/Closed:  Open Planned Release:  None
Effort:  0.00
Wiki-like text discussion box: 


* Mandatory Fields

Add a New Comment Rich Markup
   

Mon 18 Nov 2002 10:07:27 AM UTC, comment #2: 

The PID has to be established by the proc server, see io_reidentify task.

Marcus Brinkmann <marcus>
Group administrator
Mon 27 May 2002 01:02:22 PM UTC, comment #1: 

The patch by Neal can be found in Patch 332.

Most of Neal's concerns can be solved by applying two strategies: Let the user provide the process ID, and trust that information.  Use io_close to synchronize deletion of record locks.

The server also needs to get a port in the task, on which it can request a dead name notification, so it can release the locks on task death.

For the interface itself, we should either split it up in more convenient RPCs, use the 64 bit version, or use the 32 bit version and do the transition the same as we will do it when we move all the other interfaces to 64 bit.


Marcus Brinkmann <marcus>
Group administrator
-, original submission:  

From Neal H Walfield:

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.

Marcus Brinkmann <marcus>
Group administrator

 

(Note: upload size limit is set to 16384 kB, after insertion of the required escape characters.)

Attach Files:
   
   
Comment:
   

No files currently attached

 

Digest:
   task dependencies.

Items that depend on this one: None found

 

CC list is empty

 

There are 0 votes so far. Votes easily highlight which items people would like to see resolved in priority, independently of the priority of the item set by tracker managers.

Only logged-in users can vote.

 

No changes have been made to this item

Back to the top

Powered by Savane 3.14-e222.
Corresponding source code