diff options
author | Zorro Lang <zlang@redhat.com> | 2017-07-18 22:37:12 +0800 |
---|---|---|
committer | Eryu Guan <eguan@redhat.com> | 2017-07-28 18:53:50 +0800 |
commit | 80499d8f5f251e41fe5de6720a0cb98fe4b63233 (patch) | |
tree | e72605a7eb85dc8cd9a935afc101d8eb64e8848e /ltp | |
parent | fec7352230c2877f346d57bae200d1ddb1ca836b (diff) |
fsstress: new writev and readv operations test
We found some bugs by writev operations recently, writev can cover
different test than normal write operation, so add writev and readv
operations into fsstress.
Signed-off-by: Zorro Lang <zlang@redhat.com>
Reviewed-by: Eryu Guan <eguan@redhat.com>
Signed-off-by: Eryu Guan <eguan@redhat.com>
Diffstat (limited to 'ltp')
-rw-r--r-- | ltp/fsstress.c | 163 |
1 files changed, 163 insertions, 0 deletions
diff --git a/ltp/fsstress.c b/ltp/fsstress.c index e9fd2769..0ecc214c 100644 --- a/ltp/fsstress.c +++ b/ltp/fsstress.c @@ -18,6 +18,7 @@ #include <linux/fs.h> #include <setjmp.h> +#include <sys/uio.h> #include "global.h" #ifdef HAVE_ATTR_XATTR_H @@ -47,6 +48,9 @@ #define XFS_ERRTAG_MAX 17 #define XFS_IDMODULO_MAX 31 /* user/group IDs (1 << x) */ #define XFS_PROJIDMODULO_MAX 16 /* project IDs (1 << x) */ +#ifndef IOV_MAX +#define IOV_MAX 1024 +#endif #define FILELEN_MAX (32*4096) @@ -78,6 +82,7 @@ typedef enum { OP_INSERT, OP_READ, OP_READLINK, + OP_READV, OP_RENAME, OP_RESVSP, OP_RMDIR, @@ -90,6 +95,7 @@ typedef enum { OP_UNLINK, OP_UNRESVSP, OP_WRITE, + OP_WRITEV, OP_LAST } opty_t; @@ -179,6 +185,7 @@ void collapse_f(int, long); void insert_f(int, long); void read_f(int, long); void readlink_f(int, long); +void readv_f(int, long); void rename_f(int, long); void resvsp_f(int, long); void rmdir_f(int, long); @@ -191,6 +198,7 @@ void truncate_f(int, long); void unlink_f(int, long); void unresvsp_f(int, long); void write_f(int, long); +void writev_f(int, long); opdesc_t ops[] = { /* { OP_ENUM, "name", function, freq, iswrite }, */ @@ -221,6 +229,7 @@ opdesc_t ops[] = { { OP_INSERT, "insert", insert_f, 1, 1 }, { OP_READ, "read", read_f, 1, 0 }, { OP_READLINK, "readlink", readlink_f, 1, 0 }, + { OP_READV, "readv", readv_f, 1, 0 }, { OP_RENAME, "rename", rename_f, 2, 1 }, { OP_RESVSP, "resvsp", resvsp_f, 1, 1 }, { OP_RMDIR, "rmdir", rmdir_f, 1, 1 }, @@ -233,6 +242,7 @@ opdesc_t ops[] = { { OP_UNLINK, "unlink", unlink_f, 1, 1 }, { OP_UNRESVSP, "unresvsp", unresvsp_f, 1, 1 }, { OP_WRITE, "write", write_f, 4, 1 }, + { OP_WRITEV, "writev", writev_f, 4, 1 }, }, *ops_end; flist_t flist[FT_nft] = { @@ -2948,6 +2958,85 @@ readlink_f(int opno, long r) } void +readv_f(int opno, long r) +{ + char *buf; + int e; + pathname_t f; + int fd; + size_t len; + __int64_t lr; + off64_t off; + struct stat64 stb; + int v; + char st[1024]; + struct iovec *iov = NULL; + int iovcnt; + size_t iovb; + size_t iovl; + int i; + + init_pathname(&f); + if (!get_fname(FT_REGFILE, r, &f, NULL, NULL, &v)) { + if (v) + printf("%d/%d: readv - 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/%d: readv - open %s failed %d\n", + procid, opno, f.path, e); + free_pathname(&f); + return; + } + if (fstat64(fd, &stb) < 0) { + if (v) + printf("%d/%d: readv - 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/%d: readv - %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); + lseek64(fd, off, SEEK_SET); + len = (random() % FILELEN_MAX) + 1; + buf = malloc(len); + + iovcnt = (random() % MIN(len, IOV_MAX)) + 1; + iov = calloc(iovcnt, sizeof(struct iovec)); + iovl = len / iovcnt; + iovb = 0; + for (i=0; i<iovcnt; i++) { + (iov + i)->iov_base = (buf + iovb); + (iov + i)->iov_len = iovl; + iovb += iovl; + } + + e = readv(fd, iov, iovcnt) < 0 ? errno : 0; + free(buf); + if (v) + printf("%d/%d: readv %s%s [%lld,%d,%d] %d\n", + procid, opno, f.path, st, (long long)off, (int)iovl, + iovcnt, e); + free_pathname(&f); + close(fd); +} + +void rename_f(int opno, long r) { fent_t *dfep; @@ -3379,3 +3468,77 @@ write_f(int opno, long r) free_pathname(&f); close(fd); } + +void +writev_f(int opno, long r) +{ + char *buf; + int e; + pathname_t f; + int fd; + size_t len; + __int64_t lr; + off64_t off; + struct stat64 stb; + int v; + char st[1024]; + struct iovec *iov = NULL; + int iovcnt; + size_t iovb; + size_t iovl; + int i; + + init_pathname(&f); + if (!get_fname(FT_REGm, r, &f, NULL, NULL, &v)) { + if (v) + printf("%d/%d: writev - 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/%d: writev - open %s failed %d\n", + procid, opno, f.path, e); + free_pathname(&f); + return; + } + if (fstat64(fd, &stb) < 0) { + if (v) + printf("%d/%d: writev - 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; + lseek64(fd, off, SEEK_SET); + len = (random() % FILELEN_MAX) + 1; + buf = malloc(len); + memset(buf, nameseq & 0xff, len); + + iovcnt = (random() % MIN(len, IOV_MAX)) + 1; + iov = calloc(iovcnt, sizeof(struct iovec)); + iovl = len / iovcnt; + iovb = 0; + for (i=0; i<iovcnt; i++) { + (iov + i)->iov_base = (buf + iovb); + (iov + i)->iov_len = iovl; + iovb += iovl; + } + + e = writev(fd, iov, iovcnt) < 0 ? errno : 0; + free(buf); + free(iov); + if (v) + printf("%d/%d: writev %s%s [%lld,%d,%d] %d\n", + procid, opno, f.path, st, (long long)off, (int)iovl, + iovcnt, e); + free_pathname(&f); + close(fd); +} |