From 00008263782e484020420c606f7d145fe7d0a4d8 Mon Sep 17 00:00:00 2001 From: Elliott Hughes Date: Wed, 10 Sep 2014 17:39:00 -0700 Subject: [PATCH] Add posix_fadvise(3). Bug: 12449798 Change-Id: I07cbf3f670a0d1304b68148325a774f266b5c433 --- libc/Android.mk | 1 + libc/SYSCALLS.TXT | 6 +++ libc/arch-arm/syscalls/__arm_fadvise64_64.S | 22 +++++++++ libc/arch-arm64/syscalls/__fadvise64.S | 15 ++++++ libc/arch-mips/syscalls/__fadvise64.S | 19 ++++++++ libc/arch-mips64/syscalls/__fadvise64.S | 26 +++++++++++ libc/arch-x86/syscalls/__fadvise64.S | 46 +++++++++++++++++++ libc/arch-x86_64/syscalls/__fadvise64.S | 17 +++++++ libc/bionic/posix_fadvise.cpp | 51 +++++++++++++++++++++ libc/include/fcntl.h | 2 + tests/fcntl_test.cpp | 25 +++++++++- 11 files changed, 228 insertions(+), 2 deletions(-) create mode 100644 libc/arch-arm/syscalls/__arm_fadvise64_64.S create mode 100644 libc/arch-arm64/syscalls/__fadvise64.S create mode 100644 libc/arch-mips/syscalls/__fadvise64.S create mode 100644 libc/arch-mips64/syscalls/__fadvise64.S create mode 100644 libc/arch-x86/syscalls/__fadvise64.S create mode 100644 libc/arch-x86_64/syscalls/__fadvise64.S create mode 100644 libc/bionic/posix_fadvise.cpp diff --git a/libc/Android.mk b/libc/Android.mk index 50981718d..fd7c54f8e 100644 --- a/libc/Android.mk +++ b/libc/Android.mk @@ -144,6 +144,7 @@ libc_bionic_src_files := \ bionic/pause.cpp \ bionic/pipe.cpp \ bionic/poll.cpp \ + bionic/posix_fadvise.cpp \ bionic/posix_fallocate.cpp \ bionic/posix_timers.cpp \ bionic/pthread_atfork.cpp \ diff --git a/libc/SYSCALLS.TXT b/libc/SYSCALLS.TXT index 38ae8310a..3e380bdce 100644 --- a/libc/SYSCALLS.TXT +++ b/libc/SYSCALLS.TXT @@ -167,6 +167,12 @@ void* mmap|mmap64(void*, size_t, int, int, int, off_t) arm64,mips64,x86_64 int fallocate64:fallocate(int, int, off64_t, off64_t) arm,mips,x86 int fallocate|fallocate64(int, int, off_t, off_t) arm64,mips64,x86_64 +# posix_fadvise64 is awkward: arm has shuffled arguments, +# the POSIX functions don't set errno, and no architecture has posix_fadvise. +int __arm_fadvise64_64:arm_fadvise64_64(int, int, off64_t, off64_t) arm +int __fadvise64:fadvise64_64(int, off64_t, off64_t, int) mips,x86 +int __fadvise64:fadvise64(int, off64_t, off64_t, int) arm64,mips64,x86_64 + int __fstatfs64:fstatfs64(int, size_t, struct statfs*) arm,mips,x86 int fstatfs64|fstatfs:fstatfs(int, struct statfs*) arm64,mips64,x86_64 int __statfs64:statfs64(const char*, size_t, struct statfs*) arm,mips,x86 diff --git a/libc/arch-arm/syscalls/__arm_fadvise64_64.S b/libc/arch-arm/syscalls/__arm_fadvise64_64.S new file mode 100644 index 000000000..761c4d6ee --- /dev/null +++ b/libc/arch-arm/syscalls/__arm_fadvise64_64.S @@ -0,0 +1,22 @@ +/* Generated by gensyscalls.py. Do not edit. */ + +#include + +ENTRY(__arm_fadvise64_64) + mov ip, sp + stmfd sp!, {r4, r5, r6, r7} + .cfi_def_cfa_offset 16 + .cfi_rel_offset r4, 0 + .cfi_rel_offset r5, 4 + .cfi_rel_offset r6, 8 + .cfi_rel_offset r7, 12 + ldmfd ip, {r4, r5, r6} + ldr r7, =__NR_arm_fadvise64_64 + swi #0 + ldmfd sp!, {r4, r5, r6, r7} + .cfi_def_cfa_offset 0 + cmn r0, #(MAX_ERRNO + 1) + bxls lr + neg r0, r0 + b __set_errno_internal +END(__arm_fadvise64_64) diff --git a/libc/arch-arm64/syscalls/__fadvise64.S b/libc/arch-arm64/syscalls/__fadvise64.S new file mode 100644 index 000000000..695d09438 --- /dev/null +++ b/libc/arch-arm64/syscalls/__fadvise64.S @@ -0,0 +1,15 @@ +/* Generated by gensyscalls.py. Do not edit. */ + +#include + +ENTRY(__fadvise64) + mov x8, __NR_fadvise64 + svc #0 + + cmn x0, #(MAX_ERRNO + 1) + cneg x0, x0, hi + b.hi __set_errno_internal + + ret +END(__fadvise64) +.hidden __fadvise64 diff --git a/libc/arch-mips/syscalls/__fadvise64.S b/libc/arch-mips/syscalls/__fadvise64.S new file mode 100644 index 000000000..6d494a169 --- /dev/null +++ b/libc/arch-mips/syscalls/__fadvise64.S @@ -0,0 +1,19 @@ +/* Generated by gensyscalls.py. Do not edit. */ + +#include + +ENTRY(__fadvise64) + .set noreorder + .cpload t9 + li v0, __NR_fadvise64_64 + syscall + bnez a3, 1f + move a0, v0 + j ra + nop +1: + la t9,__set_errno_internal + j t9 + nop + .set reorder +END(__fadvise64) diff --git a/libc/arch-mips64/syscalls/__fadvise64.S b/libc/arch-mips64/syscalls/__fadvise64.S new file mode 100644 index 000000000..90aceb08d --- /dev/null +++ b/libc/arch-mips64/syscalls/__fadvise64.S @@ -0,0 +1,26 @@ +/* Generated by gensyscalls.py. Do not edit. */ + +#include + +ENTRY(__fadvise64) + .set push + .set noreorder + li v0, __NR_fadvise64 + syscall + bnez a3, 1f + move a0, v0 + j ra + nop +1: + move t0, ra + bal 2f + nop +2: + .cpsetup ra, t1, 2b + LA t9,__set_errno_internal + .cpreturn + j t9 + move ra, t0 + .set pop +END(__fadvise64) +.hidden __fadvise64 diff --git a/libc/arch-x86/syscalls/__fadvise64.S b/libc/arch-x86/syscalls/__fadvise64.S new file mode 100644 index 000000000..6e4298a17 --- /dev/null +++ b/libc/arch-x86/syscalls/__fadvise64.S @@ -0,0 +1,46 @@ +/* Generated by gensyscalls.py. Do not edit. */ + +#include + +ENTRY(__fadvise64) + pushl %ebx + .cfi_def_cfa_offset 8 + .cfi_rel_offset ebx, 0 + pushl %ecx + .cfi_adjust_cfa_offset 4 + .cfi_rel_offset ecx, 0 + pushl %edx + .cfi_adjust_cfa_offset 4 + .cfi_rel_offset edx, 0 + pushl %esi + .cfi_adjust_cfa_offset 4 + .cfi_rel_offset esi, 0 + pushl %edi + .cfi_adjust_cfa_offset 4 + .cfi_rel_offset edi, 0 + pushl %ebp + .cfi_adjust_cfa_offset 4 + .cfi_rel_offset ebp, 0 + mov 28(%esp), %ebx + mov 32(%esp), %ecx + mov 36(%esp), %edx + mov 40(%esp), %esi + mov 44(%esp), %edi + mov 48(%esp), %ebp + movl $__NR_fadvise64_64, %eax + int $0x80 + cmpl $-MAX_ERRNO, %eax + jb 1f + negl %eax + pushl %eax + call __set_errno_internal + addl $4, %esp +1: + popl %ebp + popl %edi + popl %esi + popl %edx + popl %ecx + popl %ebx + ret +END(__fadvise64) diff --git a/libc/arch-x86_64/syscalls/__fadvise64.S b/libc/arch-x86_64/syscalls/__fadvise64.S new file mode 100644 index 000000000..8810d88d1 --- /dev/null +++ b/libc/arch-x86_64/syscalls/__fadvise64.S @@ -0,0 +1,17 @@ +/* Generated by gensyscalls.py. Do not edit. */ + +#include + +ENTRY(__fadvise64) + movq %rcx, %r10 + movl $__NR_fadvise64, %eax + syscall + cmpq $-MAX_ERRNO, %rax + jb 1f + negl %eax + movl %eax, %edi + call __set_errno_internal +1: + ret +END(__fadvise64) +.hidden __fadvise64 diff --git a/libc/bionic/posix_fadvise.cpp b/libc/bionic/posix_fadvise.cpp new file mode 100644 index 000000000..3a74af363 --- /dev/null +++ b/libc/bionic/posix_fadvise.cpp @@ -0,0 +1,51 @@ +/* + * Copyright (C) 2014 The Android Open Source Project + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, + * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS + * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED + * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT + * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +#include + +#include "private/ErrnoRestorer.h" + +extern "C" int __arm_fadvise64_64(int, int, off64_t, off64_t); +extern "C" int __fadvise64(int, off64_t, off64_t, int); + +// No architecture actually has the 32-bit off_t system call. +int posix_fadvise(int fd, off_t offset, off_t length, int advice) { + return posix_fadvise64(fd, offset, length, advice); +} + +#if defined(__arm__) +int posix_fadvise64(int fd, off64_t offset, off64_t length, int advice) { + ErrnoRestorer errno_restorer; + return (__arm_fadvise64_64(fd, advice, offset, length) == 0) ? 0 : errno; +} +#else +int posix_fadvise64(int fd, off64_t offset, off64_t length, int advice) { + ErrnoRestorer errno_restorer; + return (__fadvise64(fd, offset, length, advice) == 0) ? 0 : errno; +} +#endif diff --git a/libc/include/fcntl.h b/libc/include/fcntl.h index 4450bb65f..8f89afbb4 100644 --- a/libc/include/fcntl.h +++ b/libc/include/fcntl.h @@ -72,6 +72,8 @@ extern int openat(int, const char*, int, ...); extern int openat64(int, const char*, int, ...); extern int open(const char*, int, ...); extern int open64(const char*, int, ...); +extern int posix_fadvise64(int, off64_t, off64_t, int); +extern int posix_fadvise(int, off_t, off_t, int); extern int posix_fallocate64(int, off64_t, off64_t); extern int posix_fallocate(int, off_t, off_t); extern ssize_t splice(int, off64_t*, int, off64_t*, size_t, unsigned int); diff --git a/tests/fcntl_test.cpp b/tests/fcntl_test.cpp index 5f2029569..3fd0a8cfb 100644 --- a/tests/fcntl_test.cpp +++ b/tests/fcntl_test.cpp @@ -70,10 +70,32 @@ TEST(fcntl, creat_creat64) { ASSERT_EQ(ENOENT, errno); } +TEST(fcntl, posix_fadvise) { + TemporaryFile tf; + errno = 0; + + EXPECT_EQ(EBADF, posix_fadvise(-1, 0, 0, POSIX_FADV_NORMAL)); + EXPECT_EQ(0, errno); + + EXPECT_EQ(EBADF, posix_fadvise64(-1, 0, 0, POSIX_FADV_NORMAL)); + EXPECT_EQ(0, errno); + + EXPECT_EQ(EINVAL, posix_fadvise(tf.fd, 0, 0, -1)); + EXPECT_EQ(0, errno); + + EXPECT_EQ(EINVAL, posix_fadvise64(tf.fd, 0, 0, -1)); + EXPECT_EQ(0, errno); + + EXPECT_EQ(0, posix_fadvise(tf.fd, 0, 0, POSIX_FADV_NORMAL)); + EXPECT_EQ(0, posix_fadvise64(tf.fd, 0, 0, POSIX_FADV_NORMAL)); +} + TEST(fcntl, fallocate_EINVAL) { TemporaryFile tf; -#if defined(__BIONIC__) + // fallocate/fallocate64 set errno. + // posix_fallocate/posix_fallocate64 return an errno value. + errno = 0; ASSERT_EQ(-1, fallocate(tf.fd, 0, 0, -1)); ASSERT_EQ(EINVAL, errno); @@ -81,7 +103,6 @@ TEST(fcntl, fallocate_EINVAL) { errno = 0; ASSERT_EQ(-1, fallocate64(tf.fd, 0, 0, -1)); ASSERT_EQ(EINVAL, errno); -#endif errno = 0; ASSERT_EQ(EINVAL, posix_fallocate(tf.fd, 0, -1));