* [PATCH 0/3] fsstress: add support for btrfs subvol and snapshot ops
@ 2019-11-14 15:58 Josef Bacik
2019-11-14 15:58 ` [PATCH 1/3] fsstress: add the ability to create/delete subvolumes Josef Bacik
` (2 more replies)
0 siblings, 3 replies; 8+ messages in thread
From: Josef Bacik @ 2019-11-14 15:58 UTC (permalink / raw)
To: fstests, kernel-team, linux-btrfs
For btrfs it would be nice to exercise our subvol and snapshot operations with
fsstress as well. The set of patches adds this ability. I've added a new file
type for subvolumes, and they behave just like directories for all intents and
purposes. The bulk of the supporting code needed for this went into the first
patch, as well as the code to add the ability to link in libbtrfsutil. The
second patch is more straightforward as it just adds the snapshot operation, and
the final patch goes through and makes everybody pick either a directory or
subvolume for their target file. I've done a bunch of testing with this on
btrfs to make sure everything works as expected. I then did a follow up run on
xfs to verify I didn't break the non-btrfs case. Thanks,
Josef
^ permalink raw reply [flat|nested] 8+ messages in thread
* [PATCH 1/3] fsstress: add the ability to create/delete subvolumes
2019-11-14 15:58 [PATCH 0/3] fsstress: add support for btrfs subvol and snapshot ops Josef Bacik
@ 2019-11-14 15:58 ` Josef Bacik
2019-11-14 18:14 ` [PATCH][v2] " Josef Bacik
2019-11-14 15:58 ` [PATCH 2/3] fsstress: add the ability to create snapshots Josef Bacik
2019-11-14 15:58 ` [PATCH 3/3] fsstress: allow operations to use either a directory or subvol Josef Bacik
2 siblings, 1 reply; 8+ messages in thread
From: Josef Bacik @ 2019-11-14 15:58 UTC (permalink / raw)
To: fstests, kernel-team, linux-btrfs
This patch adds support to fsstress for creating and deleting subvolumes
on a btrfs file system. We link in the libbtrfsutil library to handle
the mechanics of creating and deleting subvolumes instead of duplicating
the ioctl logic. There is code to check if we're on a btrfs fs at
startup time and if so 0 out the frequency of the btrfs specific
operations.
Signed-off-by: Josef Bacik <josef@toxicpanda.com>
---
configure.ac | 1 +
include/builddefs.in | 1 +
ltp/Makefile | 4 +
ltp/fsstress.c | 228 ++++++++++++++++++++++++++++++++++-------
m4/package_libbtrfs.m4 | 5 +
5 files changed, 204 insertions(+), 35 deletions(-)
create mode 100644 m4/package_libbtrfs.m4
diff --git a/configure.ac b/configure.ac
index 19798824..4bb50b32 100644
--- a/configure.ac
+++ b/configure.ac
@@ -67,6 +67,7 @@ AC_PACKAGE_WANT_FALLOCATE
AC_PACKAGE_WANT_OPEN_BY_HANDLE_AT
AC_PACKAGE_WANT_LINUX_PRCTL_H
AC_PACKAGE_WANT_LINUX_FS_H
+AC_PACKAGE_WANT_LIBBTRFSUTIL
AC_HAVE_COPY_FILE_RANGE
diff --git a/include/builddefs.in b/include/builddefs.in
index 2605e42d..e7894b1a 100644
--- a/include/builddefs.in
+++ b/include/builddefs.in
@@ -68,6 +68,7 @@ HAVE_ATTR_LIST = @have_attr_list@
HAVE_FIEMAP = @have_fiemap@
HAVE_FALLOCATE = @have_fallocate@
HAVE_COPY_FILE_RANGE = @have_copy_file_range@
+HAVE_LIBBTRFSUTIL = @have_libbtrfsutil@
GCCFLAGS = -funsigned-char -fno-strict-aliasing -Wall
diff --git a/ltp/Makefile b/ltp/Makefile
index e4ca45f4..ebf40336 100644
--- a/ltp/Makefile
+++ b/ltp/Makefile
@@ -24,6 +24,10 @@ LCFLAGS += -DAIO
LLDLIBS += -laio -lpthread
endif
+ifeq ($(HAVE_LIBBTRFSUTIL), true)
+LLDLIBS += -lbtrfsutil
+endif
+
ifeq ($(HAVE_FALLOCATE), true)
LCFLAGS += -DFALLOCATE
endif
diff --git a/ltp/fsstress.c b/ltp/fsstress.c
index 9f5ec1d0..e0636a12 100644
--- a/ltp/fsstress.c
+++ b/ltp/fsstress.c
@@ -53,6 +53,10 @@ io_context_t io_ctx;
#define SYS_renameat2 353
#endif
+#ifdef HAVE_BTRFSUTIL_H
+#include <btrfsutil.h>
+#endif
+
static int renameat2(int dfd1, const char *path1,
int dfd2, const char *path2,
unsigned int flags)
@@ -127,6 +131,8 @@ typedef enum {
OP_SETXATTR,
OP_SPLICE,
OP_STAT,
+ OP_SUBVOL_CREATE,
+ OP_SUBVOL_DELETE,
OP_SYMLINK,
OP_SYNC,
OP_TRUNCATE,
@@ -149,6 +155,7 @@ typedef struct opdesc {
typedef struct fent {
int id;
+ int ft;
int parent;
int xattr_counter;
} fent_t;
@@ -176,20 +183,22 @@ struct print_string {
int max;
};
-#define FT_DIR 0
-#define FT_DIRm (1 << FT_DIR)
-#define FT_REG 1
-#define FT_REGm (1 << FT_REG)
-#define FT_SYM 2
-#define FT_SYMm (1 << FT_SYM)
-#define FT_DEV 3
-#define FT_DEVm (1 << FT_DEV)
-#define FT_RTF 4
-#define FT_RTFm (1 << FT_RTF)
-#define FT_nft 5
-#define FT_ANYm ((1 << FT_nft) - 1)
+#define FT_DIR 0
+#define FT_DIRm (1 << FT_DIR)
+#define FT_REG 1
+#define FT_REGm (1 << FT_REG)
+#define FT_SYM 2
+#define FT_SYMm (1 << FT_SYM)
+#define FT_DEV 3
+#define FT_DEVm (1 << FT_DEV)
+#define FT_RTF 4
+#define FT_RTFm (1 << FT_RTF)
+#define FT_SUBVOL 5
+#define FT_SUBVOLm (1 << FT_SUBVOL)
+#define FT_nft 6
+#define FT_ANYm ((1 << FT_nft) - 1)
#define FT_REGFILE (FT_REGm | FT_RTFm)
-#define FT_NOTDIR (FT_ANYm & ~FT_DIRm)
+#define FT_NOTDIR (FT_ANYm & (~FT_DIRm & ~FT_SUBVOLm))
#define FLIST_SLOT_INCR 16
#define NDCACHE 64
@@ -248,6 +257,8 @@ void setfattr_f(int, long);
void setxattr_f(int, long);
void splice_f(int, long);
void stat_f(int, long);
+void subvol_create_f(int, long);
+void subvol_delete_f(int, long);
void symlink_f(int, long);
void sync_f(int, long);
void truncate_f(int, long);
@@ -313,6 +324,8 @@ opdesc_t ops[] = {
{ OP_SETXATTR, "setxattr", setxattr_f, 1, 1 },
{ OP_SPLICE, "splice", splice_f, 1, 1 },
{ OP_STAT, "stat", stat_f, 1, 0 },
+ { OP_SUBVOL_CREATE, "subvol_create", subvol_create_f, 1, 1},
+ { OP_SUBVOL_DELETE, "subvol_delete", subvol_delete_f, 1, 1},
{ OP_SYMLINK, "symlink", symlink_f, 2, 1 },
{ OP_SYNC, "sync", sync_f, 1, 1 },
{ OP_TRUNCATE, "truncate", truncate_f, 2, 1 },
@@ -328,6 +341,7 @@ flist_t flist[FT_nft] = {
{ 0, 0, 'l', NULL },
{ 0, 0, 'c', NULL },
{ 0, 0, 'r', NULL },
+ { 0, 0, 's', NULL },
};
int dcache[NDCACHE];
@@ -372,11 +386,11 @@ int creat_path(pathname_t *, mode_t);
void dcache_enter(int, int);
void dcache_init(void);
fent_t *dcache_lookup(int);
-void dcache_purge(int);
+void dcache_purge(int, int);
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 *);
+int fent_to_name(pathname_t *, fent_t *);
bool fents_ancestor_check(fent_t *, fent_t *);
void fix_parent(int, int, bool);
void free_pathname(pathname_t *);
@@ -407,6 +421,7 @@ int unlink_path(pathname_t *);
void usage(void);
void write_freq(void);
void zero_freq(void);
+void non_btrfs_freq(const char *);
void sg_handler(int signum)
{
@@ -560,6 +575,7 @@ int main(int argc, char **argv)
exit(1);
}
+ non_btrfs_freq(dirname);
(void)mkdir(dirname, 0777);
if (logname && logname[0] != '/') {
if (!getcwd(rpath, sizeof(rpath))){
@@ -795,6 +811,7 @@ add_to_flist(int ft, int id, int parent, int xattr_counter)
}
fep = &ftp->fents[ftp->nfiles++];
fep->id = id;
+ fep->ft = ft;
fep->parent = parent;
fep->xattr_counter = xattr_counter;
}
@@ -962,18 +979,22 @@ dcache_lookup(int dirid)
int i;
i = dcache[dirid % NDCACHE];
- if (i >= 0 && (fep = &flist[FT_DIR].fents[i])->id == dirid)
+ if (i >= 0 && i < flist[FT_DIR].nfiles &&
+ (fep = &flist[FT_DIR].fents[i])->id == dirid)
+ return fep;
+ if (i >= 0 && i < flist[FT_SUBVOL].nfiles &&
+ (fep = &flist[FT_SUBVOL].fents[i])->id == dirid)
return fep;
return NULL;
}
void
-dcache_purge(int dirid)
+dcache_purge(int dirid, int ft)
{
int *dcp;
-
dcp = &dcache[dirid % NDCACHE];
- if (*dcp >= 0 && flist[FT_DIR].fents[*dcp].id == dirid)
+ if (*dcp >= 0 && *dcp < flist[ft].nfiles &&
+ flist[ft].fents[*dcp].id == dirid)
*dcp = -1;
}
@@ -989,32 +1010,58 @@ del_from_flist(int ft, int slot)
flist_t *ftp;
ftp = &flist[ft];
- if (ft == FT_DIR)
- dcache_purge(ftp->fents[slot].id);
+ if (ft == FT_DIR || ft == FT_SUBVOL)
+ dcache_purge(ftp->fents[slot].id, ft);
if (slot != ftp->nfiles - 1) {
- if (ft == FT_DIR)
- dcache_purge(ftp->fents[ftp->nfiles - 1].id);
+ if (ft == FT_DIR || ft == FT_SUBVOL)
+ dcache_purge(ftp->fents[ftp->nfiles - 1].id, ft);
ftp->fents[slot] = ftp->fents[--ftp->nfiles];
} else
ftp->nfiles--;
}
+void
+delete_subvol_children(int parid)
+{
+ flist_t *flp;
+ int i;
+again:
+ for (i = 0, flp = flist; i < FT_nft; i++, flp++) {
+ int c;
+ for (c = 0; c < flp->nfiles; c++) {
+ if (flp->fents[c].parent == parid) {
+ int id = flp->fents[c].id;
+ del_from_flist(i, c);
+ if (i == FT_DIR || i == FT_SUBVOL)
+ delete_subvol_children(id);
+ goto again;
+ }
+ }
+ }
+}
+
fent_t *
dirid_to_fent(int dirid)
{
fent_t *efep;
fent_t *fep;
flist_t *flp;
+ int ft = FT_DIR;
if ((fep = dcache_lookup(dirid)))
return fep;
- flp = &flist[FT_DIR];
+again:
+ flp = &flist[ft];
for (fep = flp->fents, efep = &fep[flp->nfiles]; fep < efep; fep++) {
if (fep->id == dirid) {
dcache_enter(dirid, fep - flp->fents);
return fep;
}
}
+ if (ft == FT_DIR) {
+ ft = FT_SUBVOL;
+ goto again;
+ }
return NULL;
}
@@ -1091,8 +1138,9 @@ errout:
* Return 0 on error, 1 on success;
*/
int
-fent_to_name(pathname_t *name, flist_t *flp, fent_t *fep)
+fent_to_name(pathname_t *name, fent_t *fep)
{
+ flist_t *flp = &flist[fep->ft];
char buf[NAME_MAX + 1];
int i;
fent_t *pfep;
@@ -1112,7 +1160,7 @@ fent_to_name(pathname_t *name, flist_t *flp, fent_t *fep)
#endif
if (pfep == NULL)
return 0;
- e = fent_to_name(name, &flist[FT_DIR], pfep);
+ e = fent_to_name(name, pfep);
if (!e)
return 0;
append_pathname(name, "/");
@@ -1188,7 +1236,7 @@ generate_fname(fent_t *fep, int ft, pathname_t *name, int *idp, int *v)
/* prepend fep parent dir-name to it */
if (fep) {
- e = fent_to_name(name, &flist[FT_DIR], fep);
+ e = fent_to_name(name, fep);
if (!e)
return 0;
append_pathname(name, "/");
@@ -1270,7 +1318,7 @@ get_fname(int which, long r, pathname_t *name, flist_t **flpp, fent_t **fepp,
/* fill-in what we were asked for */
if (name) {
- e = fent_to_name(name, flp, fep);
+ e = fent_to_name(name, fep);
#ifdef DEBUG
if (!e) {
fprintf(stderr, "%d: failed to get path for entry:"
@@ -1852,6 +1900,35 @@ zero_freq(void)
p->freq = 0;
}
+#define ARRAY_SIZE(a) (sizeof(a) / sizeof(a[0]))
+
+opty_t btrfs_ops[] = {
+ OP_SUBVOL_CREATE,
+ OP_SUBVOL_DELETE,
+};
+
+void
+non_btrfs_freq(const char *path)
+{
+ opdesc_t *p;
+#ifdef HAVE_BTRFSUTIL_H
+ enum btrfs_util_error e;
+
+ e = btrfs_util_is_subvolume(path);
+ if (e != BTRFS_UTIL_ERROR_NOT_BTRFS)
+ return;
+#endif
+ for (p = ops; p < ops_end; p++) {
+ int i;
+ for (i = 0; i < ARRAY_SIZE(btrfs_ops); i++) {
+ if (p->op == btrfs_ops[i]) {
+ p->freq = 0;
+ break;
+ }
+ }
+ }
+}
+
void inode_info(char *str, size_t sz, struct stat64 *s, int verbose)
{
if (verbose)
@@ -3103,7 +3180,7 @@ creat_f(int opno, long r)
v |= v1;
if (!e) {
if (v) {
- (void)fent_to_name(&f, &flist[FT_DIR], fep);
+ (void)fent_to_name(&f, fep);
printf("%d/%d: creat - no filename from %s\n",
procid, opno, f.path);
}
@@ -3767,7 +3844,7 @@ link_f(int opno, long r)
v |= v1;
if (!e) {
if (v) {
- (void)fent_to_name(&l, &flist[FT_DIR], fep);
+ (void)fent_to_name(&l, fep);
printf("%d/%d: link - no filename from %s\n",
procid, opno, l.path);
}
@@ -3858,7 +3935,7 @@ mkdir_f(int opno, long r)
v |= v1;
if (!e) {
if (v) {
- (void)fent_to_name(&f, &flist[FT_DIR], fep);
+ (void)fent_to_name(&f, fep);
printf("%d/%d: mkdir - no filename from %s\n",
procid, opno, f.path);
}
@@ -3896,7 +3973,7 @@ mknod_f(int opno, long r)
v |= v1;
if (!e) {
if (v) {
- (void)fent_to_name(&f, &flist[FT_DIR], fep);
+ (void)fent_to_name(&f, fep);
printf("%d/%d: mknod - no filename from %s\n",
procid, opno, f.path);
}
@@ -4364,7 +4441,7 @@ do_renameat2(int opno, long r, int mode)
v |= v1;
if (!e) {
if (v) {
- (void)fent_to_name(&f, &flist[FT_DIR], dfep);
+ (void)fent_to_name(&f, dfep);
printf("%d/%d: rename - no filename from %s\n",
procid, opno, f.path);
}
@@ -4378,6 +4455,7 @@ do_renameat2(int opno, long r, int mode)
if (e == 0) {
int xattr_counter = fep->xattr_counter;
bool swap = (mode == RENAME_EXCHANGE) ? true : false;
+ int ft = flp - flist;
oldid = fep->id;
oldparid = fep->parent;
@@ -4386,7 +4464,7 @@ do_renameat2(int opno, long r, int mode)
* Swap the parent ids for RENAME_EXCHANGE, and replace the
* old parent id for the others.
*/
- if (flp - flist == FT_DIR)
+ if (ft == FT_DIR || ft == FT_SUBVOL)
fix_parent(oldid, id, swap);
if (mode == RENAME_WHITEOUT) {
@@ -4647,6 +4725,86 @@ stat_f(int opno, long r)
free_pathname(&f);
}
+void
+subvol_create_f(int opno, long r)
+{
+#ifdef HAVE_BTRFSUTIL_H
+ enum btrfs_util_error e;
+ pathname_t f;
+ fent_t *fep;
+ int id;
+ int parid;
+ int v;
+ int v1;
+ int err;
+
+ init_pathname(&f);
+ if (!get_fname(FT_DIRm | FT_SUBVOLm, r, NULL, NULL, &fep, &v))
+ parid = -1;
+ else
+ parid = fep->id;
+ err = generate_fname(fep, FT_SUBVOL, &f, &id, &v1);
+ v |= v1;
+ if (!err) {
+ if (v) {
+ (void)fent_to_name(&f, fep);
+ printf("%d/%d: subvol_create - no filename from %s\n",
+ procid, opno, f.path);
+ }
+ free_pathname(&f);
+ return;
+ }
+ e = btrfs_util_create_subvolume(f.path, 0, NULL, NULL);
+ if (e == BTRFS_UTIL_OK)
+ add_to_flist(FT_SUBVOL, id, parid, 0);
+ if (v) {
+ printf("%d/%d: subvol_create %s %d(%s)\n", procid, opno,
+ f.path, e, btrfs_util_strerror(e));
+ printf("%d/%d: subvol_create add id=%d,parent=%d\n", procid,
+ opno, id, parid);
+ }
+ free_pathname(&f);
+#endif
+}
+
+void
+subvol_delete_f(int opno, long r)
+{
+#ifdef HAVE_BTRFSUTIL_H
+ enum btrfs_util_error e;
+ pathname_t f;
+ fent_t *fep;
+ int v;
+ int oldid;
+ int oldparid;
+
+ init_pathname(&f);
+ if (!get_fname(FT_SUBVOLm, r, &f, NULL, &fep, &v)) {
+ if (v)
+ printf("%d:%d: subvol_delete - no subvolume\n", procid,
+ opno);
+ free_pathname(&f);
+ return;
+ }
+ e = btrfs_util_delete_subvolume(f.path, 0);
+ check_cwd();
+ if (e == BTRFS_UTIL_OK) {
+ oldid = fep->id;
+ oldparid = fep->parent;
+ delete_subvol_children(oldid);
+ del_from_flist(FT_SUBVOL, fep - flist[FT_SUBVOL].fents);
+ }
+ if (v) {
+ printf("%d/%d: subvol_delete %s %d(%s)\n", procid, opno, f.path,
+ e, btrfs_util_strerror(e));
+ if (e == BTRFS_UTIL_OK)
+ printf("%d/%d: subvol_delete del entry: id=%d,parent=%d\n",
+ procid, opno, oldid, oldparid);
+ }
+ free_pathname(&f);
+#endif
+}
+
void
symlink_f(int opno, long r)
{
@@ -4670,7 +4828,7 @@ symlink_f(int opno, long r)
v |= v1;
if (!e) {
if (v) {
- (void)fent_to_name(&f, &flist[FT_DIR], fep);
+ (void)fent_to_name(&f, fep);
printf("%d/%d: symlink - no filename from %s\n",
procid, opno, f.path);
}
diff --git a/m4/package_libbtrfs.m4 b/m4/package_libbtrfs.m4
new file mode 100644
index 00000000..4822cc4a
--- /dev/null
+++ b/m4/package_libbtrfs.m4
@@ -0,0 +1,5 @@
+AC_DEFUN([AC_PACKAGE_WANT_LIBBTRFSUTIL],
+ [ AC_CHECK_HEADERS(btrfsutil.h, [ have_libbtrfsutil=true ],
+ [ have_libbtrfsutil=false ])
+ AC_SUBST(have_libbtrfsutil)
+ ])
--
2.21.0
^ permalink raw reply related [flat|nested] 8+ messages in thread
* [PATCH 2/3] fsstress: add the ability to create snapshots
2019-11-14 15:58 [PATCH 0/3] fsstress: add support for btrfs subvol and snapshot ops Josef Bacik
2019-11-14 15:58 ` [PATCH 1/3] fsstress: add the ability to create/delete subvolumes Josef Bacik
@ 2019-11-14 15:58 ` Josef Bacik
2019-12-17 16:06 ` Filipe Manana
2019-11-14 15:58 ` [PATCH 3/3] fsstress: allow operations to use either a directory or subvol Josef Bacik
2 siblings, 1 reply; 8+ messages in thread
From: Josef Bacik @ 2019-11-14 15:58 UTC (permalink / raw)
To: fstests, kernel-team, linux-btrfs
Snapshots are just fancy subvolumes, add this ability so we can stress
snapshot creation. We get the deletion with SUBVOL_DELETE.
Signed-off-by: Josef Bacik <josef@toxicpanda.com>
---
ltp/fsstress.c | 53 ++++++++++++++++++++++++++++++++++++++++++++++++++
1 file changed, 53 insertions(+)
diff --git a/ltp/fsstress.c b/ltp/fsstress.c
index e0636a12..f7f5f1dc 100644
--- a/ltp/fsstress.c
+++ b/ltp/fsstress.c
@@ -129,6 +129,7 @@ typedef enum {
OP_SETATTR,
OP_SETFATTR,
OP_SETXATTR,
+ OP_SNAPSHOT,
OP_SPLICE,
OP_STAT,
OP_SUBVOL_CREATE,
@@ -255,6 +256,7 @@ void rmdir_f(int, long);
void setattr_f(int, long);
void setfattr_f(int, long);
void setxattr_f(int, long);
+void snapshot_f(int, long);
void splice_f(int, long);
void stat_f(int, long);
void subvol_create_f(int, long);
@@ -322,6 +324,7 @@ opdesc_t ops[] = {
{ OP_SETFATTR, "setfattr", setfattr_f, 2, 1 },
/* set project id (XFS_IOC_FSSETXATTR ioctl) */
{ OP_SETXATTR, "setxattr", setxattr_f, 1, 1 },
+ { OP_SNAPSHOT, "snapshot", snapshot_f, 1, 1 },
{ OP_SPLICE, "splice", splice_f, 1, 1 },
{ OP_STAT, "stat", stat_f, 1, 0 },
{ OP_SUBVOL_CREATE, "subvol_create", subvol_create_f, 1, 1},
@@ -1903,6 +1906,7 @@ zero_freq(void)
#define ARRAY_SIZE(a) (sizeof(a) / sizeof(a[0]))
opty_t btrfs_ops[] = {
+ OP_SNAPSHOT,
OP_SUBVOL_CREATE,
OP_SUBVOL_DELETE,
};
@@ -4703,6 +4707,55 @@ out:
free_pathname(&f);
}
+void
+snapshot_f(int opno, long r)
+{
+#ifdef HAVE_BTRFSUTIL_H
+ enum btrfs_util_error e;
+ pathname_t f;
+ pathname_t newf;
+ fent_t *fep;
+ int id;
+ int parid;
+ int v;
+ int v1;
+ int err;
+
+ init_pathname(&f);
+ if (!get_fname(FT_SUBVOLm, r, &f, NULL, &fep, &v)) {
+ if (v)
+ printf("%d/%d: snapshot - no subvolume\n", procid,
+ opno);
+ free_pathname(&f);
+ return;
+ }
+ init_pathname(&newf);
+ parid = fep->id;
+ err = generate_fname(fep, FT_SUBVOL, &newf, &id, &v1);
+ v |= v1;
+ if (!err) {
+ if (v) {
+ (void)fent_to_name(&f, fep);
+ printf("%d/%d: snapshot - no filename from %s\n",
+ procid, opno, f.path);
+ }
+ free_pathname(&f);
+ return;
+ }
+ e = btrfs_util_create_snapshot(f.path, newf.path, 0, NULL, NULL);
+ if (e == BTRFS_UTIL_OK)
+ add_to_flist(FT_SUBVOL, id, parid, 0);
+ if (v) {
+ printf("%d/%d: snapshot %s->%s %d(%s)\n", procid, opno,
+ f.path, newf.path, e, btrfs_util_strerror(e));
+ printf("%d/%d: snapshot add id=%d,parent=%d\n", procid, opno,
+ id, parid);
+ }
+ free_pathname(&newf);
+ free_pathname(&f);
+#endif
+}
+
void
stat_f(int opno, long r)
{
--
2.21.0
^ permalink raw reply related [flat|nested] 8+ messages in thread
* [PATCH 3/3] fsstress: allow operations to use either a directory or subvol
2019-11-14 15:58 [PATCH 0/3] fsstress: add support for btrfs subvol and snapshot ops Josef Bacik
2019-11-14 15:58 ` [PATCH 1/3] fsstress: add the ability to create/delete subvolumes Josef Bacik
2019-11-14 15:58 ` [PATCH 2/3] fsstress: add the ability to create snapshots Josef Bacik
@ 2019-11-14 15:58 ` Josef Bacik
2019-12-17 16:10 ` Filipe Manana
2 siblings, 1 reply; 8+ messages in thread
From: Josef Bacik @ 2019-11-14 15:58 UTC (permalink / raw)
To: fstests, kernel-team, linux-btrfs
Most operations are just looking for a base directory to generate a file
in, they don't actually need a directory specifically. Add FT_ANYDIR to
cover both directories and subvolumes, and then use this in all the
places where it makes sense.
Signed-off-by: Josef Bacik <josef@toxicpanda.com>
---
ltp/fsstress.c | 21 +++++++++++----------
1 file changed, 11 insertions(+), 10 deletions(-)
diff --git a/ltp/fsstress.c b/ltp/fsstress.c
index f7f5f1dc..30b2bd94 100644
--- a/ltp/fsstress.c
+++ b/ltp/fsstress.c
@@ -200,6 +200,7 @@ struct print_string {
#define FT_ANYm ((1 << FT_nft) - 1)
#define FT_REGFILE (FT_REGm | FT_RTFm)
#define FT_NOTDIR (FT_ANYm & (~FT_DIRm & ~FT_SUBVOLm))
+#define FT_ANYDIR (FT_DIRm | FT_SUBVOLm)
#define FLIST_SLOT_INCR 16
#define NDCACHE 64
@@ -3165,7 +3166,7 @@ creat_f(int opno, long r)
int v;
int v1;
- if (!get_fname(FT_DIRm, r, NULL, NULL, &fep, &v1))
+ if (!get_fname(FT_ANYDIR, r, NULL, NULL, &fep, &v1))
parid = -1;
else
parid = fep->id;
@@ -3729,7 +3730,7 @@ getdents_f(int opno, long r)
int v;
init_pathname(&f);
- if (!get_fname(FT_DIRm, r, &f, NULL, NULL, &v))
+ if (!get_fname(FT_ANYDIR, r, &f, NULL, NULL, &v))
append_pathname(&f, ".");
dir = opendir_path(&f);
check_cwd();
@@ -3761,7 +3762,7 @@ getfattr_f(int opno, long r)
int xattr_num;
init_pathname(&f);
- if (!get_fname(FT_REGFILE | FT_DIRm, r, &f, NULL, &fep, &v)) {
+ if (!get_fname(FT_REGFILE | FT_ANYDIR, r, &f, NULL, &fep, &v)) {
if (v)
printf("%d/%d: getfattr - no filename\n", procid, opno);
goto out;
@@ -3880,7 +3881,7 @@ listfattr_f(int opno, long r)
int buffer_len;
init_pathname(&f);
- if (!get_fname(FT_REGFILE | FT_DIRm, r, &f, NULL, &fep, &v)) {
+ if (!get_fname(FT_REGFILE | FT_ANYDIR, r, &f, NULL, &fep, &v)) {
if (v)
printf("%d/%d: listfattr - no filename\n", procid, opno);
goto out;
@@ -3930,7 +3931,7 @@ mkdir_f(int opno, long r)
int v;
int v1;
- if (!get_fname(FT_DIRm, r, NULL, NULL, &fep, &v))
+ if (!get_fname(FT_ANYDIR, r, NULL, NULL, &fep, &v))
parid = -1;
else
parid = fep->id;
@@ -3968,7 +3969,7 @@ mknod_f(int opno, long r)
int v;
int v1;
- if (!get_fname(FT_DIRm, r, NULL, NULL, &fep, &v))
+ if (!get_fname(FT_ANYDIR, r, NULL, NULL, &fep, &v))
parid = -1;
else
parid = fep->id;
@@ -4326,7 +4327,7 @@ removefattr_f(int opno, long r)
int xattr_num;
init_pathname(&f);
- if (!get_fname(FT_REGFILE | FT_DIRm, r, &f, NULL, &fep, &v)) {
+ if (!get_fname(FT_REGFILE | FT_ANYDIR, r, &f, NULL, &fep, &v)) {
if (v)
printf("%d/%d: removefattr - no filename\n", procid, opno);
goto out;
@@ -4646,7 +4647,7 @@ setfattr_f(int opno, long r)
int xattr_num;
init_pathname(&f);
- if (!get_fname(FT_REGFILE | FT_DIRm, r, &f, NULL, &fep, &v)) {
+ if (!get_fname(FT_REGFILE | FT_ANYDIR, r, &f, NULL, &fep, &v)) {
if (v)
printf("%d/%d: setfattr - no filename\n", procid, opno);
goto out;
@@ -4792,7 +4793,7 @@ subvol_create_f(int opno, long r)
int err;
init_pathname(&f);
- if (!get_fname(FT_DIRm | FT_SUBVOLm, r, NULL, NULL, &fep, &v))
+ if (!get_fname(FT_ANYDIR, r, NULL, NULL, &fep, &v))
parid = -1;
else
parid = fep->id;
@@ -4872,7 +4873,7 @@ symlink_f(int opno, long r)
int v1;
char *val;
- if (!get_fname(FT_DIRm, r, NULL, NULL, &fep, &v))
+ if (!get_fname(FT_ANYDIR, r, NULL, NULL, &fep, &v))
parid = -1;
else
parid = fep->id;
--
2.21.0
^ permalink raw reply related [flat|nested] 8+ messages in thread
* [PATCH][v2] fsstress: add the ability to create/delete subvolumes
2019-11-14 15:58 ` [PATCH 1/3] fsstress: add the ability to create/delete subvolumes Josef Bacik
@ 2019-11-14 18:14 ` Josef Bacik
2019-12-17 15:55 ` Filipe Manana
0 siblings, 1 reply; 8+ messages in thread
From: Josef Bacik @ 2019-11-14 18:14 UTC (permalink / raw)
To: fstests, kernel-team, linux-btrfs
This patch adds support to fsstress for creating and deleting subvolumes
on a btrfs file system. We link in the libbtrfsutil library to handle
the mechanics of creating and deleting subvolumes instead of duplicating
the ioctl logic. There is code to check if we're on a btrfs fs at
startup time and if so 0 out the frequency of the btrfs specific
operations.
Signed-off-by: Josef Bacik <josef@toxicpanda.com>
---
v1->v2:
- fixed the #include location for btrfsutil.h in fsstress.c. The old centos box
I had built this fine, but on modern boxes I was tripped up because I put this
in a weird #ifdef thing for renameat2. Moving it to the top so it actually
gets included and the build works.
configure.ac | 1 +
include/builddefs.in | 1 +
ltp/Makefile | 4 +
ltp/fsstress.c | 227 ++++++++++++++++++++++++++++++++++-------
m4/package_libbtrfs.m4 | 5 +
5 files changed, 203 insertions(+), 35 deletions(-)
create mode 100644 m4/package_libbtrfs.m4
diff --git a/configure.ac b/configure.ac
index 19798824..4bb50b32 100644
--- a/configure.ac
+++ b/configure.ac
@@ -67,6 +67,7 @@ AC_PACKAGE_WANT_FALLOCATE
AC_PACKAGE_WANT_OPEN_BY_HANDLE_AT
AC_PACKAGE_WANT_LINUX_PRCTL_H
AC_PACKAGE_WANT_LINUX_FS_H
+AC_PACKAGE_WANT_LIBBTRFSUTIL
AC_HAVE_COPY_FILE_RANGE
diff --git a/include/builddefs.in b/include/builddefs.in
index 2605e42d..e7894b1a 100644
--- a/include/builddefs.in
+++ b/include/builddefs.in
@@ -68,6 +68,7 @@ HAVE_ATTR_LIST = @have_attr_list@
HAVE_FIEMAP = @have_fiemap@
HAVE_FALLOCATE = @have_fallocate@
HAVE_COPY_FILE_RANGE = @have_copy_file_range@
+HAVE_LIBBTRFSUTIL = @have_libbtrfsutil@
GCCFLAGS = -funsigned-char -fno-strict-aliasing -Wall
diff --git a/ltp/Makefile b/ltp/Makefile
index e4ca45f4..ebf40336 100644
--- a/ltp/Makefile
+++ b/ltp/Makefile
@@ -24,6 +24,10 @@ LCFLAGS += -DAIO
LLDLIBS += -laio -lpthread
endif
+ifeq ($(HAVE_LIBBTRFSUTIL), true)
+LLDLIBS += -lbtrfsutil
+endif
+
ifeq ($(HAVE_FALLOCATE), true)
LCFLAGS += -DFALLOCATE
endif
diff --git a/ltp/fsstress.c b/ltp/fsstress.c
index 9f5ec1d0..45325a67 100644
--- a/ltp/fsstress.c
+++ b/ltp/fsstress.c
@@ -10,6 +10,9 @@
#include <stddef.h>
#include "global.h"
+#ifdef HAVE_BTRFSUTIL_H
+#include <btrfsutil.h>
+#endif
#ifdef HAVE_ATTR_ATTRIBUTES_H
#include <attr/attributes.h>
#endif
@@ -127,6 +130,8 @@ typedef enum {
OP_SETXATTR,
OP_SPLICE,
OP_STAT,
+ OP_SUBVOL_CREATE,
+ OP_SUBVOL_DELETE,
OP_SYMLINK,
OP_SYNC,
OP_TRUNCATE,
@@ -149,6 +154,7 @@ typedef struct opdesc {
typedef struct fent {
int id;
+ int ft;
int parent;
int xattr_counter;
} fent_t;
@@ -176,20 +182,22 @@ struct print_string {
int max;
};
-#define FT_DIR 0
-#define FT_DIRm (1 << FT_DIR)
-#define FT_REG 1
-#define FT_REGm (1 << FT_REG)
-#define FT_SYM 2
-#define FT_SYMm (1 << FT_SYM)
-#define FT_DEV 3
-#define FT_DEVm (1 << FT_DEV)
-#define FT_RTF 4
-#define FT_RTFm (1 << FT_RTF)
-#define FT_nft 5
-#define FT_ANYm ((1 << FT_nft) - 1)
+#define FT_DIR 0
+#define FT_DIRm (1 << FT_DIR)
+#define FT_REG 1
+#define FT_REGm (1 << FT_REG)
+#define FT_SYM 2
+#define FT_SYMm (1 << FT_SYM)
+#define FT_DEV 3
+#define FT_DEVm (1 << FT_DEV)
+#define FT_RTF 4
+#define FT_RTFm (1 << FT_RTF)
+#define FT_SUBVOL 5
+#define FT_SUBVOLm (1 << FT_SUBVOL)
+#define FT_nft 6
+#define FT_ANYm ((1 << FT_nft) - 1)
#define FT_REGFILE (FT_REGm | FT_RTFm)
-#define FT_NOTDIR (FT_ANYm & ~FT_DIRm)
+#define FT_NOTDIR (FT_ANYm & (~FT_DIRm & ~FT_SUBVOLm))
#define FLIST_SLOT_INCR 16
#define NDCACHE 64
@@ -248,6 +256,8 @@ void setfattr_f(int, long);
void setxattr_f(int, long);
void splice_f(int, long);
void stat_f(int, long);
+void subvol_create_f(int, long);
+void subvol_delete_f(int, long);
void symlink_f(int, long);
void sync_f(int, long);
void truncate_f(int, long);
@@ -313,6 +323,8 @@ opdesc_t ops[] = {
{ OP_SETXATTR, "setxattr", setxattr_f, 1, 1 },
{ OP_SPLICE, "splice", splice_f, 1, 1 },
{ OP_STAT, "stat", stat_f, 1, 0 },
+ { OP_SUBVOL_CREATE, "subvol_create", subvol_create_f, 1, 1},
+ { OP_SUBVOL_DELETE, "subvol_delete", subvol_delete_f, 1, 1},
{ OP_SYMLINK, "symlink", symlink_f, 2, 1 },
{ OP_SYNC, "sync", sync_f, 1, 1 },
{ OP_TRUNCATE, "truncate", truncate_f, 2, 1 },
@@ -328,6 +340,7 @@ flist_t flist[FT_nft] = {
{ 0, 0, 'l', NULL },
{ 0, 0, 'c', NULL },
{ 0, 0, 'r', NULL },
+ { 0, 0, 's', NULL },
};
int dcache[NDCACHE];
@@ -372,11 +385,11 @@ int creat_path(pathname_t *, mode_t);
void dcache_enter(int, int);
void dcache_init(void);
fent_t *dcache_lookup(int);
-void dcache_purge(int);
+void dcache_purge(int, int);
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 *);
+int fent_to_name(pathname_t *, fent_t *);
bool fents_ancestor_check(fent_t *, fent_t *);
void fix_parent(int, int, bool);
void free_pathname(pathname_t *);
@@ -407,6 +420,7 @@ int unlink_path(pathname_t *);
void usage(void);
void write_freq(void);
void zero_freq(void);
+void non_btrfs_freq(const char *);
void sg_handler(int signum)
{
@@ -560,6 +574,7 @@ int main(int argc, char **argv)
exit(1);
}
+ non_btrfs_freq(dirname);
(void)mkdir(dirname, 0777);
if (logname && logname[0] != '/') {
if (!getcwd(rpath, sizeof(rpath))){
@@ -795,6 +810,7 @@ add_to_flist(int ft, int id, int parent, int xattr_counter)
}
fep = &ftp->fents[ftp->nfiles++];
fep->id = id;
+ fep->ft = ft;
fep->parent = parent;
fep->xattr_counter = xattr_counter;
}
@@ -962,18 +978,22 @@ dcache_lookup(int dirid)
int i;
i = dcache[dirid % NDCACHE];
- if (i >= 0 && (fep = &flist[FT_DIR].fents[i])->id == dirid)
+ if (i >= 0 && i < flist[FT_DIR].nfiles &&
+ (fep = &flist[FT_DIR].fents[i])->id == dirid)
+ return fep;
+ if (i >= 0 && i < flist[FT_SUBVOL].nfiles &&
+ (fep = &flist[FT_SUBVOL].fents[i])->id == dirid)
return fep;
return NULL;
}
void
-dcache_purge(int dirid)
+dcache_purge(int dirid, int ft)
{
int *dcp;
-
dcp = &dcache[dirid % NDCACHE];
- if (*dcp >= 0 && flist[FT_DIR].fents[*dcp].id == dirid)
+ if (*dcp >= 0 && *dcp < flist[ft].nfiles &&
+ flist[ft].fents[*dcp].id == dirid)
*dcp = -1;
}
@@ -989,32 +1009,58 @@ del_from_flist(int ft, int slot)
flist_t *ftp;
ftp = &flist[ft];
- if (ft == FT_DIR)
- dcache_purge(ftp->fents[slot].id);
+ if (ft == FT_DIR || ft == FT_SUBVOL)
+ dcache_purge(ftp->fents[slot].id, ft);
if (slot != ftp->nfiles - 1) {
- if (ft == FT_DIR)
- dcache_purge(ftp->fents[ftp->nfiles - 1].id);
+ if (ft == FT_DIR || ft == FT_SUBVOL)
+ dcache_purge(ftp->fents[ftp->nfiles - 1].id, ft);
ftp->fents[slot] = ftp->fents[--ftp->nfiles];
} else
ftp->nfiles--;
}
+void
+delete_subvol_children(int parid)
+{
+ flist_t *flp;
+ int i;
+again:
+ for (i = 0, flp = flist; i < FT_nft; i++, flp++) {
+ int c;
+ for (c = 0; c < flp->nfiles; c++) {
+ if (flp->fents[c].parent == parid) {
+ int id = flp->fents[c].id;
+ del_from_flist(i, c);
+ if (i == FT_DIR || i == FT_SUBVOL)
+ delete_subvol_children(id);
+ goto again;
+ }
+ }
+ }
+}
+
fent_t *
dirid_to_fent(int dirid)
{
fent_t *efep;
fent_t *fep;
flist_t *flp;
+ int ft = FT_DIR;
if ((fep = dcache_lookup(dirid)))
return fep;
- flp = &flist[FT_DIR];
+again:
+ flp = &flist[ft];
for (fep = flp->fents, efep = &fep[flp->nfiles]; fep < efep; fep++) {
if (fep->id == dirid) {
dcache_enter(dirid, fep - flp->fents);
return fep;
}
}
+ if (ft == FT_DIR) {
+ ft = FT_SUBVOL;
+ goto again;
+ }
return NULL;
}
@@ -1091,8 +1137,9 @@ errout:
* Return 0 on error, 1 on success;
*/
int
-fent_to_name(pathname_t *name, flist_t *flp, fent_t *fep)
+fent_to_name(pathname_t *name, fent_t *fep)
{
+ flist_t *flp = &flist[fep->ft];
char buf[NAME_MAX + 1];
int i;
fent_t *pfep;
@@ -1112,7 +1159,7 @@ fent_to_name(pathname_t *name, flist_t *flp, fent_t *fep)
#endif
if (pfep == NULL)
return 0;
- e = fent_to_name(name, &flist[FT_DIR], pfep);
+ e = fent_to_name(name, pfep);
if (!e)
return 0;
append_pathname(name, "/");
@@ -1188,7 +1235,7 @@ generate_fname(fent_t *fep, int ft, pathname_t *name, int *idp, int *v)
/* prepend fep parent dir-name to it */
if (fep) {
- e = fent_to_name(name, &flist[FT_DIR], fep);
+ e = fent_to_name(name, fep);
if (!e)
return 0;
append_pathname(name, "/");
@@ -1270,7 +1317,7 @@ get_fname(int which, long r, pathname_t *name, flist_t **flpp, fent_t **fepp,
/* fill-in what we were asked for */
if (name) {
- e = fent_to_name(name, flp, fep);
+ e = fent_to_name(name, fep);
#ifdef DEBUG
if (!e) {
fprintf(stderr, "%d: failed to get path for entry:"
@@ -1852,6 +1899,35 @@ zero_freq(void)
p->freq = 0;
}
+#define ARRAY_SIZE(a) (sizeof(a) / sizeof(a[0]))
+
+opty_t btrfs_ops[] = {
+ OP_SUBVOL_CREATE,
+ OP_SUBVOL_DELETE,
+};
+
+void
+non_btrfs_freq(const char *path)
+{
+ opdesc_t *p;
+#ifdef HAVE_BTRFSUTIL_H
+ enum btrfs_util_error e;
+
+ e = btrfs_util_is_subvolume(path);
+ if (e != BTRFS_UTIL_ERROR_NOT_BTRFS)
+ return;
+#endif
+ for (p = ops; p < ops_end; p++) {
+ int i;
+ for (i = 0; i < ARRAY_SIZE(btrfs_ops); i++) {
+ if (p->op == btrfs_ops[i]) {
+ p->freq = 0;
+ break;
+ }
+ }
+ }
+}
+
void inode_info(char *str, size_t sz, struct stat64 *s, int verbose)
{
if (verbose)
@@ -3103,7 +3179,7 @@ creat_f(int opno, long r)
v |= v1;
if (!e) {
if (v) {
- (void)fent_to_name(&f, &flist[FT_DIR], fep);
+ (void)fent_to_name(&f, fep);
printf("%d/%d: creat - no filename from %s\n",
procid, opno, f.path);
}
@@ -3767,7 +3843,7 @@ link_f(int opno, long r)
v |= v1;
if (!e) {
if (v) {
- (void)fent_to_name(&l, &flist[FT_DIR], fep);
+ (void)fent_to_name(&l, fep);
printf("%d/%d: link - no filename from %s\n",
procid, opno, l.path);
}
@@ -3858,7 +3934,7 @@ mkdir_f(int opno, long r)
v |= v1;
if (!e) {
if (v) {
- (void)fent_to_name(&f, &flist[FT_DIR], fep);
+ (void)fent_to_name(&f, fep);
printf("%d/%d: mkdir - no filename from %s\n",
procid, opno, f.path);
}
@@ -3896,7 +3972,7 @@ mknod_f(int opno, long r)
v |= v1;
if (!e) {
if (v) {
- (void)fent_to_name(&f, &flist[FT_DIR], fep);
+ (void)fent_to_name(&f, fep);
printf("%d/%d: mknod - no filename from %s\n",
procid, opno, f.path);
}
@@ -4364,7 +4440,7 @@ do_renameat2(int opno, long r, int mode)
v |= v1;
if (!e) {
if (v) {
- (void)fent_to_name(&f, &flist[FT_DIR], dfep);
+ (void)fent_to_name(&f, dfep);
printf("%d/%d: rename - no filename from %s\n",
procid, opno, f.path);
}
@@ -4378,6 +4454,7 @@ do_renameat2(int opno, long r, int mode)
if (e == 0) {
int xattr_counter = fep->xattr_counter;
bool swap = (mode == RENAME_EXCHANGE) ? true : false;
+ int ft = flp - flist;
oldid = fep->id;
oldparid = fep->parent;
@@ -4386,7 +4463,7 @@ do_renameat2(int opno, long r, int mode)
* Swap the parent ids for RENAME_EXCHANGE, and replace the
* old parent id for the others.
*/
- if (flp - flist == FT_DIR)
+ if (ft == FT_DIR || ft == FT_SUBVOL)
fix_parent(oldid, id, swap);
if (mode == RENAME_WHITEOUT) {
@@ -4647,6 +4724,86 @@ stat_f(int opno, long r)
free_pathname(&f);
}
+void
+subvol_create_f(int opno, long r)
+{
+#ifdef HAVE_BTRFSUTIL_H
+ enum btrfs_util_error e;
+ pathname_t f;
+ fent_t *fep;
+ int id;
+ int parid;
+ int v;
+ int v1;
+ int err;
+
+ init_pathname(&f);
+ if (!get_fname(FT_DIRm | FT_SUBVOLm, r, NULL, NULL, &fep, &v))
+ parid = -1;
+ else
+ parid = fep->id;
+ err = generate_fname(fep, FT_SUBVOL, &f, &id, &v1);
+ v |= v1;
+ if (!err) {
+ if (v) {
+ (void)fent_to_name(&f, fep);
+ printf("%d/%d: subvol_create - no filename from %s\n",
+ procid, opno, f.path);
+ }
+ free_pathname(&f);
+ return;
+ }
+ e = btrfs_util_create_subvolume(f.path, 0, NULL, NULL);
+ if (e == BTRFS_UTIL_OK)
+ add_to_flist(FT_SUBVOL, id, parid, 0);
+ if (v) {
+ printf("%d/%d: subvol_create %s %d(%s)\n", procid, opno,
+ f.path, e, btrfs_util_strerror(e));
+ printf("%d/%d: subvol_create add id=%d,parent=%d\n", procid,
+ opno, id, parid);
+ }
+ free_pathname(&f);
+#endif
+}
+
+void
+subvol_delete_f(int opno, long r)
+{
+#ifdef HAVE_BTRFSUTIL_H
+ enum btrfs_util_error e;
+ pathname_t f;
+ fent_t *fep;
+ int v;
+ int oldid;
+ int oldparid;
+
+ init_pathname(&f);
+ if (!get_fname(FT_SUBVOLm, r, &f, NULL, &fep, &v)) {
+ if (v)
+ printf("%d:%d: subvol_delete - no subvolume\n", procid,
+ opno);
+ free_pathname(&f);
+ return;
+ }
+ e = btrfs_util_delete_subvolume(f.path, 0);
+ check_cwd();
+ if (e == BTRFS_UTIL_OK) {
+ oldid = fep->id;
+ oldparid = fep->parent;
+ delete_subvol_children(oldid);
+ del_from_flist(FT_SUBVOL, fep - flist[FT_SUBVOL].fents);
+ }
+ if (v) {
+ printf("%d/%d: subvol_delete %s %d(%s)\n", procid, opno, f.path,
+ e, btrfs_util_strerror(e));
+ if (e == BTRFS_UTIL_OK)
+ printf("%d/%d: subvol_delete del entry: id=%d,parent=%d\n",
+ procid, opno, oldid, oldparid);
+ }
+ free_pathname(&f);
+#endif
+}
+
void
symlink_f(int opno, long r)
{
@@ -4670,7 +4827,7 @@ symlink_f(int opno, long r)
v |= v1;
if (!e) {
if (v) {
- (void)fent_to_name(&f, &flist[FT_DIR], fep);
+ (void)fent_to_name(&f, fep);
printf("%d/%d: symlink - no filename from %s\n",
procid, opno, f.path);
}
diff --git a/m4/package_libbtrfs.m4 b/m4/package_libbtrfs.m4
new file mode 100644
index 00000000..4822cc4a
--- /dev/null
+++ b/m4/package_libbtrfs.m4
@@ -0,0 +1,5 @@
+AC_DEFUN([AC_PACKAGE_WANT_LIBBTRFSUTIL],
+ [ AC_CHECK_HEADERS(btrfsutil.h, [ have_libbtrfsutil=true ],
+ [ have_libbtrfsutil=false ])
+ AC_SUBST(have_libbtrfsutil)
+ ])
--
2.21.0
^ permalink raw reply related [flat|nested] 8+ messages in thread
* Re: [PATCH][v2] fsstress: add the ability to create/delete subvolumes
2019-11-14 18:14 ` [PATCH][v2] " Josef Bacik
@ 2019-12-17 15:55 ` Filipe Manana
0 siblings, 0 replies; 8+ messages in thread
From: Filipe Manana @ 2019-12-17 15:55 UTC (permalink / raw)
To: Josef Bacik; +Cc: fstests, kernel-team, linux-btrfs
On Thu, Nov 14, 2019 at 6:15 PM Josef Bacik <josef@toxicpanda.com> wrote:
>
> This patch adds support to fsstress for creating and deleting subvolumes
> on a btrfs file system. We link in the libbtrfsutil library to handle
> the mechanics of creating and deleting subvolumes instead of duplicating
> the ioctl logic. There is code to check if we're on a btrfs fs at
> startup time and if so 0 out the frequency of the btrfs specific
> operations.
>
> Signed-off-by: Josef Bacik <josef@toxicpanda.com>
Very useful and works on my test environments, thanks.
Reviewed-by: Filipe Manana <fdmanana@suse.com>
> ---
> v1->v2:
> - fixed the #include location for btrfsutil.h in fsstress.c. The old centos box
> I had built this fine, but on modern boxes I was tripped up because I put this
> in a weird #ifdef thing for renameat2. Moving it to the top so it actually
> gets included and the build works.
>
> configure.ac | 1 +
> include/builddefs.in | 1 +
> ltp/Makefile | 4 +
> ltp/fsstress.c | 227 ++++++++++++++++++++++++++++++++++-------
> m4/package_libbtrfs.m4 | 5 +
> 5 files changed, 203 insertions(+), 35 deletions(-)
> create mode 100644 m4/package_libbtrfs.m4
>
> diff --git a/configure.ac b/configure.ac
> index 19798824..4bb50b32 100644
> --- a/configure.ac
> +++ b/configure.ac
> @@ -67,6 +67,7 @@ AC_PACKAGE_WANT_FALLOCATE
> AC_PACKAGE_WANT_OPEN_BY_HANDLE_AT
> AC_PACKAGE_WANT_LINUX_PRCTL_H
> AC_PACKAGE_WANT_LINUX_FS_H
> +AC_PACKAGE_WANT_LIBBTRFSUTIL
>
> AC_HAVE_COPY_FILE_RANGE
>
> diff --git a/include/builddefs.in b/include/builddefs.in
> index 2605e42d..e7894b1a 100644
> --- a/include/builddefs.in
> +++ b/include/builddefs.in
> @@ -68,6 +68,7 @@ HAVE_ATTR_LIST = @have_attr_list@
> HAVE_FIEMAP = @have_fiemap@
> HAVE_FALLOCATE = @have_fallocate@
> HAVE_COPY_FILE_RANGE = @have_copy_file_range@
> +HAVE_LIBBTRFSUTIL = @have_libbtrfsutil@
>
> GCCFLAGS = -funsigned-char -fno-strict-aliasing -Wall
>
> diff --git a/ltp/Makefile b/ltp/Makefile
> index e4ca45f4..ebf40336 100644
> --- a/ltp/Makefile
> +++ b/ltp/Makefile
> @@ -24,6 +24,10 @@ LCFLAGS += -DAIO
> LLDLIBS += -laio -lpthread
> endif
>
> +ifeq ($(HAVE_LIBBTRFSUTIL), true)
> +LLDLIBS += -lbtrfsutil
> +endif
> +
> ifeq ($(HAVE_FALLOCATE), true)
> LCFLAGS += -DFALLOCATE
> endif
> diff --git a/ltp/fsstress.c b/ltp/fsstress.c
> index 9f5ec1d0..45325a67 100644
> --- a/ltp/fsstress.c
> +++ b/ltp/fsstress.c
> @@ -10,6 +10,9 @@
> #include <stddef.h>
> #include "global.h"
>
> +#ifdef HAVE_BTRFSUTIL_H
> +#include <btrfsutil.h>
> +#endif
> #ifdef HAVE_ATTR_ATTRIBUTES_H
> #include <attr/attributes.h>
> #endif
> @@ -127,6 +130,8 @@ typedef enum {
> OP_SETXATTR,
> OP_SPLICE,
> OP_STAT,
> + OP_SUBVOL_CREATE,
> + OP_SUBVOL_DELETE,
> OP_SYMLINK,
> OP_SYNC,
> OP_TRUNCATE,
> @@ -149,6 +154,7 @@ typedef struct opdesc {
>
> typedef struct fent {
> int id;
> + int ft;
> int parent;
> int xattr_counter;
> } fent_t;
> @@ -176,20 +182,22 @@ struct print_string {
> int max;
> };
>
> -#define FT_DIR 0
> -#define FT_DIRm (1 << FT_DIR)
> -#define FT_REG 1
> -#define FT_REGm (1 << FT_REG)
> -#define FT_SYM 2
> -#define FT_SYMm (1 << FT_SYM)
> -#define FT_DEV 3
> -#define FT_DEVm (1 << FT_DEV)
> -#define FT_RTF 4
> -#define FT_RTFm (1 << FT_RTF)
> -#define FT_nft 5
> -#define FT_ANYm ((1 << FT_nft) - 1)
> +#define FT_DIR 0
> +#define FT_DIRm (1 << FT_DIR)
> +#define FT_REG 1
> +#define FT_REGm (1 << FT_REG)
> +#define FT_SYM 2
> +#define FT_SYMm (1 << FT_SYM)
> +#define FT_DEV 3
> +#define FT_DEVm (1 << FT_DEV)
> +#define FT_RTF 4
> +#define FT_RTFm (1 << FT_RTF)
> +#define FT_SUBVOL 5
> +#define FT_SUBVOLm (1 << FT_SUBVOL)
> +#define FT_nft 6
> +#define FT_ANYm ((1 << FT_nft) - 1)
> #define FT_REGFILE (FT_REGm | FT_RTFm)
> -#define FT_NOTDIR (FT_ANYm & ~FT_DIRm)
> +#define FT_NOTDIR (FT_ANYm & (~FT_DIRm & ~FT_SUBVOLm))
>
> #define FLIST_SLOT_INCR 16
> #define NDCACHE 64
> @@ -248,6 +256,8 @@ void setfattr_f(int, long);
> void setxattr_f(int, long);
> void splice_f(int, long);
> void stat_f(int, long);
> +void subvol_create_f(int, long);
> +void subvol_delete_f(int, long);
> void symlink_f(int, long);
> void sync_f(int, long);
> void truncate_f(int, long);
> @@ -313,6 +323,8 @@ opdesc_t ops[] = {
> { OP_SETXATTR, "setxattr", setxattr_f, 1, 1 },
> { OP_SPLICE, "splice", splice_f, 1, 1 },
> { OP_STAT, "stat", stat_f, 1, 0 },
> + { OP_SUBVOL_CREATE, "subvol_create", subvol_create_f, 1, 1},
> + { OP_SUBVOL_DELETE, "subvol_delete", subvol_delete_f, 1, 1},
> { OP_SYMLINK, "symlink", symlink_f, 2, 1 },
> { OP_SYNC, "sync", sync_f, 1, 1 },
> { OP_TRUNCATE, "truncate", truncate_f, 2, 1 },
> @@ -328,6 +340,7 @@ flist_t flist[FT_nft] = {
> { 0, 0, 'l', NULL },
> { 0, 0, 'c', NULL },
> { 0, 0, 'r', NULL },
> + { 0, 0, 's', NULL },
> };
>
> int dcache[NDCACHE];
> @@ -372,11 +385,11 @@ int creat_path(pathname_t *, mode_t);
> void dcache_enter(int, int);
> void dcache_init(void);
> fent_t *dcache_lookup(int);
> -void dcache_purge(int);
> +void dcache_purge(int, int);
> 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 *);
> +int fent_to_name(pathname_t *, fent_t *);
> bool fents_ancestor_check(fent_t *, fent_t *);
> void fix_parent(int, int, bool);
> void free_pathname(pathname_t *);
> @@ -407,6 +420,7 @@ int unlink_path(pathname_t *);
> void usage(void);
> void write_freq(void);
> void zero_freq(void);
> +void non_btrfs_freq(const char *);
>
> void sg_handler(int signum)
> {
> @@ -560,6 +574,7 @@ int main(int argc, char **argv)
> exit(1);
> }
>
> + non_btrfs_freq(dirname);
> (void)mkdir(dirname, 0777);
> if (logname && logname[0] != '/') {
> if (!getcwd(rpath, sizeof(rpath))){
> @@ -795,6 +810,7 @@ add_to_flist(int ft, int id, int parent, int xattr_counter)
> }
> fep = &ftp->fents[ftp->nfiles++];
> fep->id = id;
> + fep->ft = ft;
> fep->parent = parent;
> fep->xattr_counter = xattr_counter;
> }
> @@ -962,18 +978,22 @@ dcache_lookup(int dirid)
> int i;
>
> i = dcache[dirid % NDCACHE];
> - if (i >= 0 && (fep = &flist[FT_DIR].fents[i])->id == dirid)
> + if (i >= 0 && i < flist[FT_DIR].nfiles &&
> + (fep = &flist[FT_DIR].fents[i])->id == dirid)
> + return fep;
> + if (i >= 0 && i < flist[FT_SUBVOL].nfiles &&
> + (fep = &flist[FT_SUBVOL].fents[i])->id == dirid)
> return fep;
> return NULL;
> }
>
> void
> -dcache_purge(int dirid)
> +dcache_purge(int dirid, int ft)
> {
> int *dcp;
> -
> dcp = &dcache[dirid % NDCACHE];
> - if (*dcp >= 0 && flist[FT_DIR].fents[*dcp].id == dirid)
> + if (*dcp >= 0 && *dcp < flist[ft].nfiles &&
> + flist[ft].fents[*dcp].id == dirid)
> *dcp = -1;
> }
>
> @@ -989,32 +1009,58 @@ del_from_flist(int ft, int slot)
> flist_t *ftp;
>
> ftp = &flist[ft];
> - if (ft == FT_DIR)
> - dcache_purge(ftp->fents[slot].id);
> + if (ft == FT_DIR || ft == FT_SUBVOL)
> + dcache_purge(ftp->fents[slot].id, ft);
> if (slot != ftp->nfiles - 1) {
> - if (ft == FT_DIR)
> - dcache_purge(ftp->fents[ftp->nfiles - 1].id);
> + if (ft == FT_DIR || ft == FT_SUBVOL)
> + dcache_purge(ftp->fents[ftp->nfiles - 1].id, ft);
> ftp->fents[slot] = ftp->fents[--ftp->nfiles];
> } else
> ftp->nfiles--;
> }
>
> +void
> +delete_subvol_children(int parid)
> +{
> + flist_t *flp;
> + int i;
> +again:
> + for (i = 0, flp = flist; i < FT_nft; i++, flp++) {
> + int c;
> + for (c = 0; c < flp->nfiles; c++) {
> + if (flp->fents[c].parent == parid) {
> + int id = flp->fents[c].id;
> + del_from_flist(i, c);
> + if (i == FT_DIR || i == FT_SUBVOL)
> + delete_subvol_children(id);
> + goto again;
> + }
> + }
> + }
> +}
> +
> fent_t *
> dirid_to_fent(int dirid)
> {
> fent_t *efep;
> fent_t *fep;
> flist_t *flp;
> + int ft = FT_DIR;
>
> if ((fep = dcache_lookup(dirid)))
> return fep;
> - flp = &flist[FT_DIR];
> +again:
> + flp = &flist[ft];
> for (fep = flp->fents, efep = &fep[flp->nfiles]; fep < efep; fep++) {
> if (fep->id == dirid) {
> dcache_enter(dirid, fep - flp->fents);
> return fep;
> }
> }
> + if (ft == FT_DIR) {
> + ft = FT_SUBVOL;
> + goto again;
> + }
> return NULL;
> }
>
> @@ -1091,8 +1137,9 @@ errout:
> * Return 0 on error, 1 on success;
> */
> int
> -fent_to_name(pathname_t *name, flist_t *flp, fent_t *fep)
> +fent_to_name(pathname_t *name, fent_t *fep)
> {
> + flist_t *flp = &flist[fep->ft];
> char buf[NAME_MAX + 1];
> int i;
> fent_t *pfep;
> @@ -1112,7 +1159,7 @@ fent_to_name(pathname_t *name, flist_t *flp, fent_t *fep)
> #endif
> if (pfep == NULL)
> return 0;
> - e = fent_to_name(name, &flist[FT_DIR], pfep);
> + e = fent_to_name(name, pfep);
> if (!e)
> return 0;
> append_pathname(name, "/");
> @@ -1188,7 +1235,7 @@ generate_fname(fent_t *fep, int ft, pathname_t *name, int *idp, int *v)
>
> /* prepend fep parent dir-name to it */
> if (fep) {
> - e = fent_to_name(name, &flist[FT_DIR], fep);
> + e = fent_to_name(name, fep);
> if (!e)
> return 0;
> append_pathname(name, "/");
> @@ -1270,7 +1317,7 @@ get_fname(int which, long r, pathname_t *name, flist_t **flpp, fent_t **fepp,
>
> /* fill-in what we were asked for */
> if (name) {
> - e = fent_to_name(name, flp, fep);
> + e = fent_to_name(name, fep);
> #ifdef DEBUG
> if (!e) {
> fprintf(stderr, "%d: failed to get path for entry:"
> @@ -1852,6 +1899,35 @@ zero_freq(void)
> p->freq = 0;
> }
>
> +#define ARRAY_SIZE(a) (sizeof(a) / sizeof(a[0]))
> +
> +opty_t btrfs_ops[] = {
> + OP_SUBVOL_CREATE,
> + OP_SUBVOL_DELETE,
> +};
> +
> +void
> +non_btrfs_freq(const char *path)
> +{
> + opdesc_t *p;
> +#ifdef HAVE_BTRFSUTIL_H
> + enum btrfs_util_error e;
> +
> + e = btrfs_util_is_subvolume(path);
> + if (e != BTRFS_UTIL_ERROR_NOT_BTRFS)
> + return;
> +#endif
> + for (p = ops; p < ops_end; p++) {
> + int i;
> + for (i = 0; i < ARRAY_SIZE(btrfs_ops); i++) {
> + if (p->op == btrfs_ops[i]) {
> + p->freq = 0;
> + break;
> + }
> + }
> + }
> +}
> +
> void inode_info(char *str, size_t sz, struct stat64 *s, int verbose)
> {
> if (verbose)
> @@ -3103,7 +3179,7 @@ creat_f(int opno, long r)
> v |= v1;
> if (!e) {
> if (v) {
> - (void)fent_to_name(&f, &flist[FT_DIR], fep);
> + (void)fent_to_name(&f, fep);
> printf("%d/%d: creat - no filename from %s\n",
> procid, opno, f.path);
> }
> @@ -3767,7 +3843,7 @@ link_f(int opno, long r)
> v |= v1;
> if (!e) {
> if (v) {
> - (void)fent_to_name(&l, &flist[FT_DIR], fep);
> + (void)fent_to_name(&l, fep);
> printf("%d/%d: link - no filename from %s\n",
> procid, opno, l.path);
> }
> @@ -3858,7 +3934,7 @@ mkdir_f(int opno, long r)
> v |= v1;
> if (!e) {
> if (v) {
> - (void)fent_to_name(&f, &flist[FT_DIR], fep);
> + (void)fent_to_name(&f, fep);
> printf("%d/%d: mkdir - no filename from %s\n",
> procid, opno, f.path);
> }
> @@ -3896,7 +3972,7 @@ mknod_f(int opno, long r)
> v |= v1;
> if (!e) {
> if (v) {
> - (void)fent_to_name(&f, &flist[FT_DIR], fep);
> + (void)fent_to_name(&f, fep);
> printf("%d/%d: mknod - no filename from %s\n",
> procid, opno, f.path);
> }
> @@ -4364,7 +4440,7 @@ do_renameat2(int opno, long r, int mode)
> v |= v1;
> if (!e) {
> if (v) {
> - (void)fent_to_name(&f, &flist[FT_DIR], dfep);
> + (void)fent_to_name(&f, dfep);
> printf("%d/%d: rename - no filename from %s\n",
> procid, opno, f.path);
> }
> @@ -4378,6 +4454,7 @@ do_renameat2(int opno, long r, int mode)
> if (e == 0) {
> int xattr_counter = fep->xattr_counter;
> bool swap = (mode == RENAME_EXCHANGE) ? true : false;
> + int ft = flp - flist;
>
> oldid = fep->id;
> oldparid = fep->parent;
> @@ -4386,7 +4463,7 @@ do_renameat2(int opno, long r, int mode)
> * Swap the parent ids for RENAME_EXCHANGE, and replace the
> * old parent id for the others.
> */
> - if (flp - flist == FT_DIR)
> + if (ft == FT_DIR || ft == FT_SUBVOL)
> fix_parent(oldid, id, swap);
>
> if (mode == RENAME_WHITEOUT) {
> @@ -4647,6 +4724,86 @@ stat_f(int opno, long r)
> free_pathname(&f);
> }
>
> +void
> +subvol_create_f(int opno, long r)
> +{
> +#ifdef HAVE_BTRFSUTIL_H
> + enum btrfs_util_error e;
> + pathname_t f;
> + fent_t *fep;
> + int id;
> + int parid;
> + int v;
> + int v1;
> + int err;
> +
> + init_pathname(&f);
> + if (!get_fname(FT_DIRm | FT_SUBVOLm, r, NULL, NULL, &fep, &v))
> + parid = -1;
> + else
> + parid = fep->id;
> + err = generate_fname(fep, FT_SUBVOL, &f, &id, &v1);
> + v |= v1;
> + if (!err) {
> + if (v) {
> + (void)fent_to_name(&f, fep);
> + printf("%d/%d: subvol_create - no filename from %s\n",
> + procid, opno, f.path);
> + }
> + free_pathname(&f);
> + return;
> + }
> + e = btrfs_util_create_subvolume(f.path, 0, NULL, NULL);
> + if (e == BTRFS_UTIL_OK)
> + add_to_flist(FT_SUBVOL, id, parid, 0);
> + if (v) {
> + printf("%d/%d: subvol_create %s %d(%s)\n", procid, opno,
> + f.path, e, btrfs_util_strerror(e));
> + printf("%d/%d: subvol_create add id=%d,parent=%d\n", procid,
> + opno, id, parid);
> + }
> + free_pathname(&f);
> +#endif
> +}
> +
> +void
> +subvol_delete_f(int opno, long r)
> +{
> +#ifdef HAVE_BTRFSUTIL_H
> + enum btrfs_util_error e;
> + pathname_t f;
> + fent_t *fep;
> + int v;
> + int oldid;
> + int oldparid;
> +
> + init_pathname(&f);
> + if (!get_fname(FT_SUBVOLm, r, &f, NULL, &fep, &v)) {
> + if (v)
> + printf("%d:%d: subvol_delete - no subvolume\n", procid,
> + opno);
> + free_pathname(&f);
> + return;
> + }
> + e = btrfs_util_delete_subvolume(f.path, 0);
> + check_cwd();
> + if (e == BTRFS_UTIL_OK) {
> + oldid = fep->id;
> + oldparid = fep->parent;
> + delete_subvol_children(oldid);
> + del_from_flist(FT_SUBVOL, fep - flist[FT_SUBVOL].fents);
> + }
> + if (v) {
> + printf("%d/%d: subvol_delete %s %d(%s)\n", procid, opno, f.path,
> + e, btrfs_util_strerror(e));
> + if (e == BTRFS_UTIL_OK)
> + printf("%d/%d: subvol_delete del entry: id=%d,parent=%d\n",
> + procid, opno, oldid, oldparid);
> + }
> + free_pathname(&f);
> +#endif
> +}
> +
> void
> symlink_f(int opno, long r)
> {
> @@ -4670,7 +4827,7 @@ symlink_f(int opno, long r)
> v |= v1;
> if (!e) {
> if (v) {
> - (void)fent_to_name(&f, &flist[FT_DIR], fep);
> + (void)fent_to_name(&f, fep);
> printf("%d/%d: symlink - no filename from %s\n",
> procid, opno, f.path);
> }
> diff --git a/m4/package_libbtrfs.m4 b/m4/package_libbtrfs.m4
> new file mode 100644
> index 00000000..4822cc4a
> --- /dev/null
> +++ b/m4/package_libbtrfs.m4
> @@ -0,0 +1,5 @@
> +AC_DEFUN([AC_PACKAGE_WANT_LIBBTRFSUTIL],
> + [ AC_CHECK_HEADERS(btrfsutil.h, [ have_libbtrfsutil=true ],
> + [ have_libbtrfsutil=false ])
> + AC_SUBST(have_libbtrfsutil)
> + ])
> --
> 2.21.0
>
--
Filipe David Manana,
“Whether you think you can, or you think you can't — you're right.”
^ permalink raw reply [flat|nested] 8+ messages in thread
* Re: [PATCH 2/3] fsstress: add the ability to create snapshots
2019-11-14 15:58 ` [PATCH 2/3] fsstress: add the ability to create snapshots Josef Bacik
@ 2019-12-17 16:06 ` Filipe Manana
0 siblings, 0 replies; 8+ messages in thread
From: Filipe Manana @ 2019-12-17 16:06 UTC (permalink / raw)
To: Josef Bacik; +Cc: fstests, kernel-team, linux-btrfs
On Thu, Nov 14, 2019 at 3:59 PM Josef Bacik <josef@toxicpanda.com> wrote:
>
> Snapshots are just fancy subvolumes, add this ability so we can stress
> snapshot creation. We get the deletion with SUBVOL_DELETE.
>
> Signed-off-by: Josef Bacik <josef@toxicpanda.com>
Looks good, and it works on my test boxes.
Reviewed-by: Filipe Manana <fdmanana@suse.com>
> ---
> ltp/fsstress.c | 53 ++++++++++++++++++++++++++++++++++++++++++++++++++
> 1 file changed, 53 insertions(+)
>
> diff --git a/ltp/fsstress.c b/ltp/fsstress.c
> index e0636a12..f7f5f1dc 100644
> --- a/ltp/fsstress.c
> +++ b/ltp/fsstress.c
> @@ -129,6 +129,7 @@ typedef enum {
> OP_SETATTR,
> OP_SETFATTR,
> OP_SETXATTR,
> + OP_SNAPSHOT,
> OP_SPLICE,
> OP_STAT,
> OP_SUBVOL_CREATE,
> @@ -255,6 +256,7 @@ void rmdir_f(int, long);
> void setattr_f(int, long);
> void setfattr_f(int, long);
> void setxattr_f(int, long);
> +void snapshot_f(int, long);
> void splice_f(int, long);
> void stat_f(int, long);
> void subvol_create_f(int, long);
> @@ -322,6 +324,7 @@ opdesc_t ops[] = {
> { OP_SETFATTR, "setfattr", setfattr_f, 2, 1 },
> /* set project id (XFS_IOC_FSSETXATTR ioctl) */
> { OP_SETXATTR, "setxattr", setxattr_f, 1, 1 },
> + { OP_SNAPSHOT, "snapshot", snapshot_f, 1, 1 },
> { OP_SPLICE, "splice", splice_f, 1, 1 },
> { OP_STAT, "stat", stat_f, 1, 0 },
> { OP_SUBVOL_CREATE, "subvol_create", subvol_create_f, 1, 1},
> @@ -1903,6 +1906,7 @@ zero_freq(void)
> #define ARRAY_SIZE(a) (sizeof(a) / sizeof(a[0]))
>
> opty_t btrfs_ops[] = {
> + OP_SNAPSHOT,
> OP_SUBVOL_CREATE,
> OP_SUBVOL_DELETE,
> };
> @@ -4703,6 +4707,55 @@ out:
> free_pathname(&f);
> }
>
> +void
> +snapshot_f(int opno, long r)
> +{
> +#ifdef HAVE_BTRFSUTIL_H
> + enum btrfs_util_error e;
> + pathname_t f;
> + pathname_t newf;
> + fent_t *fep;
> + int id;
> + int parid;
> + int v;
> + int v1;
> + int err;
> +
> + init_pathname(&f);
> + if (!get_fname(FT_SUBVOLm, r, &f, NULL, &fep, &v)) {
> + if (v)
> + printf("%d/%d: snapshot - no subvolume\n", procid,
> + opno);
> + free_pathname(&f);
> + return;
> + }
> + init_pathname(&newf);
> + parid = fep->id;
> + err = generate_fname(fep, FT_SUBVOL, &newf, &id, &v1);
> + v |= v1;
> + if (!err) {
> + if (v) {
> + (void)fent_to_name(&f, fep);
> + printf("%d/%d: snapshot - no filename from %s\n",
> + procid, opno, f.path);
> + }
> + free_pathname(&f);
> + return;
> + }
> + e = btrfs_util_create_snapshot(f.path, newf.path, 0, NULL, NULL);
> + if (e == BTRFS_UTIL_OK)
> + add_to_flist(FT_SUBVOL, id, parid, 0);
> + if (v) {
> + printf("%d/%d: snapshot %s->%s %d(%s)\n", procid, opno,
> + f.path, newf.path, e, btrfs_util_strerror(e));
> + printf("%d/%d: snapshot add id=%d,parent=%d\n", procid, opno,
> + id, parid);
> + }
> + free_pathname(&newf);
> + free_pathname(&f);
> +#endif
> +}
> +
> void
> stat_f(int opno, long r)
> {
> --
> 2.21.0
>
--
Filipe David Manana,
“Whether you think you can, or you think you can't — you're right.”
^ permalink raw reply [flat|nested] 8+ messages in thread
* Re: [PATCH 3/3] fsstress: allow operations to use either a directory or subvol
2019-11-14 15:58 ` [PATCH 3/3] fsstress: allow operations to use either a directory or subvol Josef Bacik
@ 2019-12-17 16:10 ` Filipe Manana
0 siblings, 0 replies; 8+ messages in thread
From: Filipe Manana @ 2019-12-17 16:10 UTC (permalink / raw)
To: Josef Bacik; +Cc: fstests, kernel-team, linux-btrfs
On Thu, Nov 14, 2019 at 3:59 PM Josef Bacik <josef@toxicpanda.com> wrote:
>
> Most operations are just looking for a base directory to generate a file
> in, they don't actually need a directory specifically. Add FT_ANYDIR to
> cover both directories and subvolumes, and then use this in all the
> places where it makes sense.
>
> Signed-off-by: Josef Bacik <josef@toxicpanda.com>
Looks good and it works for me, thanks.
Reviewed-by: Filipe Manana <fdmanana@suse.com>
> ---
> ltp/fsstress.c | 21 +++++++++++----------
> 1 file changed, 11 insertions(+), 10 deletions(-)
>
> diff --git a/ltp/fsstress.c b/ltp/fsstress.c
> index f7f5f1dc..30b2bd94 100644
> --- a/ltp/fsstress.c
> +++ b/ltp/fsstress.c
> @@ -200,6 +200,7 @@ struct print_string {
> #define FT_ANYm ((1 << FT_nft) - 1)
> #define FT_REGFILE (FT_REGm | FT_RTFm)
> #define FT_NOTDIR (FT_ANYm & (~FT_DIRm & ~FT_SUBVOLm))
> +#define FT_ANYDIR (FT_DIRm | FT_SUBVOLm)
>
> #define FLIST_SLOT_INCR 16
> #define NDCACHE 64
> @@ -3165,7 +3166,7 @@ creat_f(int opno, long r)
> int v;
> int v1;
>
> - if (!get_fname(FT_DIRm, r, NULL, NULL, &fep, &v1))
> + if (!get_fname(FT_ANYDIR, r, NULL, NULL, &fep, &v1))
> parid = -1;
> else
> parid = fep->id;
> @@ -3729,7 +3730,7 @@ getdents_f(int opno, long r)
> int v;
>
> init_pathname(&f);
> - if (!get_fname(FT_DIRm, r, &f, NULL, NULL, &v))
> + if (!get_fname(FT_ANYDIR, r, &f, NULL, NULL, &v))
> append_pathname(&f, ".");
> dir = opendir_path(&f);
> check_cwd();
> @@ -3761,7 +3762,7 @@ getfattr_f(int opno, long r)
> int xattr_num;
>
> init_pathname(&f);
> - if (!get_fname(FT_REGFILE | FT_DIRm, r, &f, NULL, &fep, &v)) {
> + if (!get_fname(FT_REGFILE | FT_ANYDIR, r, &f, NULL, &fep, &v)) {
> if (v)
> printf("%d/%d: getfattr - no filename\n", procid, opno);
> goto out;
> @@ -3880,7 +3881,7 @@ listfattr_f(int opno, long r)
> int buffer_len;
>
> init_pathname(&f);
> - if (!get_fname(FT_REGFILE | FT_DIRm, r, &f, NULL, &fep, &v)) {
> + if (!get_fname(FT_REGFILE | FT_ANYDIR, r, &f, NULL, &fep, &v)) {
> if (v)
> printf("%d/%d: listfattr - no filename\n", procid, opno);
> goto out;
> @@ -3930,7 +3931,7 @@ mkdir_f(int opno, long r)
> int v;
> int v1;
>
> - if (!get_fname(FT_DIRm, r, NULL, NULL, &fep, &v))
> + if (!get_fname(FT_ANYDIR, r, NULL, NULL, &fep, &v))
> parid = -1;
> else
> parid = fep->id;
> @@ -3968,7 +3969,7 @@ mknod_f(int opno, long r)
> int v;
> int v1;
>
> - if (!get_fname(FT_DIRm, r, NULL, NULL, &fep, &v))
> + if (!get_fname(FT_ANYDIR, r, NULL, NULL, &fep, &v))
> parid = -1;
> else
> parid = fep->id;
> @@ -4326,7 +4327,7 @@ removefattr_f(int opno, long r)
> int xattr_num;
>
> init_pathname(&f);
> - if (!get_fname(FT_REGFILE | FT_DIRm, r, &f, NULL, &fep, &v)) {
> + if (!get_fname(FT_REGFILE | FT_ANYDIR, r, &f, NULL, &fep, &v)) {
> if (v)
> printf("%d/%d: removefattr - no filename\n", procid, opno);
> goto out;
> @@ -4646,7 +4647,7 @@ setfattr_f(int opno, long r)
> int xattr_num;
>
> init_pathname(&f);
> - if (!get_fname(FT_REGFILE | FT_DIRm, r, &f, NULL, &fep, &v)) {
> + if (!get_fname(FT_REGFILE | FT_ANYDIR, r, &f, NULL, &fep, &v)) {
> if (v)
> printf("%d/%d: setfattr - no filename\n", procid, opno);
> goto out;
> @@ -4792,7 +4793,7 @@ subvol_create_f(int opno, long r)
> int err;
>
> init_pathname(&f);
> - if (!get_fname(FT_DIRm | FT_SUBVOLm, r, NULL, NULL, &fep, &v))
> + if (!get_fname(FT_ANYDIR, r, NULL, NULL, &fep, &v))
> parid = -1;
> else
> parid = fep->id;
> @@ -4872,7 +4873,7 @@ symlink_f(int opno, long r)
> int v1;
> char *val;
>
> - if (!get_fname(FT_DIRm, r, NULL, NULL, &fep, &v))
> + if (!get_fname(FT_ANYDIR, r, NULL, NULL, &fep, &v))
> parid = -1;
> else
> parid = fep->id;
> --
> 2.21.0
>
--
Filipe David Manana,
“Whether you think you can, or you think you can't — you're right.”
^ permalink raw reply [flat|nested] 8+ messages in thread
end of thread, other threads:[~2019-12-17 16:10 UTC | newest]
Thread overview: 8+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2019-11-14 15:58 [PATCH 0/3] fsstress: add support for btrfs subvol and snapshot ops Josef Bacik
2019-11-14 15:58 ` [PATCH 1/3] fsstress: add the ability to create/delete subvolumes Josef Bacik
2019-11-14 18:14 ` [PATCH][v2] " Josef Bacik
2019-12-17 15:55 ` Filipe Manana
2019-11-14 15:58 ` [PATCH 2/3] fsstress: add the ability to create snapshots Josef Bacik
2019-12-17 16:06 ` Filipe Manana
2019-11-14 15:58 ` [PATCH 3/3] fsstress: allow operations to use either a directory or subvol Josef Bacik
2019-12-17 16:10 ` Filipe Manana
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).