From mboxrd@z Thu Jan 1 00:00:00 1970 From: Ricky Ng-Adam Subject: [2.6.10-rc3:fs/locks.c] fcntl F_SETLEASE/[ F_WRLCK| F_RDLCK] inconsistencies Date: Sun, 05 Dec 2004 17:13:37 -0500 Message-ID: Mime-Version: 1.0 Content-Type: multipart/mixed; boundary="------------060908030109030701020007" Return-path: Received: from main.gmane.org ([80.91.229.2]:56283 "EHLO main.gmane.org") by vger.kernel.org with ESMTP id S261406AbULEWWa (ORCPT ); Sun, 5 Dec 2004 17:22:30 -0500 Received: from root by main.gmane.org with local (Exim 3.35 #1 (Debian)) id 1Cb4lw-0002Dr-00 for ; Sun, 05 Dec 2004 23:22:28 +0100 Received: from modemcable009.253-37-24.mc.videotron.ca ([24.37.253.9]) by main.gmane.org with esmtp (Gmexim 0.1 (Debian)) id 1AlnuQ-0007hv-00 for ; Sun, 05 Dec 2004 23:22:28 +0100 Received: from rngadam by modemcable009.253-37-24.mc.videotron.ca with local (Gmexim 0.1 (Debian)) id 1AlnuQ-0007hv-00 for ; Sun, 05 Dec 2004 23:22:28 +0100 To: linux-fsdevel@vger.kernel.org Sender: linux-fsdevel-owner@vger.kernel.org List-Id: linux-fsdevel.vger.kernel.org This is a multi-part message in MIME format. --------------060908030109030701020007 Content-Type: text/plain; charset=us-ascii; format=flowed Content-Transfer-Encoding: 7bit Hello! Behavior for fcntl seems to have changed for F_SETLEASE between 2.6.9 and 2.6.10-rcX. I've noticed this problem while running LTP (Linux Test Project) suite; test fcntl23 FAIL while it doesn't in 2.6.8.1 and 2.6.9. I've noticed that this bit of code was added in fs/locks.c:__setlease: error = -EAGAIN; if ((arg == F_RDLCK) && (atomic_read(&inode->i_writecount) > 0)) goto out; if ((arg == F_WRLCK) && ((atomic_read(&dentry->d_count) > 1) || (atomic_read(&inode->i_count) > 1))) goto out; With this change, doing a fd = open("/tmp/mytest", O_RDONLY|O_CREAT,0777) and trying to do fcntl(fd, F_SETLEASE, F_RDLCK) FAILs with EAGAIN (Resource temporarily unavailable). If I change if ((arg == F_RDLCK) && (atomic_read(&inode->i_writecount) > 0)) to if ((arg == F_RDLCK) && (atomic_read(&inode->i_writecount) > 1)) it works for F_RDLCK. After all, the process calling fcntl may have the file opened for writing... I'm attaching sample programs that I ran on each. There results are here: 2.6.8: warren:~# ./rdlck handler called! warren:~# ./wrlck F_SETLEASE, F_WRLCK failed: 11, Resource temporarily unavailable 2.6.8.1 (on coLinux; 2.6.8.1-co-0.6.2-pre6): colinux:~# ./rdlck handler called! colinux:~# ./wrlck handler called! 2.6.9: warren:~# ./rdlck handler called! warren:~# ./wrlck F_SETLEASE, F_WRLCK failed: 11, Resource temporarily unavailable 2.6.10-rc3: warren:~# ./rdlck F_SETLEASE, F_RDLCK failed: 11, Resource temporarily unavailable warren:~# ./wrlck F_SETLEASE, F_WRLCK failed: 11, Resource temporarily unavailable 2.6.10-rc3, modified: warren:~# ./rdlck handler called! warren:~# ./wrlck F_SETLEASE, F_WRLCK failed: 11, Resource temporarily unavailable Is the test wrong or is this a bug? Why is it never possible to get a F_WRLCK (except, strangely, on coLinux)? Thanks, Ricky Ng-Adam --------------060908030109030701020007 Content-Type: text/plain; name="wrlck.c" Content-Transfer-Encoding: 7bit Content-Disposition: inline; filename="wrlck.c" #define _GNU_SOURCE #include #include #include #include int event_fd; struct sigaction act; void handler(int sig, siginfo_t *si, void *data) { event_fd = si->si_fd; printf("handler called!\n"); exit(0); } int main(void) { int fd; act.sa_sigaction = handler; sigemptyset(&act.sa_mask); act.sa_flags = SA_SIGINFO; sigaction(SIGRTMIN, &act, NULL); if ((fd = open("/tmp/mytest", O_RDONLY|O_CREAT,0777)) == -1) printf("Create file failed: %d, %s \n", errno, strerror(errno)); fcntl(fd, F_SETSIG, SIGRTMIN); if(fcntl(fd, F_SETLEASE, F_WRLCK) == -1) { printf("F_SETLEASE, F_WRLCK failed: %d, %s \n", errno, strerror(errno)); exit(1); } fd = open("/tmp/mytest", O_RDWR|O_CREAT,0777); while(1) sleep(1); } --------------060908030109030701020007 Content-Type: text/plain; name="rdlck.c" Content-Transfer-Encoding: 7bit Content-Disposition: inline; filename="rdlck.c" #define _GNU_SOURCE #include #include #include #include int event_fd; struct sigaction act; void handler(int sig, siginfo_t *si, void *data) { event_fd = si->si_fd; printf("handler called!\n"); exit(0); } int main(void) { int fd; act.sa_sigaction = handler; sigemptyset(&act.sa_mask); act.sa_flags = SA_SIGINFO; sigaction(SIGRTMIN, &act, NULL); if ((fd = open("/tmp/mytest", O_RDWR|O_CREAT,0777)) == -1) printf("Create file failed: %d, %s \n", errno, strerror(errno)); fcntl(fd, F_SETSIG, SIGRTMIN); if(fcntl(fd, F_SETLEASE, F_RDLCK) == -1) { printf("F_SETLEASE, F_RDLCK failed: %d, %s \n", errno, strerror(errno)); exit(1); } fd = open("/tmp/mytest", O_RDWR|O_CREAT,0777); while(1) sleep(1); } --------------060908030109030701020007--