• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 // SPDX-License-Identifier: GPL-2.0-or-later
2 /*
3  * Copyright (C) 2024 Andrea Cervesato andrea.cervesato@suse.com
4  */
5 
6 /*\
7  * [Description]
8  *
9  * This test verifies that ioctl() FICLONE feature clones file content from
10  * one file to an another.
11  *
12  * [Algorithm]
13  *
14  * - populate source file
15  * - clone source content inside destination file
16  * - verify that source content has been cloned inside destination file
17  * - write a single byte inside destination file
18  * - verify that source content didn't change while destination did
19  */
20 
21 #include "tst_test.h"
22 #include "lapi/ficlone.h"
23 
24 #define MNTPOINT "mnt"
25 #define SRCPATH MNTPOINT "/file0"
26 #define DSTPATH MNTPOINT "/file1"
27 
28 #define FILEDATA "qwerty"
29 #define FILESIZE sizeof(FILEDATA)
30 
31 static int src_fd = -1;
32 static int dst_fd = -1;
33 
run(void)34 static void run(void)
35 {
36 	char buff[FILESIZE];
37 	struct stat src_stat;
38 	struct stat dst_stat;
39 
40 	src_fd = SAFE_OPEN(SRCPATH, O_CREAT | O_RDWR, 0640);
41 	dst_fd = SAFE_OPEN(DSTPATH, O_CREAT | O_RDWR, 0640);
42 
43 	tst_res(TINFO, "Writing data inside src file");
44 
45 	SAFE_WRITE(1, src_fd, FILEDATA, FILESIZE);
46 	SAFE_FSYNC(src_fd);
47 
48 	TST_EXP_PASS(ioctl(dst_fd, FICLONE, src_fd));
49 	if (TST_RET == -1)
50 		return;
51 
52 	SAFE_FSYNC(dst_fd);
53 
54 	tst_res(TINFO, "Verifing that data is cloned between files");
55 
56 	SAFE_FSTAT(src_fd, &src_stat);
57 	SAFE_FSTAT(dst_fd, &dst_stat);
58 
59 	TST_EXP_EXPR(src_stat.st_ino != dst_stat.st_ino,
60 		"inode is different. %lu != %lu",
61 		src_stat.st_ino,
62 		dst_stat.st_ino);
63 
64 	TST_EXP_EQ_LI(src_stat.st_size, dst_stat.st_size);
65 
66 	SAFE_READ(0, dst_fd, buff, FILESIZE);
67 
68 	TST_EXP_EXPR(!strncmp(buff, FILEDATA, FILESIZE),
69 		"dst file has the src file content (\"%s\" - %ld bytes)",
70 		buff,
71 		FILESIZE);
72 
73 	tst_res(TINFO, "Writing a byte inside dst file");
74 
75 	SAFE_LSEEK(dst_fd, 0, SEEK_SET);
76 	SAFE_WRITE(SAFE_WRITE_ALL, dst_fd, "+", 1);
77 	SAFE_FSYNC(dst_fd);
78 
79 	tst_res(TINFO, "Verifing that src file content didn't change");
80 
81 	SAFE_FSTAT(src_fd, &src_stat);
82 	SAFE_FSTAT(dst_fd, &dst_stat);
83 
84 	TST_EXP_EQ_LI(dst_stat.st_size, src_stat.st_size);
85 
86 	SAFE_READ(0, src_fd, buff, FILESIZE);
87 
88 	TST_EXP_EXPR(!strncmp(buff, FILEDATA, FILESIZE),
89 		"src file content didn't change");
90 
91 	SAFE_CLOSE(src_fd);
92 	SAFE_CLOSE(dst_fd);
93 
94 	SAFE_UNLINK(SRCPATH);
95 	SAFE_UNLINK(DSTPATH);
96 }
97 
cleanup(void)98 static void cleanup(void)
99 {
100 	if (src_fd != -1)
101 		SAFE_CLOSE(src_fd);
102 
103 	if (dst_fd != -1)
104 		SAFE_CLOSE(dst_fd);
105 }
106 
107 static struct tst_test test = {
108 	.test_all = run,
109 	.cleanup = cleanup,
110 	.min_kver = "4.5",
111 	.needs_root = 1,
112 	.mount_device = 1,
113 	.mntpoint = MNTPOINT,
114 	.filesystems = (struct tst_fs []) {
115 		{.type = "btrfs"},
116 		{.type = "bcachefs"},
117 		{
118 			.type = "xfs",
119 			.min_kver = "4.16",
120 			.mkfs_ver = "mkfs.xfs >= 1.5.0",
121 			.mkfs_opts = (const char *const []) {"-m", "reflink=1", NULL},
122 		},
123 		{}
124 	}
125 };
126