OSDN Git Service

Add fallocate/fallocate64/posix_fallocate/posix_fallocate64.
authorElliott Hughes <enh@google.com>
Tue, 4 Feb 2014 00:20:46 +0000 (16:20 -0800)
committerElliott Hughes <enh@google.com>
Tue, 4 Feb 2014 00:20:46 +0000 (16:20 -0800)
Bug: 5287571
Bug: 12612860
Change-Id: I4501b9c6cdf9a830336ce0b3afc4ea716b6a0f6f

16 files changed:
libc/Android.mk
libc/SYSCALLS.TXT
libc/arch-arm/syscalls.mk
libc/arch-arm/syscalls/fallocate64.S [new file with mode: 0644]
libc/arch-arm64/syscalls.mk
libc/arch-arm64/syscalls/fallocate.S [new file with mode: 0644]
libc/arch-mips/syscalls.mk
libc/arch-mips/syscalls/fallocate64.S [new file with mode: 0644]
libc/arch-x86/syscalls.mk
libc/arch-x86/syscalls/fallocate64.S [new file with mode: 0644]
libc/arch-x86_64/syscalls.mk
libc/arch-x86_64/syscalls/fallocate.S [new file with mode: 0644]
libc/bionic/legacy_32_bit_support.cpp
libc/bionic/posix_fallocate.cpp [new file with mode: 0644]
libc/include/fcntl.h
tests/fcntl_test.cpp

index ea46bf9..7edadd7 100644 (file)
@@ -232,6 +232,7 @@ libc_bionic_src_files := \
     bionic/pause.cpp \
     bionic/pipe.cpp \
     bionic/poll.cpp \
+    bionic/posix_fallocate.cpp \
     bionic/pthread_atfork.cpp \
     bionic/pthread_attr.cpp \
     bionic/pthread_cond.cpp \
index 0951648..0555983 100644 (file)
@@ -169,6 +169,9 @@ int truncate|truncate64(const char*, off_t) arm64,x86_64
 # (mmap only gets two lines because we only used the 64-bit variant on 32-bit systems.)
 void* __mmap2:mmap2(void*, size_t, int, int, int, long)   arm,mips,x86
 void* mmap|mmap64(void*, size_t, int, int, int, off_t)  arm64,x86_64
+# (fallocate only gets two lines because there is no 32-bit variant.)
+int fallocate64:fallocate(int, int, off64_t, off64_t) arm,mips,x86
+int fallocate|fallocate64(int, int, off_t, off_t) arm64,x86_64
 
 # file system
 int     chdir(const char*)              all
index 83e6a97..f039bcb 100644 (file)
@@ -56,6 +56,7 @@ syscall_src += arch-arm/syscalls/epoll_ctl.S
 syscall_src += arch-arm/syscalls/eventfd.S
 syscall_src += arch-arm/syscalls/execve.S
 syscall_src += arch-arm/syscalls/faccessat.S
+syscall_src += arch-arm/syscalls/fallocate64.S
 syscall_src += arch-arm/syscalls/fchdir.S
 syscall_src += arch-arm/syscalls/fchmod.S
 syscall_src += arch-arm/syscalls/fchmodat.S
diff --git a/libc/arch-arm/syscalls/fallocate64.S b/libc/arch-arm/syscalls/fallocate64.S
new file mode 100644 (file)
index 0000000..c6992b0
--- /dev/null
@@ -0,0 +1,22 @@
+/* Generated by gensyscalls.py. Do not edit. */
+
+#include <private/bionic_asm.h>
+
+ENTRY(fallocate64)
+    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_fallocate
+    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
+END(fallocate64)
index f1de5a5..07ad5d5 100644 (file)
@@ -48,6 +48,7 @@ syscall_src += arch-arm64/syscalls/epoll_ctl.S
 syscall_src += arch-arm64/syscalls/eventfd.S
 syscall_src += arch-arm64/syscalls/execve.S
 syscall_src += arch-arm64/syscalls/faccessat.S
+syscall_src += arch-arm64/syscalls/fallocate.S
 syscall_src += arch-arm64/syscalls/fchdir.S
 syscall_src += arch-arm64/syscalls/fchmod.S
 syscall_src += arch-arm64/syscalls/fchmodat.S
diff --git a/libc/arch-arm64/syscalls/fallocate.S b/libc/arch-arm64/syscalls/fallocate.S
new file mode 100644 (file)
index 0000000..e79b96a
--- /dev/null
@@ -0,0 +1,24 @@
+/* Generated by gensyscalls.py. Do not edit. */
+
+#include <private/bionic_asm.h>
+
+ENTRY(fallocate)
+    stp     x29, x30, [sp, #-16]!
+    mov     x29,  sp
+    str     x8,       [sp, #-16]!
+
+    mov     x8, __NR_fallocate
+    svc     #0
+
+    ldr     x8,       [sp], #16
+    ldp     x29, x30, [sp], #16
+
+    cmn     x0, #(MAX_ERRNO + 1)
+    cneg    x0, x0, hi
+    b.hi    __set_errno
+
+    ret
+END(fallocate)
+
+    .globl _C_LABEL(fallocate64)
+    .equ _C_LABEL(fallocate64), _C_LABEL(fallocate)
index 8d87b29..a376c12 100644 (file)
@@ -56,6 +56,7 @@ syscall_src += arch-mips/syscalls/epoll_ctl.S
 syscall_src += arch-mips/syscalls/eventfd.S
 syscall_src += arch-mips/syscalls/execve.S
 syscall_src += arch-mips/syscalls/faccessat.S
+syscall_src += arch-mips/syscalls/fallocate64.S
 syscall_src += arch-mips/syscalls/fchdir.S
 syscall_src += arch-mips/syscalls/fchmod.S
 syscall_src += arch-mips/syscalls/fchmodat.S
diff --git a/libc/arch-mips/syscalls/fallocate64.S b/libc/arch-mips/syscalls/fallocate64.S
new file mode 100644 (file)
index 0000000..e844d16
--- /dev/null
@@ -0,0 +1,23 @@
+/* Generated by gensyscalls.py. Do not edit. */
+
+#include <asm/unistd.h>
+    .text
+    .globl fallocate64
+    .align 4
+    .ent fallocate64
+
+fallocate64:
+    .set noreorder
+    .cpload $t9
+    li $v0, __NR_fallocate
+    syscall
+    bnez $a3, 1f
+    move $a0, $v0
+    j $ra
+    nop
+1:
+    la $t9,__set_errno
+    j $t9
+    nop
+    .set reorder
+    .end fallocate64
index b7d1e08..6d368b3 100644 (file)
@@ -55,6 +55,7 @@ syscall_src += arch-x86/syscalls/epoll_ctl.S
 syscall_src += arch-x86/syscalls/eventfd.S
 syscall_src += arch-x86/syscalls/execve.S
 syscall_src += arch-x86/syscalls/faccessat.S
+syscall_src += arch-x86/syscalls/fallocate64.S
 syscall_src += arch-x86/syscalls/fchdir.S
 syscall_src += arch-x86/syscalls/fchmod.S
 syscall_src += arch-x86/syscalls/fchmodat.S
diff --git a/libc/arch-x86/syscalls/fallocate64.S b/libc/arch-x86/syscalls/fallocate64.S
new file mode 100644 (file)
index 0000000..7e03c54
--- /dev/null
@@ -0,0 +1,42 @@
+/* Generated by gensyscalls.py. Do not edit. */
+
+#include <private/bionic_asm.h>
+
+ENTRY(fallocate64)
+    pushl   %ebx
+    pushl   %ecx
+    pushl   %edx
+    pushl   %esi
+    pushl   %edi
+    pushl   %ebp
+    .cfi_def_cfa_offset 24
+    .cfi_rel_offset ebx, 0
+    .cfi_rel_offset ecx, 4
+    .cfi_rel_offset edx, 8
+    .cfi_rel_offset esi, 12
+    .cfi_rel_offset edi, 16
+    .cfi_rel_offset ebp, 20
+    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_fallocate, %eax
+    int     $0x80
+    cmpl    $-MAX_ERRNO, %eax
+    jb      1f
+    negl    %eax
+    pushl   %eax
+    call    __set_errno
+    addl    $4, %esp
+    orl     $-1, %eax
+1:
+    popl    %ebp
+    popl    %edi
+    popl    %esi
+    popl    %edx
+    popl    %ecx
+    popl    %ebx
+    ret
+END(fallocate64)
index ec09e77..13d921a 100644 (file)
@@ -49,6 +49,7 @@ syscall_src += arch-x86_64/syscalls/epoll_ctl.S
 syscall_src += arch-x86_64/syscalls/eventfd.S
 syscall_src += arch-x86_64/syscalls/execve.S
 syscall_src += arch-x86_64/syscalls/faccessat.S
+syscall_src += arch-x86_64/syscalls/fallocate.S
 syscall_src += arch-x86_64/syscalls/fchdir.S
 syscall_src += arch-x86_64/syscalls/fchmod.S
 syscall_src += arch-x86_64/syscalls/fchmodat.S
diff --git a/libc/arch-x86_64/syscalls/fallocate.S b/libc/arch-x86_64/syscalls/fallocate.S
new file mode 100644 (file)
index 0000000..e6959ca
--- /dev/null
@@ -0,0 +1,20 @@
+/* Generated by gensyscalls.py. Do not edit. */
+
+#include <private/bionic_asm.h>
+
+ENTRY(fallocate)
+    movq    %rcx, %r10
+    movl    $__NR_fallocate, %eax
+    syscall
+    cmpq    $-MAX_ERRNO, %rax
+    jb      1f
+    negl    %eax
+    movl    %eax, %edi
+    call    __set_errno
+    orq     $-1, %rax
+1:
+    ret
+END(fallocate)
+
+    .globl _C_LABEL(fallocate64)
+    .equ _C_LABEL(fallocate64), _C_LABEL(fallocate)
index d7ccdb9..411daa0 100644 (file)
@@ -27,6 +27,7 @@
  */
 
 #include <errno.h>
+#include <fcntl.h>
 #include <stdarg.h>
 #include <sys/resource.h>
 #include <sys/types.h>
@@ -86,6 +87,11 @@ ssize_t pwrite(int fd, const void* buf, size_t byte_count, off_t offset) {
   return pwrite64(fd, buf, byte_count, static_cast<off64_t>(offset));
 }
 
+// There is no fallocate for 32-bit off_t, so we need to widen and call fallocate64.
+int fallocate(int fd, int mode, off_t offset, off_t length) {
+  return fallocate64(fd, mode, static_cast<off64_t>(offset), static_cast<off64_t>(length));
+}
+
 // There is no getrlimit64 system call, so we need to use prlimit64.
 int getrlimit64(int resource, rlimit64* limits64) {
   return prlimit64(0, resource, NULL, limits64);
diff --git a/libc/bionic/posix_fallocate.cpp b/libc/bionic/posix_fallocate.cpp
new file mode 100644 (file)
index 0000000..bdc1636
--- /dev/null
@@ -0,0 +1,41 @@
+/*
+ * 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 <fcntl.h>
+
+#include "private/ErrnoRestorer.h"
+
+int posix_fallocate(int fd, off_t offset, off_t length) {
+  ErrnoRestorer errno_restorer;
+  return (fallocate(fd, 0, offset, length) == 0) ? 0 : errno;
+}
+
+int posix_fallocate64(int fd, off64_t offset, off64_t length) {
+  ErrnoRestorer errno_restorer;
+  return (fallocate64(fd, 0, offset, length) == 0) ? 0 : errno;
+}
index f6a89ef..b7b91f2 100644 (file)
@@ -41,11 +41,15 @@ __BEGIN_DECLS
 #define O_ASYNC  FASYNC
 #endif
 
-extern int  open(const char*  path, int  mode, ...);
-extern int  openat(int fd, const char*  path, int  mode, ...);
-extern int  unlinkat(int dirfd, const char *pathname, int flags);
-extern int  fcntl(int   fd, int   command, ...);
-extern int  creat(const char*  path, mode_t  mode);
+extern int creat(const char*, mode_t);
+extern int fallocate64(int, int, off64_t, off64_t);
+extern int fallocate(int, int, off_t, off_t);
+extern int fcntl(int, int, ...);
+extern int openat(int, const char*, int, ...);
+extern int open(const char*, int, ...);
+extern int posix_fallocate64(int, off64_t, off64_t);
+extern int posix_fallocate(int, off_t, off_t);
+extern int unlinkat(int, const char*, int);
 
 #if defined(__BIONIC_FORTIFY)
 
index a094fac..d14243e 100644 (file)
@@ -19,6 +19,8 @@
 #include <errno.h>
 #include <fcntl.h>
 
+#include "TemporaryFile.h"
+
 TEST(fcntl, fcntl_smoke) {
   int fd = open("/proc/version", O_RDONLY);
   ASSERT_TRUE(fd != -1);
@@ -34,3 +36,50 @@ TEST(fcntl, fcntl_smoke) {
   ASSERT_TRUE(flags != -1);
   ASSERT_EQ(FD_CLOEXEC, flags & FD_CLOEXEC);
 }
+
+TEST(fcntl, fallocate_EINVAL) {
+  TemporaryFile tf;
+
+#if !defined(__GLIBC__)
+  errno = 0;
+  ASSERT_EQ(-1, fallocate(tf.fd, 0, 0, -1));
+  ASSERT_EQ(EINVAL, errno);
+
+  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));
+  ASSERT_EQ(0, errno);
+
+  errno = 0;
+  ASSERT_EQ(EINVAL, posix_fallocate64(tf.fd, 0, -1));
+  ASSERT_EQ(0, errno);
+}
+
+TEST(fcntl, fallocate) {
+  TemporaryFile tf;
+  struct stat sb;
+  ASSERT_EQ(0, fstat(tf.fd, &sb));
+  ASSERT_EQ(0, sb.st_size);
+
+#if !defined(__GLIBC__)
+  ASSERT_EQ(0, fallocate(tf.fd, 0, 0, 1));
+  ASSERT_EQ(0, fstat(tf.fd, &sb));
+  ASSERT_EQ(1, sb.st_size);
+
+  ASSERT_EQ(0, fallocate64(tf.fd, 0, 0, 2));
+  ASSERT_EQ(0, fstat(tf.fd, &sb));
+  ASSERT_EQ(2, sb.st_size);
+#endif
+
+  ASSERT_EQ(0, posix_fallocate(tf.fd, 0, 3));
+  ASSERT_EQ(0, fstat(tf.fd, &sb));
+  ASSERT_EQ(3, sb.st_size);
+
+  ASSERT_EQ(0, posix_fallocate64(tf.fd, 0, 4));
+  ASSERT_EQ(0, fstat(tf.fd, &sb));
+  ASSERT_EQ(4, sb.st_size);
+}