1f08c3bdfSopenharmony_ci// SPDX-License-Identifier: GPL-2.0-or-later
2f08c3bdfSopenharmony_ci/*
3f08c3bdfSopenharmony_ci * Copyright (c) 2023 FUJITSU LIMITED. All rights reserved.
4f08c3bdfSopenharmony_ci * Author: Yang Xu <xuyang2018.jy@fujitsu.com>
5f08c3bdfSopenharmony_ci */
6f08c3bdfSopenharmony_ci
7f08c3bdfSopenharmony_ci/*\
8f08c3bdfSopenharmony_ci * [Description]
9f08c3bdfSopenharmony_ci *
10f08c3bdfSopenharmony_ci * It is a basic test for STATX_DIOALIGN mask on block device.
11f08c3bdfSopenharmony_ci *
12f08c3bdfSopenharmony_ci * - STATX_DIOALIGN   Want stx_dio_mem_align and stx_dio_offset_align value
13f08c3bdfSopenharmony_ci *
14f08c3bdfSopenharmony_ci * These two values are tightly coupled to the kernel's current DIO
15f08c3bdfSopenharmony_ci * restrictions on block devices.
16f08c3bdfSopenharmony_ci *
17f08c3bdfSopenharmony_ci * Minimum Linux version required is v6.1.
18f08c3bdfSopenharmony_ci */
19f08c3bdfSopenharmony_ci
20f08c3bdfSopenharmony_ci#define _GNU_SOURCE
21f08c3bdfSopenharmony_ci#include <sys/types.h>
22f08c3bdfSopenharmony_ci#include <sys/mount.h>
23f08c3bdfSopenharmony_ci#include <unistd.h>
24f08c3bdfSopenharmony_ci#include <stdlib.h>
25f08c3bdfSopenharmony_ci#include <stdbool.h>
26f08c3bdfSopenharmony_ci#include <stdio.h>
27f08c3bdfSopenharmony_ci#include "tst_test.h"
28f08c3bdfSopenharmony_ci#include "lapi/stat.h"
29f08c3bdfSopenharmony_ci
30f08c3bdfSopenharmony_cistatic char sys_bdev_dma_path[1024], sys_bdev_logical_path[1024];
31f08c3bdfSopenharmony_ci
32f08c3bdfSopenharmony_cistatic void verify_statx(void)
33f08c3bdfSopenharmony_ci{
34f08c3bdfSopenharmony_ci	struct statx buf;
35f08c3bdfSopenharmony_ci
36f08c3bdfSopenharmony_ci	TST_EXP_PASS_SILENT(statx(AT_FDCWD, tst_device->dev, 0, STATX_DIOALIGN, &buf),
37f08c3bdfSopenharmony_ci		"statx(AT_FDCWD, %s, 0, STATX_DIOALIGN, &buf)", tst_device->dev);
38f08c3bdfSopenharmony_ci
39f08c3bdfSopenharmony_ci	if (!(buf.stx_mask & STATX_DIOALIGN)) {
40f08c3bdfSopenharmony_ci		tst_res(TCONF, "Filesystem does not support STATX_DIOALIGN");
41f08c3bdfSopenharmony_ci		return;
42f08c3bdfSopenharmony_ci	}
43f08c3bdfSopenharmony_ci
44f08c3bdfSopenharmony_ci#ifdef HAVE_STRUCT_STATX_STX_DIO_MEM_ALIGN
45f08c3bdfSopenharmony_ci	/*
46f08c3bdfSopenharmony_ci	 * This test is tightly coupled to the kernel's current DIO restrictions
47f08c3bdfSopenharmony_ci	 * on block devices. The general rule of DIO needing to be aligned to the
48f08c3bdfSopenharmony_ci	 * block device's logical block size was relaxed to allow user buffers
49f08c3bdfSopenharmony_ci	 * (but not file offsets) aligned to the DMA alignment instead. See v6.0
50f08c3bdfSopenharmony_ci	 * commit bf8d08532bc1 ("iomap: add support for dma aligned direct-io") and
51f08c3bdfSopenharmony_ci	 * they are subject to further change in the future.
52f08c3bdfSopenharmony_ci	 * Also can see commit 2d985f8c6b9 ("vfs: support STATX_DIOALIGN on block devices).
53f08c3bdfSopenharmony_ci	 */
54f08c3bdfSopenharmony_ci	TST_ASSERT_ULONG(sys_bdev_dma_path, buf.stx_dio_mem_align - 1);
55f08c3bdfSopenharmony_ci	TST_ASSERT_ULONG(sys_bdev_logical_path, buf.stx_dio_offset_align);
56f08c3bdfSopenharmony_ci#else
57f08c3bdfSopenharmony_ci	tst_res(TCONF, "glibc statx struct miss stx_dio_mem_align field");
58f08c3bdfSopenharmony_ci#endif
59f08c3bdfSopenharmony_ci}
60f08c3bdfSopenharmony_ci
61f08c3bdfSopenharmony_cistatic void setup(void)
62f08c3bdfSopenharmony_ci{
63f08c3bdfSopenharmony_ci	char full_name[256];
64f08c3bdfSopenharmony_ci	char *dev_name;
65f08c3bdfSopenharmony_ci
66f08c3bdfSopenharmony_ci	strcpy(full_name, tst_device->dev);
67f08c3bdfSopenharmony_ci	dev_name = SAFE_BASENAME(full_name);
68f08c3bdfSopenharmony_ci	sprintf(sys_bdev_logical_path, "/sys/block/%s/queue/logical_block_size", dev_name);
69f08c3bdfSopenharmony_ci
70f08c3bdfSopenharmony_ci	/*
71f08c3bdfSopenharmony_ci	 * Since /sys/block/%s/queue doesn't exist for partition, we need to
72f08c3bdfSopenharmony_ci	 * use a while to search block device instead of partition.
73f08c3bdfSopenharmony_ci	 */
74f08c3bdfSopenharmony_ci	while (access(sys_bdev_logical_path, F_OK) != 0) {
75f08c3bdfSopenharmony_ci		dev_name[strlen(dev_name)-1] = '\0';
76f08c3bdfSopenharmony_ci		sprintf(sys_bdev_logical_path, "/sys/block/%s/queue/logical_block_size", dev_name);
77f08c3bdfSopenharmony_ci	}
78f08c3bdfSopenharmony_ci
79f08c3bdfSopenharmony_ci	sprintf(sys_bdev_dma_path, "/sys/block/%s/queue/dma_alignment", dev_name);
80f08c3bdfSopenharmony_ci	if (access(sys_bdev_dma_path, F_OK) != 0)
81f08c3bdfSopenharmony_ci		tst_brk(TCONF, "dma_alignment sysfs file doesn't exist");
82f08c3bdfSopenharmony_ci}
83f08c3bdfSopenharmony_ci
84f08c3bdfSopenharmony_cistatic struct tst_test test = {
85f08c3bdfSopenharmony_ci	.test_all = verify_statx,
86f08c3bdfSopenharmony_ci	.setup = setup,
87f08c3bdfSopenharmony_ci	.needs_device = 1,
88f08c3bdfSopenharmony_ci	.needs_root = 1,
89f08c3bdfSopenharmony_ci};
90