• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 // SPDX-License-Identifier: GPL-2.0-or-later
2 /*
3  * Copyright (c) International Business Machines  Corp., 2014
4  */
5 
6 /*\
7  * [Description]
8  *
9  * Testcase copied from sendfile02.c to test the basic functionality of
10  * the sendfile() system call on large file. There is a kernel bug which
11  * introduced by commit 8f9c0119d7ba9 and fixed by commit 5d73320a96fcc.
12  *
13  * Only supports 64bit systems.
14  *
15  * [Algorithm]
16  *
17  * 1. Call sendfile() with offset at 0.
18  * 2. Call sendfile() with offset at 3GB.
19  */
20 
21 #include <inttypes.h>
22 #include <sys/sendfile.h>
23 
24 #include "tst_test.h"
25 #include "lapi/abisize.h"
26 
27 #ifndef TST_ABI32
28 
29 #define ONE_GB		(INT64_C(1) << 30)
30 #define IN_FILE		"in_file"
31 #define OUT_FILE	"out_file"
32 
33 static struct test_case_t {
34 	char *desc;
35 	off_t offset;
36 	int64_t count;
37 	int64_t exp_retval;
38 	int64_t exp_updated_offset;
39 } tc[] = {
40 	{ "offset at 0", 0, ONE_GB, ONE_GB, ONE_GB },
41 	{ "offset at 3GB", 3 * ONE_GB, ONE_GB, ONE_GB, 4 * ONE_GB }
42 };
43 
setup(void)44 static void setup(void)
45 {
46 	int i, fd;
47 
48 	if (!tst_fs_has_free(".", 5, TST_GB))
49 		tst_brk(TCONF, "Test on large file needs 5G free space");
50 
51 	fd = SAFE_CREAT(IN_FILE, 00700);
52 	for (i = 1; i <= (4 * 1024); ++i) {
53 		SAFE_LSEEK(fd, 1024 * 1024 - 1, SEEK_CUR);
54 		SAFE_WRITE(SAFE_WRITE_ALL, fd, "C", 1);
55 	}
56 	SAFE_CLOSE(fd);
57 
58 	fd = SAFE_CREAT(OUT_FILE, 00700);
59 	SAFE_CLOSE(fd);
60 }
61 
run(unsigned int i)62 static void run(unsigned int i)
63 {
64 	int in_fd = SAFE_OPEN(IN_FILE, O_RDONLY);
65 	int out_fd = SAFE_OPEN(OUT_FILE, O_WRONLY);
66 	off_t offset = tc[i].offset;
67 
68 	off_t before_pos, after_pos;
69 	before_pos = SAFE_LSEEK(in_fd, 0, SEEK_CUR);
70 
71 	TEST(sendfile(out_fd, in_fd, &offset, tc[i].count));
72 	after_pos = SAFE_LSEEK(in_fd, 0, SEEK_CUR);
73 
74 	if (TST_RET != tc[i].exp_retval)
75 		tst_res(TFAIL, "sendfile() failed to return expected value, "
76 			       "expected: %" PRId64 ", got: %ld",
77 			tc[i].exp_retval, TST_RET);
78 	else if (offset != tc[i].exp_updated_offset)
79 		tst_res(TFAIL, "sendfile() failed to update OFFSET parameter to "
80 			       "expected value, expected: %" PRId64 ", got: %" PRId64,
81 			tc[i].exp_updated_offset, (int64_t)(offset));
82 	else if (before_pos != after_pos)
83 		tst_res(TFAIL, "sendfile() updated the file position of in_fd "
84 			       "unexpectedly, expected file position: %" PRId64
85 			       ", actual file position %" PRId64,
86 			(int64_t)(before_pos), (int64_t)(after_pos));
87 	else
88 		tst_res(TPASS, "sendfile() with %s", tc[i].desc);
89 
90 	SAFE_CLOSE(in_fd);
91 	SAFE_CLOSE(out_fd);
92 }
93 
94 static struct tst_test test = {
95 	.needs_tmpdir = 1,
96 	.setup = setup,
97 	.test = run,
98 	.tcnt = ARRAY_SIZE(tc),
99 	.max_runtime = 120,
100 	.tags = (const struct tst_tag[]) {
101 		{"linux-git", "5d73320a96fcc"},
102 		{}
103 	}
104 };
105 
106 #else
107 TST_TEST_TCONF("This test is only for 64bit");
108 #endif
109