From: kaixuxia <xiakaixu1987@gmail.com>
To: fstests@vger.kernel.org
Cc: linux-xfs@vger.kernel.org, guaneryu@gmail.com,
bfoster@redhat.com, newtongao@tencent.com,
jasperwang@tencent.com
Subject: [PATCH v3 3/4] fsstress: add EXCHANGE renameat2 support
Date: Thu, 31 Oct 2019 14:41:48 +0800 [thread overview]
Message-ID: <cd82570764e56234fbbf8dd20cc9d51aee07c4df.1572503039.git.kaixuxia@tencent.com> (raw)
In-Reply-To: <cover.1572503039.git.kaixuxia@tencent.com>
In-Reply-To: <cover.1572503039.git.kaixuxia@tencent.com>
Support the EXCHANGE renameat2 syscall in fsstress.
In order to maintain filelist/filename integrity, we restrict
rexchange to files of the same type.
Signed-off-by: kaixuxia <kaixuxia@tencent.com>
---
ltp/fsstress.c | 117 ++++++++++++++++++++++++++++++++++++++++++++++-----------
1 file changed, 96 insertions(+), 21 deletions(-)
diff --git a/ltp/fsstress.c b/ltp/fsstress.c
index ecc1adc..0125571 100644
--- a/ltp/fsstress.c
+++ b/ltp/fsstress.c
@@ -69,6 +69,9 @@ static int renameat2(int dfd1, const char *path1,
#ifndef RENAME_NOREPLACE
#define RENAME_NOREPLACE (1 << 0) /* Don't overwrite target */
#endif
+#ifndef RENAME_EXCHANGE
+#define RENAME_EXCHANGE (1 << 1) /* Exchange source and dest */
+#endif
#ifndef RENAME_WHITEOUT
#define RENAME_WHITEOUT (1 << 2) /* Whiteout source */
#endif
@@ -115,6 +118,7 @@ typedef enum {
OP_REMOVEFATTR,
OP_RENAME,
OP_RNOREPLACE,
+ OP_REXCHANGE,
OP_RWHITEOUT,
OP_RESVSP,
OP_RMDIR,
@@ -235,6 +239,7 @@ void readv_f(int, long);
void removefattr_f(int, long);
void rename_f(int, long);
void rnoreplace_f(int, long);
+void rexchange_f(int, long);
void rwhiteout_f(int, long);
void resvsp_f(int, long);
void rmdir_f(int, long);
@@ -296,6 +301,7 @@ opdesc_t ops[] = {
{ OP_REMOVEFATTR, "removefattr", removefattr_f, 1, 1 },
{ OP_RENAME, "rename", rename_f, 2, 1 },
{ OP_RNOREPLACE, "rnoreplace", rnoreplace_f, 2, 1 },
+ { OP_REXCHANGE, "rexchange", rexchange_f, 2, 1 },
{ OP_RWHITEOUT, "rwhiteout", rwhiteout_f, 2, 1 },
{ OP_RESVSP, "resvsp", resvsp_f, 1, 1 },
{ OP_RMDIR, "rmdir", rmdir_f, 1, 1 },
@@ -371,7 +377,8 @@ void del_from_flist(int, int);
int dirid_to_name(char *, int);
void doproc(void);
int fent_to_name(pathname_t *, flist_t *, fent_t *);
-void fix_parent(int, int);
+bool fents_ancestor_check(fent_t *, fent_t *);
+void fix_parent(int, int, bool);
void free_pathname(pathname_t *);
int generate_fname(fent_t *, int, pathname_t *, int *, int *);
int generate_xattr_name(int, char *, int);
@@ -1117,8 +1124,22 @@ fent_to_name(pathname_t *name, flist_t *flp, fent_t *fep)
return 1;
}
+bool
+fents_ancestor_check(fent_t *fep, fent_t *dfep)
+{
+ fent_t *tmpfep;
+
+ for (tmpfep = fep; tmpfep->parent != -1;
+ tmpfep = dirid_to_fent(tmpfep->parent)) {
+ if (tmpfep->parent == dfep->id)
+ return true;
+ }
+
+ return false;
+}
+
void
-fix_parent(int oldid, int newid)
+fix_parent(int oldid, int newid, bool swap)
{
fent_t *fep;
flist_t *flp;
@@ -1129,6 +1150,8 @@ fix_parent(int oldid, int newid)
for (j = 0, fep = flp->fents; j < flp->nfiles; j++, fep++) {
if (fep->parent == oldid)
fep->parent = newid;
+ else if (swap && fep->parent == newid)
+ fep->parent = oldid;
}
}
}
@@ -4256,6 +4279,7 @@ out:
struct print_flags renameat2_flags [] = {
{ RENAME_NOREPLACE, "NOREPLACE"},
+ { RENAME_EXCHANGE, "EXCHANGE"},
{ RENAME_WHITEOUT, "WHITEOUT"},
{ -1, NULL}
};
@@ -4291,41 +4315,86 @@ do_renameat2(int opno, long r, int mode)
return;
}
- /* get an existing directory for the destination parent directory name */
- if (!get_fname(FT_DIRm, random(), NULL, NULL, &dfep, &v))
- parid = -1;
- else
- parid = dfep->id;
- v |= v1;
+ /*
+ * Both pathnames must exist for the RENAME_EXCHANGE, and in
+ * order to maintain filelist/filename integrity, we should
+ * restrict exchange operation to files of the same type.
+ */
+ if (mode == RENAME_EXCHANGE) {
+ which = 1 << (flp - flist);
+ init_pathname(&newf);
+ if (!get_fname(which, random(), &newf, NULL, &dfep, &v)) {
+ if (v)
+ printf("%d/%d: rename - no target filename\n",
+ procid, opno);
+ free_pathname(&newf);
+ free_pathname(&f);
+ return;
+ }
+ if (which == FT_DIRm && (fents_ancestor_check(fep, dfep) ||
+ fents_ancestor_check(dfep, fep))) {
+ if (v)
+ printf("%d/%d: rename(REXCHANGE) %s and %s "
+ "have ancestor-descendant relationship\n",
+ procid, opno, f.path, newf.path);
+ free_pathname(&newf);
+ free_pathname(&f);
+ return;
+ }
+ v |= v1;
+ id = dfep->id;
+ parid = dfep->parent;
+ } else {
+ /*
+ * Get an existing directory for the destination parent
+ * directory name.
+ */
+ if (!get_fname(FT_DIRm, random(), NULL, NULL, &dfep, &v))
+ parid = -1;
+ else
+ parid = dfep->id;
+ v |= v1;
- /* generate a new path using an existing parent directory in name */
- init_pathname(&newf);
- e = generate_fname(dfep, flp - flist, &newf, &id, &v1);
- v |= v1;
- if (!e) {
- if (v) {
- (void)fent_to_name(&f, &flist[FT_DIR], dfep);
- printf("%d/%d: rename - no filename from %s\n",
- procid, opno, f.path);
+ /*
+ * Generate a new path using an existing parent directory
+ * in name.
+ */
+ init_pathname(&newf);
+ e = generate_fname(dfep, flp - flist, &newf, &id, &v1);
+ v |= v1;
+ if (!e) {
+ if (v) {
+ (void)fent_to_name(&f, &flist[FT_DIR], dfep);
+ printf("%d/%d: rename - no filename from %s\n",
+ procid, opno, f.path);
+ }
+ free_pathname(&newf);
+ free_pathname(&f);
+ return;
}
- free_pathname(&newf);
- free_pathname(&f);
- return;
}
e = rename_path(&f, &newf, mode) < 0 ? errno : 0;
check_cwd();
if (e == 0) {
int xattr_counter = fep->xattr_counter;
+ bool swap = (mode == RENAME_EXCHANGE) ? true : false;
oldid = fep->id;
oldparid = fep->parent;
+ /*
+ * Swap the parent ids for RENAME_EXCHANGE, and replace the
+ * old parent id for the others.
+ */
if (flp - flist == FT_DIR)
- fix_parent(oldid, id);
+ fix_parent(oldid, id, swap);
if (mode == RENAME_WHITEOUT) {
fep->xattr_counter = 0;
add_to_flist(flp - flist, id, parid, xattr_counter);
+ } else if (mode == RENAME_EXCHANGE) {
+ fep->xattr_counter = dfep->xattr_counter;
+ dfep->xattr_counter = xattr_counter;
} else {
del_from_flist(flp - flist, fep - flp->fents);
add_to_flist(flp - flist, id, parid, xattr_counter);
@@ -4359,6 +4428,12 @@ rnoreplace_f(int opno, long r)
}
void
+rexchange_f(int opno, long r)
+{
+ do_renameat2(opno, r, RENAME_EXCHANGE);
+}
+
+void
rwhiteout_f(int opno, long r)
{
do_renameat2(opno, r, RENAME_WHITEOUT);
--
1.8.3.1
next prev parent reply other threads:[~2019-10-31 6:41 UTC|newest]
Thread overview: 6+ messages / expand[flat|nested] mbox.gz Atom feed top
2019-10-31 6:41 [PATCH v3 0/4] xfstests: add deadlock between the AGI and AGF with RENAME_WHITEOUT test kaixuxia
2019-10-31 6:41 ` [PATCH v3 1/4] fsstress: show the real file id and parid in rename_f() kaixuxia
2019-10-31 6:41 ` [PATCH v3 2/4] fsstress: add NOREPLACE and WHITEOUT renameat2 support kaixuxia
2019-10-31 6:41 ` kaixuxia [this message]
2019-11-01 17:24 ` [PATCH v3 3/4] fsstress: add EXCHANGE " Brian Foster
2019-10-31 6:41 ` [PATCH v3 4/4] xfs: test the deadlock between the AGI and AGF with RENAME_WHITEOUT kaixuxia
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=cd82570764e56234fbbf8dd20cc9d51aee07c4df.1572503039.git.kaixuxia@tencent.com \
--to=xiakaixu1987@gmail.com \
--cc=bfoster@redhat.com \
--cc=fstests@vger.kernel.org \
--cc=guaneryu@gmail.com \
--cc=jasperwang@tencent.com \
--cc=linux-xfs@vger.kernel.org \
--cc=newtongao@tencent.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 a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).