[PATCH v1 4/4] liburing: Add new test program to verify xattr support

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



Summary:

This adds a new test program to test the xattr support:
- fgetxattr
- fsetxattr
- getxattr
- setxattr

It also includes test cases for failure conditions and
for passing in an invalid sqe. The test case for checking
of invalid SQE, must be enabled by defining
DESTRUCTIVE_TESTING.

Signed-off-by: Stefan Roesch <shr@xxxxxx>
---
 test/Makefile |   1 +
 test/xattr.c  | 425 ++++++++++++++++++++++++++++++++++++++++++++++++++
 2 files changed, 426 insertions(+)
 create mode 100644 test/xattr.c

diff --git a/test/Makefile b/test/Makefile
index c09078a..aa2da4e 100644
--- a/test/Makefile
+++ b/test/Makefile
@@ -147,6 +147,7 @@ test_srcs := \
 	timeout-overflow.c \
 	unlink.c \
 	wakeup-hang.c \
+	xattr.c \
 	skip-cqe.c \
 	# EOL
 
diff --git a/test/xattr.c b/test/xattr.c
new file mode 100644
index 0000000..017017e
--- /dev/null
+++ b/test/xattr.c
@@ -0,0 +1,425 @@
+#include <assert.h>
+#include <fcntl.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <sys/xattr.h>
+#include <unistd.h>
+
+#include "helpers.h"
+#include "liburing.h"
+
+/* Define constants. */
+#define XATTR_SIZE  255
+#define QUEUE_DEPTH 32
+
+#define FILENAME    "xattr.test"
+#define KEY1        "user.val1"
+#define KEY2        "user.val2"
+#define VALUE1      "value1"
+#define VALUE2      "value2-a-lot-longer"
+
+
+/* Call fsetxattr. */
+int io_uring_fsetxattr(struct io_uring *ring,
+		       int              fd,
+		       const char      *name,
+		       const void      *value,
+		       size_t           size,
+		       int              flags)
+{
+	struct io_uring_sqe *sqe;
+	struct io_uring_cqe *cqe;
+	int ret;
+
+	sqe = io_uring_get_sqe(ring);
+	if (!sqe) {
+		fprintf(stderr, "Error cannot get sqe\n");
+		return -1;
+	}
+
+	io_uring_prep_fsetxattr(sqe, fd, name, value, flags, size);
+
+	ret = io_uring_submit(ring);
+	if (ret != 1) {
+		fprintf(stderr, "Error io_uring_submit_and_wait: ret=%d\n", ret);
+		return -1;
+	}
+
+	ret = io_uring_wait_cqe(ring, &cqe);
+	if (ret) {
+		fprintf(stderr, "Error io_uring_wait_cqe: ret=%d\n", ret);
+		return -1;
+	}
+
+	ret = cqe->res;
+	io_uring_cqe_seen(ring, cqe);
+
+	return ret;
+}
+
+/* Submit fgetxattr request. */
+int io_uring_fgetxattr(struct io_uring *ring,
+		       int              fd,
+		       const char      *name,
+		       void            *value,
+		       size_t           size)
+{
+	struct io_uring_sqe *sqe;
+	struct io_uring_cqe *cqe;
+	int ret;
+
+	sqe = io_uring_get_sqe(ring);
+	if (!sqe) {
+		fprintf(stderr, "Error cannot get sqe\n");
+		return -1;
+	}
+
+	io_uring_prep_fgetxattr(sqe, fd, name, value, size);
+
+	ret = io_uring_submit(ring);
+	if (ret != 1) {
+		fprintf(stderr, "Error io_uring_submit_and_wait: ret=%d\n", ret);
+		return -1;
+	}
+
+	ret = io_uring_wait_cqe(ring, &cqe);
+	if (ret) {
+		fprintf(stderr, "Error io_uring_wait_cqe: ret=%d\n", ret);
+		return -1;
+	}
+
+	ret = cqe->res;
+	if (ret == -1) {
+		fprintf(stderr, "Error couldn'tget value\n");
+		return -1;
+	}
+
+	io_uring_cqe_seen(ring, cqe);
+	return ret;
+}
+
+/* Call setxattr. */
+int io_uring_setxattr(struct io_uring *ring,
+		      const char      *path,
+		      const char      *name,
+		      const void      *value,
+		      size_t           size,
+		      int              flags)
+{
+	struct io_uring_sqe *sqe;
+	struct io_uring_cqe *cqe;
+	int ret;
+
+	sqe = io_uring_get_sqe(ring);
+	if (!sqe) {
+		fprintf(stderr, "Error cannot get sqe\n");
+		return -1;
+	}
+
+	io_uring_prep_setxattr(sqe, name, value, path, flags, size);
+
+	ret = io_uring_submit_and_wait(ring, 1);
+	if (ret != 1) {
+		fprintf(stderr, "Error io_uring_submit_and_wait: ret=%d\n", ret);
+		return -1;
+	}
+
+	ret = io_uring_wait_cqe(ring, &cqe);
+	if (ret) {
+		fprintf(stderr, "Error io_uring_wait_cqe: ret=%d\n", ret);
+		return -1;
+	}
+
+	ret = cqe->res;
+	io_uring_cqe_seen(ring, cqe);
+
+	return ret;
+}
+
+/* Submit getxattr request. */
+int io_uring_getxattr(struct io_uring *ring,
+		      const char      *path,
+		      const char      *name,
+		      void            *value,
+		      size_t           size)
+{
+	struct io_uring_sqe *sqe;
+	struct io_uring_cqe *cqe;
+	int ret;
+
+	sqe = io_uring_get_sqe(ring);
+	if (!sqe) {
+		fprintf(stderr, "Error cannot get sqe\n");
+		return -1;
+	}
+
+	io_uring_prep_getxattr(sqe, name, value, path, size);
+
+	ret = io_uring_submit(ring);
+	if (ret != 1) {
+		fprintf(stderr, "Error io_uring_submit_and_wait: ret=%d\n", ret);
+		return -1;
+	}
+
+	ret = io_uring_wait_cqe(ring, &cqe);
+	if (ret) {
+		fprintf(stderr, "Error io_uring_wait_cqe: ret=%d\n", ret);
+		return -1;
+	}
+
+	ret = cqe->res;
+	if (ret == -1) {
+		fprintf(stderr, "Error couldn'tget value\n");
+		return -1;
+	}
+
+	io_uring_cqe_seen(ring, cqe);
+	return ret;
+}
+
+/* Test driver for fsetxattr and fgetxattr. */
+int test_fxattr(void)
+{
+	int rc = 0;
+	size_t value_len;
+	struct io_uring ring;
+	char value[XATTR_SIZE];
+
+	/* Init io-uring queue. */
+	int ret = io_uring_queue_init(QUEUE_DEPTH, &ring, 0);
+	if (ret) {
+		fprintf(stderr, "child: ring setup failed: %d\n", ret);
+		return -1;
+	}
+
+	/* Create the test file. */
+	int fd = open(FILENAME, O_CREAT | O_RDWR);
+	if (fd < 0) {
+		fprintf(stderr, "Error: cannot open file: ret=%d\n", fd);
+		return -1;
+	}
+
+	/* Test writing attributes. */
+	if (io_uring_fsetxattr(&ring, fd, KEY1, VALUE1, strlen(VALUE1), 0) == -1) {
+		fprintf(stderr, "Error fsetxattr cannot write key1\n");
+		rc = -1;
+		goto Exit;
+	}
+
+	if (io_uring_fsetxattr(&ring, fd, KEY2, VALUE2, strlen(VALUE2), 0) == -1) {
+		fprintf(stderr, "Error fsetxattr cannot write key1\n");
+		rc = -1;
+		goto Exit;
+	}
+
+	/* Test reading attributes. */
+	value_len = io_uring_fgetxattr(&ring, fd, KEY1, value, XATTR_SIZE);
+	if (value_len != strlen(value) || strncmp(value, VALUE1, value_len)) {
+		fprintf(stderr, "Error: fgetxattr expectd value: %s, returned value: %s\n", VALUE1, value);
+		rc = -1;
+		goto Exit;
+	}
+
+	value_len = io_uring_fgetxattr(&ring, fd, KEY2, value, XATTR_SIZE);
+	if (value_len != strlen(value)|| strncmp(value, VALUE2, value_len)) {
+		fprintf(stderr, "Error: fgetxattr expectd value: %s, returned value: %s\n", VALUE2, value);
+		rc = -1;
+		goto Exit;
+	}
+
+	/* Cleanup. */
+Exit:
+	close(fd);
+	unlink(FILENAME);
+
+	io_uring_queue_exit(&ring);
+
+	return rc;
+}
+
+/* Test driver for setxattr and getxattr. */
+int test_xattr(void)
+{
+	int rc = 0;
+	int value_len;
+	struct io_uring ring;
+	char value[XATTR_SIZE];
+
+	/* Init io-uring queue. */
+	int ret = io_uring_queue_init(QUEUE_DEPTH, &ring, 0);
+	if (ret) {
+		fprintf(stderr, "child: ring setup failed: %d\n", ret);
+		return -1;
+	}
+
+	/* Create the test file. */
+	t_create_file(FILENAME, 0);
+
+	/* Test writing attributes. */
+	if (io_uring_setxattr(&ring, FILENAME, KEY1, VALUE1, strlen(VALUE1), 0) == -1) {
+		fprintf(stderr, "Error setxattr cannot write key1\n");
+		rc = -1;
+		goto Exit;
+	}
+
+	if (io_uring_setxattr(&ring, FILENAME, KEY2, VALUE2, strlen(VALUE2), 0) == -1) {
+		fprintf(stderr, "Error setxattr cannot write key1\n");
+		rc = -1;
+		goto Exit;
+	}
+
+	/* Test reading attributes. */
+	value_len = io_uring_getxattr(&ring, FILENAME, KEY1, value, XATTR_SIZE);
+	if (value_len != strlen(VALUE1) || strncmp(value, VALUE1, value_len)) {
+		fprintf(stderr, "Error: getxattr expectd value: %s, returned value: %s\n", VALUE1, value);
+		rc = -1;
+		goto Exit;
+	}
+
+	value_len = io_uring_getxattr(&ring, FILENAME, KEY2, value, XATTR_SIZE);
+	if (value_len != strlen(VALUE2) || strncmp(value, VALUE2, value_len)) {
+		fprintf(stderr, "Error: getxattr expectd value: %s, returned value: %s\n", VALUE2, value);
+		rc = -1;
+		goto Exit;
+	}
+
+	/* Cleanup. */
+Exit:
+	io_uring_queue_exit(&ring);
+	unlink(FILENAME);
+
+	return rc;
+}
+
+/* Test driver for failure cases of fsetxattr and fgetxattr. */
+int test_failure_fxattr(void)
+{
+	int rc = 0;
+	struct io_uring ring;
+	char value[XATTR_SIZE];
+
+	/* Init io-uring queue. */
+	int ret = io_uring_queue_init(QUEUE_DEPTH, &ring, 0);
+	if (ret) {
+		fprintf(stderr, "child: ring setup failed: %d\n", ret);
+		return -1;
+	}
+
+	/* Create the test file. */
+	int fd = open(FILENAME, O_CREAT | O_RDWR);
+	if (fd < 0) {
+		fprintf(stderr, "Error: cannot open file: ret=%d\n", fd);
+		return -1;
+	}
+
+	/* Test writing attributes. */
+	assert(io_uring_fsetxattr(&ring, -1, KEY1, VALUE1, strlen(VALUE1), 0) < 0);
+	assert(io_uring_fsetxattr(&ring, fd, NULL, VALUE1, strlen(VALUE1), 0) < 0);
+	assert(io_uring_fsetxattr(&ring, fd, KEY1, NULL,   strlen(VALUE1), 0) < 0);
+	assert(io_uring_fsetxattr(&ring, fd, KEY1, VALUE1, 0,              0) == 0);
+	assert(io_uring_fsetxattr(&ring, fd, KEY1, VALUE1, -1,             0) < 0);
+
+	/* Test reading attributes. */
+	assert(io_uring_fgetxattr(&ring, -1, KEY1, value, XATTR_SIZE) < 0);
+	assert(io_uring_fgetxattr(&ring, fd, NULL, value, XATTR_SIZE) < 0);
+	assert(io_uring_fgetxattr(&ring, fd, KEY1, value, 0)          == 0);
+
+	/* Cleanup. */
+	close(fd);
+	unlink(FILENAME);
+
+	io_uring_queue_exit(&ring);
+
+	return rc;
+}
+
+
+/* Test driver for failure cases for setxattr and getxattr. */
+int test_failure_xattr(void)
+{
+	int rc = 0;
+	struct io_uring ring;
+	char value[XATTR_SIZE];
+
+	/* Init io-uring queue. */
+	int ret = io_uring_queue_init(QUEUE_DEPTH, &ring, 0);
+	if (ret) {
+		fprintf(stderr, "child: ring setup failed: %d\n", ret);
+		return -1;
+	}
+
+	/* Create the test file. */
+	t_create_file(FILENAME, 0);
+
+	/* Test writing attributes. */
+	assert(io_uring_setxattr(&ring, "complete garbage", KEY1, VALUE1, strlen(VALUE1), 0) < 0);
+	assert(io_uring_setxattr(&ring, NULL,     KEY1, VALUE1, strlen(VALUE1), 0) < 0);
+	assert(io_uring_setxattr(&ring, FILENAME, NULL, VALUE1, strlen(VALUE1), 0) < 0);
+	assert(io_uring_setxattr(&ring, FILENAME, KEY1, NULL,   strlen(VALUE1), 0) < 0);
+	assert(io_uring_setxattr(&ring, FILENAME, KEY1, VALUE1, 0,              0) == 0);
+
+	/* Test reading attributes. */
+	assert(io_uring_getxattr(&ring, "complete garbage", KEY1, value, XATTR_SIZE) < 0);
+	assert(io_uring_getxattr(&ring, NULL,     KEY1, value, XATTR_SIZE) < 0);
+	assert(io_uring_getxattr(&ring, FILENAME, NULL, value, XATTR_SIZE) < 0);
+	assert(io_uring_getxattr(&ring, FILENAME, KEY1, NULL,  XATTR_SIZE) == 0);
+	assert(io_uring_getxattr(&ring, FILENAME, KEY1, value, 0)          == 0);
+
+	/* Cleanup. */
+	io_uring_queue_exit(&ring);
+	unlink(FILENAME);
+
+	return rc;
+}
+
+/* Test for invalid SQE, this will cause a segmentation fault if enabled. */
+int test_invalid_sqe(void)
+{
+#ifdef DESTRUCTIVE_TEST
+	struct io_uring_sqe *sqe = NULL;
+	struct io_uring_cqe *cqe = NULL;
+	struct io_uring ring;
+
+	/* Init io-uring queue. */
+	int ret = io_uring_queue_init(QUEUE_DEPTH, &ring, 0);
+	if (ret) {
+		fprintf(stderr, "child: ring setup failed: %d\n", ret);
+		return -1;
+	}
+
+	/* Pass invalid SQE. */
+	io_uring_prep_setxattr(sqe, FILENAME, KEY1, VALUE1, strlen(VALUE1), 0);
+
+	ret = io_uring_submit(&ring);
+	if (ret != 1) {
+		fprintf(stderr, "Error io_uring_submit_and_wait: ret=%d\n", ret);
+		return -1;
+	}
+
+	ret = io_uring_wait_cqe(&ring, &cqe);
+	if (ret) {
+		fprintf(stderr, "Error io_uring_wait_cqe: ret=%d\n", ret);
+		return -1;
+	}
+
+	ret = cqe->res;
+	io_uring_cqe_seen(&ring, cqe);
+
+	return ret;
+#else
+	return 0;
+#endif
+}
+
+/* Test driver. */
+int main(int argc, char **argv) {
+	if (test_fxattr()
+		|| test_xattr()
+	    || test_failure_fxattr()
+		|| test_failure_xattr()
+	    || test_invalid_sqe())
+		return EXIT_FAILURE;
+
+	return EXIT_SUCCESS;
+}
-- 
2.30.2





[Index of Archives]     [Linux Samsung SoC]     [Linux Rockchip SoC]     [Linux Actions SoC]     [Linux for Synopsys ARC Processors]     [Linux NFS]     [Linux NILFS]     [Linux USB Devel]     [Video for Linux]     [Linux Audio Users]     [Yosemite News]     [Linux Kernel]     [Linux SCSI]


  Powered by Linux