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(a)lists.nfs-ganesha.org To unsubscribe send an
email to support-leave(a)lists.nfs-ganesha.org