Skip to contentSkip to conversation

syscalls/fcntl36: add tests for OFD locks

PATCH Superseded Xiong Zhou 2 participants 17 messages Aug 11, 2017 – Sep 5, 2017

lore
Share & tools
lore

Xiong Zhou

author
#0 lore raw

PATCH 1/1 syscalls/fcntl36: add tests for OFD locks

---
 testcases/kernel/syscalls/fcntl/Makefile  |   3 +
 testcases/kernel/syscalls/fcntl/fcntl36.c | 315 ++++++++++++++++++++++++++++++
 2 files changed, 318 insertions(+)
 create mode 100644 testcases/kernel/syscalls/fcntl/fcntl36.c
testcases/kernel/syscalls/fcntl/Makefile +3 -0
index d78dd72..ae37214 100644
@@ -24,6 +24,9 @@ fcntl33_64: LDLIBS+=-lrt
 fcntl34: LDLIBS += -lpthread
 fcntl34_64: LDLIBS += -lpthread
 
+fcntl36: LDLIBS += -lpthread
+fcntl36_64: LDLIBS += -lpthread
+
 include $(top_srcdir)/include/mk/testcases.mk
 include $(abs_srcdir)/../utils/newer_64.mk
 
testcases/kernel/syscalls/fcntl/fcntl36.c new file +315 -0

315 lines not on this page · raw message

Signature · 1 line
1.8.3.1
#1 lore raw

PATCH 1/1 syscalls/fcntl36: add tests for OFD locks

Hi!

Quoted 2 lines
 testcases/kernel/syscalls/fcntl/Makefile  |   3 +
 testcases/kernel/syscalls/fcntl/fcntl36.c | 315 ++++++++++++++++++++++++++++++

You have to add a record to the corresponding runtest file as well.

Quoted 35 lines
testcases/kernel/syscalls/fcntl/Makefile +3 -0
index d78dd72..ae37214 100644
@@ -24,6 +24,9 @@ fcntl33_64: LDLIBS+=-lrt
 fcntl34: LDLIBS += -lpthread
 fcntl34_64: LDLIBS += -lpthread
 
+fcntl36: LDLIBS += -lpthread
+fcntl36_64: LDLIBS += -lpthread
+
 include $(top_srcdir)/include/mk/testcases.mk
 include $(abs_srcdir)/../utils/newer_64.mk
 
testcases/kernel/syscalls/fcntl/fcntl36.c new file +15 -0
new file mode 100644
index 0000000..4c55279
@@ -0,0 +1,315 @@
+/*
+ * Copyright (c) 2017 Red Hat Inc. All Rights Reserved.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation; either version 2 of
+ * the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it would be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.

testcases/kernel/syscalls/fcntl/fcntl36.c line 25

Quoted 10 lines
testcases/kernel/syscalls/fcntl/fcntl36.c new file +10 -0
+ *
+ * Author: Xiong Zhou <[email protected]>
+ *
+ * This is testing OFD locks racing with POSIX locks:
+ *
+ *	OFD read  lock   vs   OFD   write lock
+ *	OFD read  lock   vs   POSIX write lock
+ *	OFD write lock   vs   POSIX write lock
+ *	OFD write lock   vs   POSIX read  lock
+ *	OFD write lock   vs   OFD   write lock

What exactly are we trying to test here? This description should be more verbose.

Quoted 31 lines
testcases/kernel/syscalls/fcntl/fcntl36.c new file +31 -0
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <unistd.h>
+#include <stdio.h>
+#include <fcntl.h>
+#include <pthread.h>
+#include <sched.h>
+#include <errno.h>
+
+#include "lapi/fcntl.h"
+#include "tst_safe_pthread.h"
+#include "tst_test.h"
+
+static int thread_cnt;
+static const int max_thread_cnt = 32;
+static const char fname[] = "tst_ofd_locks";
+static int write_flag_cnt;
+const int write_size = 4096;
+
+static void setup(void)
+{
+	thread_cnt = tst_ncpus_conf() * 3;
+	if (thread_cnt > max_thread_cnt)
+		thread_cnt = max_thread_cnt;
+}
+
+static void spawn_threads(pthread_t *id, void *(*thread_fn)(void *))
+{
+	intptr_t i;
+
+	for (i = 0; i < thread_cnt; ++i)

testcases/kernel/syscalls/fcntl/fcntl36.c line 69

Quoted 10 lines
testcases/kernel/syscalls/fcntl/fcntl36.c new file +10 -0
+		SAFE_PTHREAD_CREATE(id + i, NULL, thread_fn, (void *)i);
+}
+
+static void wait_threads(pthread_t *id)
+{
+	int i;
+
+	for (i = 0; i < thread_cnt; ++i)
+		SAFE_PTHREAD_JOIN(id[i], NULL);
+}

Now these two functions are a bit unconsitent since the thread_cnt is passed in global variable while the id is passed as a parameter. It would be a bit cleaner if we passed both as a parameter.

testcases/kernel/syscalls/fcntl/fcntl36.c line 80

Quoted 10 lines
testcases/kernel/syscalls/fcntl/fcntl36.c new file +10 -0
+/* Loop OFD wlock writing data*/
+static void *thread_fn_ofd_wlock(void *arg)
+{
+	unsigned char buf[write_size];
+	long start = (intptr_t)arg * write_size;
+	int fd = SAFE_OPEN(fname, O_RDWR);
+	int i = 0;
+
+	/* write with half writesize offset in the second spawning */
+	start += (write_flag_cnt % 2) * write_size / 2;

Why do we do this?

I guess that it's for the case where we run OFD wlocks concurently and we want them to overlap.

However there are a few problems with this approach, one is that propagating pthread parameters via global variables is not safe. There is no guarantee that all the threads has already finished setting the start variable when we change it in the main thread. The clean solution to this problem is to pack the paramters into a structure and pass it to this function as a paramter, which would in turn mean that we have to prepare an array of these structures in the main thread, we can do that on the stack in the test function since we wait all the threads before we leave it (otherwise we would end up using part of stack that will be rewritten later).

If we move the loop that creates the threads to the test function we can do something as:

struct param {
	long offset;
	long length;
};

...
void do_test(...)

{
	...

	struct param params[threads_cnt];

	for (i = 0; i < threads_cnt; i++) {
		params[i].offset = ...;
		params[i].lenght = ...;
		SAFE_PTHREAD_CREATE(id + i, NULL, fn, params);
	}

	...

	for (i = 0; i < threads_cnt; i++)
		SAFE_PTHREAD_JOIN(id[i]);

	...
}
Quoted 18 lines
testcases/kernel/syscalls/fcntl/fcntl36.c new file +18 -0
+	memset(buf, 'o', write_size);
+
+	struct flock64 lck = {
+		.l_whence = SEEK_SET,
+		.l_start  = start,
+		.l_len    = write_size,
+		.l_pid    = 0,
+	};
+
+	struct timespec ts = {
+               .tv_sec = 0,
+               .tv_nsec = 50000000,
+	};
+
+	for (; i < thread_cnt; i++) {
+
+		lck.l_type = F_WRLCK;
+		SAFE_FCNTL(fd, F_OFD_SETLKW, &lck);

testcases/kernel/syscalls/fcntl/fcntl36.c line 108

Quoted 10 lines
testcases/kernel/syscalls/fcntl/fcntl36.c new file +10 -0
+
+		SAFE_LSEEK(fd, start, SEEK_SET);
+		SAFE_WRITE(1, fd, buf, write_size);
+
+		lck.l_type = F_UNLCK;
+		SAFE_FCNTL(fd, F_OFD_SETLKW, &lck);
+
+		nanosleep(&ts, NULL);
+		sched_yield();
+	}

I do not get why we loop thread_cnt times here at all and why do we call the nanosleep() between the locking attempts.

Quoted 54 lines
testcases/kernel/syscalls/fcntl/fcntl36.c new file +54 -0
+	SAFE_CLOSE(fd);
+
+	return NULL;
+}
+
+/* Loop POSIX wlock writing data*/
+static void *thread_fn_posix_wlock(void *arg)
+{
+	unsigned char buf[write_size];
+	long start = (intptr_t)arg * write_size;
+	int fd = SAFE_OPEN(fname, O_RDWR);
+	int i = 0;
+
+	memset(buf, 'p', write_size);
+
+	struct flock64 lck = {
+		.l_whence = SEEK_SET,
+		.l_start  = start,
+		.l_len    = write_size,
+	};
+
+	for (; i < thread_cnt; i++) {
+
+		lck.l_type = F_WRLCK;
+		SAFE_FCNTL(fd, F_SETLKW, &lck);
+
+		SAFE_LSEEK(fd, start, SEEK_SET);
+		SAFE_WRITE(1, fd, buf, write_size);
+
+		lck.l_type = F_UNLCK;
+		SAFE_FCNTL(fd, F_SETLKW, &lck);
+
+		sched_yield();
+	}
+
+	SAFE_CLOSE(fd);
+
+	return NULL;
+}
+
+/* Loop OFD rlock reading data*/
+static void *thread_fn_ofd_rlock(void *arg)
+{
+	unsigned char buf[write_size];
+	long start = (intptr_t)arg * write_size;
+	int fd = SAFE_OPEN(fname, O_RDWR);
+	int i = 0;
+
+	memset(buf, (intptr_t)arg, write_size);
+
+	struct flock64 lck = {
+		.l_whence = SEEK_SET,
+		.l_start  = start,
+		.l_len    = write_size,

testcases/kernel/syscalls/fcntl/fcntl36.c line 173

Quoted 10 lines
testcases/kernel/syscalls/fcntl/fcntl36.c new file +10 -0
+		.l_pid    = 0,
+	};
+
+	for (; i < thread_cnt; i++) {
+
+		lck.l_type = F_RDLCK;
+		if (fcntl(fd, F_OFD_SETLK, &lck) == -1) {
+			/* can only fail with EAGAIN */
+			if (errno != EAGAIN)
+				tst_brk(TBROK, "errno not equal to EAGAIN");

In which case do we get EAGAIN?

Also the tst_brk should include TERRNO here.

testcases/kernel/syscalls/fcntl/fcntl36.c line 178

Quoted 5 lines
testcases/kernel/syscalls/fcntl/fcntl36.c new file +5 -0
+		} else {
+
+			/* rlock acquired */
+			SAFE_LSEEK(fd, start, SEEK_SET);
+			SAFE_READ(0, fd, buf, write_size);

Shouldn't we check here that the whole block has the same value?

Since in the combination where we run writers vs readers the check that the file has consistent content at the end of the run does not really check anything.

Also each of the writers should write a random character into its block and the value should change on each iteration. Then we can check that the readers see only consistently filled blocks.

Quoted 29 lines
testcases/kernel/syscalls/fcntl/fcntl36.c new file +29 -0
+			lck.l_type = F_UNLCK;
+			SAFE_FCNTL(fd, F_OFD_SETLK, &lck);
+		}
+		sched_yield();
+	}
+
+	SAFE_CLOSE(fd);
+
+	return NULL;
+}
+
+/* Loop POSIX rlock reading data */
+static void *thread_fn_posix_rlock(void *arg)
+{
+	unsigned char buf[write_size];
+	long start = (intptr_t)arg * write_size;
+	int fd = SAFE_OPEN(fname, O_RDWR);
+	int i = 0;
+
+	memset(buf, (intptr_t)arg, write_size);
+
+	struct flock64 lck = {
+		.l_whence = SEEK_SET,
+		.l_start  = start,
+		.l_len    = write_size,
+	};
+
+	for (; i < thread_cnt; i++) {
+

testcases/kernel/syscalls/fcntl/fcntl36.c line 218

Quoted 10 lines
testcases/kernel/syscalls/fcntl/fcntl36.c new file +10 -0
+		lck.l_type = F_RDLCK;
+		if (fcntl(fd, F_SETLK, &lck) == -1) {
+			/* can only fail with EAGAIN */
+			if (errno != EAGAIN)
+				tst_brk(TBROK, "errno not equal to EAGAIN");
+		} else {
+
+			/* rlock acquired */
+			SAFE_LSEEK(fd, start, SEEK_SET);
+			SAFE_READ(0, fd, buf, write_size);

And here as well.

Quoted 36 lines
testcases/kernel/syscalls/fcntl/fcntl36.c new file +36 -0
+			lck.l_type = F_UNLCK;
+			SAFE_FCNTL(fd, F_SETLK, &lck);
+		}
+		sched_yield();
+	}
+
+	SAFE_CLOSE(fd);
+
+	return NULL;
+}
+
+static int test_fn(void *f0(void *), void *f1(void *))
+{
+	intptr_t i;
+	int k;
+	pthread_t id0[thread_cnt];
+	pthread_t id1[thread_cnt];
+	unsigned char buf[write_size];
+
+	int fd = SAFE_OPEN(fname, O_CREAT | O_TRUNC | O_RDWR, 0600);
+
+	spawn_threads(id0, f0);
+	write_flag_cnt++;
+	spawn_threads(id1, f1);
+
+	wait_threads(id0);
+	wait_threads(id1);
+
+	tst_res(TINFO, "Verifying file's data");
+	SAFE_LSEEK(fd, 0, SEEK_SET);
+
+	for (i = 0; i <= thread_cnt; ++i) {
+
+		SAFE_READ(1, fd, buf, write_size/2);
+
+		if (buf[0] != 'o' && buf[0] != 'p') {

testcases/kernel/syscalls/fcntl/fcntl36.c line 308

Quoted 10 lines
testcases/kernel/syscalls/fcntl/fcntl36.c new file +10 -0
+			tst_res(TFAIL, "unexpected data read");
+			return -1;
+		}
+
+		for (k = 1; k < write_size/2; ++k) {
+			if (buf[k] != buf[0]) {
+				tst_res(TFAIL, "unexpected block read");
+				return -1;
+			}
+		}

This check is really needed only in a case that we run two writers concurently, but I guess that doing it at the end of the test does not harm.

Quoted 32 lines
testcases/kernel/syscalls/fcntl/fcntl36.c new file +32 -0
+	}
+	SAFE_CLOSE(fd);
+
+	return 0;
+}
+
+static void tests(void)
+{
+	int ret = 0;
+
+	tst_res(TINFO, "OFD read locks vs OFD write locks");
+	ret = test_fn(thread_fn_ofd_wlock, thread_fn_ofd_rlock);
+	if (ret == 0)
+		tst_res(TPASS, "access between threads synchronized");
+
+	ret = 0;
+	write_flag_cnt = 0;
+	tst_res(TINFO, "OFD write locks vs POSIX write locks");
+	ret = test_fn(thread_fn_ofd_wlock, thread_fn_posix_wlock);
+	if (ret == 0)
+		tst_res(TPASS, "access between threads synchronized");
+
+	ret = 0;
+	write_flag_cnt = 0;
+	tst_res(TINFO, "OFD read locks vs POSIX write locks");
+	ret = test_fn(thread_fn_ofd_rlock, thread_fn_posix_wlock);
+	if (ret == 0)
+		tst_res(TPASS, "access between threads synchronized");
+
+	ret = 0;
+	write_flag_cnt = 0;
+	tst_res(TINFO, "OFD write locks vs POSIX read locks");

testcases/kernel/syscalls/fcntl/fcntl36.c line 307

Quoted 10 lines
testcases/kernel/syscalls/fcntl/fcntl36.c new file +10 -0
+	ret = test_fn(thread_fn_ofd_wlock, thread_fn_posix_rlock);
+	if (ret == 0)
+		tst_res(TPASS, "access between threads synchronized");
+
+	ret = 0;
+	write_flag_cnt = 0;
+	tst_res(TINFO, "OFD write locks vs OFD write locks");
+	ret = test_fn(thread_fn_ofd_wlock, thread_fn_ofd_wlock);
+	if (ret == 0)
+		tst_res(TPASS, "access between threads synchronized");

Can we split this into a separate tests? Just create a structure with two funciton pointers and a string for a description and we can use .test with an index into an array of these.

Also there is no reason to print the TPASS message here, why don't we do that in the test_fn() function?

And there is absolutely no need to zero the ret variable as well and the write_flag_cnt should be reset in the test_fn() where it's actually set.

testcases/kernel/syscalls/fcntl/fcntl36.c line 311

Quoted 4 lines
testcases/kernel/syscalls/fcntl/fcntl36.c new file +4 -0
+}
+
+static struct tst_test test = {
+	.min_kver = "3.15.0",

^
No need for the .0 at the end "3.15" is a valid version string.

Quoted 10 lines
testcases/kernel/syscalls/fcntl/fcntl36.c new file +4 -0
+	.needs_tmpdir = 1,
+	.test_all = tests,
+	.setup = setup
+};
Signature · 5 lines
1.8.3.1


-- 
Mailing list info: https://lists.linux.it/listinfo/ltp
Signature · 2 lines
Cyril Hrubis
[email protected]
author
#2 lore raw

PATCH v2 1/1 syscalls/fcntl36: add tests for OFD locks

---

v2:
Basically rewritten.
Pass structure parameter to threads.
Block on read lock.
Spawn racing threads one by one.
Use tcnt iteration.

 runtest/syscalls                          |   2 +
 testcases/kernel/syscalls/fcntl/Makefile  |   3 +
 testcases/kernel/syscalls/fcntl/fcntl36.c | 380 ++++++++++++++++++++++++++++++
 3 files changed, 385 insertions(+)
 create mode 100644 testcases/kernel/syscalls/fcntl/fcntl36.c
runtest/syscalls +2 -0
index 407e055..f2b2cbc 100644
@@ -271,6 +271,8 @@ fcntl34 fcntl34
 fcntl34_64 fcntl34_64
 fcntl35 fcntl35
 fcntl35_64 fcntl35_64
+fcntl36 fcntl36
+fcntl36_64 fcntl36_64
 
 fdatasync01 fdatasync01
 fdatasync02 fdatasync02
testcases/kernel/syscalls/fcntl/Makefile +3 -0
index d78dd72..ae37214 100644
@@ -24,6 +24,9 @@ fcntl33_64: LDLIBS+=-lrt
 fcntl34: LDLIBS += -lpthread
 fcntl34_64: LDLIBS += -lpthread
 
+fcntl36: LDLIBS += -lpthread
+fcntl36_64: LDLIBS += -lpthread
+
 include $(top_srcdir)/include/mk/testcases.mk
 include $(abs_srcdir)/../utils/newer_64.mk
 
testcases/kernel/syscalls/fcntl/fcntl36.c new file +380 -0

380 lines not on this page · raw message

Signature · 1 line
1.8.3.1
#3 lore raw

PATCH v2 1/1 syscalls/fcntl36: add tests for OFD locks

Hi!

Quoted 62 lines
testcases/kernel/syscalls/fcntl/fcntl36.c new file +62 -0
+/*
+ * Copyright (c) 2017 Red Hat Inc. All Rights Reserved.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation; either version 2 of
+ * the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it would be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ *
+ * Author: Xiong Zhou <[email protected]>
+ *
+ * This is testing OFD locks racing with POSIX locks:
+ *
+ *	OFD read  lock   vs   OFD   write lock
+ *	OFD read  lock   vs   POSIX write lock
+ *	OFD write lock   vs   POSIX write lock
+ *	OFD write lock   vs   POSIX read  lock
+ *	OFD write lock   vs   OFD   write lock
+ *
+ * For example:
+ *
+ * 	Init an file with preset values.
+ *
+ * 	Threads acquire OFD READ  locks to read  a 4k section start from 0;
+ * 		checking data read back, there should not be any surprise
+ * 		values and data should be consistent in a 2k block.
+ *
+ * 	Threads acquire OFD WRITE locks to write a 4k section start from 2k,
+ * 		writing different values in different threads.
+ *
+ * 	Check file data after racing, there should not be any surprise values
+ * 		and data should be consistent in a 2k block.
+ *
+ *
+ */
+
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <unistd.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <fcntl.h>
+#include <pthread.h>
+#include <sched.h>
+#include <errno.h>
+
+#include "lapi/fcntl.h"
+#include "tst_safe_pthread.h"
+#include "tst_test.h"
+
+static int thread_cnt;
+static const int max_thread_cnt = 32;
+static const char fname[] = "tst_ofd_posix_locks";
+const long write_size = 4096;
+

testcases/kernel/syscalls/fcntl/fcntl36.c line 72

Quoted 10 lines
testcases/kernel/syscalls/fcntl/fcntl36.c new file +10 -0
+struct param {
+	long offset;
+	long length;
+	long cnt;
+};
+
+static void setup(void)
+{
+	int fd = SAFE_OPEN(fname, O_CREAT | O_TRUNC | O_RDWR, 0600);
+	char *s = NULL;

There is not need to initialize the variable since it's set just a few lines below.

testcases/kernel/syscalls/fcntl/fcntl36.c line 86

Quoted 13 lines
testcases/kernel/syscalls/fcntl/fcntl36.c new file +13 -0
+	thread_cnt = tst_ncpus_conf() * 3;
+	if (thread_cnt > max_thread_cnt)
+		thread_cnt = max_thread_cnt;
+
+	s = SAFE_MALLOC(thread_cnt * write_size);
+	memset(s, 1, thread_cnt * write_size);
+	SAFE_WRITE(1, fd, s, thread_cnt * write_size);
+
+	SAFE_CLOSE(fd);
+	if (s) {
+		free(s);
+		s = NULL;
+	}

And there is no need both for the if (), since free(NULL) is no-op and for the s = NULL since the variable gets out of scope anyway.

Moreover we do have tst_fill_file() function exactly for this purpose.

Quoted 97 lines
testcases/kernel/syscalls/fcntl/fcntl36.c new file +97 -0
+}
+
+static void spawn_threads(int cnt, pthread_t *id0, pthread_t *id1,
+		void *(*thread_f0)(void *), void *(*thread_f1)(void *),
+		struct param *p0, struct param *p1)
+{
+	int i;
+
+	for (i = 0; i < cnt; i++) {
+		SAFE_PTHREAD_CREATE(id0 + i, NULL, thread_f0, (void *)&p0[i]);
+		SAFE_PTHREAD_CREATE(id1 + i, NULL, thread_f1, (void *)&p1[i]);
+	}
+}
+
+static void wait_threads(int cnt, pthread_t *id0, pthread_t *id1)
+{
+	int i;
+
+	for (i = 0; i < cnt; i++) {
+		SAFE_PTHREAD_JOIN(id0[i], NULL);
+		SAFE_PTHREAD_JOIN(id1[i], NULL);
+	}
+}
+
+/* OFD write lock writing data*/
+static void *fn_ofd_w(void *arg)
+{
+	unsigned char buf[write_size];
+	struct param *pa = (struct param *)arg;
+	int fd = SAFE_OPEN(fname, O_RDWR);
+
+	struct flock64 lck = {
+		.l_whence = SEEK_SET,
+		.l_start  = pa->offset,
+		.l_len    = pa->length,
+		.l_pid    = 0,
+	};
+
+	memset(buf, pa->cnt, write_size);
+
+	lck.l_type = F_WRLCK;
+	SAFE_FCNTL(fd, F_OFD_SETLKW, &lck);
+
+	SAFE_LSEEK(fd, pa->offset, SEEK_SET);
+	SAFE_WRITE(1, fd, buf, pa->length);
+
+	lck.l_type = F_UNLCK;
+	SAFE_FCNTL(fd, F_OFD_SETLKW, &lck);
+
+	sched_yield();
+	SAFE_CLOSE(fd);
+
+	return NULL;
+}
+
+/* POSIX write lock writing data*/
+static void *fn_posix_w(void *arg)
+{
+	unsigned char buf[write_size];
+	struct param *pa = (struct param *)arg;
+	int fd = SAFE_OPEN(fname, O_RDWR);
+
+	memset(buf, pa->cnt, write_size);
+
+	struct flock64 lck = {
+		.l_whence = SEEK_SET,
+		.l_start  = pa->offset,
+		.l_len    = pa->length,
+	};
+
+	lck.l_type = F_WRLCK;
+	SAFE_FCNTL(fd, F_SETLKW, &lck);
+
+	SAFE_LSEEK(fd, pa->offset, SEEK_SET);
+	SAFE_WRITE(1, fd, buf, pa->length);
+
+	lck.l_type = F_UNLCK;
+	SAFE_FCNTL(fd, F_SETLKW, &lck);
+
+	sched_yield();
+	SAFE_CLOSE(fd);
+
+	return NULL;
+}
+
+/* OFD read lock reading data*/
+static void *fn_ofd_r(void *arg)
+{
+	unsigned char buf[write_size];
+	struct param *pa = (struct param *)arg;
+	int i;
+	int fd = SAFE_OPEN(fname, O_RDWR);
+
+	memset(buf, 0, write_size);
+
+	struct flock64 lck = {
+		.l_whence = SEEK_SET,

testcases/kernel/syscalls/fcntl/fcntl36.c line 193

Quoted 10 lines
testcases/kernel/syscalls/fcntl/fcntl36.c new file +10 -0
+		.l_start  = pa->offset,
+		.l_len    = pa->length,
+		.l_pid    = 0,
+	};
+
+	lck.l_type = F_RDLCK;
+	if (fcntl(fd, F_OFD_SETLKW, &lck) == -1) {
+
+		tst_brk(TBROK | TERRNO, "acquiring OFD read lock failed");
+	} else {

We can use SAFE_FCNTL() here since the file is pre-allocated, right?

Quoted 46 lines
testcases/kernel/syscalls/fcntl/fcntl36.c new file +46 -0
+
+		/* rlock acquired */
+		SAFE_LSEEK(fd, pa->offset, SEEK_SET);
+		SAFE_READ(1, fd, buf, pa->length);
+
+		/* Verifying data read */
+		for (i = 0; i < pa->length; i++) {
+
+			if (buf[i] < 1 || buf[i] > thread_cnt + 1) {
+				tst_res(TFAIL, "unexpected data "
+					"offset %ld value %d",
+					pa->offset + i, buf[i]);
+				break;
+			}
+
+			if ((i < pa->length / 2 && buf[i] != buf[0]) ||
+				(i >= pa->length / 2 &&
+					buf[i] != buf[pa->length / 2])) {
+				tst_res(TFAIL, "unexpected data "
+					"offset %ld value %d",
+					pa->offset + i, buf[i]);
+				break;
+			}
+		}
+
+		lck.l_type = F_UNLCK;
+		SAFE_FCNTL(fd, F_OFD_SETLK, &lck);
+	}
+
+	sched_yield();
+	SAFE_CLOSE(fd);
+
+	return NULL;
+}
+
+/* POSIX read lock reading data */
+static void *fn_posix_r(void *arg)
+{
+	unsigned char buf[write_size];
+	struct param *pa = (struct param *)arg;
+	int i;
+	int fd = SAFE_OPEN(fname, O_RDWR);
+
+	memset(buf, 0, write_size);
+
+	struct flock64 lck = {

testcases/kernel/syscalls/fcntl/fcntl36.c line 249

Quoted 10 lines
testcases/kernel/syscalls/fcntl/fcntl36.c new file +10 -0
+		.l_whence = SEEK_SET,
+		.l_start  = pa->offset,
+		.l_len    = pa->length,
+	};
+
+	lck.l_type = F_RDLCK;
+	if (fcntl(fd, F_SETLKW, &lck) == -1) {
+
+		tst_brk(TBROK | TERRNO, "acquiring OFD read lock failed");
+	} else {

And here as well.

Quoted 23 lines
testcases/kernel/syscalls/fcntl/fcntl36.c new file +23 -0
+		/* rlock acquired */
+		SAFE_LSEEK(fd, pa->offset, SEEK_SET);
+		SAFE_READ(1, fd, buf, pa->length);
+
+		/* Verifying data read */
+		for (i = 0; i < pa->length; i++) {
+
+			if (buf[i] < 1 || buf[i] > thread_cnt + 1) {
+				tst_res(TFAIL, "unexpected data, "
+					"offset %ld value %d",
+					pa->offset + i, buf[i]);
+				break;
+			}
+
+			if ((i < pa->length / 2 && buf[i] != buf[0]) ||
+				(i >= pa->length / 2 &&
+					buf[i] != buf[pa->length / 2])) {
+				tst_res(TFAIL, "unexpected data, "
+					"offset %ld value %d",
+					pa->offset + i, buf[i]);
+				break;
+			}
+		}

testcases/kernel/syscalls/fcntl/fcntl36.c line 283

Quoted 10 lines
testcases/kernel/syscalls/fcntl/fcntl36.c new file +10 -0
+
+		lck.l_type = F_UNLCK;
+		SAFE_FCNTL(fd, F_SETLK, &lck);
+	}
+
+	sched_yield();
+	SAFE_CLOSE(fd);
+
+	return NULL;
+}

These functions do just one iteration now. We should run them in a loop for some time in order stress the locks a bit. The easiest way would be to declare global volatile flag and loop while it's set in these functions, sleep in the main thread for a bit between spawn_threads() and join_threads() then reset the flag and join the threads. We can even add a test parameter for how long the test should run.

And if we do that we should as well change the value writers write on each iteration otherwise we wouldn't test anything after first iteration in the writer vs reader case. I would pass the cnt as it's done here but will increment it each iteration and set it to 2 once it reaches 256 in order to fit into a byte.

testcases/kernel/syscalls/fcntl/fcntl36.c line 286

Quoted 2 lines
testcases/kernel/syscalls/fcntl/fcntl36.c new file +2 -0
+/* Test different functions and verify data */
+static int test_fn(void *f0(void *), void *f1(void *), char *msg)

Again this should be just void since we do not use the returned value at all.

testcases/kernel/syscalls/fcntl/fcntl36.c line 295

Quoted 9 lines
testcases/kernel/syscalls/fcntl/fcntl36.c new file +9 -0
+{
+	int i, k, fd;
+	pthread_t id0[thread_cnt];
+	pthread_t id1[thread_cnt];
+	struct param p0[thread_cnt];
+	struct param p1[thread_cnt];
+	unsigned char buf[write_size];
+
+	setup();

This is not right, if we want to rewrite the test file before each test the code to write the file should be here and the setup should contain only the check for thread_cnt.

Quoted 10 lines
testcases/kernel/syscalls/fcntl/fcntl36.c new file +10 -0
+	tst_res(TINFO, msg);
+
+	for (i = 0; i < thread_cnt; i++) {
+
+		p0[i].offset = i * write_size;
+		p0[i].length = write_size;
+		p0[i].cnt = i + 2;
+
+		p1[i].offset = i * write_size;
+		p1[i].offset += write_size / 2;

testcases/kernel/syscalls/fcntl/fcntl36.c line 315

Quoted 10 lines
testcases/kernel/syscalls/fcntl/fcntl36.c new file +10 -0
+		p1[i].length = write_size;
+		p1[i].cnt = i + 2;
+	}
+
+	spawn_threads(thread_cnt, id0, id1, f0, f1, p0, p1);
+	wait_threads(thread_cnt, id0, id1);
+
+	tst_res(TINFO, "Verifying file's data");
+	fd = SAFE_OPEN(fname, O_RDWR);
+	memset(buf, 0, write_size);

Here again, we actually fill the buffer with data and we make sure that it has been filled (since we pass 1 to the SAFE_READ() as first paramter) hence there is absolutely no need to initialize the buffer here.

Quoted 47 lines
testcases/kernel/syscalls/fcntl/fcntl36.c new file +47 -0
+	SAFE_LSEEK(fd, 0, SEEK_SET);
+
+	for (i = 0; i <= thread_cnt; i++) {
+
+		SAFE_READ(1, fd, buf, write_size/2);
+
+		for (k = 0; k < write_size/2; k++) {
+
+			if (buf[k] < 2 || buf[k] > thread_cnt + 1) {
+				if (i == 0 && buf[k] == 1)
+					continue;
+				tst_res(TFAIL, "unexpected data, "
+					"offset %ld value %d",
+					i * write_size + k, buf[k]);
+				return -1;
+			}
+		}
+
+		for (k = 1; k < write_size/2; k++) {
+			if (buf[k] != buf[0]) {
+				tst_res(TFAIL, "unexpected block read");
+				return -1;
+			}
+		}
+	}
+
+	SAFE_CLOSE(fd);
+	tst_res(TPASS, "access between threads synchronized");
+
+	return 0;
+}
+
+static void tests(unsigned int i)
+{
+	switch (i) {
+	case 0:
+		test_fn(fn_ofd_r, fn_ofd_w,
+			"OFD read locks vs OFD write locks");
+		break;
+	case 1:
+		test_fn(fn_ofd_w, fn_posix_w,
+			"OFD write locks vs POSIX write locks");
+		break;
+	case 2:
+		test_fn(fn_ofd_r, fn_posix_w,
+			"OFD read locks vs POSIX write locks");
+		break;

testcases/kernel/syscalls/fcntl/fcntl36.c line 372

Quoted 10 lines
testcases/kernel/syscalls/fcntl/fcntl36.c new file +10 -0
+	case 3:
+		test_fn(fn_posix_r, fn_ofd_w,
+			"OFD write locks vs POSIX read locks");
+		break;
+	case 4:
+		test_fn(fn_ofd_w, fn_ofd_w,
+			"OFD write locks vs OFD write locks");
+		break;
+	}
+}

We may as well add these into a structure and use index into an array instead of the switch, something as:

static struct tcase {
	void* (*fn1)(void *);
	void* (*fn2)(void *);
	const char *desc;
} tcases[] = {
	{fn_ofd_r, fn_ofd_w, "OFD read locks vs OFD write locks"},
	...
};

static void tests(unsigned int i)

{
	test(tcase[i].fn0, tcase[i].fn1, tcase[i].desc);
}

testcases/kernel/syscalls/fcntl/fcntl36.c line 380

Quoted 7 lines
testcases/kernel/syscalls/fcntl/fcntl36.c new file +7 -0
+static struct tst_test test = {
+	.min_kver = "3.15",
+	.needs_tmpdir = 1,
+	.test = tests,
+	.tcnt = 5,
+	.setup = setup
+};

Otherwise it looks good.

Signature · 2 lines
Cyril Hrubis
[email protected]
author
#4 lore raw

PATCH v3 1/1 syscalls/fcntl36: add tests for OFD locks

Testing OFD locks racing with POSIX locks:

  OFD read  lock   vs   OFD   write lock
  OFD read  lock   vs   POSIX write lock
  OFD write lock   vs   POSIX write lock
  OFD write lock   vs   POSIX read  lock
  OFD write lock   vs   OFD   write lock

---

v3:
Use tst_fill_file.
Loop in test function.
Other fix.

v2:
Basically rewritten.
Pass structure parameter to threads.
Block on read lock.
Spawn racing threads one by one.
Use tcnt iteration.

 runtest/syscalls                          |   2 +
 testcases/kernel/syscalls/fcntl/Makefile  |   3 +
 testcases/kernel/syscalls/fcntl/fcntl36.c | 386 ++++++++++++++++++++++++++++++
 3 files changed, 391 insertions(+)
 create mode 100644 testcases/kernel/syscalls/fcntl/fcntl36.c
runtest/syscalls +2 -0
index 407e055..f2b2cbc 100644
@@ -271,6 +271,8 @@ fcntl34 fcntl34
 fcntl34_64 fcntl34_64
 fcntl35 fcntl35
 fcntl35_64 fcntl35_64
+fcntl36 fcntl36
+fcntl36_64 fcntl36_64
 
 fdatasync01 fdatasync01
 fdatasync02 fdatasync02
testcases/kernel/syscalls/fcntl/Makefile +3 -0
index d78dd72..ae37214 100644
@@ -24,6 +24,9 @@ fcntl33_64: LDLIBS+=-lrt
 fcntl34: LDLIBS += -lpthread
 fcntl34_64: LDLIBS += -lpthread
 
+fcntl36: LDLIBS += -lpthread
+fcntl36_64: LDLIBS += -lpthread
+
 include $(top_srcdir)/include/mk/testcases.mk
 include $(abs_srcdir)/../utils/newer_64.mk
 
testcases/kernel/syscalls/fcntl/fcntl36.c new file +386 -0

386 lines not on this page · raw message

Signature · 1 line
1.8.3.1
#5 lore raw

PATCH v3 1/1 syscalls/fcntl36: add tests for OFD locks

Hi!

Quoted 3 lines
 runtest/syscalls                          |   2 +
 testcases/kernel/syscalls/fcntl/Makefile  |   3 +
 testcases/kernel/syscalls/fcntl/fcntl36.c | 386 ++++++++++++++++++++++++++++++

Don't forget about .gitignore entry as well.

...

Quoted 24 lines
testcases/kernel/syscalls/fcntl/fcntl36.c new file +24 -0
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <unistd.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <fcntl.h>
+#include <pthread.h>
+#include <sched.h>
+#include <errno.h>
+
+#include "lapi/fcntl.h"
+#include "tst_safe_pthread.h"
+#include "tst_test.h"
+
+static int thread_cnt;
+static volatile int loop_flag;
+static const int max_thread_cnt = 32;
+static const char fname[] = "tst_ofd_posix_locks";
+static const long write_size = 4096;
+
+struct param {
+	long offset;
+	long length;
+	long cnt;

testcases/kernel/syscalls/fcntl/fcntl36.c line 77

Quoted 10 lines
testcases/kernel/syscalls/fcntl/fcntl36.c new file +10 -0
+};
+
+static void setup(void)
+{
+	thread_cnt = tst_ncpus_conf() * 3;
+	if (thread_cnt > max_thread_cnt)
+		thread_cnt = max_thread_cnt;
+}
+
+#define debug
             ^

Forget to remove this

Quoted 9 lines
testcases/kernel/syscalls/fcntl/fcntl36.c new file +9 -0
+/* OFD write lock writing data*/
+static void *fn_ofd_w(void *arg)
+{
+	unsigned char buf[write_size];
+	struct param *pa = (struct param *)arg;
+	int fd = SAFE_OPEN(fname, O_RDWR);
+	long wt = pa->cnt;
+
+	struct flock64 lck = {

testcases/kernel/syscalls/fcntl/fcntl36.c line 97

Quoted 10 lines
testcases/kernel/syscalls/fcntl/fcntl36.c new file +10 -0
+		.l_whence = SEEK_SET,
+		.l_start  = pa->offset,
+		.l_len    = pa->length,
+		.l_pid    = 0,
+	};
+
+	while (1) {
+
+		if (loop_flag == 1)
+			break;

Common, why not just while (loop_flag) ?

And we set the loop_flag to 1 before we spawn the threads and then reset it to 0 after we do the sleep.

Quoted 30 lines
testcases/kernel/syscalls/fcntl/fcntl36.c new file +30 -0
+		memset(buf, wt, write_size);
+
+		lck.l_type = F_WRLCK;
+		SAFE_FCNTL(fd, F_OFD_SETLKW, &lck);
+
+		SAFE_LSEEK(fd, pa->offset, SEEK_SET);
+		SAFE_WRITE(1, fd, buf, pa->length);
+
+		lck.l_type = F_UNLCK;
+		SAFE_FCNTL(fd, F_OFD_SETLKW, &lck);
+
+		wt++;
+		if (wt >= 255)
+			wt = pa->cnt;
+
+		sched_yield();
+	}
+
+	SAFE_CLOSE(fd);
+	return NULL;
+}
+
+/* POSIX write lock writing data*/
+static void *fn_posix_w(void *arg)
+{
+	unsigned char buf[write_size];
+	struct param *pa = (struct param *)arg;
+	int fd = SAFE_OPEN(fname, O_RDWR);
+	long wt = pa->cnt;
+

testcases/kernel/syscalls/fcntl/fcntl36.c line 138

Quoted 10 lines
testcases/kernel/syscalls/fcntl/fcntl36.c new file +10 -0
+	struct flock64 lck = {
+		.l_whence = SEEK_SET,
+		.l_start  = pa->offset,
+		.l_len    = pa->length,
+	};
+
+	while (1) {
+
+		if (loop_flag == 1)
+			break;

Here as well.

Quoted 31 lines
testcases/kernel/syscalls/fcntl/fcntl36.c new file +31 -0
+		memset(buf, wt, write_size);
+
+		lck.l_type = F_WRLCK;
+		SAFE_FCNTL(fd, F_SETLKW, &lck);
+
+		SAFE_LSEEK(fd, pa->offset, SEEK_SET);
+		SAFE_WRITE(1, fd, buf, pa->length);
+
+		lck.l_type = F_UNLCK;
+		SAFE_FCNTL(fd, F_SETLKW, &lck);
+
+		wt++;
+		if (wt >= 255)
+			wt = pa->cnt;
+
+		sched_yield();
+	}
+
+	SAFE_CLOSE(fd);
+	return NULL;
+}
+
+/* OFD read lock reading data*/
+static void *fn_ofd_r(void *arg)
+{
+	unsigned char buf[write_size];
+	struct param *pa = (struct param *)arg;
+	int i;
+	int fd = SAFE_OPEN(fname, O_RDWR);
+
+	struct flock64 lck = {

testcases/kernel/syscalls/fcntl/fcntl36.c line 180

Quoted 10 lines
testcases/kernel/syscalls/fcntl/fcntl36.c new file +10 -0
+		.l_whence = SEEK_SET,
+		.l_start  = pa->offset,
+		.l_len    = pa->length,
+		.l_pid    = 0,
+	};
+
+	while (1) {
+
+		if (loop_flag == 1)
+			break;

And here as well.

Quoted 11 lines
testcases/kernel/syscalls/fcntl/fcntl36.c new file +11 -0
+		memset(buf, 0, write_size);
+
+		lck.l_type = F_RDLCK;
+		SAFE_FCNTL(fd, F_OFD_SETLKW, &lck);
+
+		/* rlock acquired */
+		SAFE_LSEEK(fd, pa->offset, SEEK_SET);
+		SAFE_READ(1, fd, buf, pa->length);
+
+		/* Verifying data read */
+		for (i = 0; i < pa->length; i++) {

testcases/kernel/syscalls/fcntl/fcntl36.c line 202

Quoted 10 lines
testcases/kernel/syscalls/fcntl/fcntl36.c new file +10 -0
+
+			if (buf[i] < 1 || buf[i] > 254) {
+
+				tst_res(TFAIL, "Unexpected data "
+					"offset %ld value %d",
+					pa->offset + i, buf[i]);
+				break;
+			}
+
+			long tmp = pa->length / 2;

We can simplify this with:

			int j = i / (pa->length/2);

			if (buf[i] != buf[j]) {
				...
			}
Quoted 28 lines
testcases/kernel/syscalls/fcntl/fcntl36.c new file +28 -0
+			if ((i < tmp && buf[i] != buf[0]) ||
+			    (i >= tmp && buf[i] != buf[tmp])) {
+
+				tst_res(TFAIL, "Unexpected data "
+					"offset %ld value %d",
+					pa->offset + i, buf[i]);
+				break;
+			}
+		}
+
+		lck.l_type = F_UNLCK;
+		SAFE_FCNTL(fd, F_OFD_SETLK, &lck);
+
+		sched_yield();
+	}
+
+	SAFE_CLOSE(fd);
+	return NULL;
+}
+
+/* POSIX read lock reading data */
+static void *fn_posix_r(void *arg)
+{
+	unsigned char buf[write_size];
+	struct param *pa = (struct param *)arg;
+	int i;
+	int fd = SAFE_OPEN(fname, O_RDWR);
+

testcases/kernel/syscalls/fcntl/fcntl36.c line 241

Quoted 10 lines
testcases/kernel/syscalls/fcntl/fcntl36.c new file +10 -0
+	struct flock64 lck = {
+		.l_whence = SEEK_SET,
+		.l_start  = pa->offset,
+		.l_len    = pa->length,
+	};
+
+	while (1) {
+
+		if (loop_flag == 1)
+			break;

Here as well.

Quoted 11 lines
testcases/kernel/syscalls/fcntl/fcntl36.c new file +11 -0
+		memset(buf, 0, write_size);
+
+		lck.l_type = F_RDLCK;
+		SAFE_FCNTL(fd, F_SETLKW, &lck);
+
+		/* rlock acquired */
+		SAFE_LSEEK(fd, pa->offset, SEEK_SET);
+		SAFE_READ(1, fd, buf, pa->length);
+
+		/* Verifying data read */
+		for (i = 0; i < pa->length; i++) {

testcases/kernel/syscalls/fcntl/fcntl36.c line 263

Quoted 10 lines
testcases/kernel/syscalls/fcntl/fcntl36.c new file +10 -0
+
+			if (buf[i] < 1 || buf[i] > 254) {
+
+				tst_res(TFAIL, "Unexpected data, "
+					"offset %ld value %d",
+					pa->offset + i, buf[i]);
+				break;
+			}
+
+			long tmp = pa->length / 2;

And here as well.

Quoted 23 lines
testcases/kernel/syscalls/fcntl/fcntl36.c new file +23 -0
+			if ((i < tmp && buf[i] != buf[0]) ||
+			    (i >= tmp && buf[i] != buf[tmp])) {
+
+				tst_res(TFAIL, "Unexpected data, "
+					"offset %ld value %d",
+					pa->offset + i, buf[i]);
+				break;
+			}
+		}
+
+		lck.l_type = F_UNLCK;
+		SAFE_FCNTL(fd, F_SETLK, &lck);
+
+		sched_yield();
+	}
+
+	SAFE_CLOSE(fd);
+	return NULL;
+}
+
+/* Test different functions and verify data */
+static void test_fn(void *f0(void *), void *f1(void *), const char *msg)
+{

testcases/kernel/syscalls/fcntl/fcntl36.c line 297

Quoted 10 lines
testcases/kernel/syscalls/fcntl/fcntl36.c new file +10 -0
+	int i, k, fd;
+	pthread_t id0[thread_cnt];
+	pthread_t id1[thread_cnt];
+	struct param p0[thread_cnt];
+	struct param p1[thread_cnt];
+	unsigned char buf[write_size];
+
+	if (tst_fill_file(fname, 1, write_size, thread_cnt)) {
+		tst_brk(TBROK, "Failed to create tst file");
+	}

No need for the curly braces around single line statement here.

Quoted 11 lines
testcases/kernel/syscalls/fcntl/fcntl36.c new file +11 -0
+	tst_res(TINFO, msg);
+
+	for (i = 0; i < thread_cnt; i++) {
+
+		p0[i].offset = i * write_size;
+		p0[i].length = write_size;
+		p0[i].cnt = i + 2;
+
+		p1[i].offset = i * write_size;
+		p1[i].offset += write_size / 2;
+		p1[i].length = write_size;

testcases/kernel/syscalls/fcntl/fcntl36.c line 319

Quoted 10 lines
testcases/kernel/syscalls/fcntl/fcntl36.c new file +10 -0
+		p1[i].cnt = i + 2;
+	}
+
+	loop_flag = 0;
+	for (i = 0; i < thread_cnt; i++) {
+		SAFE_PTHREAD_CREATE(id0 + i, NULL, f0, (void *)&p0[i]);
+		SAFE_PTHREAD_CREATE(id1 + i, NULL, f1, (void *)&p1[i]);
+	}
+
+	sleep(3);

I would go fo 1s for default run, but that is very minor.

testcases/kernel/syscalls/fcntl/fcntl36.c line 328

Quoted 9 lines
testcases/kernel/syscalls/fcntl/fcntl36.c new file +9 -0
+	loop_flag = 1;
+	for (i = 0; i < thread_cnt; i++) {
+		SAFE_PTHREAD_JOIN(id0[i], NULL);
+		SAFE_PTHREAD_JOIN(id1[i], NULL);
+	}
+
+	tst_res(TINFO, "Verifying file's data");
+	fd = SAFE_OPEN(fname, O_RDWR);
+	SAFE_LSEEK(fd, 0, SEEK_SET);

We do not write to the file, so we may as well open it RDONLY and since we are opening it we don't have to seek it to the start.

Quoted 15 lines
testcases/kernel/syscalls/fcntl/fcntl36.c new file +15 -0
+	for (i = 0; i < thread_cnt * 2; i++) {
+
+		SAFE_READ(1, fd, buf, write_size/2);
+
+		for (k = 0; k < write_size/2; k++) {
+
+			if (buf[k] < 2 || buf[k] > 254) {
+
+				if (i == 0 && buf[k] == 1)
+					continue;
+				tst_res(TFAIL, "Unexpected data, "
+					"offset %ld value %d",
+					i * write_size / 2 + k, buf[k]);
+				return;
+			}

testcases/kernel/syscalls/fcntl/fcntl36.c line 354

Quoted 10 lines
testcases/kernel/syscalls/fcntl/fcntl36.c new file +10 -0
+		}
+
+		for (k = 1; k < write_size/2; k++) {
+
+			if (buf[k] != buf[0]) {
+				tst_res(TFAIL, "Unexpected block read");
+				return;
+			}
+		}
+	}

We should close the fd before the return here.

testcases/kernel/syscalls/fcntl/fcntl36.c line 357

Quoted 2 lines
testcases/kernel/syscalls/fcntl/fcntl36.c new file +2 -0
+	SAFE_CLOSE(fd);
+	tst_res(TPASS, "Access between threads synchronized");

And here we would print TPASS even if reader thread failed the test. So we should either change tst_res() to tst_brk() in the reader thread functions so that we exit the test if we read back wrong data. Or setup a global failure counter and print TPASS only if the counter was not set from one of the reader threads. Or propagate the failure from the tread return value (the one you get from SAFE_JOIN()).

Quoted 17 lines
testcases/kernel/syscalls/fcntl/fcntl36.c new file +17 -0
+}
+
+static struct tcase {
+
+	void *(*fn0)(void *);
+	void *(*fn1)(void *);
+	const char *desc;
+
+} tcases[] = {
+
+	{fn_ofd_r,   fn_ofd_w,   "OFD read locks vs OFD write locks"},
+	{fn_ofd_w,   fn_posix_w, "OFD write locks vs POSIX write locks"},
+	{fn_ofd_r,   fn_posix_w, "OFD read locks vs POSIX write locks"},
+	{fn_posix_r, fn_ofd_w,   "OFD write locks vs POSIX read locks"},
+	{fn_ofd_w,   fn_ofd_w,   "OFD write locks vs OFD write locks"},
+};
+

testcases/kernel/syscalls/fcntl/fcntl36.c line 384

Quoted 10 lines
testcases/kernel/syscalls/fcntl/fcntl36.c new file +10 -0
+static void tests(unsigned int i)
+{
+	test_fn(tcases[i].fn0, tcases[i].fn1, tcases[i].desc);
+}
+
+static struct tst_test test = {
+	.min_kver = "3.15",
+	.needs_tmpdir = 1,
+	.test = tests,
+	.tcnt = 5,

^
ARRAY_SIZE(tcases) is safer here, that way it will be correct even if we add/remove tests in the array.

Quoted 5 lines
testcases/kernel/syscalls/fcntl/fcntl36.c new file +2 -0
+	.setup = setup
+};
Signature · 1 line
1.8.3.1
Signature · 2 lines
Cyril Hrubis
[email protected]
author
#6 lore raw

PATCH v3 1/1 syscalls/fcntl36: add tests for OFD locks

Quoted 6 lines · Cyril Hrubis

Hi!

Quoted 3 lines
 runtest/syscalls                          |   2 +
 testcases/kernel/syscalls/fcntl/Makefile  |   3 +
 testcases/kernel/syscalls/fcntl/fcntl36.c | 386 ++++++++++++++++++++++++++++++

Don't forget about .gitignore entry as well.

Ha, now i found the right one, :)

Quoted 5 lines

...

Quoted 2 lines
testcases/kernel/syscalls/fcntl/fcntl36.c new file +2 -0
+#include <sys/types.h>
+#include <sys/stat.h>

...

Quoted 16 lines
Quoted 4 lines
testcases/kernel/syscalls/fcntl/fcntl36.c new file +4 -0
+		SAFE_READ(1, fd, buf, pa->length);
+
+		/* Verifying data read */
+		for (i = 0; i < pa->length; i++) {

testcases/kernel/syscalls/fcntl/fcntl36.c line 202

Quoted 10 lines
testcases/kernel/syscalls/fcntl/fcntl36.c new file +10 -0
+
+			if (buf[i] < 1 || buf[i] > 254) {
+
+				tst_res(TFAIL, "Unexpected data "
+					"offset %ld value %d",
+					pa->offset + i, buf[i]);
+				break;
+			}
+
+			long tmp = pa->length / 2;

We can simplify this with:

Quoted 5 lines
			int j = i / (pa->length/2);

			if (buf[i] != buf[j]) {
				...
			}

After checking, this is not what I meant to check here about this data verifying.

We could read 4k data that first half 2k of it have the same value and the another half 2k have a different value.

Quoted 11 lines
Quoted 11 lines
testcases/kernel/syscalls/fcntl/fcntl36.c new file +10 -0
+			if ((i < tmp && buf[i] != buf[0]) ||
+			    (i >= tmp && buf[i] != buf[tmp])) {
+
+				tst_res(TFAIL, "Unexpected data "
+					"offset %ld value %d",
+					pa->offset + i, buf[i]);
+				break;
+			}
+		}
+

...

Quoted 5 lines

testcases/kernel/syscalls/fcntl/fcntl36.c line 297

Quoted 3 lines
testcases/kernel/syscalls/fcntl/fcntl36.c new file +3 -0
+	if (tst_fill_file(fname, 1, write_size, thread_cnt)) {
+		tst_brk(TBROK, "Failed to create tst file");
+	}

No need for the curly braces around single line statement here.

I thought it's safer for a macro. Now it's one line function in the macro, not hurting to remove the braces.

Thanks for reviewing!
Xiong

#7 lore raw

PATCH v3 1/1 syscalls/fcntl36: add tests for OFD locks

Hi!

Quoted 8 lines
Quoted 5 lines

testcases/kernel/syscalls/fcntl/fcntl36.c line 297

Quoted 3 lines
testcases/kernel/syscalls/fcntl/fcntl36.c new file +3 -0
+	if (tst_fill_file(fname, 1, write_size, thread_cnt)) {
+		tst_brk(TBROK, "Failed to create tst file");
+	}

No need for the curly braces around single line statement here.

I thought it's safer for a macro. Now it's one line function in the macro, not hurting to remove the braces.

Even macros that have several lines are safe in LTP since we use the do { ... } while (0) idiom.

Signature · 2 lines
Cyril Hrubis
[email protected]
author
#8 lore raw

PATCH v4 1/1 syscalls/fcntl36: add tests for OFD locks

Testing OFD locks racing with POSIX locks:

  OFD read  lock   vs   OFD   write lock
  OFD read  lock   vs   POSIX write lock
  OFD write lock   vs   POSIX write lock
  OFD write lock   vs   POSIX read  lock
  OFD write lock   vs   OFD   write lock

---

v4:
Add .gitignore entry.
Count failures in reader, then check it in main loop. Other fix.

v3:
Use tst_fill_file.
Loop in test function.
Other fix.

v2:
Basically rewritten.
Pass structure parameter to threads.
Block on read lock.
Spawn racing threads one by one.
Use tcnt iteration.

 runtest/syscalls                          |   2 +
 testcases/kernel/syscalls/.gitignore      |   2 +
 testcases/kernel/syscalls/fcntl/Makefile  |   3 +
 testcases/kernel/syscalls/fcntl/fcntl36.c | 378 ++++++++++++++++++++++++++++++
 4 files changed, 385 insertions(+)
 create mode 100644 testcases/kernel/syscalls/fcntl/fcntl36.c
runtest/syscalls +2 -0
index 407e055..f2b2cbc 100644
@@ -271,6 +271,8 @@ fcntl34 fcntl34
 fcntl34_64 fcntl34_64
 fcntl35 fcntl35
 fcntl35_64 fcntl35_64
+fcntl36 fcntl36
+fcntl36_64 fcntl36_64
 
 fdatasync01 fdatasync01
 fdatasync02 fdatasync02
testcases/kernel/syscalls/.gitignore +2 -0
index 2a7026d..32193e1 100644
@@ -234,6 +234,8 @@
 /fcntl/fcntl34_64
 /fcntl/fcntl35
 /fcntl/fcntl35_64
+/fcntl/fcntl36
+/fcntl/fcntl36_64
 /fdatasync/fdatasync01
 /fdatasync/fdatasync02
 /flistxattr/flistxattr01
testcases/kernel/syscalls/fcntl/Makefile +3 -0
index d78dd72..ae37214 100644
@@ -24,6 +24,9 @@ fcntl33_64: LDLIBS+=-lrt
 fcntl34: LDLIBS += -lpthread
 fcntl34_64: LDLIBS += -lpthread
 
+fcntl36: LDLIBS += -lpthread
+fcntl36_64: LDLIBS += -lpthread
+
 include $(top_srcdir)/include/mk/testcases.mk
 include $(abs_srcdir)/../utils/newer_64.mk
 
testcases/kernel/syscalls/fcntl/fcntl36.c new file +378 -0

378 lines not on this page · raw message

Signature · 1 line
1.8.3.1
#9 lore raw

PATCH v3 1/1 syscalls/fcntl36: add tests for OFD locks

In reply to Xiong Zhou

Hi!

Quoted 25 lines
Quoted 2 lines
Quoted 2 lines
testcases/kernel/syscalls/fcntl/fcntl36.c new file +2 -0
+#include <sys/types.h>
+#include <sys/stat.h>

...

Quoted 16 lines
Quoted 4 lines
testcases/kernel/syscalls/fcntl/fcntl36.c new file +4 -0
+		SAFE_READ(1, fd, buf, pa->length);
+
+		/* Verifying data read */
+		for (i = 0; i < pa->length; i++) {

testcases/kernel/syscalls/fcntl/fcntl36.c line 202

Quoted 10 lines
testcases/kernel/syscalls/fcntl/fcntl36.c new file +10 -0
+
+			if (buf[i] < 1 || buf[i] > 254) {
+
+				tst_res(TFAIL, "Unexpected data "
+					"offset %ld value %d",
+					pa->offset + i, buf[i]);
+				break;
+			}
+
+			long tmp = pa->length / 2;

We can simplify this with:

Quoted 5 lines
			int j = i / (pa->length/2);

			if (buf[i] != buf[j]) {
				...
			}
Quoted 5 lines

After checking, this is not what I meant to check here about this data verifying.

We could read 4k data that first half 2k of it have the same value and the another half 2k have a different value.

Ah right, made a silly mistake the correct formula is:

	int j = (i / (pa->length/2)) * pa->length/2;

The previous one was yielding incorrect result for i >= pa->length/2.

Signature · 2 lines
Cyril Hrubis
[email protected]
author
#10 lore raw

PATCH v5 1/1 syscalls/fcntl36: add tests for OFD locks

Testing OFD locks racing with POSIX locks:

  OFD read  lock   vs   OFD   write lock
  OFD read  lock   vs   POSIX write lock
  OFD write lock   vs   POSIX write lock
  OFD write lock   vs   POSIX read  lock
  OFD write lock   vs   OFD   write lock

---

v5:
Optimize data checking.

v4:
Add .gitignore entry.
Count failures in reader, then check it in main loop. Other fix.

v3:
Use tst_fill_file.
Loop in test function.
Other fix.

v2:
Basically rewritten.
Pass structure parameter to threads.
Block on read lock.
Spawn racing threads one by one.
Use tcnt iteration.

 runtest/syscalls                          |   2 +
 testcases/kernel/syscalls/.gitignore      |   2 +
 testcases/kernel/syscalls/fcntl/Makefile  |   3 +
 testcases/kernel/syscalls/fcntl/fcntl36.c | 376 ++++++++++++++++++++++++++++++
 4 files changed, 383 insertions(+)
 create mode 100644 testcases/kernel/syscalls/fcntl/fcntl36.c
runtest/syscalls +2 -0
index 407e055..f2b2cbc 100644
@@ -271,6 +271,8 @@ fcntl34 fcntl34
 fcntl34_64 fcntl34_64
 fcntl35 fcntl35
 fcntl35_64 fcntl35_64
+fcntl36 fcntl36
+fcntl36_64 fcntl36_64
 
 fdatasync01 fdatasync01
 fdatasync02 fdatasync02
testcases/kernel/syscalls/.gitignore +2 -0
index 2a7026d..32193e1 100644
@@ -234,6 +234,8 @@
 /fcntl/fcntl34_64
 /fcntl/fcntl35
 /fcntl/fcntl35_64
+/fcntl/fcntl36
+/fcntl/fcntl36_64
 /fdatasync/fdatasync01
 /fdatasync/fdatasync02
 /flistxattr/flistxattr01
testcases/kernel/syscalls/fcntl/Makefile +3 -0
index d78dd72..ae37214 100644
@@ -24,6 +24,9 @@ fcntl33_64: LDLIBS+=-lrt
 fcntl34: LDLIBS += -lpthread
 fcntl34_64: LDLIBS += -lpthread
 
+fcntl36: LDLIBS += -lpthread
+fcntl36_64: LDLIBS += -lpthread
+
 include $(top_srcdir)/include/mk/testcases.mk
 include $(abs_srcdir)/../utils/newer_64.mk
 
testcases/kernel/syscalls/fcntl/fcntl36.c new file +376 -0

376 lines not on this page · raw message

Signature · 1 line
1.8.3.1
#11 lore raw

PATCH v5 1/1 syscalls/fcntl36: add tests for OFD locks

Hi!

Quoted 14 lines
testcases/kernel/syscalls/fcntl/fcntl36.c new file +14 -0
+/* OFD write lock writing data*/
+static void *fn_ofd_w(void *arg)
+{
+	unsigned char buf[write_size];
+	struct param *pa = (struct param *)arg;
+	int fd = SAFE_OPEN(fname, O_RDWR);
+	long wt = pa->cnt;
+
+	struct flock64 lck = {
+		.l_whence = SEEK_SET,
+		.l_start  = pa->offset,
+		.l_len    = pa->length,
+		.l_pid    = 0,
+	};

testcases/kernel/syscalls/fcntl/fcntl36.c line 101

Quoted 10 lines
testcases/kernel/syscalls/fcntl/fcntl36.c new file +10 -0
+
+	while (loop_flag) {
+
+		memset(buf, wt, write_size);
+
+		lck.l_type = F_WRLCK;
+		SAFE_FCNTL(fd, F_OFD_SETLKW, &lck);
+
+		SAFE_LSEEK(fd, pa->offset, SEEK_SET);
+		SAFE_WRITE(1, fd, buf, pa->length);

Just a minor note, we use both write_size and pa->length randomly here and in all of the test functions. It would be a much cleaner to use only pa->lenght instead.

Quoted 16 lines
testcases/kernel/syscalls/fcntl/fcntl36.c new file +16 -0
+/* Test different functions and verify data */
+static void test_fn(void *f0(void *), void *f1(void *), const char *msg)
+{
+	int i, k, fd;
+	pthread_t id0[thread_cnt];
+	pthread_t id1[thread_cnt];
+	struct param p0[thread_cnt];
+	struct param p1[thread_cnt];
+	unsigned char buf[write_size];
+
+	if (tst_fill_file(fname, 1, write_size, thread_cnt))
+		tst_brk(TBROK, "Failed to create tst file");
+
+	tst_res(TINFO, msg);
+
+	for (i = 0; i < thread_cnt; i++) {

testcases/kernel/syscalls/fcntl/fcntl36.c line 299

Quoted 10 lines
testcases/kernel/syscalls/fcntl/fcntl36.c new file +10 -0
+
+		p0[i].offset = i * write_size;
+		p0[i].length = write_size;
+		p0[i].cnt = i + 2;
+
+		p1[i].offset = i * write_size;
+		p1[i].offset += write_size / 2;
+		p1[i].length = write_size;
+		p1[i].cnt = i + 2;
+	}

We should reset the fail_cnt here. And it would be safer to rename it to fail_flag and set it to 1 on a failure because if we are terribly unlucky the incements can overflow and we may as well end up with a zero.

Otherwise it looks good.

Signature · 2 lines
Cyril Hrubis
[email protected]
author
#12 lore raw

PATCH v6 1/1 syscalls/fcntl36: add tests for OFD locks

Testing OFD locks racing with POSIX locks:

  OFD read  lock   vs   OFD   write lock
  OFD read  lock   vs   POSIX write lock
  OFD write lock   vs   POSIX write lock
  OFD write lock   vs   POSIX read  lock
  OFD write lock   vs   OFD   write lock
  OFD   r/w locks  vs   POSIX write locks
  POSIX r/w locks  vs   OFD   write locks
  OFD   r/w locks  vs   POSIX read  locks
  POSIX r/w locks  vs   OFD   read  locks
  OFD   r/w locks  vs   POSIX r/w   locks

---

v6:
Use param->length in thread_fn as r/w size instead of
write_size directly, thanks to C99.

Reset fail_flag after each sub case.

Race up to 4 bunches of threads acquiring these 4 kinds of locks,
not just only 2 of them. (kind crazy)

v5:
Optimize data checking.

v4:
Add .gitignore entry.
Count failures in reader, then check it in main loop. Other fix.

v3:
Use tst_fill_file.
Loop in test function.
Other fix.

v2:
Basically rewritten.
Pass structure parameter to threads.
Block on read lock.
Spawn racing threads one by one.
Use tcnt iteration.

 runtest/syscalls                          |   2 +
 testcases/kernel/syscalls/.gitignore      |   2 +
 testcases/kernel/syscalls/fcntl/Makefile  |   3 +
 testcases/kernel/syscalls/fcntl/fcntl36.c | 429 ++++++++++++++++++++++++++++++
 4 files changed, 436 insertions(+)
 create mode 100644 testcases/kernel/syscalls/fcntl/fcntl36.c
runtest/syscalls +2 -0
index 407e055..f2b2cbc 100644
@@ -271,6 +271,8 @@ fcntl34 fcntl34
 fcntl34_64 fcntl34_64
 fcntl35 fcntl35
 fcntl35_64 fcntl35_64
+fcntl36 fcntl36
+fcntl36_64 fcntl36_64
 
 fdatasync01 fdatasync01
 fdatasync02 fdatasync02
testcases/kernel/syscalls/.gitignore +2 -0
index 2a7026d..32193e1 100644
@@ -234,6 +234,8 @@
 /fcntl/fcntl34_64
 /fcntl/fcntl35
 /fcntl/fcntl35_64
+/fcntl/fcntl36
+/fcntl/fcntl36_64
 /fdatasync/fdatasync01
 /fdatasync/fdatasync02
 /flistxattr/flistxattr01
testcases/kernel/syscalls/fcntl/Makefile +3 -0
index d78dd72..ae37214 100644
@@ -24,6 +24,9 @@ fcntl33_64: LDLIBS+=-lrt
 fcntl34: LDLIBS += -lpthread
 fcntl34_64: LDLIBS += -lpthread
 
+fcntl36: LDLIBS += -lpthread
+fcntl36_64: LDLIBS += -lpthread
+
 include $(top_srcdir)/include/mk/testcases.mk
 include $(abs_srcdir)/../utils/newer_64.mk
 
testcases/kernel/syscalls/fcntl/fcntl36.c new file +429 -0

429 lines not on this page · raw message

Signature · 1 line
1.8.3.1
#13 lore raw

PATCH v6 1/1 syscalls/fcntl36: add tests for OFD locks

Hi!

Quoted 14 lines
testcases/kernel/syscalls/fcntl/fcntl36.c new file +14 -0
+} tcases[] = {
+
+	{fn_ofd_r,   fn_ofd_w,
+		NULL, NULL, "OFD read  locks vs OFD   write locks"},
+	{fn_ofd_w,   fn_posix_w,
+		NULL, NULL, "OFD write locks vs POSIX write locks"},
+	{fn_ofd_r,   fn_posix_w,
+		NULL, NULL, "OFD read  locks vs POSIX write locks"},
+	{fn_posix_r, fn_ofd_w,
+		NULL, NULL, "OFD write locks vs POSIX read  locks"},
+	{fn_ofd_w,   fn_ofd_w,
+		NULL, NULL, "OFD write locks vs OFD   write locks"},
+
+	{fn_ofd_r,   fn_ofd_w,   fn_posix_w,

testcases/kernel/syscalls/fcntl/fcntl36.c line 414

Quoted 10 lines
testcases/kernel/syscalls/fcntl/fcntl36.c new file +10 -0
+		      NULL, "OFD   r/w locks vs POSIX write locks"},
+	{fn_posix_r, fn_ofd_w,   fn_posix_w,
+		      NULL, "POSIX r/w locks vs OFD   write locks"},
+	{fn_ofd_r,   fn_posix_r, fn_ofd_w,
+		      NULL, "OFD   r/w locks vs POSIX read locks"},
+	{fn_ofd_r,   fn_posix_r, fn_posix_w,
+		      NULL, "POSIX r/w locks vs OFD   read locks"},
+
+	{fn_ofd_r,   fn_posix_r, fn_posix_w, fn_ofd_w,
+			    "OFD   r/w locks vs POSIX r/w locks"},

The cases that concurently run posix read vs. posix write locks unfortunately does not work, since posix locks are process based we cannot have more than one lock on a file region per process (threads are counted as single process as well) and conflicting locks are converted i.e. the last two will fail with wrongly read data in the fn_posix_r funciton in a case that posix read and posix write locks were held concurently (which happens for me and the test fails on my testing machine).

We can run as many threads with ofd locks as we want, since these are based on open file descriptors and we can add exactly one posix lock thread to the mix as well but no more than that.

Moreover I think that we may need a pthread_barrier before we close the file descriptors in the test functions since the posix locks are dropped when any file descriptor asociated with the file is closed, since if we run more than two threads and ofd thread closes the fd, the posix thread looses it's lock and the remaining ofd thread(s) run concurently, it's unlikely that something like this would happen, but it's possible.

Quoted 18 lines
testcases/kernel/syscalls/fcntl/fcntl36.c new file +15 -0
+};
+
+static void tests(unsigned int i)
+{
+	test_fn(tcases[i].fn0, tcases[i].fn1,
+		tcases[i].fn2, tcases[i].fn3, tcases[i].desc);
+}
+
+static struct tst_test test = {
+	.min_kver = "3.15",
+	.needs_tmpdir = 1,
+	.test = tests,
+	.tcnt = ARRAY_SIZE(tcases),
+	.setup = setup
+};
Signature · 1 line
1.8.3.1
Signature · 2 lines
Cyril Hrubis
[email protected]
author
#14 lore raw

PATCH v7 1/1 syscalls/fcntl36: add tests for OFD locks

Testing OFD locks racing with POSIX locks:

  OFD read  lock   vs   OFD   write lock
  OFD read  lock   vs   POSIX write lock
  OFD write lock   vs   POSIX write lock
  OFD write lock   vs   POSIX read  lock
  OFD write lock   vs   OFD   write lock
  OFD   r/w locks  vs   POSIX write locks
  OFD   r/w locks  vs   POSIX read  locks

---

v7:
Add pthread_barrier.
Run only one kind of POSIX lock threads.
Add fn_dummy, save efforts to look at thread funcs before firing them.

v6:
Use param->length in thread_fn as r/w size instead of
write_size directly. Thanks to C99.

Reset fail_flag after each sub case.

Race up to 4 bunches of threads acquiring these 4 kinds of locks,
not just only 2 of them. (kind crazy)

v5:
Optimize data checking.

v4:
Add .gitignore entry.
Count failures in reader, then check it in main loop. Other fix.

v3:
Use tst_fill_file.
Loop in test function.
Other fix.

v2:
Basically rewritten.
Pass structure parameter to threads.
Block on read lock.
Spawn racing threads one by one.
Use tcnt iteration.

 runtest/syscalls                          |   2 +
 testcases/kernel/syscalls/.gitignore      |   2 +
 testcases/kernel/syscalls/fcntl/Makefile  |   3 +
 testcases/kernel/syscalls/fcntl/fcntl36.c | 419 ++++++++++++++++++++++++++++++
 4 files changed, 426 insertions(+)
 create mode 100644 testcases/kernel/syscalls/fcntl/fcntl36.c
runtest/syscalls +2 -0
index 407e055..f2b2cbc 100644
@@ -271,6 +271,8 @@ fcntl34 fcntl34
 fcntl34_64 fcntl34_64
 fcntl35 fcntl35
 fcntl35_64 fcntl35_64
+fcntl36 fcntl36
+fcntl36_64 fcntl36_64
 
 fdatasync01 fdatasync01
 fdatasync02 fdatasync02
testcases/kernel/syscalls/.gitignore +2 -0
index 2a7026d..32193e1 100644
@@ -234,6 +234,8 @@
 /fcntl/fcntl34_64
 /fcntl/fcntl35
 /fcntl/fcntl35_64
+/fcntl/fcntl36
+/fcntl/fcntl36_64
 /fdatasync/fdatasync01
 /fdatasync/fdatasync02
 /flistxattr/flistxattr01
testcases/kernel/syscalls/fcntl/Makefile +3 -0
index d78dd72..ae37214 100644
@@ -24,6 +24,9 @@ fcntl33_64: LDLIBS+=-lrt
 fcntl34: LDLIBS += -lpthread
 fcntl34_64: LDLIBS += -lpthread
 
+fcntl36: LDLIBS += -lpthread
+fcntl36_64: LDLIBS += -lpthread
+
 include $(top_srcdir)/include/mk/testcases.mk
 include $(abs_srcdir)/../utils/newer_64.mk
 
testcases/kernel/syscalls/fcntl/fcntl36.c new file +419 -0

419 lines not on this page · raw message

Signature · 1 line
1.8.3.1
#15 lore raw

PATCH v7 1/1 syscalls/fcntl36: add tests for OFD locks

Hi!
Pushed with minor changes, mostly whitespace related, thanks.

Signature · 2 lines
Cyril Hrubis
[email protected]
author
#16 lore raw

PATCH v7 1/1 syscalls/fcntl36: add tests for OFD locks

Quoted 2 lines · Cyril Hrubis

Hi!
Pushed with minor changes, mostly whitespace related, thanks.

Thanks for reviewing!

Quoted 4 lines
Signature · 3 lines
-- 
Cyril Hrubis
[email protected]