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