1f08c3bdfSopenharmony_ci// SPDX-License-Identifier: GPL-2.0-or-later 2f08c3bdfSopenharmony_ci/* 3f08c3bdfSopenharmony_ci * Copyright (c) 2018 FUJITSU LIMITED. All rights reserved. 4f08c3bdfSopenharmony_ci * Author: Xiao Yang <yangx.jy@cn.fujitsu.com> 5f08c3bdfSopenharmony_ci */ 6f08c3bdfSopenharmony_ci 7f08c3bdfSopenharmony_ci/* 8f08c3bdfSopenharmony_ci * Description: 9f08c3bdfSopenharmony_ci * Check the basic functionality of the preadv(2) for the file 10f08c3bdfSopenharmony_ci * opened with O_DIRECT in all filesystem. 11f08c3bdfSopenharmony_ci * preadv(2) should succeed to read the expected content of data 12f08c3bdfSopenharmony_ci * and after reading the file, the file offset is not changed. 13f08c3bdfSopenharmony_ci */ 14f08c3bdfSopenharmony_ci 15f08c3bdfSopenharmony_ci#define _GNU_SOURCE 16f08c3bdfSopenharmony_ci#include <stdlib.h> 17f08c3bdfSopenharmony_ci#include <string.h> 18f08c3bdfSopenharmony_ci#include <sys/uio.h> 19f08c3bdfSopenharmony_ci#include <sys/ioctl.h> 20f08c3bdfSopenharmony_ci#include <sys/mount.h> 21f08c3bdfSopenharmony_ci#include "tst_test.h" 22f08c3bdfSopenharmony_ci#include "preadv.h" 23f08c3bdfSopenharmony_ci 24f08c3bdfSopenharmony_ci#define MNTPOINT "mntpoint" 25f08c3bdfSopenharmony_ci#define FNAME MNTPOINT"/file" 26f08c3bdfSopenharmony_ci 27f08c3bdfSopenharmony_cistatic int fd; 28f08c3bdfSopenharmony_cistatic off_t blk_off, zero_off; 29f08c3bdfSopenharmony_cistatic ssize_t blksz; 30f08c3bdfSopenharmony_cistatic char *pop_buf; 31f08c3bdfSopenharmony_ci 32f08c3bdfSopenharmony_cistatic struct iovec rd_iovec[] = { 33f08c3bdfSopenharmony_ci {NULL, 0}, 34f08c3bdfSopenharmony_ci {NULL, 0}, 35f08c3bdfSopenharmony_ci}; 36f08c3bdfSopenharmony_ci 37f08c3bdfSopenharmony_cistatic struct tcase { 38f08c3bdfSopenharmony_ci int count; 39f08c3bdfSopenharmony_ci off_t *offset; 40f08c3bdfSopenharmony_ci ssize_t *size; 41f08c3bdfSopenharmony_ci char content; 42f08c3bdfSopenharmony_ci} tcases[] = { 43f08c3bdfSopenharmony_ci {1, &zero_off, &blksz, 0x61}, 44f08c3bdfSopenharmony_ci {2, &zero_off, &blksz, 0x61}, 45f08c3bdfSopenharmony_ci {1, &blk_off, &blksz, 0x62}, 46f08c3bdfSopenharmony_ci}; 47f08c3bdfSopenharmony_ci 48f08c3bdfSopenharmony_cistatic void verify_direct_preadv(unsigned int n) 49f08c3bdfSopenharmony_ci{ 50f08c3bdfSopenharmony_ci int i; 51f08c3bdfSopenharmony_ci char *vec; 52f08c3bdfSopenharmony_ci struct tcase *tc = &tcases[n]; 53f08c3bdfSopenharmony_ci 54f08c3bdfSopenharmony_ci vec = rd_iovec[0].iov_base; 55f08c3bdfSopenharmony_ci memset(vec, 0x00, blksz); 56f08c3bdfSopenharmony_ci 57f08c3bdfSopenharmony_ci SAFE_LSEEK(fd, 0, SEEK_SET); 58f08c3bdfSopenharmony_ci 59f08c3bdfSopenharmony_ci TEST(preadv(fd, rd_iovec, tc->count, *tc->offset)); 60f08c3bdfSopenharmony_ci if (TST_RET < 0) { 61f08c3bdfSopenharmony_ci tst_res(TFAIL | TTERRNO, "preadv(O_DIRECT) fails"); 62f08c3bdfSopenharmony_ci return; 63f08c3bdfSopenharmony_ci } 64f08c3bdfSopenharmony_ci 65f08c3bdfSopenharmony_ci if (TST_RET != *tc->size) { 66f08c3bdfSopenharmony_ci tst_res(TFAIL, "preadv(O_DIRECT) read %li bytes, expected %zi", 67f08c3bdfSopenharmony_ci TST_RET, *tc->size); 68f08c3bdfSopenharmony_ci return; 69f08c3bdfSopenharmony_ci } 70f08c3bdfSopenharmony_ci 71f08c3bdfSopenharmony_ci for (i = 0; i < *tc->size; i++) { 72f08c3bdfSopenharmony_ci if (vec[i] != tc->content) 73f08c3bdfSopenharmony_ci break; 74f08c3bdfSopenharmony_ci } 75f08c3bdfSopenharmony_ci 76f08c3bdfSopenharmony_ci if (i < *tc->size) { 77f08c3bdfSopenharmony_ci tst_res(TFAIL, "Buffer wrong at %i have %02x expected %02x", 78f08c3bdfSopenharmony_ci i, vec[i], tc->content); 79f08c3bdfSopenharmony_ci return; 80f08c3bdfSopenharmony_ci } 81f08c3bdfSopenharmony_ci 82f08c3bdfSopenharmony_ci if (SAFE_LSEEK(fd, 0, SEEK_CUR) != 0) { 83f08c3bdfSopenharmony_ci tst_res(TFAIL, "preadv(O_DIRECT) has changed file offset"); 84f08c3bdfSopenharmony_ci return; 85f08c3bdfSopenharmony_ci } 86f08c3bdfSopenharmony_ci 87f08c3bdfSopenharmony_ci tst_res(TPASS, "preadv(O_DIRECT) read %zi bytes successfully " 88f08c3bdfSopenharmony_ci "with content '%c' expectedly", *tc->size, tc->content); 89f08c3bdfSopenharmony_ci} 90f08c3bdfSopenharmony_ci 91f08c3bdfSopenharmony_cistatic void setup(void) 92f08c3bdfSopenharmony_ci{ 93f08c3bdfSopenharmony_ci int dev_fd, ret; 94f08c3bdfSopenharmony_ci 95f08c3bdfSopenharmony_ci dev_fd = SAFE_OPEN(tst_device->dev, O_RDWR); 96f08c3bdfSopenharmony_ci SAFE_IOCTL(dev_fd, BLKSSZGET, &ret); 97f08c3bdfSopenharmony_ci SAFE_CLOSE(dev_fd); 98f08c3bdfSopenharmony_ci 99f08c3bdfSopenharmony_ci if (ret <= 0) 100f08c3bdfSopenharmony_ci tst_brk(TBROK, "BLKSSZGET returned invalid block size %i", ret); 101f08c3bdfSopenharmony_ci 102f08c3bdfSopenharmony_ci tst_res(TINFO, "Using block size %i", ret); 103f08c3bdfSopenharmony_ci 104f08c3bdfSopenharmony_ci blksz = ret; 105f08c3bdfSopenharmony_ci blk_off = ret; 106f08c3bdfSopenharmony_ci 107f08c3bdfSopenharmony_ci fd = SAFE_OPEN(FNAME, O_RDWR | O_CREAT | O_DIRECT, 0644); 108f08c3bdfSopenharmony_ci 109f08c3bdfSopenharmony_ci pop_buf = SAFE_MEMALIGN(blksz, blksz); 110f08c3bdfSopenharmony_ci memset(pop_buf, 0x61, blksz); 111f08c3bdfSopenharmony_ci SAFE_WRITE(SAFE_WRITE_ALL, fd, pop_buf, blksz); 112f08c3bdfSopenharmony_ci 113f08c3bdfSopenharmony_ci memset(pop_buf, 0x62, blksz); 114f08c3bdfSopenharmony_ci SAFE_WRITE(SAFE_WRITE_ALL, fd, pop_buf, blksz); 115f08c3bdfSopenharmony_ci 116f08c3bdfSopenharmony_ci rd_iovec[0].iov_base = SAFE_MEMALIGN(blksz, blksz); 117f08c3bdfSopenharmony_ci rd_iovec[0].iov_len = blksz; 118f08c3bdfSopenharmony_ci} 119f08c3bdfSopenharmony_ci 120f08c3bdfSopenharmony_cistatic void cleanup(void) 121f08c3bdfSopenharmony_ci{ 122f08c3bdfSopenharmony_ci free(pop_buf); 123f08c3bdfSopenharmony_ci free(rd_iovec[0].iov_base); 124f08c3bdfSopenharmony_ci 125f08c3bdfSopenharmony_ci if (fd > 0) 126f08c3bdfSopenharmony_ci SAFE_CLOSE(fd); 127f08c3bdfSopenharmony_ci} 128f08c3bdfSopenharmony_ci 129f08c3bdfSopenharmony_cistatic struct tst_test test = { 130f08c3bdfSopenharmony_ci .tcnt = ARRAY_SIZE(tcases), 131f08c3bdfSopenharmony_ci .setup = setup, 132f08c3bdfSopenharmony_ci .cleanup = cleanup, 133f08c3bdfSopenharmony_ci .test = verify_direct_preadv, 134f08c3bdfSopenharmony_ci .mntpoint = MNTPOINT, 135f08c3bdfSopenharmony_ci .mount_device = 1, 136f08c3bdfSopenharmony_ci .all_filesystems = 1, 137f08c3bdfSopenharmony_ci .skip_filesystems = (const char *[]) { 138f08c3bdfSopenharmony_ci "tmpfs", 139f08c3bdfSopenharmony_ci NULL 140f08c3bdfSopenharmony_ci } 141f08c3bdfSopenharmony_ci}; 142