From c8698edd542e82e347a281a369819cd0eb5a608f Mon Sep 17 00:00:00 2001 From: wangzhengyong Date: Mon, 12 Jun 2017 21:25:32 +0800 Subject: [PATCH] test/librbd: add compare_and_write test for fsx Signed-off-by: Zhengyong Wang --- src/test/librbd/fsx.cc | 111 +++++++++++++++++++++++++++++++++++++++-- 1 file changed, 108 insertions(+), 3 deletions(-) diff --git a/src/test/librbd/fsx.cc b/src/test/librbd/fsx.cc index 12e1eaddde426..0376c0d1dca66 100644 --- a/src/test/librbd/fsx.cc +++ b/src/test/librbd/fsx.cc @@ -89,6 +89,7 @@ int logcount = 0; /* total ops */ * FALLOCATE: - 5 * PUNCH HOLE: - 6 * WRITESAME: - 7 + * COMPAREANDWRITE: - 8 * * When mapped read/writes are disabled, they are simply converted to normal * reads and writes. When fallocate/fpunch calls are disabled, they are @@ -113,10 +114,11 @@ int logcount = 0; /* total ops */ #define OP_FALLOCATE 5 #define OP_PUNCH_HOLE 6 #define OP_WRITESAME 7 +#define OP_COMPARE_AND_WRITE 8 /* rbd-specific operations */ -#define OP_CLONE 8 -#define OP_FLATTEN 9 -#define OP_MAX_FULL 10 +#define OP_CLONE 9 +#define OP_FLATTEN 10 +#define OP_MAX_FULL 11 /* operation modifiers */ #define OP_CLOSEOPEN 100 @@ -511,6 +513,8 @@ struct rbd_operations { int (*flatten)(struct rbd_ctx *ctx); ssize_t (*writesame)(struct rbd_ctx *ctx, uint64_t off, size_t len, const char *buf, size_t data_len); + ssize_t (*compare_and_write)(struct rbd_ctx *ctx, uint64_t off, size_t len, + const char *cmp_buf, const char *buf); }; char *pool; /* name of the pool our test image is in */ @@ -678,6 +682,29 @@ librbd_writesame(struct rbd_ctx *ctx, uint64_t off, size_t len, return n; } +ssize_t +librbd_compare_and_write(struct rbd_ctx *ctx, uint64_t off, size_t len, + const char *cmp_buf, const char *buf) +{ + ssize_t n; + int ret; + uint64_t mismatch_off = 0; + + n = rbd_compare_and_write(ctx->image, off, len, cmp_buf, buf, &mismatch_off, 0); + if (n < 0) { + prt("rbd_compare_and_write mismatch(%llu, %zu, %llu) failed\n", + off, len, mismatch_off); + return n; + } + + ret = librbd_verify_object_map(ctx); + if (ret < 0) { + return ret; + } + return n; + +} + int librbd_get_size(struct rbd_ctx *ctx, uint64_t *size) { @@ -796,6 +823,7 @@ const struct rbd_operations librbd_operations = { librbd_clone, librbd_flatten, librbd_writesame, + librbd_compare_and_write, }; int @@ -1306,6 +1334,18 @@ logdump(void) badoff < lp->args[0] + lp->args[1]) prt("\t***WSWSWSWS"); break; + case OP_COMPARE_AND_WRITE: + prt("COMPARE_AND_WRITE 0x%x thru 0x%x\t(0x%x bytes)", + lp->args[0], lp->args[0] + lp->args[1] - 1, + lp->args[1]); + if (lp->args[0] > lp->args[2]) + prt(" HOLE"); + else if (lp->args[0] + lp->args[1] > lp->args[2]) + prt(" EXTEND"); + if ((badoff >= lp->args[0] || badoff >=lp->args[2]) && + badoff < lp->args[0] + lp->args[1]) + prt("\t***WWWW"); + break; case OP_CLONE: prt("CLONE"); break; @@ -1915,6 +1955,61 @@ dowritesame(unsigned offset, unsigned size) doflush(offset, size); } +void +docompareandwrite(unsigned offset, unsigned size) +{ + int ret; + + offset -= offset % writebdy; + if (o_direct) + size -= size % writebdy; + + if (size == 0) { + if (!quiet && testcalls > simulatedopcount && !o_direct) + prt("skipping zero size read\n"); + log4(OP_SKIPPED, OP_READ, offset, size); + return; + } + + if (size + offset > file_size) { + if (!quiet && testcalls > simulatedopcount) + prt("skipping seek/compare past end of file\n"); + log4(OP_SKIPPED, OP_COMPARE_AND_WRITE, offset, size); + return; + } + + log4(OP_COMPARE_AND_WRITE, offset, size, 0); + + if (testcalls <= simulatedopcount) + return; + + if (!quiet && + ((progressinterval && testcalls % progressinterval == 0) || + (debug && + (monitorstart == -1 || + (static_cast(offset + size) > monitorstart && + (monitorend == -1 || + static_cast(offset) <= monitorend)))))) + prt("%lu compareandwrite\t0x%x thru\t0x%x\t(0x%x bytes)\n", testcalls, + offset, offset + size - 1, size); + + ret = ops->compare_and_write(&ctx, offset, size, good_buf + offset, + good_buf + offset); + if (ret != (ssize_t)size) { + if (ret == -EILSEQ || ret == -EINVAL) + return; + if (ret < 0) + prterrcode("docompareandwrite: ops->compare_and_write", ret); + else + prt("short write: 0x%x bytes instead of 0x%x\n", ret, size); + report_failure(151); + return; + } + + if (flush_enabled) + doflush(offset, size); +} + void clone_filename(char *buf, size_t len, int clones) { snprintf(buf, len, "%s/fsx-%s-parent%d", @@ -2292,6 +2387,12 @@ test(void) log4(OP_SKIPPED, OP_WRITESAME, offset, size); goto out; } + case OP_COMPARE_AND_WRITE: + /* compare_and_write not implemented */ + if (!ops->compare_and_write) { + log4(OP_SKIPPED, OP_COMPARE_AND_WRITE, offset, size); + goto out; + } } switch (op) { @@ -2330,6 +2431,10 @@ test(void) TRIM_OFF_LEN(offset, size, maxfilelen); dowritesame(offset, size); break; + case OP_COMPARE_AND_WRITE: + TRIM_OFF_LEN(offset, size, file_size); + docompareandwrite(offset, size); + break; case OP_CLONE: do_clone(); -- 2.39.5