Message ID | 20230530203707.2965684-2-aahringo@redhat.com |
---|---|
State | Changes Requested |
Headers | show |
Series | fcntl: add more testcases | expand |
Hi Alexander, > This patch adds fcntl40 to test similar owner values for classical owner > locks. There was an issue been found in the gfs2 filesystem because > there can be collisions with identical owner values. Thanks for your work! ... > +++ b/testcases/kernel/syscalls/fcntl/fcntl40.c > @@ -0,0 +1,188 @@ There is no SPDX and copyright, see other files: // SPDX-License-Identifier: GPL-2.0-or-later /* * Copyright (c) 2023 ... */ > +/* NOTE: this should be /*\ to be able to get the description in our automatically generated documentation https://github.com/linux-test-project/ltp/releases/download/20230516/metadata.20230516.html > + * [Description] > + * Tests gfs2 dlm posix op queue handling in the kernel. > + * It is recommended to run watch -n 0.1 "dlm_tool plocks $LS" > + * aside to monitor dlm plock handling. > + * > + * [How to use it] > + * Call it with TMPDIR=/mnt ./fcntl40 where TMPDIR is a gfs2 mountpoint. I wonder if we could check for GFS2_MAGIC (we'd need to add it to include/tst_fs.h => 0x01161970) and quit the test with tst_brk(TCONF) if TMPDIR is not on gfs2. ATM we don't have any helper in struct tst_test, which would do it. > + * Try it on other filesystems to compare results. > + * > + * [What's it doing] nit: I'd replace this with [Algorithm]. ... > +void do_child(void) This should be static (in all files). make check (or make check-fcntl40) is your friend. > +{ > + pthread_t t1, t2; > + > + SAFE_PTHREAD_CREATE(&t1, NULL, do_thread1, NULL); > + SAFE_PTHREAD_CREATE(&t2, NULL, do_thread2, NULL); > + > + SAFE_PTHREAD_JOIN(t1, NULL); > + SAFE_PTHREAD_JOIN(t2, NULL); > + > + tst_res(TPASS, "Child passed!"); > +} > + > +void do_parent(void) This should also be static. > +{ > + struct flock fl = { > + .l_whence = SEEK_SET, > + }; > + > + /* wait for 1 seconds so thread2 lock 1-1 tries to acquires at first > + * than thread1 lock 0-0 tries to acquired to have a specific waiting > + * order in dlm posix handling. > + */ > + sleep(1); I wonder if there could be some proactive check instead of sleep. FYI we have undocumented TST_RETRY_FUNC() in C API. > + /* tell thread2 to call SETLKW for lock 0-0 */ > + TST_CHECKPOINT_WAKE(1); > + /* wait 3 seconds for thread 1 and 2 being in waiting state */ > + sleep(3); > + > + /* unlock 0-1, should be successful */ > + fl.l_type = F_UNLCK; > + fl.l_start = 1; > + fl.l_len = 1; > + tst_res(TINFO, "unlock region 1-1 thread2"); > + SAFE_FCNTL(fd, F_SETLK, &fl); > + > + /* wait until thread 2 got acquired and leave waiting */ > + TST_CHECKPOINT_WAIT(2); > + > + fl.l_start = 0; > + fl.l_len = 1; > + fl.l_type = F_UNLCK; > + tst_res(TINFO, "unlock region 0-0 thread2"); > + SAFE_FCNTL(fd, F_SETLK, &fl); > +} > + > +static void fcntl40_test(void) > +{ > + struct flock fl = { > + .l_type = F_WRLCK, > + .l_whence = SEEK_SET, > + .l_start = 0L, > + .l_len = 2L, > + }; > + pid_t pid; > + > + tst_res(TINFO, "parent lock region 0-1 - should be successful"); > + SAFE_FCNTL(fd, F_SETLK, &fl); > + tst_res(TINFO, "parent region 0-1 locked"); > + > + pid = SAFE_FORK(); > + if (pid == 0) { > + do_child(); > + return; > + } > + > + do_parent(); > + wait(NULL); waitpid() should be replaced by tst_reap_children(), see https://github.com/linux-test-project/ltp/wiki/C-Test-API#18-doing-the-test-in-the-child-process > + > + tst_res(TPASS, "Parent passed!"); There is TPASS in child, does it really need to be in the parent as well? > +} > + > +static void setup(void) > +{ > + fd = SAFE_OPEN("filename", O_RDWR | O_CREAT, 0700); > +} > + > +static void cleanup(void) > +{ > + if (fd > -1) > + SAFE_CLOSE(fd); > +} > + > +static struct tst_test test = { > + .forks_child = 1, > + .needs_checkpoints = 1, > + .test_all = fcntl40_test, > + .setup = setup, > + .cleanup = cleanup, > +};
Hi, On Wed, Jun 21, 2023 at 5:10 AM Petr Vorel <pvorel@suse.cz> wrote: > > Hi Alexander, > > > This patch adds fcntl40 to test similar owner values for classical owner > > locks. There was an issue been found in the gfs2 filesystem because > > there can be collisions with identical owner values. > > Thanks for your work! > > ... > > +++ b/testcases/kernel/syscalls/fcntl/fcntl40.c > > @@ -0,0 +1,188 @@ > There is no SPDX and copyright, see other files: > > // SPDX-License-Identifier: GPL-2.0-or-later > /* > * Copyright (c) 2023 ... > */ > > > +/* > NOTE: this should be /*\ > to be able to get the description in our automatically generated documentation > > https://github.com/linux-test-project/ltp/releases/download/20230516/metadata.20230516.html > ok > > + * [Description] > > + * Tests gfs2 dlm posix op queue handling in the kernel. > > + * It is recommended to run watch -n 0.1 "dlm_tool plocks $LS" > > + * aside to monitor dlm plock handling. > > + * > > + * [How to use it] > > + * Call it with TMPDIR=/mnt ./fcntl40 where TMPDIR is a gfs2 mountpoint. > I wonder if we could check for GFS2_MAGIC (we'd need to add it to > include/tst_fs.h => 0x01161970) and quit the test with tst_brk(TCONF) if TMPDIR > is not on gfs2. > > ATM we don't have any helper in struct tst_test, which would do it. > I will mention that gfs2 is only an example here. It becomes interesting when a file system implements its own .lock() callback OR if somebody wants to test file system core, when a filesystem does not implement its own .lock(). > > + * Try it on other filesystems to compare results. > > + * > > + * [What's it doing] > nit: I'd replace this with [Algorithm]. > ok. > ... > > +void do_child(void) > This should be static (in all files). > > make check (or make check-fcntl40) is your friend. > ok. Thanks for telling me about make check. > > +{ > > + pthread_t t1, t2; > > + > > + SAFE_PTHREAD_CREATE(&t1, NULL, do_thread1, NULL); > > + SAFE_PTHREAD_CREATE(&t2, NULL, do_thread2, NULL); > > + > > + SAFE_PTHREAD_JOIN(t1, NULL); > > + SAFE_PTHREAD_JOIN(t2, NULL); > > + > > + tst_res(TPASS, "Child passed!"); > > +} > > + > > +void do_parent(void) > This should also be static. > ok. > > +{ > > + struct flock fl = { > > + .l_whence = SEEK_SET, > > + }; > > + > > + /* wait for 1 seconds so thread2 lock 1-1 tries to acquires at first > > + * than thread1 lock 0-0 tries to acquired to have a specific waiting > > + * order in dlm posix handling. > > + */ > > + sleep(1); > > I wonder if there could be some proactive check instead of sleep. > FYI we have undocumented TST_RETRY_FUNC() in C API. > I try to look into it. > > + /* tell thread2 to call SETLKW for lock 0-0 */ > > + TST_CHECKPOINT_WAKE(1); > > + /* wait 3 seconds for thread 1 and 2 being in waiting state */ > > + sleep(3); > > + > > + /* unlock 0-1, should be successful */ > > + fl.l_type = F_UNLCK; > > + fl.l_start = 1; > > + fl.l_len = 1; > > + tst_res(TINFO, "unlock region 1-1 thread2"); > > + SAFE_FCNTL(fd, F_SETLK, &fl); > > + > > + /* wait until thread 2 got acquired and leave waiting */ > > + TST_CHECKPOINT_WAIT(2); > > + > > + fl.l_start = 0; > > + fl.l_len = 1; > > + fl.l_type = F_UNLCK; > > + tst_res(TINFO, "unlock region 0-0 thread2"); > > + SAFE_FCNTL(fd, F_SETLK, &fl); > > +} > > + > > +static void fcntl40_test(void) > > +{ > > + struct flock fl = { > > + .l_type = F_WRLCK, > > + .l_whence = SEEK_SET, > > + .l_start = 0L, > > + .l_len = 2L, > > + }; > > + pid_t pid; > > + > > + tst_res(TINFO, "parent lock region 0-1 - should be successful"); > > + SAFE_FCNTL(fd, F_SETLK, &fl); > > + tst_res(TINFO, "parent region 0-1 locked"); > > + > > + pid = SAFE_FORK(); > > + if (pid == 0) { > > + do_child(); > > + return; > > + } > > + > > + do_parent(); > > + wait(NULL); > > waitpid() should be replaced by tst_reap_children(), see > https://github.com/linux-test-project/ltp/wiki/C-Test-API#18-doing-the-test-in-the-child-process > ok. Thanks. > > + > > + tst_res(TPASS, "Parent passed!"); > There is TPASS in child, does it really need to be in the parent as well? no. - Alex
Hi Alex, ... > > > + * [Description] > > > + * Tests gfs2 dlm posix op queue handling in the kernel. > > > + * It is recommended to run watch -n 0.1 "dlm_tool plocks $LS" > > > + * aside to monitor dlm plock handling. > > > + * > > > + * [How to use it] > > > + * Call it with TMPDIR=/mnt ./fcntl40 where TMPDIR is a gfs2 mountpoint. > > I wonder if we could check for GFS2_MAGIC (we'd need to add it to > > include/tst_fs.h => 0x01161970) and quit the test with tst_brk(TCONF) if TMPDIR > > is not on gfs2. > > ATM we don't have any helper in struct tst_test, which would do it. > I will mention that gfs2 is only an example here. It becomes > interesting when a file system implements its own .lock() callback OR > if somebody wants to test file system core, when a filesystem does not > implement its own .lock(). I see .lock is implemented in 9p, afs, ceph, cifs, ocfs2, orangefs, even NFS. "file system core": do you mean VFS? Because that would be more usable than the filesystems above (which are quite exotic). ... Kind regards, Petr
Hi Alex, ... > > > + tst_res(TPASS, "Parent passed!"); > > There is TPASS in child, does it really need to be in the parent as well? > no. Thanks for info, let's skip it then in the parent. Kind regards, Petr
Hi, On Sun, Jul 2, 2023 at 3:18 PM Petr Vorel <pvorel@suse.cz> wrote: > > Hi Alex, > > ... > > > > + * [Description] > > > > + * Tests gfs2 dlm posix op queue handling in the kernel. > > > > + * It is recommended to run watch -n 0.1 "dlm_tool plocks $LS" > > > > + * aside to monitor dlm plock handling. > > > > + * > > > > + * [How to use it] > > > > + * Call it with TMPDIR=/mnt ./fcntl40 where TMPDIR is a gfs2 mountpoint. > > > I wonder if we could check for GFS2_MAGIC (we'd need to add it to > > > include/tst_fs.h => 0x01161970) and quit the test with tst_brk(TCONF) if TMPDIR > > > is not on gfs2. > > > > ATM we don't have any helper in struct tst_test, which would do it. > > > > I will mention that gfs2 is only an example here. It becomes > > interesting when a file system implements its own .lock() callback OR > > if somebody wants to test file system core, when a filesystem does not > > implement its own .lock(). > > I see .lock is implemented in 9p, afs, ceph, cifs, ocfs2, orangefs, even NFS. > "file system core": do you mean VFS? Because that would be more usable than the > filesystems above (which are quite exotic). > It depends here what they are doing in .lock() - If they just call locks_lock_file_wait() or similar helpers depending on the call, then they don't do much different than what vfs is doing. In case of gfs2/ocfs it is very special, it redirects their calls to DLM and DLM has its own whole posix implementation behind it. We only call locks_lock_file_wait() to keep the Linux bookkeeping in /proc/locks. What I am doing here is mostly trusting the Linux implementation and comparing results from e.g. tmpfs with GFS2 and I found issues. For now I trust the Linux implementation and check if we have a different result here. I need to be very careful here because GFS2/OCFS2 are cluster filesystems and the fcntl() interface was never made for cluster filesystems. However I currently only test "one node" locking and this should deliver the same results as tmpfs, etc. - Alex
> Hi, > On Sun, Jul 2, 2023 at 3:18 PM Petr Vorel <pvorel@suse.cz> wrote: > > Hi Alex, > > ... > > > > > + * [Description] > > > > > + * Tests gfs2 dlm posix op queue handling in the kernel. > > > > > + * It is recommended to run watch -n 0.1 "dlm_tool plocks $LS" > > > > > + * aside to monitor dlm plock handling. > > > > > + * > > > > > + * [How to use it] > > > > > + * Call it with TMPDIR=/mnt ./fcntl40 where TMPDIR is a gfs2 mountpoint. > > > > I wonder if we could check for GFS2_MAGIC (we'd need to add it to > > > > include/tst_fs.h => 0x01161970) and quit the test with tst_brk(TCONF) if TMPDIR > > > > is not on gfs2. > > > > ATM we don't have any helper in struct tst_test, which would do it. > > > I will mention that gfs2 is only an example here. It becomes > > > interesting when a file system implements its own .lock() callback OR > > > if somebody wants to test file system core, when a filesystem does not > > > implement its own .lock(). > > I see .lock is implemented in 9p, afs, ceph, cifs, ocfs2, orangefs, even NFS. > > "file system core": do you mean VFS? Because that would be more usable than the > > filesystems above (which are quite exotic). > It depends here what they are doing in .lock() - If they just call > locks_lock_file_wait() or similar helpers depending on the call, then > they don't do much different than what vfs is doing. > In case of gfs2/ocfs it is very special, it redirects their calls to > DLM and DLM has its own whole posix implementation behind it. We only > call locks_lock_file_wait() to keep the Linux bookkeeping in > /proc/locks. > What I am doing here is mostly trusting the Linux implementation and > comparing results from e.g. tmpfs with GFS2 and I found issues. > For now I trust the Linux implementation and check if we have a > different result here. I need to be very careful here because > GFS2/OCFS2 are cluster filesystems and the fcntl() interface was never > made for cluster filesystems. However I currently only test "one node" > locking and this should deliver the same results as tmpfs, etc. Thanks for info. I'm still not sure if this is useful only for gfs2/ocfs and we should prepare block device with gfs2 or ocfs and test filesystem on it. Or if it would be useful to test other filesystem implementation. In this latter case we usually use .all_filesystems (we don't have proper docs for .all_filesystems, the closest is [1]) and test is then run on various common filesystems (see fs_type_whitelist[] in lib/tst_supported_fs_types.c), but in that case gfs2 would be skipped (it's not a common filesystem). In case preparing block device with gfs2 something like this might work: static struct tst_test test = { ... .dev_fs_type = "gfs2", .format_device = 1, .dev_fs_opts = (const char *const []){ "-t", "mycluster:mygfs2", "-p", "lock_dlm", "-j" , "2" , NULL}, Kind regards, Petr [1] https://github.com/linux-test-project/ltp/wiki/C-Test-API#113-filesystem-type-detection-and-skiplist > - Alex
Hi, On Fri, Jul 7, 2023 at 4:14 AM Petr Vorel <pvorel@suse.cz> wrote: > > > Hi, > > > On Sun, Jul 2, 2023 at 3:18 PM Petr Vorel <pvorel@suse.cz> wrote: > > > > Hi Alex, > > > > ... > > > > > > + * [Description] > > > > > > + * Tests gfs2 dlm posix op queue handling in the kernel. > > > > > > + * It is recommended to run watch -n 0.1 "dlm_tool plocks $LS" > > > > > > + * aside to monitor dlm plock handling. > > > > > > + * > > > > > > + * [How to use it] > > > > > > + * Call it with TMPDIR=/mnt ./fcntl40 where TMPDIR is a gfs2 mountpoint. > > > > > I wonder if we could check for GFS2_MAGIC (we'd need to add it to > > > > > include/tst_fs.h => 0x01161970) and quit the test with tst_brk(TCONF) if TMPDIR > > > > > is not on gfs2. > > > > > > ATM we don't have any helper in struct tst_test, which would do it. > > > > > > I will mention that gfs2 is only an example here. It becomes > > > > interesting when a file system implements its own .lock() callback OR > > > > if somebody wants to test file system core, when a filesystem does not > > > > implement its own .lock(). > > > > I see .lock is implemented in 9p, afs, ceph, cifs, ocfs2, orangefs, even NFS. > > > "file system core": do you mean VFS? Because that would be more usable than the > > > filesystems above (which are quite exotic). > > > > It depends here what they are doing in .lock() - If they just call > > locks_lock_file_wait() or similar helpers depending on the call, then > > they don't do much different than what vfs is doing. > > In case of gfs2/ocfs it is very special, it redirects their calls to > > DLM and DLM has its own whole posix implementation behind it. We only > > call locks_lock_file_wait() to keep the Linux bookkeeping in > > /proc/locks. > > > What I am doing here is mostly trusting the Linux implementation and > > comparing results from e.g. tmpfs with GFS2 and I found issues. > > > For now I trust the Linux implementation and check if we have a > > different result here. I need to be very careful here because > > GFS2/OCFS2 are cluster filesystems and the fcntl() interface was never > > made for cluster filesystems. However I currently only test "one node" > > locking and this should deliver the same results as tmpfs, etc. > > Thanks for info. I'm still not sure if this is useful only for gfs2/ocfs > and we should prepare block device with gfs2 or ocfs and test filesystem on it. > Or if it would be useful to test other filesystem implementation. In this latter > case we usually use .all_filesystems (we don't have proper docs for > .all_filesystems, the closest is [1]) and test is then run on various common > filesystems (see fs_type_whitelist[] in lib/tst_supported_fs_types.c), but in > that case gfs2 would be skipped (it's not a common filesystem). > > In case preparing block device with gfs2 something like this might work: > > static struct tst_test test = { > ... > .dev_fs_type = "gfs2", > .format_device = 1, > .dev_fs_opts = (const char *const []){ "-t", "mycluster:mygfs2", "-p", "lock_dlm", "-j" , "2" , NULL}, > Can I override this setting by some ENV because I actually want to run it on a different filesystem which is using VFS posix lock implementation, because as I said I want to compare the results. - Alex
> Hi, > On Fri, Jul 7, 2023 at 4:14 AM Petr Vorel <pvorel@suse.cz> wrote: > > > Hi, > > > On Sun, Jul 2, 2023 at 3:18 PM Petr Vorel <pvorel@suse.cz> wrote: > > > > Hi Alex, > > > > ... > > > > > > > + * [Description] > > > > > > > + * Tests gfs2 dlm posix op queue handling in the kernel. > > > > > > > + * It is recommended to run watch -n 0.1 "dlm_tool plocks $LS" > > > > > > > + * aside to monitor dlm plock handling. > > > > > > > + * > > > > > > > + * [How to use it] > > > > > > > + * Call it with TMPDIR=/mnt ./fcntl40 where TMPDIR is a gfs2 mountpoint. > > > > > > I wonder if we could check for GFS2_MAGIC (we'd need to add it to > > > > > > include/tst_fs.h => 0x01161970) and quit the test with tst_brk(TCONF) if TMPDIR > > > > > > is not on gfs2. > > > > > > ATM we don't have any helper in struct tst_test, which would do it. > > > > > I will mention that gfs2 is only an example here. It becomes > > > > > interesting when a file system implements its own .lock() callback OR > > > > > if somebody wants to test file system core, when a filesystem does not > > > > > implement its own .lock(). > > > > I see .lock is implemented in 9p, afs, ceph, cifs, ocfs2, orangefs, even NFS. > > > > "file system core": do you mean VFS? Because that would be more usable than the > > > > filesystems above (which are quite exotic). > > > It depends here what they are doing in .lock() - If they just call > > > locks_lock_file_wait() or similar helpers depending on the call, then > > > they don't do much different than what vfs is doing. > > > In case of gfs2/ocfs it is very special, it redirects their calls to > > > DLM and DLM has its own whole posix implementation behind it. We only > > > call locks_lock_file_wait() to keep the Linux bookkeeping in > > > /proc/locks. > > > What I am doing here is mostly trusting the Linux implementation and > > > comparing results from e.g. tmpfs with GFS2 and I found issues. > > > For now I trust the Linux implementation and check if we have a > > > different result here. I need to be very careful here because > > > GFS2/OCFS2 are cluster filesystems and the fcntl() interface was never > > > made for cluster filesystems. However I currently only test "one node" > > > locking and this should deliver the same results as tmpfs, etc. > > Thanks for info. I'm still not sure if this is useful only for gfs2/ocfs > > and we should prepare block device with gfs2 or ocfs and test filesystem on it. > > Or if it would be useful to test other filesystem implementation. In this latter > > case we usually use .all_filesystems (we don't have proper docs for > > .all_filesystems, the closest is [1]) and test is then run on various common > > filesystems (see fs_type_whitelist[] in lib/tst_supported_fs_types.c), but in > > that case gfs2 would be skipped (it's not a common filesystem). > > In case preparing block device with gfs2 something like this might work: > > static struct tst_test test = { > > ... > > .dev_fs_type = "gfs2", > > .format_device = 1, > > .dev_fs_opts = (const char *const []){ "-t", "mycluster:mygfs2", "-p", "lock_dlm", "-j" , "2" , NULL}, > Can I override this setting by some ENV because I actually want to run > it on a different filesystem which is using VFS posix lock > implementation, because as I said I want to compare the results. Sure, there is LTP_DEV_FS_TYPE. But the point is to write test which will be useful for the default scenario. Kind regards, Petr > - Alex
diff --git a/testcases/kernel/syscalls/fcntl/.gitignore b/testcases/kernel/syscalls/fcntl/.gitignore index 10cb0995f..e558cfe83 100644 --- a/testcases/kernel/syscalls/fcntl/.gitignore +++ b/testcases/kernel/syscalls/fcntl/.gitignore @@ -74,3 +74,5 @@ /fcntl38_64 /fcntl39 /fcntl39_64 +/fcntl40 +/fcntl40_64 diff --git a/testcases/kernel/syscalls/fcntl/Makefile b/testcases/kernel/syscalls/fcntl/Makefile index df663a50a..c3196a527 100644 --- a/testcases/kernel/syscalls/fcntl/Makefile +++ b/testcases/kernel/syscalls/fcntl/Makefile @@ -12,6 +12,9 @@ fcntl34_64: LDLIBS += -lpthread fcntl36: LDLIBS += -lpthread fcntl36_64: LDLIBS += -lpthread +fcntl40: LDLIBS += -lpthread +fcntl40_64: LDLIBS += -lpthread + include $(top_srcdir)/include/mk/testcases.mk include $(abs_srcdir)/../utils/newer_64.mk diff --git a/testcases/kernel/syscalls/fcntl/fcntl40.c b/testcases/kernel/syscalls/fcntl/fcntl40.c new file mode 100644 index 000000000..829685436 --- /dev/null +++ b/testcases/kernel/syscalls/fcntl/fcntl40.c @@ -0,0 +1,188 @@ +/* + * [Description] + * Tests gfs2 dlm posix op queue handling in the kernel. + * It is recommended to run watch -n 0.1 "dlm_tool plocks $LS" + * aside to monitor dlm plock handling. + * + * [How to use it] + * Call it with TMPDIR=/mnt ./fcntl40 where TMPDIR is a gfs2 mountpoint. + * Try it on other filesystems to compare results. + * + * [What's it doing] + * + * The test shows that we currently have problems with the operation lookup + * functionality [0] when we using threads. The owner value is the same for two + * locks being in WAITING state. dlm_controld "dlm_tool plocks $LS" will show + * it correctly that the specific lock is not in waiting anymore. The issue + * begins matching the right iter->done in the kernel at dev_write() see [0]. + * + * What this test does is (using dlm_controld interval range interpretation): + * + * parent: + * + * 1. lock[0-1] + * + * child: + * + * thread1: + * + * 2. lockw[1-1] - important 1-1 at first because the order of WAITING state + * locks matters + * + * thread2: + * + * 3. lockw[0-0] + * + * parent: + * + * 4. unlock[1-1] - will give a iter->done = 1 in [0] for lock at 3. and the + * application results in a deadlock + * 5. unlock[0-0] + * + * We have this issue also with SETLK, GETLK - it's easier to reproduce + * with SETLKW because dev_write() is more controlable by doing unlocks. + * + * OFD (open filedescriptor locks) are also affected and should be able + * to reproduce with fork() only and not threads. The owner value of [0] + * depends on "struct file *" pointer in this case. + * + * [0] https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/tree/fs/dlm/plock.c?h=v6.3#n432 + */ + +#include <sys/wait.h> +#include <pthread.h> + +#include "tst_safe_pthread.h" +#include "tst_test.h" + +static int fd; + +static void *do_thread1(void *arg) +{ + const struct flock fl_0_0 = { + .l_type = F_WRLCK, + .l_whence = SEEK_SET, + .l_start = 0L, + .l_len = 1L, + }; + (void)arg; + + tst_res(TINFO, "thread1 waits for thread2 to lock 1-1"); + TST_CHECKPOINT_WAIT(1); + + tst_res(TINFO, "thread1 lock region 0-0 - It should block"); + SAFE_FCNTL(fd, F_SETLKW, &fl_0_0); + tst_res(TINFO, "lock region 0-0 acquired"); + + return NULL; +} + +static void *do_thread2(void *arg) +{ + const struct flock fl_1_1 = { + .l_type = F_WRLCK, + .l_whence = SEEK_SET, + .l_start = 1L, + .l_len = 1L, + }; + (void)arg; + + tst_res(TINFO, "thread1 lock region 1-1 - It should block"); + SAFE_FCNTL(fd, F_SETLKW, &fl_1_1); + tst_res(TINFO, "lock region 1-1 acquired"); + + TST_CHECKPOINT_WAKE(2); + + return NULL; +} + +void do_child(void) +{ + pthread_t t1, t2; + + SAFE_PTHREAD_CREATE(&t1, NULL, do_thread1, NULL); + SAFE_PTHREAD_CREATE(&t2, NULL, do_thread2, NULL); + + SAFE_PTHREAD_JOIN(t1, NULL); + SAFE_PTHREAD_JOIN(t2, NULL); + + tst_res(TPASS, "Child passed!"); +} + +void do_parent(void) +{ + struct flock fl = { + .l_whence = SEEK_SET, + }; + + /* wait for 1 seconds so thread2 lock 1-1 tries to acquires at first + * than thread1 lock 0-0 tries to acquired to have a specific waiting + * order in dlm posix handling. + */ + sleep(1); + /* tell thread2 to call SETLKW for lock 0-0 */ + TST_CHECKPOINT_WAKE(1); + /* wait 3 seconds for thread 1 and 2 being in waiting state */ + sleep(3); + + /* unlock 0-1, should be successful */ + fl.l_type = F_UNLCK; + fl.l_start = 1; + fl.l_len = 1; + tst_res(TINFO, "unlock region 1-1 thread2"); + SAFE_FCNTL(fd, F_SETLK, &fl); + + /* wait until thread 2 got acquired and leave waiting */ + TST_CHECKPOINT_WAIT(2); + + fl.l_start = 0; + fl.l_len = 1; + fl.l_type = F_UNLCK; + tst_res(TINFO, "unlock region 0-0 thread2"); + SAFE_FCNTL(fd, F_SETLK, &fl); +} + +static void fcntl40_test(void) +{ + struct flock fl = { + .l_type = F_WRLCK, + .l_whence = SEEK_SET, + .l_start = 0L, + .l_len = 2L, + }; + pid_t pid; + + tst_res(TINFO, "parent lock region 0-1 - should be successful"); + SAFE_FCNTL(fd, F_SETLK, &fl); + tst_res(TINFO, "parent region 0-1 locked"); + + pid = SAFE_FORK(); + if (pid == 0) { + do_child(); + return; + } + + do_parent(); + wait(NULL); + + tst_res(TPASS, "Parent passed!"); +} + +static void setup(void) +{ + fd = SAFE_OPEN("filename", O_RDWR | O_CREAT, 0700); +} + +static void cleanup(void) +{ + if (fd > -1) + SAFE_CLOSE(fd); +} + +static struct tst_test test = { + .forks_child = 1, + .needs_checkpoints = 1, + .test_all = fcntl40_test, + .setup = setup, + .cleanup = cleanup, +};
This patch adds fcntl40 to test similar owner values for classical owner locks. There was an issue been found in the gfs2 filesystem because there can be collisions with identical owner values. Signed-off-by: Alexander Aring <aahringo@redhat.com> --- testcases/kernel/syscalls/fcntl/.gitignore | 2 + testcases/kernel/syscalls/fcntl/Makefile | 3 + testcases/kernel/syscalls/fcntl/fcntl40.c | 188 +++++++++++++++++++++ 3 files changed, 193 insertions(+) create mode 100644 testcases/kernel/syscalls/fcntl/fcntl40.c