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
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
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"
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;
}