All of lore.kernel.org
 help / color / mirror / Atom feed
From: "Darrick J. Wong" <djwong@kernel.org>
To: djwong@kernel.org, zlang@redhat.com
Cc: linux-xfs@vger.kernel.org, fstests@vger.kernel.org, guan@eryu.me
Subject: [PATCH 7/7] fsstress: update for FIEXCHANGE_RANGE
Date: Tue, 28 Feb 2023 18:59:43 -0800	[thread overview]
Message-ID: <167763958362.3796922.2350291536547146358.stgit@magnolia> (raw)
In-Reply-To: <167763954409.3796922.11086772690906428270.stgit@magnolia>

From: Darrick J. Wong <djwong@kernel.org>

Teach this stress tool to be able to use the file content exchange
ioctl.

Signed-off-by: Darrick J. Wong <djwong@kernel.org>
---
 ltp/fsstress.c |  168 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++
 1 file changed, 168 insertions(+)


diff --git a/ltp/fsstress.c b/ltp/fsstress.c
index 10608fb554..0fba3d92a0 100644
--- a/ltp/fsstress.c
+++ b/ltp/fsstress.c
@@ -143,6 +143,7 @@ typedef enum {
 	OP_URING_WRITE,
 	OP_WRITE,
 	OP_WRITEV,
+	OP_XCHGRANGE,
 	OP_LAST
 } opty_t;
 
@@ -272,6 +273,8 @@ void	uring_read_f(opnum_t, long);
 void	uring_write_f(opnum_t, long);
 void	write_f(opnum_t, long);
 void	writev_f(opnum_t, long);
+void	xchgrange_f(opnum_t, long);
+
 char	*xattr_flag_to_string(int);
 
 struct opdesc	ops[OP_LAST]	= {
@@ -340,6 +343,7 @@ struct opdesc	ops[OP_LAST]	= {
 	[OP_URING_WRITE]   = {"uring_write",   uring_write_f,	1, 1 },
 	[OP_WRITE]	   = {"write",	       write_f,		4, 1 },
 	[OP_WRITEV]	   = {"writev",	       writev_f,	4, 1 },
+	[OP_XCHGRANGE]	   = {"xchgrange",     xchgrange_f,	4, 1 },
 }, *ops_end;
 
 flist_t	flist[FT_nft] = {
@@ -2494,6 +2498,170 @@ chown_f(opnum_t opno, long r)
 	free_pathname(&f);
 }
 
+/* exchange some arbitrary range of f1 to f2...fn. */
+void
+xchgrange_f(
+	opnum_t			opno,
+	long			r)
+{
+#ifdef FIEXCHANGE_RANGE
+	struct file_xchg_range	fxr = { 0 };
+	static __u64		swap_flags = 0;
+	struct pathname		fpath1;
+	struct pathname		fpath2;
+	struct stat64		stat1;
+	struct stat64		stat2;
+	char			inoinfo1[1024];
+	char			inoinfo2[1024];
+	off64_t			lr;
+	off64_t			off1;
+	off64_t			off2;
+	off64_t			max_off2;
+	size_t			len;
+	int			v1;
+	int			v2;
+	int			fd1;
+	int			fd2;
+	int			ret;
+	int			tries = 0;
+	int			e;
+
+	/* Load paths */
+	init_pathname(&fpath1);
+	if (!get_fname(FT_REGm, r, &fpath1, NULL, NULL, &v1)) {
+		if (v1)
+			printf("%d/%lld: xchgrange read - no filename\n",
+				procid, opno);
+		goto out_fpath1;
+	}
+
+	init_pathname(&fpath2);
+	if (!get_fname(FT_REGm, random(), &fpath2, NULL, NULL, &v2)) {
+		if (v2)
+			printf("%d/%lld: xchgrange write - no filename\n",
+				procid, opno);
+		goto out_fpath2;
+	}
+
+	/* Open files */
+	fd1 = open_path(&fpath1, O_RDONLY);
+	e = fd1 < 0 ? errno : 0;
+	check_cwd();
+	if (fd1 < 0) {
+		if (v1)
+			printf("%d/%lld: xchgrange read - open %s failed %d\n",
+				procid, opno, fpath1.path, e);
+		goto out_fpath2;
+	}
+
+	fd2 = open_path(&fpath2, O_WRONLY);
+	e = fd2 < 0 ? errno : 0;
+	check_cwd();
+	if (fd2 < 0) {
+		if (v2)
+			printf("%d/%lld: xchgrange write - open %s failed %d\n",
+				procid, opno, fpath2.path, e);
+		goto out_fd1;
+	}
+
+	/* Get file stats */
+	if (fstat64(fd1, &stat1) < 0) {
+		if (v1)
+			printf("%d/%lld: xchgrange read - fstat64 %s failed %d\n",
+				procid, opno, fpath1.path, errno);
+		goto out_fd2;
+	}
+	inode_info(inoinfo1, sizeof(inoinfo1), &stat1, v1);
+
+	if (fstat64(fd2, &stat2) < 0) {
+		if (v2)
+			printf("%d/%lld: xchgrange write - fstat64 %s failed %d\n",
+				procid, opno, fpath2.path, errno);
+		goto out_fd2;
+	}
+	inode_info(inoinfo2, sizeof(inoinfo2), &stat2, v2);
+
+	if (stat1.st_size < (stat1.st_blksize * 2) ||
+	    stat2.st_size < (stat2.st_blksize * 2)) {
+		if (v2)
+			printf("%d/%lld: xchgrange - files are too small\n",
+				procid, opno);
+		goto out_fd2;
+	}
+
+	/* Never let us swap more than 1/4 of the files. */
+	len = (random() % FILELEN_MAX) + 1;
+	if (len > stat1.st_size / 4)
+		len = stat1.st_size / 4;
+	if (len > stat2.st_size / 4)
+		len = stat2.st_size / 4;
+	len = rounddown_64(len, stat1.st_blksize);
+	if (len == 0)
+		len = stat1.st_blksize;
+
+	/* Calculate offsets */
+	lr = ((int64_t)random() << 32) + random();
+	if (stat1.st_size == len)
+		off1 = 0;
+	else
+		off1 = (off64_t)(lr % MIN(stat1.st_size - len, MAXFSIZE));
+	off1 %= maxfsize;
+	off1 = rounddown_64(off1, stat1.st_blksize);
+
+	/*
+	 * If srcfile == destfile, randomly generate destination ranges
+	 * until we find one that doesn't overlap the source range.
+	 */
+	max_off2 = MIN(stat2.st_size  - len, MAXFSIZE);
+	do {
+		lr = ((int64_t)random() << 32) + random();
+		if (stat2.st_size == len)
+			off2 = 0;
+		else
+			off2 = (off64_t)(lr % max_off2);
+		off2 %= maxfsize;
+		off2 = rounddown_64(off2, stat2.st_blksize);
+	} while (stat1.st_ino == stat2.st_ino &&
+		 llabs(off2 - off1) < len &&
+		 tries++ < 10);
+
+	/* Swap data blocks */
+	fxr.file1_fd = fd1;
+	fxr.file1_offset = off1;
+	fxr.length = len;
+	fxr.file2_offset = off2;
+	fxr.flags = swap_flags;
+
+retry:
+	ret = ioctl(fd2, FIEXCHANGE_RANGE, &fxr);
+	e = ret < 0 ? errno : 0;
+	if (e == EOPNOTSUPP && !(swap_flags & FILE_XCHG_RANGE_NONATOMIC)) {
+		swap_flags = FILE_XCHG_RANGE_NONATOMIC;
+		fxr.flags |= swap_flags;
+		goto retry;
+	}
+	if (v1 || v2) {
+		printf("%d/%lld: xchgrange %s%s [%lld,%lld] -> %s%s [%lld,%lld]",
+			procid, opno,
+			fpath1.path, inoinfo1, (long long)off1, (long long)len,
+			fpath2.path, inoinfo2, (long long)off2, (long long)len);
+
+		if (ret < 0)
+			printf(" error %d", e);
+		printf("\n");
+	}
+
+out_fd2:
+	close(fd2);
+out_fd1:
+	close(fd1);
+out_fpath2:
+	free_pathname(&fpath2);
+out_fpath1:
+	free_pathname(&fpath1);
+#endif
+}
+
 /* reflink some arbitrary range of f1 to f2. */
 void
 clonerange_f(


  parent reply	other threads:[~2023-03-01  2:59 UTC|newest]

Thread overview: 11+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2023-03-01  2:59 [PATCHSET v24.2 0/7] fstests: atomic file updates Darrick J. Wong
2023-03-01  2:59 ` [PATCH 1/7] xfs/122: fix for swapext log items Darrick J. Wong
2023-03-01  2:59 ` [PATCH 2/7] generic: test old xfs extent swapping ioctl Darrick J. Wong
2023-03-01  2:59 ` [PATCH 3/7] generic: test new vfs swapext ioctl Darrick J. Wong
2023-03-01  2:59 ` [PATCH 4/7] generic, xfs: test scatter-gather atomic file updates Darrick J. Wong
2023-03-01  2:59 ` [PATCH 5/7] generic: test that file privilege gets dropped with FIEXCHANGE_RANGE Darrick J. Wong
2023-03-01  2:59 ` [PATCH 6/7] fsx: support FIEXCHANGE_RANGE Darrick J. Wong
2023-03-01  2:59 ` Darrick J. Wong [this message]
2023-03-02  9:42   ` [PATCH 7/7] fsstress: update for FIEXCHANGE_RANGE Zorro Lang
2023-03-02 15:36     ` Darrick J. Wong
  -- strict thread matches above, loose matches on Subject: below --
2022-12-30 22:19 [PATCHSET v24.0 0/7] fstests: atomic file updates Darrick J. Wong
2022-12-30 22:19 ` [PATCH 7/7] fsstress: update for FIEXCHANGE_RANGE Darrick J. Wong

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=167763958362.3796922.2350291536547146358.stgit@magnolia \
    --to=djwong@kernel.org \
    --cc=fstests@vger.kernel.org \
    --cc=guan@eryu.me \
    --cc=linux-xfs@vger.kernel.org \
    --cc=zlang@redhat.com \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.