preadv/pwritev: create compat_readv()

Previous message: [thread] [date] [author]
Next message: [thread] [date] [author]
From: Linux Kernel Mailing List
Date: Thursday, April 2, 2009 - 10:04 pm

Gitweb:     http://git.kernel.org/linus/dac1213842f5caf081804a11d87d2a39a21d6f55
Commit:     dac1213842f5caf081804a11d87d2a39a21d6f55
Parent:     98310e581e098514867573031b2bfa4ba89c0d93
Author:     Gerd Hoffmann <kraxel@redhat.com>
AuthorDate: Thu Apr 2 16:59:20 2009 -0700
Committer:  Linus Torvalds <torvalds@linux-foundation.org>
CommitDate: Thu Apr 2 19:05:07 2009 -0700

    preadv/pwritev: create compat_readv()
    
    This patch series:
    
    Implement the preadv() and pwritev() syscalls.  *BSD has this syscall for
    quite some time.
    
    Test code:
    
    #if 0
    set -x
    gcc -Wall -O2 -o preadv $0
    exit 0
    #endif
    /*
     * preadv demo / test
     *
     * (c) 2008 Gerd Hoffmann <kraxel@redhat.com>
     *
     * build with "sh $thisfile"
     */
    
    #include <stdio.h>
    #include <stdlib.h>
    #include <unistd.h>
    #include <errno.h>
    #include <inttypes.h>
    #include <sys/uio.h>
    
    /* ----------------------------------------------------------------- */
    /* syscall windup                                                    */
    
    #include <sys/syscall.h>
    #if 0
    /* WARNING: Be sure you know what you are doing if you enable this.
     * linux syscall code isn't upstream yet, syscall numbers are subject
     * to change */
    # ifndef __NR_preadv
    #  ifdef __i386__
    #   define __NR_preadv  333
    #   define __NR_pwritev 334
    #  endif
    #  ifdef __x86_64__
    #   define __NR_preadv  295
    #   define __NR_pwritev 296
    #  endif
    # endif
    #endif
    #ifndef __NR_preadv
    # error preadv/pwritev syscall numbers are unknown
    #endif
    
    static ssize_t preadv(int fd, const struct iovec *iov, int iovcnt, off_t offset)
    {
        uint32_t pos_high = (offset >> 32) & 0xffffffff;
        uint32_t pos_low  =  offset        & 0xffffffff;
    
        return syscall(__NR_preadv, fd, iov, iovcnt, pos_high, pos_low);
    }
    
    static ssize_t pwritev(int fd, const struct iovec *iov, int iovcnt, off_t offset)
    {
        uint32_t pos_high = (offset >> 32) & 0xffffffff;
        uint32_t pos_low  =  offset        & 0xffffffff;
    
        return syscall(__NR_pwritev, fd, iov, iovcnt, pos_high, pos_low);
    }
    
    /* ----------------------------------------------------------------- */
    /* demo/test app                                                     */
    
    static char filename[] = "/tmp/preadv-XXXXXX";
    static char outbuf[11] = "0123456789";
    static char inbuf[11]  = "----------";
    
    static struct iovec ovec[2] = {{
            .iov_base = outbuf + 5,
            .iov_len  = 5,
        },{
            .iov_base = outbuf + 0,
            .iov_len  = 5,
        }};
    
    static struct iovec ivec[3] = {{
            .iov_base = inbuf + 6,
            .iov_len  = 2,
        },{
            .iov_base = inbuf + 4,
            .iov_len  = 2,
        },{
            .iov_base = inbuf + 2,
            .iov_len  = 2,
        }};
    
    void cleanup(void)
    {
        unlink(filename);
    }
    
    int main(int argc, char **argv)
    {
        int fd, rc;
    
        fd = mkstemp(filename);
        if (-1 == fd) {
            perror("mkstemp");
            exit(1);
        }
        atexit(cleanup);
    
        /* write to file: "56789-01234" */
        rc = pwritev(fd, ovec, 2, 0);
        if (rc < 0) {
            perror("pwritev");
            exit(1);
        }
    
        /* read from file: "78-90-12" */
        rc = preadv(fd, ivec, 3, 2);
        if (rc < 0) {
            perror("preadv");
            exit(1);
        }
    
        printf("result  : %s\n", inbuf);
        printf("expected: %s\n", "--129078--");
        exit(0);
    }
    
    This patch:
    
    Factor out some code from compat_sys_readv() which can be shared with the
    upcoming compat_sys_preadv().
    
    Signed-off-by: Gerd Hoffmann <kraxel@redhat.com>
    Cc: Arnd Bergmann <arnd@arndb.de>
    Cc: Al Viro <viro@zeniv.linux.org.uk>
    Cc: <linux-api@vger.kernel.org>
    Cc: <linux-arch@vger.kernel.org>
    Cc: Ralf Baechle <ralf@linux-mips.org>
    Signed-off-by: Andrew Morton <akpm@linux-foundation.org>
    Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
---
 fs/compat.c |   26 ++++++++++++++++++--------
 1 files changed, 18 insertions(+), 8 deletions(-)

diff --git a/fs/compat.c b/fs/compat.c
index 55efdfe..e99048c 100644
--- a/fs/compat.c
+++ b/fs/compat.c
@@ -1195,16 +1195,12 @@ out:
 	return ret;
 }
 
-asmlinkage ssize_t
-compat_sys_readv(unsigned long fd, const struct compat_iovec __user *vec, unsigned long vlen)
+static size_t compat_readv(struct file *file,
+			   const struct compat_iovec __user *vec,
+			   unsigned long vlen, loff_t *pos)
 {
-	struct file *file;
 	ssize_t ret = -EBADF;
 
-	file = fget(fd);
-	if (!file)
-		return -EBADF;
-
 	if (!(file->f_mode & FMODE_READ))
 		goto out;
 
@@ -1212,12 +1208,26 @@ compat_sys_readv(unsigned long fd, const struct compat_iovec __user *vec, unsign
 	if (!file->f_op || (!file->f_op->aio_read && !file->f_op->read))
 		goto out;
 
-	ret = compat_do_readv_writev(READ, file, vec, vlen, &file->f_pos);
+	ret = compat_do_readv_writev(READ, file, vec, vlen, pos);
 
 out:
 	if (ret > 0)
 		add_rchar(current, ret);
 	inc_syscr(current);
+	return ret;
+}
+
+asmlinkage ssize_t
+compat_sys_readv(unsigned long fd, const struct compat_iovec __user *vec,
+		 unsigned long vlen)
+{
+	struct file *file;
+	ssize_t ret;
+
+	file = fget(fd);
+	if (!file)
+		return -EBADF;
+	ret = compat_readv(file, vec, vlen, &file->f_pos);
 	fput(file);
 	return ret;
 }
--
To unsubscribe from this list: send the line "unsubscribe git-commits-head" in
the body of a message to majordomo@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Previous message: [thread] [date] [author]
Next message: [thread] [date] [author]

Messages in current thread:
preadv/pwritev: create compat_readv(), Linux Kernel Mailing ..., (Thu Apr 2, 10:04 pm)