All,
Given two threads (1 and 2) of the same process - that are using fcntl to lock the same file - and operations issued in the following order
open1 open2 lock1 lock2 unlock1 close1 unlock2 close2
close1 seems to be unlocking lock2
That is happening because of a lovely feature of POSIX locks where any close releases all the locks on the file held by the process. Also, the process is the lock owner, so you can't use locks to synchronize between two threads.
Ganesha is getting into a state when it gets the unlock2 in which it starts failing subsequent lock requests This happens when mounting with vers=4.0 This happens with both Ganesha 3.5 and Ganesha 5.9 This does not happen if flock is used instead of fcntl
Can you get a tcpdump trace? It would also be helpful to open an issue on github if you are able to. I suspect something is going wrong with the lock and open owners. It may be a client bug.
This does not happen when mounting with vers=4.1 Here too, close1 seems to be unlocking lock2 However when Ganesha gets unlock2, it logs the following, but honours subsequent lock requests "Unlock success on file with no locks"
4.1 handles open and lock owners slightly differently in a way that doesn't get tripped up.
Linux Kernel Client is 4.18
Here is the simple program to reproduce the problem
#include <stdio.h> #include <pthread.h> #include <stdlib.h> #include <unistd.h> #include <sys/stat.h> #include <fcntl.h> #include <errno.h> #include <string.h> #include <sys/syscall.h> #define BUF_SIZE 512 int a = 0; void *func_thread(void *p) { printf("start %s\n", p); int fd; struct flock fl; int microsecond = 0.1 * 1000000; int byte_num; char buf[BUF_SIZE]; pid_t tid; tid = syscall(SYS_gettid); fd = open(p, O_RDWR); if (fd == -1) { /* Handle error */; printf("[%d] open err.\n", tid); } fl.l_type = F_RDLCK; fl.l_whence = SEEK_SET; fl.l_start = 0; fl.l_len = 0; printf("[%d] start F_SETLK.\n", tid); if (fcntl(fd, F_SETLK, &fl) == -1) { if (errno == EACCES || errno == EAGAIN) { printf("[%d] Already locked by another process\n", tid); /* We can't get the lock at the moment */ } else { /* Handle unexpected error */ printf("fcntl F_RDLCK err.\n"); fprintf(stderr,"[%d] func_thread : %s\n",tid, strerror(errno)); close(fd); pthread_exit(0); } } else { /* Lock was granted... / / Unlock the locked bytes */ printf("[%d] start F_UNLCK.\n", tid); fl.l_type = F_UNLCK; fl.l_whence = SEEK_SET; fl.l_start = 0; fl.l_len = 0; if (fcntl(fd, F_SETLK, &fl) == -1) { /* Handle error */; printf("fcntl F_UNLCK err.\n"); fprintf(stderr,"[%d] func_thread : %s\n", tid, strerror(errno)); close(fd); pthread_exit(0); } } close(fd); printf("[%d] success.\n", tid); pthread_exit(0); } int main(int argc, char *argv[]) { pthread_t pthread0, pthread1, pthread2, pthread3, pthread4; int status; status = pthread_create( &pthread0, NULL, &func_thread, argv[1]); if(status!=0){ fprintf(stderr,"pthread_create : %s\n",strerror(status)); } else{ printf("pthread0=%d\n", pthread0); } status = pthread_create( &pthread1, NULL, &func_thread, argv[1]); if(status!=0){ fprintf(stderr,"pthread_create : %s\n",strerror(status)); } else{ printf("pthread1=%d\n", pthread1); } pthread_join(pthread0, NULL); pthread_join(pthread1, NULL); return 0; } _______________________________________________ Support mailing list -- support@lists.nfs-ganesha.org To unsubscribe send an email to support-leave@lists.nfs-ganesha.org