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 pwritev(2) for the file 10f08c3bdfSopenharmony_ci * opened with O_DIRECT in all filesystem. 11f08c3bdfSopenharmony_ci * pwritev(2) should succeed to write the expected content of data 12f08c3bdfSopenharmony_ci * and after writing 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 "pwritev.h" 23f08c3bdfSopenharmony_ci#include "tst_safe_prw.h" 24f08c3bdfSopenharmony_ci 25f08c3bdfSopenharmony_ci#define MNTPOINT "mntpoint" 26f08c3bdfSopenharmony_ci#define FNAME MNTPOINT"/file" 27f08c3bdfSopenharmony_ci 28f08c3bdfSopenharmony_cistatic char *initbuf, *preadbuf; 29f08c3bdfSopenharmony_cistatic int fd; 30f08c3bdfSopenharmony_cistatic off_t blk_off, zero_off; 31f08c3bdfSopenharmony_cistatic ssize_t blksz; 32f08c3bdfSopenharmony_ci 33f08c3bdfSopenharmony_cistatic struct iovec wr_iovec[] = { 34f08c3bdfSopenharmony_ci {NULL, 0}, 35f08c3bdfSopenharmony_ci {NULL, 0}, 36f08c3bdfSopenharmony_ci}; 37f08c3bdfSopenharmony_ci 38f08c3bdfSopenharmony_cistatic struct tcase { 39f08c3bdfSopenharmony_ci int count; 40f08c3bdfSopenharmony_ci off_t *offset; 41f08c3bdfSopenharmony_ci ssize_t *size; 42f08c3bdfSopenharmony_ci} tcases[] = { 43f08c3bdfSopenharmony_ci {1, &zero_off, &blksz}, 44f08c3bdfSopenharmony_ci {2, &zero_off, &blksz}, 45f08c3bdfSopenharmony_ci {1, &blk_off, &blksz}, 46f08c3bdfSopenharmony_ci}; 47f08c3bdfSopenharmony_ci 48f08c3bdfSopenharmony_cistatic void verify_direct_pwritev(unsigned int n) 49f08c3bdfSopenharmony_ci{ 50f08c3bdfSopenharmony_ci int i; 51f08c3bdfSopenharmony_ci struct tcase *tc = &tcases[n]; 52f08c3bdfSopenharmony_ci 53f08c3bdfSopenharmony_ci SAFE_PWRITE(1, fd, initbuf, blksz * 2, 0); 54f08c3bdfSopenharmony_ci 55f08c3bdfSopenharmony_ci TEST(pwritev(fd, wr_iovec, tc->count, *tc->offset)); 56f08c3bdfSopenharmony_ci if (TST_RET < 0) { 57f08c3bdfSopenharmony_ci tst_res(TFAIL | TTERRNO, "pwritev(O_DIRECT) fails"); 58f08c3bdfSopenharmony_ci return; 59f08c3bdfSopenharmony_ci } 60f08c3bdfSopenharmony_ci 61f08c3bdfSopenharmony_ci if (TST_RET != *tc->size) { 62f08c3bdfSopenharmony_ci tst_res(TFAIL, "pwritev(O_DIRECT) wrote %li bytes, expected %zi", 63f08c3bdfSopenharmony_ci TST_RET, *tc->size); 64f08c3bdfSopenharmony_ci return; 65f08c3bdfSopenharmony_ci } 66f08c3bdfSopenharmony_ci 67f08c3bdfSopenharmony_ci if (SAFE_LSEEK(fd, 0, SEEK_CUR) != 0) { 68f08c3bdfSopenharmony_ci tst_res(TFAIL, "pwritev(O_DIRECT) had changed file offset"); 69f08c3bdfSopenharmony_ci return; 70f08c3bdfSopenharmony_ci } 71f08c3bdfSopenharmony_ci 72f08c3bdfSopenharmony_ci memset(preadbuf, 0x00, blksz); 73f08c3bdfSopenharmony_ci SAFE_PREAD(1, fd, preadbuf, *tc->size, *tc->offset); 74f08c3bdfSopenharmony_ci 75f08c3bdfSopenharmony_ci for (i = 0; i < *tc->size; i++) { 76f08c3bdfSopenharmony_ci if (preadbuf[i] != 0x61) 77f08c3bdfSopenharmony_ci break; 78f08c3bdfSopenharmony_ci } 79f08c3bdfSopenharmony_ci 80f08c3bdfSopenharmony_ci if (i != *tc->size) { 81f08c3bdfSopenharmony_ci tst_res(TFAIL, "Buffer wrong at %i have %02x expected 0x61", 82f08c3bdfSopenharmony_ci i, preadbuf[i]); 83f08c3bdfSopenharmony_ci return; 84f08c3bdfSopenharmony_ci } 85f08c3bdfSopenharmony_ci 86f08c3bdfSopenharmony_ci tst_res(TPASS, "pwritev(O_DIRECT) wrote %zi bytes successfully " 87f08c3bdfSopenharmony_ci "with content 'a' expectedly ", *tc->size); 88f08c3bdfSopenharmony_ci} 89f08c3bdfSopenharmony_ci 90f08c3bdfSopenharmony_cistatic void setup(void) 91f08c3bdfSopenharmony_ci{ 92f08c3bdfSopenharmony_ci int dev_fd, ret; 93f08c3bdfSopenharmony_ci 94f08c3bdfSopenharmony_ci dev_fd = SAFE_OPEN(tst_device->dev, O_RDWR); 95f08c3bdfSopenharmony_ci SAFE_IOCTL(dev_fd, BLKSSZGET, &ret); 96f08c3bdfSopenharmony_ci SAFE_CLOSE(dev_fd); 97f08c3bdfSopenharmony_ci 98f08c3bdfSopenharmony_ci if (ret <= 0) 99f08c3bdfSopenharmony_ci tst_brk(TBROK, "BLKSSZGET returned invalid block size %i", ret); 100f08c3bdfSopenharmony_ci 101f08c3bdfSopenharmony_ci tst_res(TINFO, "Using block size %i", ret); 102f08c3bdfSopenharmony_ci 103f08c3bdfSopenharmony_ci blksz = ret; 104f08c3bdfSopenharmony_ci blk_off = ret; 105f08c3bdfSopenharmony_ci 106f08c3bdfSopenharmony_ci fd = SAFE_OPEN(FNAME, O_RDWR | O_CREAT | O_DIRECT, 0644); 107f08c3bdfSopenharmony_ci 108f08c3bdfSopenharmony_ci initbuf = SAFE_MEMALIGN(blksz, blksz * 2); 109f08c3bdfSopenharmony_ci memset(initbuf, 0x00, blksz * 2); 110f08c3bdfSopenharmony_ci 111f08c3bdfSopenharmony_ci preadbuf = SAFE_MEMALIGN(blksz, blksz); 112f08c3bdfSopenharmony_ci 113f08c3bdfSopenharmony_ci wr_iovec[0].iov_base = SAFE_MEMALIGN(blksz, blksz); 114f08c3bdfSopenharmony_ci wr_iovec[0].iov_len = blksz; 115f08c3bdfSopenharmony_ci memset(wr_iovec[0].iov_base, 0x61, blksz); 116f08c3bdfSopenharmony_ci} 117f08c3bdfSopenharmony_ci 118f08c3bdfSopenharmony_cistatic void cleanup(void) 119f08c3bdfSopenharmony_ci{ 120f08c3bdfSopenharmony_ci free(initbuf); 121f08c3bdfSopenharmony_ci free(preadbuf); 122f08c3bdfSopenharmony_ci free(wr_iovec[0].iov_base); 123f08c3bdfSopenharmony_ci 124f08c3bdfSopenharmony_ci if (fd > 0) 125f08c3bdfSopenharmony_ci SAFE_CLOSE(fd); 126f08c3bdfSopenharmony_ci} 127f08c3bdfSopenharmony_ci 128f08c3bdfSopenharmony_cistatic struct tst_test test = { 129f08c3bdfSopenharmony_ci .tcnt = ARRAY_SIZE(tcases), 130f08c3bdfSopenharmony_ci .setup = setup, 131f08c3bdfSopenharmony_ci .cleanup = cleanup, 132f08c3bdfSopenharmony_ci .test = verify_direct_pwritev, 133f08c3bdfSopenharmony_ci .mntpoint = MNTPOINT, 134f08c3bdfSopenharmony_ci .mount_device = 1, 135f08c3bdfSopenharmony_ci .all_filesystems = 1, 136f08c3bdfSopenharmony_ci .skip_filesystems = (const char *[]){ 137f08c3bdfSopenharmony_ci "tmpfs", 138f08c3bdfSopenharmony_ci NULL 139f08c3bdfSopenharmony_ci } 140f08c3bdfSopenharmony_ci}; 141