1 /* 2 * Copyright (c) International Business Machines Corp., 2001 3 * 07/2001 Ported by Wayne Boyer 4 * Copyright (c) 2017 Fujitsu Ltd. 5 * 04/2017 Modified by Jinhui Huang 6 * 7 * This program is free software; you can redistribute it and/or modify 8 * it under the terms of the GNU General Public License as published by 9 * the Free Software Foundation; either version 2 of the License, or 10 * (at your option) any later version. 11 * 12 * This program is distributed in the hope that it will be useful, 13 * but WITHOUT ANY WARRANTY; without even the implied warranty of 14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See 15 * the GNU General Public License for more details. 16 * 17 * You should have received a copy of the GNU General Public License 18 * along with this program; if not, write to the Free Software 19 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA 20 */ 21 /* 22 * DESCRIPTION 23 * test 1: 24 * Read with an invalid file descriptor, and expect an EBADF. 25 * 26 * test 2: 27 * The parameter passed to read is a directory, check if the errno is 28 * set to EISDIR. 29 * 30 * test 3: 31 * Buf is outside the accessible address space, expect an EFAULT. 32 * 33 * test 4: 34 * The file was opened with the O_DIRECT flag, and transfer sizes was not 35 * multiples of the logical block size of the file system, expect an 36 * EINVAL. 37 * 38 * test 5: 39 * The file was opened with the O_DIRECT flag, and the alignment of the 40 * user buffer was not multiples of the logical block size of the file 41 * system, expect an EINVAL. 42 */ 43 44 #define _GNU_SOURCE 45 46 #include <stdio.h> 47 #include <stdlib.h> 48 #include <errno.h> 49 #include "tst_test.h" 50 51 static int badfd = -1; 52 static int fd2, fd3, fd4 = -1; 53 static char buf[BUFSIZ]; 54 static void *bufaddr = buf; 55 static void *outside_buf = (void *)-1; 56 static void *addr4; 57 static void *addr5; 58 static long fs_type; 59 60 static struct tcase { 61 int *fd; 62 void **buf; 63 size_t count; 64 int exp_error; 65 } tcases[] = { 66 {&badfd, &bufaddr, 1, EBADF}, 67 {&fd2, &bufaddr, 1, EISDIR}, 68 #ifndef UCLINUX 69 {&fd3, &outside_buf, 1, EFAULT}, 70 #endif 71 {&fd4, &addr4, 1, EINVAL}, 72 {&fd4, &addr5, 4096, EINVAL}, 73 }; 74 75 static void verify_read(unsigned int n) 76 { 77 struct tcase *tc = &tcases[n]; 78 79 if (tc->fd == &fd4 && *tc->fd == -1) { 80 tst_res(TCONF, "O_DIRECT not supported on %s filesystem", 81 tst_fs_type_name(fs_type)); 82 return; 83 } 84 85 TEST(read(*tc->fd, *tc->buf, tc->count)); 86 87 if (*tc->fd == fd4 && TEST_RETURN >= 0) { 88 tst_res(TPASS, 89 "O_DIRECT unaligned reads fallbacks to buffered I/O"); 90 return; 91 } 92 93 if (TEST_RETURN != -1) { 94 tst_res(TFAIL, "read() succeeded unexpectedly"); 95 return; 96 } 97 98 if (TEST_ERRNO == tc->exp_error) { 99 tst_res(TPASS | TTERRNO, "read() failed as expected"); 100 } else { 101 tst_res(TFAIL | TTERRNO, "read() failed unexpectedly, " 102 "expected %s", tst_strerrno(tc->exp_error)); 103 } 104 } 105 106 static void setup(void) 107 { 108 fd2 = SAFE_OPEN(".", O_DIRECTORY); 109 110 SAFE_FILE_PRINTF("test_file", "A"); 111 112 fd3 = SAFE_OPEN("test_file", O_RDWR); 113 114 #if !defined(UCLINUX) 115 outside_buf = SAFE_MMAP(0, 1, PROT_NONE, 116 MAP_PRIVATE | MAP_ANONYMOUS, 0, 0); 117 #endif 118 119 addr4 = SAFE_MEMALIGN(getpagesize(), (4096 * 10)); 120 addr5 = addr4 + 1; 121 122 fs_type = tst_fs_type("."); 123 if (fs_type != TST_TMPFS_MAGIC) 124 fd4 = SAFE_OPEN("test_file", O_RDWR | O_DIRECT); 125 } 126 127 static void cleanup(void) 128 { 129 free(addr4); 130 131 if (fd4 > 0) 132 SAFE_CLOSE(fd4); 133 134 if (fd3 > 0) 135 SAFE_CLOSE(fd3); 136 137 if (fd2 > 0) 138 SAFE_CLOSE(fd2); 139 } 140 141 static struct tst_test test = { 142 .tcnt = ARRAY_SIZE(tcases), 143 .test = verify_read, 144 .setup = setup, 145 .cleanup = cleanup, 146 .needs_tmpdir = 1, 147 }; 148