• Gerd Hoffmann's avatar
    preadv/pwritev: create compat_readv() · dac12138
    Gerd Hoffmann authored
    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: default avatarGerd 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: default avatarAndrew Morton <akpm@linux-foundation.org>
    Signed-off-by: default avatarLinus Torvalds <torvalds@linux-foundation.org>
    dac12138
compat.c 54.6 KB