#define RENAME_WHITEOUT (1 << 2) /* Whiteout source */
#endif
+#ifndef RWF_DONTCACHE
+#define RWF_DONTCACHE 0x80
+#endif
+
+/*
+ * Default to RWF_DONTCACHE being available, turn it off if -EOPNOTSUPP
+ * is seen during issue.
+ */
+static int have_rwf_dontcache = 1;
+
#define FILELEN_MAX (32*4096)
typedef enum {
OP_COLLAPSE,
OP_INSERT,
OP_READ,
+ OP_READ_DONTCACHE,
OP_READLINK,
OP_READV,
OP_REMOVEFATTR,
OP_URING_READ,
OP_URING_WRITE,
OP_WRITE,
+ OP_WRITE_DONTCACHE,
OP_WRITEV,
OP_EXCHANGE_RANGE,
OP_LAST
void collapse_f(opnum_t, long);
void insert_f(opnum_t, long);
void unshare_f(opnum_t, long);
+void read_dontcache_f(opnum_t, long);
void read_f(opnum_t, long);
void readlink_f(opnum_t, long);
void readv_f(opnum_t, long);
void unresvsp_f(opnum_t, long);
void uring_read_f(opnum_t, long);
void uring_write_f(opnum_t, long);
+void write_dontcache_f(opnum_t, long);
void write_f(opnum_t, long);
void writev_f(opnum_t, long);
void exchangerange_f(opnum_t, long);
[OP_COLLAPSE] = {"collapse", collapse_f, 1, 1 },
[OP_INSERT] = {"insert", insert_f, 1, 1 },
[OP_READ] = {"read", read_f, 1, 0 },
+ [OP_READ_DONTCACHE] = {"read_dontcache", read_dontcache_f, 1, 0 },
[OP_READLINK] = {"readlink", readlink_f, 1, 0 },
[OP_READV] = {"readv", readv_f, 1, 0 },
/* remove (delete) extended attribute */
[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_WRITE_DONTCACHE]= {"write_dontcache", write_dontcache_f,4, 1 },
[OP_EXCHANGE_RANGE]= {"exchangerange", exchangerange_f, 2, 1 },
}, *ops_end;
close(fd);
}
+void
+read_dontcache_f(opnum_t opno, long r)
+{
+ int e;
+ pathname_t f;
+ int fd;
+ int64_t lr;
+ off64_t off;
+ struct stat64 stb;
+ int v;
+ char st[1024];
+ struct iovec iov;
+ int flags;
+
+ init_pathname(&f);
+ if (!get_fname(FT_REGFILE, r, &f, NULL, NULL, &v)) {
+ if (v)
+ printf("%d/%lld: read - no filename\n", procid, opno);
+ free_pathname(&f);
+ return;
+ }
+ fd = open_path(&f, O_RDONLY);
+ e = fd < 0 ? errno : 0;
+ check_cwd();
+ if (fd < 0) {
+ if (v)
+ printf("%d/%lld: read - open %s failed %d\n",
+ procid, opno, f.path, e);
+ free_pathname(&f);
+ return;
+ }
+ if (fstat64(fd, &stb) < 0) {
+ if (v)
+ printf("%d/%lld: read - fstat64 %s failed %d\n",
+ procid, opno, f.path, errno);
+ free_pathname(&f);
+ close(fd);
+ return;
+ }
+ inode_info(st, sizeof(st), &stb, v);
+ if (stb.st_size == 0) {
+ if (v)
+ printf("%d/%lld: read - %s%s zero size\n", procid, opno,
+ f.path, st);
+ free_pathname(&f);
+ close(fd);
+ return;
+ }
+ lr = ((int64_t)random() << 32) + random();
+ off = (off64_t)(lr % stb.st_size);
+ iov.iov_len = (random() % FILELEN_MAX) + 1;
+ iov.iov_base = malloc(iov.iov_len);
+ flags = have_rwf_dontcache ? RWF_DONTCACHE : 0;
+ e = preadv2(fd, &iov, 1, off, flags) < 0 ? errno : 0;
+ if (have_rwf_dontcache && e == EOPNOTSUPP) {
+ have_rwf_dontcache = 0;
+ e = preadv2(fd, &iov, 1, off, 0) < 0 ? errno : 0;
+ }
+ free(iov.iov_base);
+ if (v)
+ printf("%d/%lld: read dontcache %s%s [%lld,%d] %d\n",
+ procid, opno, f.path, st, (long long)off,
+ (int)iov.iov_len, e);
+ free_pathname(&f);
+ close(fd);
+}
+
void
removefattr_f(opnum_t opno, long r)
{
close(fd);
}
+void
+write_dontcache_f(opnum_t opno, long r)
+{
+ int e;
+ pathname_t f;
+ int fd;
+ int64_t lr;
+ off64_t off;
+ struct stat64 stb;
+ int v;
+ char st[1024];
+ struct iovec iov;
+ int flags;
+
+ init_pathname(&f);
+ if (!get_fname(FT_REGm, r, &f, NULL, NULL, &v)) {
+ if (v)
+ printf("%d/%lld: write - no filename\n", procid, opno);
+ free_pathname(&f);
+ return;
+ }
+ fd = open_path(&f, O_WRONLY);
+ e = fd < 0 ? errno : 0;
+ check_cwd();
+ if (fd < 0) {
+ if (v)
+ printf("%d/%lld: write - open %s failed %d\n",
+ procid, opno, f.path, e);
+ free_pathname(&f);
+ return;
+ }
+ if (fstat64(fd, &stb) < 0) {
+ if (v)
+ printf("%d/%lld: write - fstat64 %s failed %d\n",
+ procid, opno, f.path, errno);
+ free_pathname(&f);
+ close(fd);
+ return;
+ }
+ inode_info(st, sizeof(st), &stb, v);
+ lr = ((int64_t)random() << 32) + random();
+ off = (off64_t)(lr % MIN(stb.st_size + (1024 * 1024), MAXFSIZE));
+ off %= maxfsize;
+ iov.iov_len = (random() % FILELEN_MAX) + 1;
+ iov.iov_base = malloc(iov.iov_len);
+ memset(iov.iov_base, nameseq & 0xff, iov.iov_len);
+ flags = have_rwf_dontcache ? RWF_DONTCACHE : 0;
+ e = pwritev2(fd, &iov, 1, off, flags) < 0 ? errno : 0;
+ if (have_rwf_dontcache && e == EOPNOTSUPP) {
+ have_rwf_dontcache = 0;
+ e = pwritev2(fd, &iov, 1, off, 0) < 0 ? errno : 0;
+ }
+ free(iov.iov_base);
+ if (v)
+ printf("%d/%lld: write dontcache %s%s [%lld,%d] %d\n",
+ procid, opno, f.path, st, (long long)off,
+ (int)iov.iov_len, e);
+ free_pathname(&f);
+ close(fd);
+}
+
char *
xattr_flag_to_string(int flag)
{