This is a new functional test of fallocate() syscall with the focus on
FALLOC_FL_ZERO_RANGE (since Linux 3.15) and FALLOC_FL_COLLAPSE_RANGE
(since Linux 3.15) modes.

Steps of test-cases:
  * allocate a file with specified size;
  * make a hole in the middle of the file with FALLOC_FL_PUNCH_HOLE;
  * fill the hole and adjacent space with FALLOC_FL_ZERO_RANGE;
  * remove a block from a file with FALLOC_FL_COLLAPSE_RANGE

Signed-off-by: Alexey Kodanev <alexey.koda...@oracle.com>
---
v4: corrected Linux version for FALLOC_FL_ZERO_RANGE
    removed second Linux version check in test04()
    added 'EOPNOTSUPP' check for initial fallocate()
v3: correctly indented second line in if blocks and tst_resm
v2: replaced lseek, read, write, etc. with LTP safe macros
    moved FALLOC_FL_* macros to fallocate.h
    removed FALLOC_FL_KEEP_SIZE from fallocate03 (it is now in fallocate.h)
    made one more test-case (split setup())

 runtest/syscalls                                  |    1 +
 testcases/kernel/syscalls/.gitignore              |    1 +
 testcases/kernel/syscalls/fallocate/fallocate.h   |   20 ++
 testcases/kernel/syscalls/fallocate/fallocate03.c |    1 -
 testcases/kernel/syscalls/fallocate/fallocate04.c |  273 +++++++++++++++++++++
 5 files changed, 295 insertions(+), 1 deletions(-)
 create mode 100644 testcases/kernel/syscalls/fallocate/fallocate04.c

diff --git a/runtest/syscalls b/runtest/syscalls
index 7703825..126f46f 100644
--- a/runtest/syscalls
+++ b/runtest/syscalls
@@ -154,6 +154,7 @@ faccessat01 faccessat01
 fallocate01 fallocate01
 fallocate02 fallocate02
 fallocate03 fallocate03
+fallocate04 fallocate04
 
 #posix_fadvise test cases
 posix_fadvise01                      posix_fadvise01
diff --git a/testcases/kernel/syscalls/.gitignore 
b/testcases/kernel/syscalls/.gitignore
index f10e85e..afe7f3b 100644
--- a/testcases/kernel/syscalls/.gitignore
+++ b/testcases/kernel/syscalls/.gitignore
@@ -135,6 +135,7 @@
 /fallocate/fallocate01
 /fallocate/fallocate02
 /fallocate/fallocate03
+/fallocate/fallocate04
 /fchdir/fchdir01
 /fchdir/fchdir02
 /fchdir/fchdir03
diff --git a/testcases/kernel/syscalls/fallocate/fallocate.h 
b/testcases/kernel/syscalls/fallocate/fallocate.h
index b6c2203..1900aa0 100644
--- a/testcases/kernel/syscalls/fallocate/fallocate.h
+++ b/testcases/kernel/syscalls/fallocate/fallocate.h
@@ -27,6 +27,26 @@
 #include "lapi/abisize.h"
 #include "linux_syscall_numbers.h"
 
+#ifndef SEEK_HOLE
+#define SEEK_HOLE 4
+#endif
+
+#ifndef FALLOC_FL_KEEP_SIZE
+#define FALLOC_FL_KEEP_SIZE 0x01
+#endif
+
+#ifndef FALLOC_FL_PUNCH_HOLE
+#define FALLOC_FL_PUNCH_HOLE 0x02
+#endif
+
+#ifndef FALLOC_FL_COLLAPSE_RANGE
+#define FALLOC_FL_COLLAPSE_RANGE 0x08
+#endif
+
+#ifndef FALLOC_FL_ZERO_RANGE
+#define FALLOC_FL_ZERO_RANGE 0x10
+#endif
+
 #if !defined(HAVE_FALLOCATE)
 static inline long fallocate(int fd, int mode, loff_t offset, loff_t len)
 {
diff --git a/testcases/kernel/syscalls/fallocate/fallocate03.c 
b/testcases/kernel/syscalls/fallocate/fallocate03.c
index ae2476a..092d2bb 100644
--- a/testcases/kernel/syscalls/fallocate/fallocate03.c
+++ b/testcases/kernel/syscalls/fallocate/fallocate03.c
@@ -101,7 +101,6 @@
 #define BLOCKS_WRITTEN 12
 #define HOLE_SIZE_IN_BLOCKS 12
 #define DEFAULT_MODE 0
-#define FALLOC_FL_KEEP_SIZE 1  //Need to be removed once the glibce support is 
provided
 #define TRUE 0
 
 void get_blocksize(int);
diff --git a/testcases/kernel/syscalls/fallocate/fallocate04.c 
b/testcases/kernel/syscalls/fallocate/fallocate04.c
new file mode 100644
index 0000000..f99492d
--- /dev/null
+++ b/testcases/kernel/syscalls/fallocate/fallocate04.c
@@ -0,0 +1,273 @@
+/*
+ * Copyright (c) 2015 Oracle and/or its affiliates. All Rights Reserved.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation; either version 2 of
+ * the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it would be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ *
+ * Author: Alexey Kodanev <alexey.koda...@oracle.com>
+ */
+
+#define _GNU_SOURCE
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <errno.h>
+#include <sys/stat.h>
+#include <fcntl.h>
+#include <unistd.h>
+
+#include "test.h"
+#include "safe_macros.h"
+#include "fallocate.h"
+
+char *TCID = "fallocate04";
+int TST_TOTAL = 4;
+
+static int fd;
+static const char fname[] = "fallocate04.txt";
+static size_t block_size;
+static size_t buf_size;
+
+#define NUM_OF_BLOCKS  3
+
+static int verbose;
+static const option_t options[] = {
+       {"v", &verbose, NULL},
+       {NULL, NULL, NULL}
+};
+
+static void help(void)
+{
+       printf("  -v      Verbose\n");
+}
+
+static void cleanup(void)
+{
+       close(fd);
+       tst_rmdir();
+}
+
+static void get_blocksize(void)
+{
+       struct stat file_stat;
+
+       SAFE_FSTAT(cleanup, fd, &file_stat);
+
+       block_size = file_stat.st_blksize;
+       buf_size = NUM_OF_BLOCKS * block_size;
+}
+
+static size_t get_allocsize(void)
+{
+       struct stat file_stat;
+
+       SAFE_FSTAT(cleanup, fd, &file_stat);
+
+       return file_stat.st_blocks * 512;
+}
+
+static void fill_tst_buf(char buf[])
+{
+       /* fill the buffer with a, b, c, ... letters on each block */
+       int i;
+
+       for (i = 0; i < NUM_OF_BLOCKS; ++i)
+               memset(buf + i * block_size, 'a' + i, block_size);
+}
+
+static void setup(void)
+{
+       tst_tmpdir();
+
+       fd = SAFE_OPEN(cleanup, fname, O_RDWR | O_CREAT, 0700);
+
+       get_blocksize();
+}
+
+static void check_file_data(const char exp_buf[])
+{
+       size_t size = sizeof(exp_buf);
+       char rbuf[size];
+
+       tst_resm(TINFO, "reading the file, compare with expected buffer");
+
+       SAFE_LSEEK(cleanup, fd, 0, SEEK_SET);
+       SAFE_READ(cleanup, 1, fd, rbuf, size);
+
+       if (memcmp(exp_buf, rbuf, size)) {
+               if (verbose) {
+                       tst_resm_hexd(TINFO, exp_buf, size, "expected:");
+                       tst_resm_hexd(TINFO, rbuf, size, "but read:");
+               }
+               tst_brkm(TFAIL, cleanup, "not expected file data");
+       }
+}
+
+static void test01(void)
+{
+       tst_resm(TINFO, "allocate '%zu' bytes", buf_size);
+
+       if (fallocate(fd, 0, 0, buf_size) == -1) {
+               if (errno == ENOSYS || errno == EOPNOTSUPP)
+                       tst_brkm(TCONF, cleanup, "fallocate() not supported");
+               tst_brkm(TFAIL | TERRNO, cleanup, "fallocate() failed");
+       }
+
+       char buf[buf_size];
+
+       fill_tst_buf(buf);
+
+       SAFE_WRITE(cleanup, 1, fd, buf, buf_size);
+
+       tst_resm(TPASS, "test-case succeeded");
+}
+
+static void test02(void)
+{
+       size_t alloc_size0 = get_allocsize();
+
+       tst_resm(TINFO, "read allocated file size '%zu'", alloc_size0);
+       tst_resm(TINFO, "make a hole with FALLOC_FL_PUNCH_HOLE");
+
+       if (fallocate(fd, FALLOC_FL_PUNCH_HOLE | FALLOC_FL_KEEP_SIZE,
+           block_size, block_size) == -1) {
+               if (errno == EOPNOTSUPP)
+                       tst_brkm(TCONF, cleanup, "operation not supported");
+               tst_brkm(TFAIL | TERRNO, cleanup, "fallocate() failed");
+       }
+
+       tst_resm(TINFO, "check that file has a hole with lseek(,,SEEK_HOLE)");
+       off_t ret = lseek(fd, 0, SEEK_HOLE);
+
+       if (ret != (ssize_t)block_size) {
+               /* exclude error when kernel doesn't have SEEK_HOLE support */
+               if (errno != EINVAL) {
+                       tst_brkm(TFAIL | TERRNO, cleanup,
+                                "fallocate() or lseek() failed");
+               }
+               tst_resm(TWARN | TERRNO, "lseek() doesn't support SEEK_HOLE");
+       }
+       tst_resm(TINFO, "found a hole at '%ld' offset", ret);
+
+       size_t alloc_size1 = get_allocsize();
+
+       tst_resm(TINFO, "allocated file size before '%zu' and after '%zu'",
+                alloc_size0, alloc_size1);
+       if ((alloc_size0 - block_size) != alloc_size1)
+               tst_brkm(TFAIL, cleanup, "not expected allocated size");
+
+       char exp_buf[buf_size];
+
+       fill_tst_buf(exp_buf);
+       memset(exp_buf + block_size, 0, block_size);
+
+       check_file_data(exp_buf);
+
+       tst_resm(TPASS, "test-case succeeded");
+}
+
+static void test03(void)
+{
+       tst_resm(TINFO, "zeroing file space with FALLOC_FL_ZERO_RANGE");
+
+       if (tst_kvercmp(3, 15, 0) < 0) {
+               tst_brkm(TCONF, cleanup,
+                        "Test must be run with kernel 3.15 or newer");
+       }
+
+       size_t alloc_size0 = get_allocsize();
+
+       tst_resm(TINFO, "read current allocated file size '%zu'", alloc_size0);
+
+       if (fallocate(fd, FALLOC_FL_ZERO_RANGE, block_size - 1,
+           block_size + 2) == -1) {
+               if (errno == EOPNOTSUPP)
+                       tst_brkm(TCONF, cleanup, "operation not supported");
+               tst_brkm(TFAIL | TERRNO, cleanup, "fallocate failed");
+       }
+
+       /* The file hole in the specified range must be allocated and
+        * filled with zeros. Check it.
+        */
+       size_t alloc_size1 = get_allocsize();
+
+       tst_resm(TINFO, "allocated file size before '%zu' and after '%zu'",
+                alloc_size0, alloc_size1);
+       if ((alloc_size0 + block_size) != alloc_size1)
+               tst_brkm(TFAIL, cleanup, "not expected allocated size");
+
+       char exp_buf[buf_size];
+
+       fill_tst_buf(exp_buf);
+       memset(exp_buf + block_size - 1, 0, block_size + 2);
+
+       check_file_data(exp_buf);
+
+       tst_resm(TPASS, "test-case succeeded");
+}
+
+static void test04(void)
+{
+       tst_resm(TINFO, "collapsing file space with FALLOC_FL_COLLAPSE_RANGE");
+
+       size_t alloc_size0 = get_allocsize();
+
+       tst_resm(TINFO, "read current allocated file size '%zu'", alloc_size0);
+
+       if (fallocate(fd, FALLOC_FL_COLLAPSE_RANGE, block_size,
+           block_size) == -1) {
+               if (errno == EOPNOTSUPP)
+                       tst_brkm(TCONF, cleanup, "operation not supported");
+               tst_brkm(TFAIL | TERRNO, cleanup, "fallocate failed");
+       }
+
+       size_t alloc_size1 = get_allocsize();
+
+       tst_resm(TINFO, "allocated file size before '%zu' and after '%zu'",
+                alloc_size0, alloc_size1);
+       if ((alloc_size0 - block_size) != alloc_size1)
+               tst_brkm(TFAIL, cleanup, "not expected allocated size");
+
+       size_t size = buf_size - block_size;
+       char tmp_buf[buf_size];
+       char exp_buf[size];
+
+       fill_tst_buf(tmp_buf);
+
+       memcpy(exp_buf, tmp_buf, block_size);
+       memcpy(exp_buf + block_size, tmp_buf + size, block_size);
+
+       check_file_data(exp_buf);
+
+       tst_resm(TPASS, "test-case succeeded");
+}
+
+int main(int argc, char *argv[])
+{
+       int lc;
+
+       tst_parse_opts(argc, argv, options, help);
+
+       setup();
+
+       for (lc = 0; TEST_LOOPING(lc); ++lc) {
+               test01();
+               test02();
+               test03();
+               test04();
+       }
+
+       cleanup();
+
+       tst_exit();
+}
-- 
1.7.1


------------------------------------------------------------------------------
BPM Camp - Free Virtual Workshop May 6th at 10am PDT/1PM EDT
Develop your own process in accordance with the BPMN 2 standard
Learn Process modeling best practices with Bonita BPM through live exercises
http://www.bonitasoft.com/be-part-of-it/events/bpm-camp-virtual- event?utm_
source=Sourceforge_BPM_Camp_5_6_15&utm_medium=email&utm_campaign=VA_SF
_______________________________________________
Ltp-list mailing list
Ltp-list@lists.sourceforge.net
https://lists.sourceforge.net/lists/listinfo/ltp-list

Reply via email to