xref: /aosp_15_r20/external/ltp/testcases/kernel/syscalls/statx/statx11.c (revision 49cdfc7efb34551c7342be41a7384b9c40d7cab7)
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