|
| 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 | + |
| 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 | + |
| 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 | +}; |
0 commit comments