]> git.ipfire.org Git - thirdparty/xfsprogs-dev.git/commitdiff
xfs_io: implement pwritev for vectored writes
authorDave Chinner <david@fromorbit.com>
Wed, 25 Jul 2012 22:30:50 +0000 (22:30 +0000)
committerMark Tinguely <tinguely@eagdhcp-232-125.americas.sgi.com>
Mon, 24 Sep 2012 21:38:35 +0000 (16:38 -0500)
When looking at KVM based direct IO patterns, I noticed that it was
using preadv and pwritev, and I could not use xfs_io to simulate
these IO patterns. Extend the pwrite command to be able to issue
vectored write IO to enable use to simulate KVM style direct IO.

Also document the new parameters as well as all the missing pwrite
command parameters in the xfs_io(8) man page.

Signed-off-by: Dave Chinner <dchinner@redhat.com>
Reviewed-by: Christoph Hellwig <hch@lst.de>
Reviewed-by: Mark Tinguely <tinguely@sgi.com>
Signed-off-by: Mark Tinguely <tinguely@sgi.com>
io/io.h
io/pwrite.c
man/man8/xfs_io.8

diff --git a/io/io.h b/io/io.h
index 8151b7b249118692e576988dcf5e3c820be5a2a3..91f0e3e97f31db8d6e24b88aac7dc85bd8e03fff 100644 (file)
--- a/io/io.h
+++ b/io/io.h
@@ -82,6 +82,8 @@ extern unsigned int   recurse_dir;
 
 extern void            *buffer;
 extern size_t          buffersize;
+extern int             vectors;
+extern struct iovec    *iov;
 extern int             alloc_buffer(size_t, int, unsigned int);
 extern int             read_buffer(int, off64_t, long long, long long *,
                                        int, int);
index 7c3932c6f944f2c187b863fb3688c4341092479b..3689960fa066bd27384a29270fc5dc4870499886 100644 (file)
@@ -50,9 +50,46 @@ pwrite_help(void)
 " -R   -- write at random offsets in the specified range of bytes\n"
 " -Z N -- zeed the random number generator (used when writing randomly)\n"
 "         (heh, zorry, the -s/-S arguments were already in use in pwrite)\n"
+" -V N -- use vectored IO with N iovecs of blocksize each (pwritev)\n"
 "\n"));
 }
 
+static int
+do_pwrite(
+       int             fd,
+       off64_t         offset,
+       ssize_t         count,
+       ssize_t         buffer_size)
+{
+       int             vecs = 0;
+       ssize_t         oldlen = 0;
+       ssize_t         bytes = 0;
+
+
+       if (!vectors)
+               return pwrite64(fd, buffer, min(count, buffer_size), offset);
+
+       /* trim the iovec if necessary */
+       if (count < buffersize) {
+               size_t  len = 0;
+               while (len + iov[vecs].iov_len < count) {
+                       len += iov[vecs].iov_len;
+                       vecs++;
+               }
+               oldlen = iov[vecs].iov_len;
+               iov[vecs].iov_len = count - len;
+               vecs++;
+       } else {
+               vecs = vectors;
+       }
+       bytes = pwritev(fd, iov, vectors, offset);
+
+       /* restore trimmed iov */
+       if (oldlen)
+               iov[vecs - 1].iov_len = oldlen;
+
+       return bytes;
+}
 static int
 write_random(
        off64_t         offset,
@@ -76,7 +113,7 @@ write_random(
        *total = 0;
        while (count > 0) {
                off = ((random() % range) / buffersize) * buffersize;
-               bytes = pwrite64(file->fd, buffer, buffersize, off);
+               bytes = do_pwrite(file->fd, off, buffersize, buffersize);
                if (bytes == 0)
                        break;
                if (bytes < 0) {
@@ -114,7 +151,7 @@ write_backward(
        if ((bytes_requested = (off % buffersize))) {
                bytes_requested = min(cnt, bytes_requested);
                off -= bytes_requested;
-               bytes = pwrite(file->fd, buffer, bytes_requested, off);
+               bytes = do_pwrite(file->fd, off, bytes_requested, buffersize);
                if (bytes == 0)
                        return ops;
                if (bytes < 0) {
@@ -132,7 +169,7 @@ write_backward(
        while (cnt > end) {
                bytes_requested = min(cnt, buffersize);
                off -= bytes_requested;
-               bytes = pwrite64(file->fd, buffer, bytes_requested, off);
+               bytes = do_pwrite(file->fd, off, cnt, buffersize);
                if (bytes == 0)
                        break;
                if (bytes < 0) {
@@ -157,7 +194,6 @@ write_buffer(
        off64_t         skip,
        long long       *total)
 {
-       size_t          bytes_requested;
        ssize_t         bytes;
        long long       bar = min(bs, count);
        int             ops = 0;
@@ -168,8 +204,7 @@ write_buffer(
                        if (read_buffer(fd, skip + *total, bs, &bar, 0, 1) < 0)
                                break;
                }
-               bytes_requested = min(bar, count);
-               bytes = pwrite64(file->fd, buffer, bytes_requested, offset);
+               bytes = do_pwrite(file->fd, offset, count, bar);
                if (bytes == 0)
                        break;
                if (bytes < 0) {
@@ -178,7 +213,7 @@ write_buffer(
                }
                ops++;
                *total += bytes;
-               if (bytes < bytes_requested)
+               if (bytes <  min(count, bar))
                        break;
                offset += bytes;
                count -= bytes;
@@ -209,7 +244,7 @@ pwrite_f(
        init_cvtnum(&fsblocksize, &fssectsize);
        bsize = fsblocksize;
 
-       while ((c = getopt(argc, argv, "b:Cdf:i:qs:S:uwWZ:")) != EOF) {
+       while ((c = getopt(argc, argv, "b:Cdf:i:qs:S:uV:wWZ:")) != EOF) {
                switch (c) {
                case 'b':
                        tmp = cvtnum(fsblocksize, fssectsize, optarg);
@@ -258,6 +293,14 @@ pwrite_f(
                case 'u':
                        uflag = 1;
                        break;
+               case 'V':
+                       vectors = strtoul(optarg, &sp, 0);
+                       if (!sp || sp == optarg) {
+                               printf(_("non-numberic vector count == %s\n"),
+                                       optarg);
+                               return 0;
+                       }
+                       break;
                case 'w':
                        wflag = 1;
                        break;
@@ -356,7 +399,7 @@ pwrite_init(void)
        pwrite_cmd.argmax = -1;
        pwrite_cmd.flags = CMD_NOMAP_OK | CMD_FOREIGN_OK;
        pwrite_cmd.args =
-               _("[-i infile [-d] [-s skip]] [-b bs] [-S seed] [-wW] off len");
+_("[-i infile [-d] [-s skip]] [-b bs] [-S seed] [-wW] [-FBR [-Z N]] [-V N] off len");
        pwrite_cmd.oneline =
                _("writes a number of bytes at a specified offset");
        pwrite_cmd.help = pwrite_help;
index ae707f4552a12634165f806136d76e61183a2582..f7c6935772398cb477ec3e317259d1ace4268d80 100644 (file)
@@ -172,7 +172,7 @@ See the
 .B pread
 command.
 .TP
-.BI "pwrite [ \-i " file " ] [ \-d ] [ \-s " skip " ] [ \-b " size " ] [ \-S " seed " ] " "offset length"
+.BI "pwrite [ \-i " file " ] [ \-d ] [ \-s " skip " ] [ \-b " size " ] [ \-S " seed " ] [ \-FBR [ \-Z " zeed " ] ] [ \-wW ] [ \-V " vectors " ] " "offset length"
 Writes a range of bytes in a specified blocksize from the given
 .IR offset .
 The bytes written can be either a set pattern or read in from another
@@ -203,6 +203,35 @@ requests will be split. The default blocksize is 4096 bytes.
 used to set the (repeated) fill pattern which
 is used when the data to write is not coming from a file.
 The default buffer fill pattern value is 0xcdcdcdcd.
+.TP
+.B \-F
+write the buffers in a forwards sequential direction.
+.TP
+.B \-B
+write the buffers in a reserve sequential direction.
+.TP
+.B \-R
+write the buffers in the give range in a random order.
+.TP
+.B \-Z seed
+specify the random number seed used for random write
+.TP
+.B \-w
+call
+.BR fdatasync (2)
+once all writes are complete (included in timing results)
+.TP
+.B \-W
+call
+.BR fsync (2)
+once all writes are complete (included in timing results)
+.TP
+.B \-V vectors
+Use the vectored IO write syscall
+.BR pwritev (2)
+with a number of blocksize length iovecs. The number of iovecs is set by the
+.I vectors
+parameter.
 .RE
 .PD
 .TP