• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 // SPDX-License-Identifier: GPL-2.0-or-later
2 /*
3  * Copyright (c) 2019 Linaro Limited. All rights reserved.
4  * Author: Sumit Garg <sumit.garg@linaro.org>
5  */
6 
7 /*
8  * sync_file_range02
9  *
10  * It basically tests sync_file_range() to sync test file range having large
11  * dirty file pages to block device. Also, it tests all supported filesystems
12  * on a test block device.
13  */
14 
15 #define _GNU_SOURCE
16 #include <errno.h>
17 #include <stdlib.h>
18 #include <stdio.h>
19 #include <sys/types.h>
20 #include "tst_test.h"
21 #include "lapi/sync_file_range.h"
22 #include "check_sync_file_range.h"
23 
24 #define MNTPOINT		"mnt_point"
25 #define FNAME1			MNTPOINT"/test1"
26 #define FNAME2			MNTPOINT"/test2"
27 #define FNAME3			MNTPOINT"/test3"
28 #define FILE_SZ_MB		32
29 #define FILE_SZ			(FILE_SZ_MB * TST_MB)
30 #define MODE			0644
31 
32 struct testcase {
33 	char *fname;
34 	off64_t sync_off;
35 	off64_t sync_size;
36 	size_t exp_sync_size;
37 	off64_t write_off;
38 	size_t write_size_mb;
39 	const char *desc;
40 };
41 
verify_sync_file_range(struct testcase * tc)42 static void verify_sync_file_range(struct testcase *tc)
43 {
44 	int fd;
45 	unsigned long written;
46 
47 	fd = SAFE_OPEN(tc->fname, O_RDWR|O_CREAT, MODE);
48 
49 	lseek(fd, tc->write_off, SEEK_SET);
50 
51 	tst_dev_sync(fd);
52 	tst_dev_bytes_written(tst_device->dev);
53 
54 	tst_fill_fd(fd, 0, TST_MB, tc->write_size_mb);
55 
56 	TEST(sync_file_range(fd, tc->sync_off, tc->sync_size,
57 			     SYNC_FILE_RANGE_WAIT_BEFORE |
58 			     SYNC_FILE_RANGE_WRITE |
59 			     SYNC_FILE_RANGE_WAIT_AFTER));
60 
61 	if (TST_RET)
62 		tst_brk(TFAIL | TTERRNO, "sync_file_range() failed");
63 
64 	written = tst_dev_bytes_written(tst_device->dev);
65 
66 	fsync(fd);
67 
68 	SAFE_CLOSE(fd);
69 
70 	if (written >= tc->exp_sync_size)
71 		tst_res(TPASS, "%s", tc->desc);
72 	else
73 		tst_res(TFAIL, "%s: Synced %li, expected %li", tc->desc,
74 		        written, tc->exp_sync_size);
75 }
76 
77 static struct testcase testcases[] = {
78 	{FNAME1,
79 	 0, FILE_SZ,
80 	 FILE_SZ,
81 	 0, FILE_SZ_MB,
82 	 "Sync equals write"},
83 	{FNAME2,
84 	 FILE_SZ/4, FILE_SZ/2,
85 	 FILE_SZ/2,
86 	 0, FILE_SZ_MB,
87 	 "Sync inside of write"},
88 	{FNAME3,
89 	 FILE_SZ/4, FILE_SZ/2,
90 	 FILE_SZ/4,
91 	 FILE_SZ/2, FILE_SZ_MB/4,
92 	 "Sync overlaps with write"},
93 };
94 
run(unsigned int i)95 static void run(unsigned int i)
96 {
97 	verify_sync_file_range(&testcases[i]);
98 }
99 
setup(void)100 static void setup(void)
101 {
102 	if (!check_sync_file_range())
103 		tst_brk(TCONF, "sync_file_range() not supported");
104 
105 	/*
106 	 * Fat does not support sparse files, we have to pre-fill the file so
107 	 * that the zero-filled start of the file has been written to disk
108 	 * before the test starts.
109 	 */
110 	if (!strcmp(tst_device->fs_type, "vfat")) {
111 		tst_res(TINFO, "Pre-filling file");
112 		tst_fill_file(FNAME3, 0, TST_MB, FILE_SZ_MB);
113 		int fd = SAFE_OPEN(FNAME3, O_RDONLY);
114 		fsync(fd);
115 		SAFE_CLOSE(fd);
116 	}
117 }
118 
119 static struct tst_test test = {
120 	.tcnt = ARRAY_SIZE(testcases),
121 	.needs_root = 1,
122 	.mount_device = 1,
123 	.all_filesystems = 1,
124 	.dev_fs_flags = TST_FS_SKIP_FUSE,
125 	.mntpoint = MNTPOINT,
126 	.setup = setup,
127 	.test = run,
128 };
129