home *** CD-ROM | disk | FTP | other *** search
- Newsgroups: comp.unix.aix
- Path: sparky!uunet!psinntp!stiatl!jer
- From: jer@stiatl.salestech.com (John Ramspott)
- Subject: NFS File locking in AIX (bug)
- Message-ID: <1993Jan20.223356.2353@stiatl.salestech.com>
- Organization: Sales Technologies, Inc.
- Date: Wed, 20 Jan 1993 22:33:56 GMT
- Lines: 149
-
- Hello AIX developers,
-
-
- We cannot
- get file-locking working when two different processes are trying to
- append to the file from two DIFFERENT machines via NFS. The Info
- Explorer says that the NFS file lock manager supports the SVID
- advisory locking, namely fcntl() and lockf(). We use fcntl() because
- it is a part of POSIX and XPG3. The bottom line is we have tried lots
- of different things, and the resulting data file contains errors. Typically,
- a record from one process will overwrite a partial record, an entire record,
- or even multiple records of the other process. The locking does work if
- all processes are on the same machine.
-
- We have spent over two days trying to get this to work, throwing me off
- schedule quite a bit. This was suppose to just work :-). I give it a
- very high priority. Running one of the processes on the NFS Server machine
- (Barney in our case) seems to make very little difference. If two different
- machines are used, you usually get errors.
-
- The program will open a file called trylock.dat in the current directory,
- and will append 500 records to it. It also opens trylock.dat.lock, but
- never writes to it. The code as I am sending it does not use the lock file
- (it locks the file being written to), but changing the second fd parameter
- in writeline() call to fdl will have the program lock the lock file instead.
- This did not help; in fact, the resulting data file had garbage in it (same
- as if you had no locking at all).
-
- The current program locks the entire file. We have tried variations
- of just locking from the end-of-file the size of the message to be
- written. This also failed the multi-node test. We would prefer to
- just do record locking.
-
- The program writes out what it believes to be the end-of-file position
- and iteration number (loop position). If multiple processes are running,
- no value for file_ptr for one process should EVER match one from the
- other. This however does happen, causing one to overwrite the others data.
-
- Sample Program usage:
-
- trylock aaaaa > out1 (on machine 1)
- trylock BBBBBBB > out2 (on machine 2)
-
- Whatever you pass trylock, that is the buffer it appends to the trylock.dat
- file. We have noticed that using different sized buffers for each
- invocation makes errors in the file more obvious.
-
- Thank you,
- John E. Ramspott
- Software Engineer
- Sales Technologies, Inc.
- jer@salestech.com
- (404) 841-4986
-
- Compile with: c89 -o trylock trylock.c -D_ALL_SOURCE
- ------------------- trylock.c ---------------------------
- #include <unistd.h>
- #include <stdlib.h>
- #include <string.h>
- #include <stdio.h>
- #include <fcntl.h>
- #include <sys/types.h>
- #include <sys/stat.h>
-
- short count;
-
- short writeline( int fd, int fdl, char *message )
- {
- int status;
- int msg_length;
- off_t file_ptr;
- struct flock alock;
-
- msg_length = strlen( message );
-
- /* Note that this locks the entire file. We initially were using */
- /* whence = SEEK_END, start = 0, and len = msg_length, to only */
- /* lock the record we want to write to. This seems to produce the */
- /* same affect as locking the whole file -- overlapping records from */
- /* different nodes. We would prefer to just lock the area we are adding */
- /* to the end of file. */
- alock.l_type = F_WRLCK;
- alock.l_whence = SEEK_SET;
- alock.l_start = 0;
- alock.l_len = 0;
- status = fcntl( fdl, F_SETLKW, &alock );
- if (status == -1)
- return( -3 );
-
- file_ptr = lseek( fd, 0, SEEK_END );
- printf( "file_ptr = %ld iteration = %d\n", file_ptr, count );
-
- status = write( fd, message, msg_length );
- if (status == -1)
- return( -4 );
-
- alock.l_type = F_UNLCK;
- alock.l_whence = SEEK_SET;
- alock.l_start = 0;
- alock.l_len = 0;
- status = fcntl( fdl, F_SETLKW, &alock );
- if (status == -1)
- return( -1 );
-
- return( 0 );
- }
-
-
- main( int argc, char *argv[] )
- {
- int fd, fdl;
- char writeBuff[ BUFSIZ ];
- short status;
-
- strcpy( writeBuff, argv[1] );
- strcat( writeBuff, "\n" );
-
- /* We have experimented with not using O_APPEND and using */
- /* lseek(), and doing both. We have also experimented with */
- /* the O_SYNC flag, with no noticeable affect */
- fd = open( "trylock.dat", O_CREAT | O_RDWR | O_APPEND,
- S_IRUSR | S_IWUSR );
-
- fdl = open( "trylock.dat.lock", O_CREAT | O_RDWR,
- S_IRUSR | S_IWUSR );
-
- for (count = 0; count < 500; count++ )
- {
- /* The second fd parameter below is the fd to use for file */
- /* locking. Using fdl for the second parameter will cause it */
- /* to use a separate lock file instead of the one we are writing */
- /* to. Using a separate file for locking actually made the resulting */
- /* data contain more garbage and errors for us */
- status = writeline( fd, fd, writeBuff );
- if (status != 0)
- printf( "status = %d writeBuff = %s", status, writeBuff );
- /* usleep( 400000 ); Sleeping increases interleaving, but does */
- /* not solve the problem of overlapping records. */
- }
-
- close( fd );
- close ( fdl );
- }
- ------------------- end of trylock.c ------------------------
-
- --
- John E. Ramspott
- Amiga Fanatic at Large
- ..!uupsi!stiatl!jer (uupsi is a direct internet connection)
-