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 33static 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 44static 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 62static 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 94static 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 107TST_TEST_TCONF("This test is only for 64bit"); 108#endif 109