Commit 09beaff7 authored by Linus Torvalds's avatar Linus Torvalds
Browse files

Merge tag 'for-5.19/io_uring-xattr-2022-05-22' of git://git.kernel.dk/linux-block

Pull io_uring xattr support from Jens Axboe:
 "Support for the xattr variants"

* tag 'for-5.19/io_uring-xattr-2022-05-22' of git://git.kernel.dk/linux-block:
  io_uring: cleanup error-handling around io_req_complete
  io_uring: fix trace for reduced sqe padding
  io_uring: add fgetxattr and getxattr support
  io_uring: add fsetxattr and setxattr support
  fs: split off do_getxattr from getxattr
  fs: split off setxattr_copy and do_setxattr function from setxattr
parents 3a166bdb 4ffaa94b
Loading
Loading
Loading
Loading
+29 −0
Original line number Diff line number Diff line
@@ -191,3 +191,32 @@ long splice_file_to_pipe(struct file *in,
			 struct pipe_inode_info *opipe,
			 loff_t *offset,
			 size_t len, unsigned int flags);

/*
 * fs/xattr.c:
 */
struct xattr_name {
	char name[XATTR_NAME_MAX + 1];
};

struct xattr_ctx {
	/* Value of attribute */
	union {
		const void __user *cvalue;
		void __user *value;
	};
	void *kvalue;
	size_t size;
	/* Attribute name */
	struct xattr_name *kname;
	unsigned int flags;
};


ssize_t do_getxattr(struct user_namespace *mnt_userns,
		    struct dentry *d,
		    struct xattr_ctx *ctx);

int setxattr_copy(const char __user *name, struct xattr_ctx *ctx);
int do_setxattr(struct user_namespace *mnt_userns, struct dentry *dentry,
		struct xattr_ctx *ctx);
+296 −26
Original line number Diff line number Diff line
@@ -80,6 +80,7 @@
#include <linux/io_uring.h>
#include <linux/audit.h>
#include <linux/security.h>
#include <linux/xattr.h>

#define CREATE_TRACE_POINTS
#include <trace/events/io_uring.h>
@@ -803,6 +804,12 @@ struct io_async_rw {
	struct wait_page_queue		wpq;
};

struct io_xattr {
	struct file			*file;
	struct xattr_ctx		ctx;
	struct filename			*filename;
};

enum {
	REQ_F_FIXED_FILE_BIT	= IOSQE_FIXED_FILE_BIT,
	REQ_F_IO_DRAIN_BIT	= IOSQE_IO_DRAIN_BIT,
@@ -973,6 +980,7 @@ struct io_kiocb {
		struct io_symlink	symlink;
		struct io_hardlink	hardlink;
		struct io_msg		msg;
		struct io_xattr		xattr;
	};

	u8				opcode;
@@ -1281,6 +1289,14 @@ static const struct io_op_def io_op_defs[] = {
		.needs_file		= 1,
		.iopoll			= 1,
	},
	[IORING_OP_FSETXATTR] = {
		.needs_file = 1
	},
	[IORING_OP_SETXATTR] = {},
	[IORING_OP_FGETXATTR] = {
		.needs_file = 1
	},
	[IORING_OP_GETXATTR] = {},
};

/* requests with any of those set should undergo io_disarm_next() */
@@ -2333,6 +2349,8 @@ static inline void __io_req_complete(struct io_kiocb *req, unsigned issue_flags,

static inline void io_req_complete(struct io_kiocb *req, s32 res)
{
	if (res < 0)
		req_set_fail(req);
	__io_req_complete(req, 0, res, 0);
}

@@ -4299,12 +4317,258 @@ static int io_renameat(struct io_kiocb *req, unsigned int issue_flags)
				ren->newpath, ren->flags);

	req->flags &= ~REQ_F_NEED_CLEANUP;
	if (ret < 0)
		req_set_fail(req);
	io_req_complete(req, ret);
	return 0;
}

static inline void __io_xattr_finish(struct io_kiocb *req)
{
	struct io_xattr *ix = &req->xattr;

	if (ix->filename)
		putname(ix->filename);

	kfree(ix->ctx.kname);
	kvfree(ix->ctx.kvalue);
}

static void io_xattr_finish(struct io_kiocb *req, int ret)
{
	req->flags &= ~REQ_F_NEED_CLEANUP;

	__io_xattr_finish(req);
	io_req_complete(req, ret);
}

static int __io_getxattr_prep(struct io_kiocb *req,
			      const struct io_uring_sqe *sqe)
{
	struct io_xattr *ix = &req->xattr;
	const char __user *name;
	int ret;

	if (unlikely(req->ctx->flags & IORING_SETUP_IOPOLL))
		return -EINVAL;
	if (unlikely(sqe->ioprio))
		return -EINVAL;
	if (unlikely(req->flags & REQ_F_FIXED_FILE))
		return -EBADF;

	ix->filename = NULL;
	ix->ctx.kvalue = NULL;
	name = u64_to_user_ptr(READ_ONCE(sqe->addr));
	ix->ctx.cvalue = u64_to_user_ptr(READ_ONCE(sqe->addr2));
	ix->ctx.size = READ_ONCE(sqe->len);
	ix->ctx.flags = READ_ONCE(sqe->xattr_flags);

	if (ix->ctx.flags)
		return -EINVAL;

	ix->ctx.kname = kmalloc(sizeof(*ix->ctx.kname), GFP_KERNEL);
	if (!ix->ctx.kname)
		return -ENOMEM;

	ret = strncpy_from_user(ix->ctx.kname->name, name,
				sizeof(ix->ctx.kname->name));
	if (!ret || ret == sizeof(ix->ctx.kname->name))
		ret = -ERANGE;
	if (ret < 0) {
		kfree(ix->ctx.kname);
		return ret;
	}

	req->flags |= REQ_F_NEED_CLEANUP;
	return 0;
}

static int io_fgetxattr_prep(struct io_kiocb *req,
			     const struct io_uring_sqe *sqe)
{
	return __io_getxattr_prep(req, sqe);
}

static int io_getxattr_prep(struct io_kiocb *req,
			    const struct io_uring_sqe *sqe)
{
	struct io_xattr *ix = &req->xattr;
	const char __user *path;
	int ret;

	ret = __io_getxattr_prep(req, sqe);
	if (ret)
		return ret;

	path = u64_to_user_ptr(READ_ONCE(sqe->addr3));

	ix->filename = getname_flags(path, LOOKUP_FOLLOW, NULL);
	if (IS_ERR(ix->filename)) {
		ret = PTR_ERR(ix->filename);
		ix->filename = NULL;
	}

	return ret;
}

static int io_fgetxattr(struct io_kiocb *req, unsigned int issue_flags)
{
	struct io_xattr *ix = &req->xattr;
	int ret;

	if (issue_flags & IO_URING_F_NONBLOCK)
		return -EAGAIN;

	ret = do_getxattr(mnt_user_ns(req->file->f_path.mnt),
			req->file->f_path.dentry,
			&ix->ctx);

	io_xattr_finish(req, ret);
	return 0;
}

static int io_getxattr(struct io_kiocb *req, unsigned int issue_flags)
{
	struct io_xattr *ix = &req->xattr;
	unsigned int lookup_flags = LOOKUP_FOLLOW;
	struct path path;
	int ret;

	if (issue_flags & IO_URING_F_NONBLOCK)
		return -EAGAIN;

retry:
	ret = filename_lookup(AT_FDCWD, ix->filename, lookup_flags, &path, NULL);
	if (!ret) {
		ret = do_getxattr(mnt_user_ns(path.mnt),
				path.dentry,
				&ix->ctx);

		path_put(&path);
		if (retry_estale(ret, lookup_flags)) {
			lookup_flags |= LOOKUP_REVAL;
			goto retry;
		}
	}

	io_xattr_finish(req, ret);
	return 0;
}

static int __io_setxattr_prep(struct io_kiocb *req,
			const struct io_uring_sqe *sqe)
{
	struct io_xattr *ix = &req->xattr;
	const char __user *name;
	int ret;

	if (unlikely(req->ctx->flags & IORING_SETUP_IOPOLL))
		return -EINVAL;
	if (unlikely(sqe->ioprio))
		return -EINVAL;
	if (unlikely(req->flags & REQ_F_FIXED_FILE))
		return -EBADF;

	ix->filename = NULL;
	name = u64_to_user_ptr(READ_ONCE(sqe->addr));
	ix->ctx.cvalue = u64_to_user_ptr(READ_ONCE(sqe->addr2));
	ix->ctx.kvalue = NULL;
	ix->ctx.size = READ_ONCE(sqe->len);
	ix->ctx.flags = READ_ONCE(sqe->xattr_flags);

	ix->ctx.kname = kmalloc(sizeof(*ix->ctx.kname), GFP_KERNEL);
	if (!ix->ctx.kname)
		return -ENOMEM;

	ret = setxattr_copy(name, &ix->ctx);
	if (ret) {
		kfree(ix->ctx.kname);
		return ret;
	}

	req->flags |= REQ_F_NEED_CLEANUP;
	return 0;
}

static int io_setxattr_prep(struct io_kiocb *req,
			const struct io_uring_sqe *sqe)
{
	struct io_xattr *ix = &req->xattr;
	const char __user *path;
	int ret;

	ret = __io_setxattr_prep(req, sqe);
	if (ret)
		return ret;

	path = u64_to_user_ptr(READ_ONCE(sqe->addr3));

	ix->filename = getname_flags(path, LOOKUP_FOLLOW, NULL);
	if (IS_ERR(ix->filename)) {
		ret = PTR_ERR(ix->filename);
		ix->filename = NULL;
	}

	return ret;
}

static int io_fsetxattr_prep(struct io_kiocb *req,
			const struct io_uring_sqe *sqe)
{
	return __io_setxattr_prep(req, sqe);
}

static int __io_setxattr(struct io_kiocb *req, unsigned int issue_flags,
			struct path *path)
{
	struct io_xattr *ix = &req->xattr;
	int ret;

	ret = mnt_want_write(path->mnt);
	if (!ret) {
		ret = do_setxattr(mnt_user_ns(path->mnt), path->dentry, &ix->ctx);
		mnt_drop_write(path->mnt);
	}

	return ret;
}

static int io_fsetxattr(struct io_kiocb *req, unsigned int issue_flags)
{
	int ret;

	if (issue_flags & IO_URING_F_NONBLOCK)
		return -EAGAIN;

	ret = __io_setxattr(req, issue_flags, &req->file->f_path);
	io_xattr_finish(req, ret);

	return 0;
}

static int io_setxattr(struct io_kiocb *req, unsigned int issue_flags)
{
	struct io_xattr *ix = &req->xattr;
	unsigned int lookup_flags = LOOKUP_FOLLOW;
	struct path path;
	int ret;

	if (issue_flags & IO_URING_F_NONBLOCK)
		return -EAGAIN;

retry:
	ret = filename_lookup(AT_FDCWD, ix->filename, lookup_flags, &path, NULL);
	if (!ret) {
		ret = __io_setxattr(req, issue_flags, &path);
		path_put(&path);
		if (retry_estale(ret, lookup_flags)) {
			lookup_flags |= LOOKUP_REVAL;
			goto retry;
		}
	}

	io_xattr_finish(req, ret);
	return 0;
}

static int io_unlinkat_prep(struct io_kiocb *req,
			    const struct io_uring_sqe *sqe)
{
@@ -4345,8 +4609,6 @@ static int io_unlinkat(struct io_kiocb *req, unsigned int issue_flags)
		ret = do_unlinkat(un->dfd, un->filename);

	req->flags &= ~REQ_F_NEED_CLEANUP;
	if (ret < 0)
		req_set_fail(req);
	io_req_complete(req, ret);
	return 0;
}
@@ -4385,8 +4647,6 @@ static int io_mkdirat(struct io_kiocb *req, unsigned int issue_flags)
	ret = do_mkdirat(mkd->dfd, mkd->filename, mkd->mode);

	req->flags &= ~REQ_F_NEED_CLEANUP;
	if (ret < 0)
		req_set_fail(req);
	io_req_complete(req, ret);
	return 0;
}
@@ -4431,8 +4691,6 @@ static int io_symlinkat(struct io_kiocb *req, unsigned int issue_flags)
	ret = do_symlinkat(sl->oldpath, sl->new_dfd, sl->newpath);

	req->flags &= ~REQ_F_NEED_CLEANUP;
	if (ret < 0)
		req_set_fail(req);
	io_req_complete(req, ret);
	return 0;
}
@@ -4480,8 +4738,6 @@ static int io_linkat(struct io_kiocb *req, unsigned int issue_flags)
				lnk->newpath, lnk->flags);

	req->flags &= ~REQ_F_NEED_CLEANUP;
	if (ret < 0)
		req_set_fail(req);
	io_req_complete(req, ret);
	return 0;
}
@@ -4515,8 +4771,6 @@ static int io_shutdown(struct io_kiocb *req, unsigned int issue_flags)
		return -ENOTSOCK;

	ret = __sys_shutdown_sock(sock, req->shutdown.how);
	if (ret < 0)
		req_set_fail(req);
	io_req_complete(req, ret);
	return 0;
#else
@@ -4574,7 +4828,7 @@ static int io_tee(struct io_kiocb *req, unsigned int issue_flags)
done:
	if (ret != sp->len)
		req_set_fail(req);
	io_req_complete(req, ret);
	__io_req_complete(req, 0, ret, 0);
	return 0;
}

@@ -4619,7 +4873,7 @@ static int io_splice(struct io_kiocb *req, unsigned int issue_flags)
done:
	if (ret != sp->len)
		req_set_fail(req);
	io_req_complete(req, ret);
	__io_req_complete(req, 0, ret, 0);
	return 0;
}

@@ -4714,8 +4968,6 @@ static int io_fsync(struct io_kiocb *req, unsigned int issue_flags)
	ret = vfs_fsync_range(req->file, req->sync.off,
				end > 0 ? end : LLONG_MAX,
				req->sync.flags & IORING_FSYNC_DATASYNC);
	if (ret < 0)
		req_set_fail(req);
	io_req_complete(req, ret);
	return 0;
}
@@ -4741,9 +4993,7 @@ static int io_fallocate(struct io_kiocb *req, unsigned int issue_flags)
		return -EAGAIN;
	ret = vfs_fallocate(req->file, req->sync.mode, req->sync.off,
				req->sync.len);
	if (ret < 0)
		req_set_fail(req);
	else
	if (ret >= 0)
		fsnotify_modify(req->file);
	io_req_complete(req, ret);
	return 0;
@@ -5255,8 +5505,6 @@ static int io_madvise(struct io_kiocb *req, unsigned int issue_flags)
		return -EAGAIN;

	ret = do_madvise(current->mm, ma->addr, ma->len, ma->advice);
	if (ret < 0)
		req_set_fail(req);
	io_req_complete(req, ret);
	return 0;
#else
@@ -5338,9 +5586,6 @@ static int io_statx(struct io_kiocb *req, unsigned int issue_flags)

	ret = do_statx(ctx->dfd, ctx->filename, ctx->flags, ctx->mask,
		       ctx->buffer);

	if (ret < 0)
		req_set_fail(req);
	io_req_complete(req, ret);
	return 0;
}
@@ -5433,8 +5678,6 @@ static int io_sync_file_range(struct io_kiocb *req, unsigned int issue_flags)

	ret = sync_file_range(req->file, req->sync.off, req->sync.len,
				req->sync.flags);
	if (ret < 0)
		req_set_fail(req);
	io_req_complete(req, ret);
	return 0;
}
@@ -7400,6 +7643,14 @@ static int io_req_prep(struct io_kiocb *req, const struct io_uring_sqe *sqe)
		return io_linkat_prep(req, sqe);
	case IORING_OP_MSG_RING:
		return io_msg_ring_prep(req, sqe);
	case IORING_OP_FSETXATTR:
		return io_fsetxattr_prep(req, sqe);
	case IORING_OP_SETXATTR:
		return io_setxattr_prep(req, sqe);
	case IORING_OP_FGETXATTR:
		return io_fgetxattr_prep(req, sqe);
	case IORING_OP_GETXATTR:
		return io_getxattr_prep(req, sqe);
	}

	printk_once(KERN_WARNING "io_uring: unhandled opcode %d\n",
@@ -7549,6 +7800,12 @@ static void io_clean_op(struct io_kiocb *req)
			if (req->statx.filename)
				putname(req->statx.filename);
			break;
		case IORING_OP_SETXATTR:
		case IORING_OP_FSETXATTR:
		case IORING_OP_GETXATTR:
		case IORING_OP_FGETXATTR:
			__io_xattr_finish(req);
			break;
		}
	}
	if ((req->flags & REQ_F_POLLED) && req->apoll) {
@@ -7705,6 +7962,18 @@ static int io_issue_sqe(struct io_kiocb *req, unsigned int issue_flags)
	case IORING_OP_MSG_RING:
		ret = io_msg_ring(req, issue_flags);
		break;
	case IORING_OP_FSETXATTR:
		ret = io_fsetxattr(req, issue_flags);
		break;
	case IORING_OP_SETXATTR:
		ret = io_setxattr(req, issue_flags);
		break;
	case IORING_OP_FGETXATTR:
		ret = io_fgetxattr(req, issue_flags);
		break;
	case IORING_OP_GETXATTR:
		ret = io_getxattr(req, issue_flags);
		break;
	default:
		ret = -EINVAL;
		break;
@@ -12444,6 +12713,7 @@ static int __init io_uring_init(void)
	BUILD_BUG_SQE_ELEM(42, __u16,  personality);
	BUILD_BUG_SQE_ELEM(44, __s32,  splice_fd_in);
	BUILD_BUG_SQE_ELEM(44, __u32,  file_index);
	BUILD_BUG_SQE_ELEM(48, __u64,  addr3);

	BUILD_BUG_ON(sizeof(struct io_uring_files_update) !=
		     sizeof(struct io_uring_rsrc_update));
+97 −46
Original line number Diff line number Diff line
@@ -25,6 +25,8 @@

#include <linux/uaccess.h>

#include "internal.h"

static const char *
strcmp_prefix(const char *a, const char *a_prefix)
{
@@ -539,44 +541,76 @@ EXPORT_SYMBOL_GPL(vfs_removexattr);
/*
 * Extended attribute SET operations
 */
static long
setxattr(struct user_namespace *mnt_userns, struct dentry *d,
	 const char __user *name, const void __user *value, size_t size,
	 int flags)

int setxattr_copy(const char __user *name, struct xattr_ctx *ctx)
{
	int error;
	void *kvalue = NULL;
	char kname[XATTR_NAME_MAX + 1];

	if (flags & ~(XATTR_CREATE|XATTR_REPLACE))
	if (ctx->flags & ~(XATTR_CREATE|XATTR_REPLACE))
		return -EINVAL;

	error = strncpy_from_user(kname, name, sizeof(kname));
	if (error == 0 || error == sizeof(kname))
		error = -ERANGE;
	error = strncpy_from_user(ctx->kname->name, name,
				sizeof(ctx->kname->name));
	if (error == 0 || error == sizeof(ctx->kname->name))
		return  -ERANGE;
	if (error < 0)
		return error;

	if (size) {
		if (size > XATTR_SIZE_MAX)
	error = 0;
	if (ctx->size) {
		if (ctx->size > XATTR_SIZE_MAX)
			return -E2BIG;
		kvalue = kvmalloc(size, GFP_KERNEL);
		if (!kvalue)
			return -ENOMEM;
		if (copy_from_user(kvalue, value, size)) {
			error = -EFAULT;
			goto out;

		ctx->kvalue = vmemdup_user(ctx->cvalue, ctx->size);
		if (IS_ERR(ctx->kvalue)) {
			error = PTR_ERR(ctx->kvalue);
			ctx->kvalue = NULL;
		}
		if ((strcmp(kname, XATTR_NAME_POSIX_ACL_ACCESS) == 0) ||
		    (strcmp(kname, XATTR_NAME_POSIX_ACL_DEFAULT) == 0))
	}

	return error;
}

static void setxattr_convert(struct user_namespace *mnt_userns,
			     struct dentry *d, struct xattr_ctx *ctx)
{
	if (ctx->size &&
		((strcmp(ctx->kname->name, XATTR_NAME_POSIX_ACL_ACCESS) == 0) ||
		(strcmp(ctx->kname->name, XATTR_NAME_POSIX_ACL_DEFAULT) == 0)))
		posix_acl_fix_xattr_from_user(mnt_userns, d_inode(d),
						      kvalue, size);
						ctx->kvalue, ctx->size);
}

	error = vfs_setxattr(mnt_userns, d, kname, kvalue, size, flags);
out:
	kvfree(kvalue);
int do_setxattr(struct user_namespace *mnt_userns, struct dentry *dentry,
		struct xattr_ctx *ctx)
{
	setxattr_convert(mnt_userns, dentry, ctx);
	return vfs_setxattr(mnt_userns, dentry, ctx->kname->name,
			ctx->kvalue, ctx->size, ctx->flags);
}

static long
setxattr(struct user_namespace *mnt_userns, struct dentry *d,
	const char __user *name, const void __user *value, size_t size,
	int flags)
{
	struct xattr_name kname;
	struct xattr_ctx ctx = {
		.cvalue   = value,
		.kvalue   = NULL,
		.size     = size,
		.kname    = &kname,
		.flags    = flags,
	};
	int error;

	error = setxattr_copy(name, &ctx);
	if (error)
		return error;

	error = do_setxattr(mnt_userns, d, &ctx);

	kvfree(ctx.kvalue);
	return error;
}

@@ -642,44 +676,61 @@ SYSCALL_DEFINE5(fsetxattr, int, fd, const char __user *, name,
/*
 * Extended attribute GET operations
 */
static ssize_t
getxattr(struct user_namespace *mnt_userns, struct dentry *d,
	 const char __user *name, void __user *value, size_t size)
ssize_t
do_getxattr(struct user_namespace *mnt_userns, struct dentry *d,
	struct xattr_ctx *ctx)
{
	ssize_t error;
	void *kvalue = NULL;
	char kname[XATTR_NAME_MAX + 1];
	char *kname = ctx->kname->name;

	error = strncpy_from_user(kname, name, sizeof(kname));
	if (error == 0 || error == sizeof(kname))
		error = -ERANGE;
	if (error < 0)
		return error;

	if (size) {
		if (size > XATTR_SIZE_MAX)
			size = XATTR_SIZE_MAX;
		kvalue = kvzalloc(size, GFP_KERNEL);
		if (!kvalue)
	if (ctx->size) {
		if (ctx->size > XATTR_SIZE_MAX)
			ctx->size = XATTR_SIZE_MAX;
		ctx->kvalue = kvzalloc(ctx->size, GFP_KERNEL);
		if (!ctx->kvalue)
			return -ENOMEM;
	}

	error = vfs_getxattr(mnt_userns, d, kname, kvalue, size);
	error = vfs_getxattr(mnt_userns, d, kname, ctx->kvalue, ctx->size);
	if (error > 0) {
		if ((strcmp(kname, XATTR_NAME_POSIX_ACL_ACCESS) == 0) ||
		    (strcmp(kname, XATTR_NAME_POSIX_ACL_DEFAULT) == 0))
			posix_acl_fix_xattr_to_user(mnt_userns, d_inode(d),
						    kvalue, error);
		if (size && copy_to_user(value, kvalue, error))
							ctx->kvalue, error);
		if (ctx->size && copy_to_user(ctx->value, ctx->kvalue, error))
			error = -EFAULT;
	} else if (error == -ERANGE && size >= XATTR_SIZE_MAX) {
	} else if (error == -ERANGE && ctx->size >= XATTR_SIZE_MAX) {
		/* The file system tried to returned a value bigger
		   than XATTR_SIZE_MAX bytes. Not possible. */
		error = -E2BIG;
	}

	kvfree(kvalue);
	return error;
}

static ssize_t
getxattr(struct user_namespace *mnt_userns, struct dentry *d,
	 const char __user *name, void __user *value, size_t size)
{
	ssize_t error;
	struct xattr_name kname;
	struct xattr_ctx ctx = {
		.value    = value,
		.kvalue   = NULL,
		.size     = size,
		.kname    = &kname,
		.flags    = 0,
	};

	error = strncpy_from_user(kname.name, name, sizeof(kname.name));
	if (error == 0 || error == sizeof(kname.name))
		error = -ERANGE;
	if (error < 0)
		return error;

	error =  do_getxattr(mnt_userns, d, &ctx);

	kvfree(ctx.kvalue);
	return error;
}

+5 −4
Original line number Diff line number Diff line
@@ -506,7 +506,7 @@ TRACE_EVENT(io_uring_req_failed,
		__field( u16,			personality	)
		__field( u32,			file_index	)
		__field( u64,			pad1		)
		__field( u64,			pad2		)
		__field( u64,			addr3		)
		__field( int,			error		)
	),

@@ -525,14 +525,15 @@ TRACE_EVENT(io_uring_req_failed,
		__entry->personality	= sqe->personality;
		__entry->file_index	= sqe->file_index;
		__entry->pad1		= sqe->__pad2[0];
		__entry->pad2		= sqe->__pad2[1];
		__entry->addr3		= sqe->addr3;
		__entry->error		= error;
	),

	TP_printk("ring %p, req %p, user_data 0x%llx, "
		  "op %d, flags 0x%x, prio=%d, off=%llu, addr=%llu, "
		  "len=%u, rw_flags=0x%x, buf_index=%d, "
		  "personality=%d, file_index=%d, pad=0x%llx/%llx, error=%d",
		  "personality=%d, file_index=%d, pad=0x%llx, addr3=%llx, "
		  "error=%d",
		  __entry->ctx, __entry->req, __entry->user_data,
		  __entry->opcode, __entry->flags, __entry->ioprio,
		  (unsigned long long)__entry->off,
@@ -540,7 +541,7 @@ TRACE_EVENT(io_uring_req_failed,
		  __entry->op_flags,
		  __entry->buf_index, __entry->personality, __entry->file_index,
		  (unsigned long long) __entry->pad1,
		  (unsigned long long) __entry->pad2, __entry->error)
		  (unsigned long long) __entry->addr3, __entry->error)
);


+7 −1
Original line number Diff line number Diff line
@@ -45,6 +45,7 @@ struct io_uring_sqe {
		__u32		rename_flags;
		__u32		unlink_flags;
		__u32		hardlink_flags;
		__u32		xattr_flags;
	};
	__u64	user_data;	/* data to be passed back at completion time */
	/* pack this to avoid bogus arm OABI complaints */
@@ -60,7 +61,8 @@ struct io_uring_sqe {
		__s32	splice_fd_in;
		__u32	file_index;
	};
	__u64	__pad2[2];
	__u64	addr3;
	__u64	__pad2[1];
};

/*
@@ -168,6 +170,10 @@ enum {
	IORING_OP_SYMLINKAT,
	IORING_OP_LINKAT,
	IORING_OP_MSG_RING,
	IORING_OP_FSETXATTR,
	IORING_OP_SETXATTR,
	IORING_OP_FGETXATTR,
	IORING_OP_GETXATTR,

	/* this goes last, obviously */
	IORING_OP_LAST,