Score:1

flock fails with NFSv4

ph flag

I don't know why this code is not working under NFS4, using NFS3 works perfectly. The idea is to avoid the file being written while a process is still reading it.

I would like to debug, but our sys-admin is not able to. Which could be reason. Under our NFS4-Installation I always get into this condition

  if ( flock(fp,LOCK_EX) == -1)
    printf("Error: file %s is already locked\n", fileName);

the whole program is :

#include <sys/file.h>
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>

int main(int argc, char **argv){

    if (argc<2){
        printf("Usage:\n a.out fileName\n");
        return 1;
    }

    char *fileName=argv[1];
    int  fp;
     
    /* block the file, I know a process can write 
    rendering my information useless*/
    fp=open(fileName,O_RDONLY);

    if ( flock(fp,LOCK_EX) == -1){
        printf("Error: file %s is already locked\n", fileName);
    }
    else{
        printf("OK: file %s was locked\n",fileName );
    }

    /* read and parse the fileName 
       another process should not be able to write or
       modify the fileName while I am reading it
    */
    return 0;    
}

Edit: I would like to clarify. This is an fragment of the code I am using. fileName is supposed to be a valid existing file

I am reading a fileName and making a copy, editing some few parts. I know, while I am doing this, an external process can update the fileName. I would like to use a semaphore to avoid modifications on this file until I am done with it. This program was working perfectly until stop doing so. The only difference, is the file system where the fileNames are located. It was updated form NFS3 to NFS4. Even the OS (SLE15.2) is the same with kernel 5.3.18, and using strerror(errno) produces a seg fault on NFS4. The only hint when I do print("%d",error) is 9 which should be "wrong file descriptor"

Thanks for your help

Julia

Matthew Ife avatar
jo flag
The line ```if ( flock(fp,LOCK_EX) == -1){``` only tells you if the exclusive lock failed. Not why. Change the printf to ```printf("Error: file %s is already locked: %s\n", fileName, strerror(errno));``` You're only making a assumption that its a underlying problem with locking but you could have a more fundamental error (such as attempting to lock a file that does not exist).
de flag
You should print the errno (as suggested by others) to see why the lock request had failed.
djdomi avatar
za flag
I belive this question would more fit on StackOverflow instead on this site.
Score:0
de flag

NFS v3 doesn't have a locking support on the protocol level. The functionality is provided by an additional (external to nfs protocol) lock manager. On another hand, NFS v4 has locking as a part of the spec. Moreover, there are two types of locks. One is the byte range locks, the second is the access share. Though the later one is what you're looking for, the POSIX API doesn't expose it, thus are not available for linux and unix.

To get locking to work with nfs v4 and v3 you need to use byte range locking which is available as fcntl or lockf functions.

Check the code of the locking test used by nfs developers (including myself) to validate client/server behavior independent of protocol version.

http://git.linux-nfs.org/?p=steved/cthon04.git;a=blob;f=lock/tlock.c;h=8c837a87976d17c58a25c9bd08d9f935e4521402;hb=HEAD#l835

Score:0
jo flag

This section of code:

if ( flock(fp,LOCK_EX) == -1){
    printf("Error: file %s is already locked\n", fileName);
}
else{
    printf("OK: file %s was locked\n",fileName );
}

Can really only tell you that the lock failed or succeeded but not why. You should alter it to report the errno reason for the failure as it might indicate a more fundamental issue with your locking -- such as trying to open a file you dont have permission to or doesn't exist.

if ( flock(fp,LOCK_EX) == -1){
    printf("Error: file %s is already locked: %s\n", fileName, strerror(errno));
}
else{
    printf("OK: file %s was locked\n",fileName );
}

You may also want to include errno.h in the list of includes too to make sure you reach for the correct variable.

Score:0
kz flag

I just checked the manpage of flock, in the NOTES section comes the important part:

NFS details
   In Linux kernels up to 2.6.11, flock() does not lock files over NFS (i.e., the scope of locks was limited to the local system).  Instead, one could use fcntl(2) byte-range locking, which does
   work over NFS, given a sufficiently recent version of Linux and a server which supports locking.

   Since Linux 2.6.12, NFS clients support flock() locks by emulating them as fcntl(2) byte-range locks on the entire file.  This means that fcntl(2) and  flock()  locks  do  interact  with  one
   another over NFS.  It also means that in order to place an exclusive lock, the file must be opened for writing.

   Since  Linux  2.6.37,  the  kernel  supports  a compatibility mode that allows flock() locks (and also fcntl(2) byte region locks) to be treated as local; see the discussion of the local_lock
   option in nfs(5).

You only opened the file for reading, which is the reason why the flock call fails.

Julia Fischer avatar
ph flag
thank you. You have answered my question. I must read the man page
Martin avatar
kz flag
great! If my answer solved your question, please mark it as accepted answer...
mangohost

Post an answer

Most people don’t grasp that asking a lot of questions unlocks learning and improves interpersonal bonding. In Alison’s studies, for example, though people could accurately recall how many questions had been asked in their conversations, they didn’t intuit the link between questions and liking. Across four studies, in which participants were engaged in conversations themselves or read transcripts of others’ conversations, people tended not to realize that question asking would influence—or had influenced—the level of amity between the conversationalists.