| From 8fc83b7f3fd7425aa4e96c870a7d46df1d81c16c Mon Sep 17 00:00:00 2001 |
| From: Bernhard Reutner-Fischer <rep.dot.nop@gmail.com> |
| Date: Tue, 17 Apr 2012 09:30:15 +0200 |
| Subject: [PATCH] libc: add posix_fallocate() |
| |
| Signed-off-by: Bernhard Reutner-Fischer <rep.dot.nop@gmail.com> |
| --- |
| include/fcntl.h | 4 +- |
| libc/sysdeps/linux/common/Makefile.in | 3 +- |
| libc/sysdeps/linux/common/bits/kernel-features.h | 8 ++ |
| libc/sysdeps/linux/common/posix_fallocate.c | 43 ++++++++ |
| libc/sysdeps/linux/common/posix_fallocate64.c | 39 +++++++ |
| test/.gitignore | 2 + |
| test/unistd/Makefile.in | 5 +- |
| test/unistd/tst-posix_fallocate.c | 127 ++++++++++++++++++++++ |
| test/unistd/tst-posix_fallocate64.c | 2 + |
| 9 files changed, 228 insertions(+), 5 deletions(-) |
| create mode 100644 libc/sysdeps/linux/common/posix_fallocate.c |
| create mode 100644 libc/sysdeps/linux/common/posix_fallocate64.c |
| create mode 100644 test/unistd/tst-posix_fallocate.c |
| create mode 100644 test/unistd/tst-posix_fallocate64.c |
| |
| diff --git a/include/fcntl.h b/include/fcntl.h |
| index 26ad1fe..c4a47af 100644 |
| --- a/include/fcntl.h |
| +++ b/include/fcntl.h |
| @@ -210,9 +210,7 @@ extern int posix_fadvise64 (int __fd, __off64_t __offset, __off64_t __len, |
| |
| #endif |
| |
| -#if 0 /* && defined __UCLIBC_HAS_ADVANCED_REALTIME__ */ |
| - |
| -/* FIXME -- uClibc should probably implement these... */ |
| +#if defined __UCLIBC_HAS_ADVANCED_REALTIME__ |
| |
| /* Reserve storage for the data of the file associated with FD. |
| |
| diff --git a/libc/sysdeps/linux/common/Makefile.in b/libc/sysdeps/linux/common/Makefile.in |
| index e9baa47..e4ac4ff 100644 |
| --- a/libc/sysdeps/linux/common/Makefile.in |
| +++ b/libc/sysdeps/linux/common/Makefile.in |
| @@ -82,7 +82,8 @@ CSRC-$(UCLIBC_HAS_REALTIME) += clock_getres.c clock_gettime.c clock_settime.c \ |
| sched_get_priority_max.c sched_get_priority_min.c sched_getscheduler.c \ |
| sched_rr_get_interval.c sched_setparam.c sched_setscheduler.c sigqueue.c |
| # clock_getcpuclockid|clock_nanosleep|mq_timedreceive|mq_timedsend|posix_fadvise|posix_fallocate|posix_madvise|posix_memalign|posix_mem_offset|posix_spawnattr_destroy|posix_spawnattr_init|posix_spawnattr_getflags|posix_spawnattr_setflags|posix_spawnattr_getpgroup|posix_spawnattr_setpgroup|posix_spawnattr_getschedparam|posix_spawnattr_setschedparam|posix_spawnattr_getschedpolicy|posix_spawnattr_setschedpolicy|posix_spawnattr_getsigdefault|posix_spawnattr_setsigdefault|posix_spawnattr_getsigmask|posix_spawnattr_setsigmask|posix_spawnattr_init|posix_spawnattr_setflags|posix_spawnattr_setpgroup|posix_spawnattr_setschedparam|posix_spawnattr_setschedpolicy|posix_spawnattr_setsigdefault|posix_spawnattr_setsigmask|posix_spawn_file_actions_addclose|posix_spawn_file_actions_addopen|posix_spawn_file_actions_adddup2|posix_spawn_file_actions_addopen|posix_spawn_file_actions_destroy|posix_spawn_file_actions_init|posix_spawn_file_actions_init|posix_spawn|posix_spawnp|posix_spawnp|posix_typed_mem_get_info|pthread_mutex_timedlock|sem_timedwait |
| -CSRC-$(UCLIBC_HAS_ADVANCED_REALTIME) += posix_fadvise64.c posix_fadvise.c posix_madvise.c |
| +CSRC-$(UCLIBC_HAS_ADVANCED_REALTIME) += posix_fadvise64.c posix_fadvise.c posix_madvise.c \ |
| + posix_fallocate.c posix_fallocate64.c |
| CSRC-$(UCLIBC_SUSV4_LEGACY) += utime.c |
| CSRC-$(UCLIBC_HAS_EPOLL) += epoll.c |
| CSRC-$(UCLIBC_HAS_XATTR) += xattr.c |
| diff --git a/libc/sysdeps/linux/common/bits/kernel-features.h b/libc/sysdeps/linux/common/bits/kernel-features.h |
| index 5665e24..13c7a63 100644 |
| --- a/libc/sysdeps/linux/common/bits/kernel-features.h |
| +++ b/libc/sysdeps/linux/common/bits/kernel-features.h |
| @@ -496,6 +496,14 @@ |
| # define __ASSUME_PRIVATE_FUTEX 1 |
| #endif |
| |
| +/* Support for fallocate was added in 2.6.23, |
| + on s390 only after 2.6.23-rc1, on alpha only after 2.6.33-rc1. */ |
| +#if __LINUX_KERNEL_VERSION >= 0x020617 \ |
| + && (!defined __s390__ || __LINUX_KERNEL_VERSION >= 0x020618) \ |
| + && (!defined __alpha__ || __LINUX_KERNEL_VERSION >= 0x020621) |
| +# define __ASSUME_FALLOCATE 1 |
| +#endif |
| + |
| /* getcpu is a syscall for x86-64 since 3.1. */ |
| #if defined __x86_64__ && __LINUX_KERNEL_VERSION >= 0x030100 |
| # define __ASSUME_GETCPU_SYSCALL 1 |
| diff --git a/libc/sysdeps/linux/common/posix_fallocate.c b/libc/sysdeps/linux/common/posix_fallocate.c |
| new file mode 100644 |
| index 0000000..9aaa6ce |
| --- /dev/null |
| +++ b/libc/sysdeps/linux/common/posix_fallocate.c |
| @@ -0,0 +1,43 @@ |
| +/* vi: set sw=4 ts=4: */ |
| +/* |
| + * posix_fallocate() for uClibc |
| + * http://www.opengroup.org/onlinepubs/9699919799/functions/posix_fallocate.html |
| + * |
| + * Copyright (C) 2000-2006 Erik Andersen <andersen@uclibc.org> |
| + * |
| + * Licensed under the LGPL v2.1 or later, see the file COPYING.LIB in this tarball. |
| + */ |
| + |
| +#include <sys/syscall.h> |
| +#include <fcntl.h> |
| +#include <bits/kernel-features.h> |
| +#include <stdint.h> |
| + |
| +#if defined __NR_fallocate |
| +int posix_fallocate(int fd, __off_t offset, __off_t len) |
| +{ |
| + int ret; |
| + |
| +# if __WORDSIZE == 32 |
| + uint32_t off_low = offset; |
| + uint32_t len_low = len; |
| + /* may assert that these >>31 are 0 */ |
| + uint32_t zero = 0; |
| + INTERNAL_SYSCALL_DECL(err); |
| + ret = (int) (INTERNAL_SYSCALL(fallocate, err, 6, fd, 0, |
| + __LONG_LONG_PAIR (zero, off_low), |
| + __LONG_LONG_PAIR (zero, len_low))); |
| +# elif __WORDSIZE == 64 |
| + INTERNAL_SYSCALL_DECL(err); |
| + ret = (int) (INTERNAL_SYSCALL(fallocate, err, 4, fd, 0, offset, len)); |
| +# else |
| +# error your machine is neither 32 bit or 64 bit ... it must be magical |
| +#endif |
| + if (unlikely(INTERNAL_SYSCALL_ERROR_P (ret, err))) |
| + return INTERNAL_SYSCALL_ERRNO (ret, err); |
| + return 0; |
| +} |
| +# if defined __UCLIBC_HAS_LFS__ && __WORDSIZE == 64 |
| +strong_alias(posix_fallocate,posix_fallocate64) |
| +# endif |
| +#endif |
| diff --git a/libc/sysdeps/linux/common/posix_fallocate64.c b/libc/sysdeps/linux/common/posix_fallocate64.c |
| new file mode 100644 |
| index 0000000..818d868 |
| --- /dev/null |
| +++ b/libc/sysdeps/linux/common/posix_fallocate64.c |
| @@ -0,0 +1,39 @@ |
| +/* vi: set sw=4 ts=4: */ |
| +/* |
| + * posix_fallocate() for uClibc |
| + * http://www.opengroup.org/onlinepubs/9699919799/functions/posix_fallocate.html |
| + * |
| + * Copyright (C) 2000-2006 Erik Andersen <andersen@uclibc.org> |
| + * |
| + * Licensed under the LGPL v2.1 or later, see the file COPYING.LIB in this tarball. |
| + */ |
| + |
| +#include <sys/syscall.h> |
| +#include <fcntl.h> |
| +#include <bits/kernel-features.h> |
| +#include <stdint.h> |
| + |
| +#if defined __NR_fallocate |
| + |
| +# if __WORDSIZE == 64 |
| +/* Can use normal posix_fallocate() */ |
| +# elif __WORDSIZE == 32 |
| +int posix_fallocate64(int fd, __off64_t offset, __off64_t len) |
| +{ |
| + int ret; |
| + uint32_t off_low = offset & 0xffffffff; |
| + uint32_t off_high = offset >> 32; |
| + uint32_t len_low = len & 0xffffffff; |
| + uint32_t len_high = len >> 32; |
| + INTERNAL_SYSCALL_DECL(err); |
| + ret = (int) (INTERNAL_SYSCALL(fallocate, err, 6, fd, 0, |
| + __LONG_LONG_PAIR (off_high, off_low), |
| + __LONG_LONG_PAIR (len_high, len_low))); |
| + if (unlikely(INTERNAL_SYSCALL_ERROR_P (ret, err))) |
| + return INTERNAL_SYSCALL_ERRNO (ret, err); |
| + return 0; |
| +} |
| +# else |
| +# error your machine is neither 32 bit or 64 bit ... it must be magical |
| +# endif |
| +#endif |
| diff --git a/test/.gitignore b/test/.gitignore |
| index 7234c48..ef152e9 100644 |
| --- a/test/.gitignore |
| +++ b/test/.gitignore |
| @@ -305,6 +305,8 @@ unistd/getcwd |
| unistd/getopt |
| unistd/getopt_long |
| unistd/tstgetopt |
| +unistd/tst-posix_fallocate |
| +unistd/tst-posix_fallocate64 |
| unistd/tst-preadwrite |
| unistd/tst-preadwrite64 |
| unistd/vfork |
| diff --git a/test/unistd/Makefile.in b/test/unistd/Makefile.in |
| index c542f98..24b9a37 100644 |
| --- a/test/unistd/Makefile.in |
| +++ b/test/unistd/Makefile.in |
| @@ -2,7 +2,10 @@ |
| # Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball. |
| |
| ifeq ($(UCLIBC_HAS_LFS),) |
| -TESTS_DISABLED := tst-preadwrite64 |
| +TESTS_DISABLED := tst-preadwrite64 tst-posix_fallocate64 |
| +endif |
| +ifeq ($(UCLIBC_HAS_ADVANCED_REALTIME),) |
| +TESTS_DISABLED := tst-posix_fallocate |
| endif |
| OPTS_getopt := -abcXXX -9 |
| OPTS_getopt_long := --add XXX --delete YYY --verbose |
| diff --git a/test/unistd/tst-posix_fallocate.c b/test/unistd/tst-posix_fallocate.c |
| new file mode 100644 |
| index 0000000..d41c604 |
| --- /dev/null |
| +++ b/test/unistd/tst-posix_fallocate.c |
| @@ -0,0 +1,127 @@ |
| +#include <fcntl.h> |
| +#include <sys/stat.h> |
| + |
| +#ifndef TST_POSIX_FALLOCATE64 |
| +# define stat64 stat |
| +# define fstat64 fstat |
| +# else |
| +# ifndef O_LARGEFILE |
| +# error no O_LARGEFILE but you want to test with LFS enabled |
| +# endif |
| +#endif |
| + |
| +static void do_prepare (void); |
| +#define PREPARE(argc, argv) do_prepare () |
| +static int do_test (void); |
| +#define TEST_FUNCTION do_test () |
| +#include <test-skeleton.c> |
| + |
| +static int fd; |
| +static void |
| +do_prepare (void) |
| +{ |
| + fd = create_temp_file ("tst-posix_fallocate.", NULL); |
| + if (fd == -1) |
| + { |
| + printf ("cannot create temporary file: %m\n"); |
| + exit (1); |
| + } |
| +} |
| + |
| + |
| +static int |
| +do_test (void) |
| +{ |
| + struct stat64 st; |
| + |
| + if (fstat64 (fd, &st) != 0) |
| + { |
| + puts ("1st fstat failed"); |
| + return 1; |
| + } |
| + |
| + if (st.st_size != 0) |
| + { |
| + puts ("file not created with size 0"); |
| + return 1; |
| + } |
| + |
| + if (posix_fallocate (fd, 512, 768) != 0) |
| + { |
| + puts ("1st posix_fallocate call failed"); |
| + return 1; |
| + } |
| + |
| + if (fstat64 (fd, &st) != 0) |
| + { |
| + puts ("2nd fstat failed"); |
| + return 1; |
| + } |
| + |
| + if (st.st_size != 512 + 768) |
| + { |
| + printf ("file size after 1st posix_fallocate call is %llu, expected %u\n", |
| + (unsigned long long int) st.st_size, 512u + 768u); |
| + return 1; |
| + } |
| + |
| + if (posix_fallocate (fd, 0, 1024) != 0) |
| + { |
| + puts ("2nd posix_fallocate call failed"); |
| + return 1; |
| + } |
| + |
| + if (fstat64 (fd, &st) != 0) |
| + { |
| + puts ("3rd fstat failed"); |
| + return 1; |
| + } |
| + |
| + if (st.st_size != 512 + 768) |
| + { |
| + puts ("file size changed in 2nd posix_fallocate"); |
| + return 1; |
| + } |
| + |
| + if (posix_fallocate (fd, 2048, 64) != 0) |
| + { |
| + puts ("3rd posix_fallocate call failed"); |
| + return 1; |
| + } |
| + |
| + if (fstat64 (fd, &st) != 0) |
| + { |
| + puts ("4th fstat failed"); |
| + return 1; |
| + } |
| + |
| + if (st.st_size != 2048 + 64) |
| + { |
| + printf ("file size after 3rd posix_fallocate call is %llu, expected %u\n", |
| + (unsigned long long int) st.st_size, 2048u + 64u); |
| + return 1; |
| + } |
| +#ifdef TST_POSIX_FALLOCATE64 |
| + if (posix_fallocate64 (fd, 4097ULL, 4294967295ULL + 2ULL) != 0) |
| + { |
| + puts ("4th posix_fallocate call failed"); |
| + return 1; |
| + } |
| + |
| + if (fstat64 (fd, &st) != 0) |
| + { |
| + puts ("5th fstat failed"); |
| + return 1; |
| + } |
| + |
| + if (st.st_size != 4097ULL + 4294967295ULL + 2ULL) |
| + { |
| + printf ("file size after 4th posix_fallocate call is %llu, expected %llu\n", |
| + (unsigned long long int) st.st_size, 4097ULL + 4294967295ULL + 2ULL); |
| + return 1; |
| + } |
| +#endif |
| + close (fd); |
| + |
| + return 0; |
| +} |
| diff --git a/test/unistd/tst-posix_fallocate64.c b/test/unistd/tst-posix_fallocate64.c |
| new file mode 100644 |
| index 0000000..b1ee0ff |
| --- /dev/null |
| +++ b/test/unistd/tst-posix_fallocate64.c |
| @@ -0,0 +1,2 @@ |
| +#define TST_POSIX_FALLOCATE64 |
| +#include "tst-posix_fallocate.c" |
| -- |
| 1.7.10.4 |
| |