• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 // SPDX-License-Identifier: GPL-2.0
2 /*
3  * Copyright 2018 Google LLC
4  */
5 #include <stdlib.h>
6 #include <unistd.h>
7 #include <sys/types.h>
8 #include <dirent.h>
9 #include <sys/stat.h>
10 #include <fcntl.h>
11 #include <sys/mount.h>
12 #include <errno.h>
13 #include <sys/wait.h>
14 #include <sys/xattr.h>
15 #include <alloca.h>
16 #include <string.h>
17 #include <stdio.h>
18 #include <stdbool.h>
19 #include <stdint.h>
20 #include <linux/random.h>
21 #include <linux/unistd.h>
22 
23 #include "../../kselftest.h"
24 
25 #include "lz4.h"
26 #include "utils.h"
27 
28 #define __packed __attribute__((__packed__))
29 
30 #define TEST_FAILURE 1
31 #define TEST_SUCCESS 0
32 #define INCFS_MAX_MTREE_LEVELS 8
33 
34 #define INCFS_ROOT_INODE 0
35 
36 struct hash_block {
37 	char data[INCFS_DATA_FILE_BLOCK_SIZE];
38 };
39 
40 struct test_signature {
41 	void *data;
42 	size_t size;
43 
44 	char add_data[100];
45 	size_t add_data_size;
46 };
47 
48 struct test_file {
49 	int index;
50 	incfs_uuid_t id;
51 	char *name;
52 	off_t size;
53 	char root_hash[INCFS_MAX_HASH_SIZE];
54 	struct hash_block *mtree;
55 	int mtree_block_count;
56 	struct test_signature sig;
57 };
58 
59 struct test_files_set {
60 	struct test_file *files;
61 	int files_count;
62 };
63 
64 struct linux_dirent64 {
65 	uint64_t       d_ino;
66 	int64_t        d_off;
67 	unsigned short d_reclen;
68 	unsigned char  d_type;
69 	char	       d_name[0];
70 } __packed;
71 
72 /*
73  * The certificate below and the private key were created by calling:
74  *	openssl req -x509 -newkey rsa:4096 -keyout private.key -out cert.crt
75  *	-days 1000 -sha256 -nodes -outform PEM -subj
76  *	"/C=US/ST=WA/L=Kirkland/O=Example/OU=Org/CN=www.example.com"
77  */
78 char x509_cert[] =
79 "-----BEGIN CERTIFICATE-----\n"
80 "MIIFvzCCA6egAwIBAgIUXpwqelEljm6BBllRQGHLrls2MYgwDQYJKoZIhvcNAQEL\n"
81 "BQAwbzELMAkGA1UEBhMCVVMxEzARBgNVBAgMCldhc2hpbmd0b24xETAPBgNVBAcM\n"
82 "CEtpcmtsYW5kMRAwDgYDVQQKDAdFeGFtcGxlMQwwCgYDVQQLDANPcmcxGDAWBgNV\n"
83 "BAMMD3d3dy5leGFtcGxlLmNvbTAeFw0xOTA4MDgyMzA3MDZaFw0yMjA1MDQyMzA3\n"
84 "MDZaMG8xCzAJBgNVBAYTAlVTMRMwEQYDVQQIDApXYXNoaW5ndG9uMREwDwYDVQQH\n"
85 "DAhLaXJrbGFuZDEQMA4GA1UECgwHRXhhbXBsZTEMMAoGA1UECwwDT3JnMRgwFgYD\n"
86 "VQQDDA93d3cuZXhhbXBsZS5jb20wggIiMA0GCSqGSIb3DQEBAQUAA4ICDwAwggIK\n"
87 "AoICAQC1LuFW/lDV/GflqFMz7RDvFFgWld982ZuDJRaK55JNj+MI4RZNL61PDw43\n"
88 "NeeJtqUoVxSLS9wHURjSjD/CV5GudUOnzGfbwFlLko+jhYRT4HNFS+5ys1FEJLtA\n"
89 "uYcY4P9GHQEXYUX+ue82A2kJ91oY6G3vCQYJFiGteb6TRDICmug31x4pBfB8rOdt\n"
90 "4/NXS/Dn+S0/mJlxw34IKfqrlFjzUziRZtAWWqDcfxFDUizSggkdXIUq4GY38RAD\n"
91 "qGewNNCab3ClJDP7/M32BhSNgsIKhgtSTM2+ocfvBhwup+BjV6UbL21DPAshlolV\n"
92 "gSL1HM2jin5bi4bpFMreY0LXwFih87/6AVSfQHY9TZrombVZnMxvB7NG1NCSwDBT\n"
93 "qjjFb3oiSMugJzY+MhISM754m46fwUyHZ1ylWCLJEU8kQ5A1q9vvqMcaDa4uTGP3\n"
94 "UgC6SyVmZxG2o+AO6m8TRTCtqHN41mPTM9HK4T1UyuzVpykSc2LlYkKE517SyEiV\n"
95 "XDmotNb2myXNYHHTjRYNxkq75Lbii2I4Q4z8XtDngaIrhZqACKSqIt2CocGjx61S\n"
96 "oxKWi+LGa7B4NaCMjz1LnaOIsXn1rJDRnUWL49T42g4kOi/5QaC2JDygfefw1hAb\n"
97 "uxkq9EYUDg+w9broltiBf4rKAnw8JMySARnyPZbj0lhZK3va5wIDAQABo1MwUTAd\n"
98 "BgNVHQ4EFgQUo6JN3gY2yGbzOTNj8Al7hNB3rw0wHwYDVR0jBBgwFoAUo6JN3gY2\n"
99 "yGbzOTNj8Al7hNB3rw0wDwYDVR0TAQH/BAUwAwEB/zANBgkqhkiG9w0BAQsFAAOC\n"
100 "AgEAQb3pJqOzM4whfNVdpEOswd1EApcWNM1ps9iTlEEjDoRv9F7F1PW0uXCIpk3B\n"
101 "j5JgCmIxAcPnzj42rduRSx421hHMZhbAIWI/JL4ZSF64qlG0YrmJDXlJgSMoyst5\n"
102 "biUqeWgO7Js5udPt3zhkeA62z3hGM6dE5B3k7gHTaKKtK17+UeR9imZKsOK8GBnM\n"
103 "rxMPI6XghxxAK2OQ/r09DHDiyf/GxgOE46oknfXfMPx3HaSvDKrZUTZ+UvVbM5c2\n"
104 "5eXOgH5UO/e4llLknJK7CoP/R6G7pV44iT4t4t9FMnvCYvavAHwfR+6z5vTF3o8a\n"
105 "wd80fC8z1vfLsIPLROdzBl9rGCvv536fPiEA677CM1AZkjfT0a9DVzrE1NDvuCUF\n"
106 "0KgEdiNwux+hO6dbTyiS38yPT6TbpoWJptJmFhFkC4hGvUgoX/TI0covSyf74VRH\n"
107 "k3BHojOBMYiX1K66xoN7fhlGK8cith3L0XXPB8CgSEUPWURvm8RCaGuX2T3FZomF\n"
108 "BCnNpN+WNnN3Yf4OkjtuvtxxktUU7pfVLsUxrdpo/ph4rWm6U83VT/Zlq92aF4vW\n"
109 "QJ+7uraQFip7e+Gy9g3UJINm3B7b1C4ch/Z/upCZESOI/23sVGzkfTgOrS+23i6/\n"
110 "Vi9YW75zySC2FCa1AWMS1NmS5qfDSycJUgD6YvOUg0C54ZI=\n"
111 "-----END CERTIFICATE-----";
112 
113 char private_key[] =
114 "-----BEGIN PRIVATE KEY-----\n"
115 "MIIJQwIBADANBgkqhkiG9w0BAQEFAASCCS0wggkpAgEAAoICAQC1LuFW/lDV/Gfl\n"
116 "qFMz7RDvFFgWld982ZuDJRaK55JNj+MI4RZNL61PDw43NeeJtqUoVxSLS9wHURjS\n"
117 "jD/CV5GudUOnzGfbwFlLko+jhYRT4HNFS+5ys1FEJLtAuYcY4P9GHQEXYUX+ue82\n"
118 "A2kJ91oY6G3vCQYJFiGteb6TRDICmug31x4pBfB8rOdt4/NXS/Dn+S0/mJlxw34I\n"
119 "KfqrlFjzUziRZtAWWqDcfxFDUizSggkdXIUq4GY38RADqGewNNCab3ClJDP7/M32\n"
120 "BhSNgsIKhgtSTM2+ocfvBhwup+BjV6UbL21DPAshlolVgSL1HM2jin5bi4bpFMre\n"
121 "Y0LXwFih87/6AVSfQHY9TZrombVZnMxvB7NG1NCSwDBTqjjFb3oiSMugJzY+MhIS\n"
122 "M754m46fwUyHZ1ylWCLJEU8kQ5A1q9vvqMcaDa4uTGP3UgC6SyVmZxG2o+AO6m8T\n"
123 "RTCtqHN41mPTM9HK4T1UyuzVpykSc2LlYkKE517SyEiVXDmotNb2myXNYHHTjRYN\n"
124 "xkq75Lbii2I4Q4z8XtDngaIrhZqACKSqIt2CocGjx61SoxKWi+LGa7B4NaCMjz1L\n"
125 "naOIsXn1rJDRnUWL49T42g4kOi/5QaC2JDygfefw1hAbuxkq9EYUDg+w9broltiB\n"
126 "f4rKAnw8JMySARnyPZbj0lhZK3va5wIDAQABAoICAQCMKul/0J2e/ncub6t2t4dr\n"
127 "PnTrfCT6xKqPqciny4Ee6hr9So1jR2gvink380bd/mQFMmEdZqGhM3cdpAzLf82f\n"
128 "hu7BSNxsYIF0er0PB4MZFMJ4sMaXC+zp5/TJnP5MG/zBND0c5k8tQpEyWy8O28Jj\n"
129 "FKW/0F5P90Q0ncP20EJUS50tXgniOMsU2Prtw/UE6yZDgD0mPxsurMu66ycXSFwM\n"
130 "WqyfqEeBk7lw/AjR6Sft71W31lTbl+DclG0MN2OIKUPcxiwCRmDFKI36MDgERk1x\n"
131 "sMPfdrWRLj2ryDFTUuLAWBTOVEGWS0RdRsWWVaJCuHbKd6FLl0TW2xQbOfWDTjYC\n"
132 "Ps31ejh163qdbk7OGOZIbd83fP3jsyL+4eNzhUpeXMKhfG58mFIv4yhdZIUOpuL6\n"
133 "aqnoU9z9wEsJKj/SrKr3nw6tuTnmbXgNjun9LfTFmqqDRBYd0Okiprw6jHNM1jgA\n"
134 "GG0kC/K7r89jKymVDABwGMFCS33ynR1Tb6zG+cqgNMPw19Fy3uQuW21CjqSzCOyP\n"
135 "aEVCEUZeP+ofql5+7ZKi6Dj+EdTfeKt2ihgheHZZoaYSINb8tsnKbdJhwBfW9PFT\n"
136 "aT/hu3bnO2FPC8H2NGOqxOEeel9ALU4SFu1pOknEhiL3/mNfOQ+KgrSRDtNRlcL0\n"
137 "cto05J90u0cmqwWKlshfaQKCAQEA5dcklxs4ezyzt28NcsiyS02oZ+9TkQp6pCXV\n"
138 "kx7AwhivAmVTlJ+c6BegA5EPd7A1gknM3+EKzGpoBOqmlF45G57phVIAphAp4oCH\n"
139 "UOVtIQgM8p4EU2gtX+uNOopdYlpBQnWimXaHA2sOD9/yTbZ03j/McRH6D15+iCld\n"
140 "3880GHdZaYYbQmHoSDg39LRRO1bdS3WC0oKBD2gPi3K0b9RaZSwKzuVrmlvrLURj\n"
141 "WMZfmkGl4BsITfuoTxbWFVncG3Kb9eYkYUFZy4M2G/s849PS/HjrN7BvgpanjtVp\n"
142 "1/39APQfAYfUuBPbKYnb6F8dE0pb5cVd4uMZklAeTb3bXjOO9QKCAQEAyc4CxWXr\n"
143 "bG6Do5dGpWudQ7ucq00MR0T3MHQIu5XTn6BsPHAJ9ZgrQw9C24PXm2VEjjsrMs5T\n"
144 "rHNF9oeO39s25Za1iyJ+893icqA3h3ivCUOOoVE54BkuJK6REhkXPD5G1ubmxeBz\n"
145 "MKNehlpd/eSbJJArkzKFZ8sBtLt8i9VFhRnXSpDAbiMpCbjW+bem9MWdLmkenSnu\n"
146 "OUbnqYcJhFBCvOT7ZCHFCDNUNPfHcaReSY2EYjw0ZqtqAZD0Q+DL+RkLz7l1+/bF\n"
147 "eEwNjmjFTcwRyawqf38D4miU0H6ca16FkeSlbmM5p3HdwZK2HVYYz3FSwhox6Ebd\n"
148 "n6in42qfL4Ug6wKCAQAh9IDRWhIkErmyNdPUy1WbzmM8x5ye5t9rdLNywq5TfnYM\n"
149 "co/AezwhBax8GmgglIWzM9fykzqXLHklkMz/SlRBgl6ZdZ3m6qhlb/uNtfdDU/8l\n"
150 "sLaO4+sgKpp4tYxKRW8ytFJLPbmAhcZUDg+r73KgiuhXJAK/VoR29TWLJP9bRfaN\n"
151 "omRQkEpSsQuDOUhu7cxPo5KqKuGKNyNkxJNnmgWowLLwEfCtozrBO0M6EER7c4tf\n"
152 "6l51tuIMnSEPknD0FSB5WYCyZYcwi7fotlsuhVK8PdjyJzyyHDOw5FJ4uGsyQt55\n"
153 "yWlhsH1GS7mTQMn42Zlt/pR6OnbCqNdxQMUxy4gpAoIBAFvMbs5E0pb8nr0n72cI\n"
154 "UP2itl3mKpOw95D+94n9WcrfOt0zShSCKAvVQWCB1O5HXqwklj4CRWXI+iZu+7sx\n"
155 "CQPfTq3//ygH4x6paxkg+N6J8LPJMz6Rtb/R+QP2je9FlQvk9U1GEKArcLBFI0R/\n"
156 "XWOAgZHwBWd1nU0NjFY/qeQmIR02Q5LWQ7C8eG4X8MafriSShO6RSGCdtHwVhWq+\n"
157 "59ztfL3L7skQMFn37K3xS0LCMVpOcLfTeeFEgxjthVvG3OydPOJlGubiEbiaSEZf\n"
158 "cif/PUXKDYZMdIVzUsw0ryXykJ5qXKuizHFlv5oQtDCJKFBLgjBbLC2YluaIdekz\n"
159 "8gkCggEBAJWxS7EuB/qL7fOz0o3HRy0plR3qbwZ0pLoCz0Ii7WxraBS1yQwmxif1\n"
160 "Rgv89GyFqg1yQl3CSrMiw7oC9WxxxuiEZDO18c4KO3NTv9K4itN9OPQVBTHmEhod\n"
161 "KWcyP4/W/Sfuae77PyclSqUsAARRrKYn2fpLTS5ibaU0QZgHmdPgYDUrPr+6PHKK\n"
162 "ZfQKU2uBfuo6zoMbMmFi3UYG49j9rv4d6v+44vS1MPHV9JK/LD8YfBhgx8Pg/u6D\n"
163 "nUgipS48pkGjJr2u2Vu7Mx70vqz0Yf2neyyDbdLtkYauC4w7YKPTD0yzDJyGuAeB\n"
164 "GyPbW1yZa5vE302a1Cr0Cd7RC4AFAAw=\n"
165 "-----END PRIVATE KEY-----";
166 
get_test_files_set(void)167 struct test_files_set get_test_files_set(void)
168 {
169 	static struct test_file files[] = {
170 		{ .index = 0, .name = "file_one_byte", .size = 1 },
171 		{ .index = 1,
172 		  .name = "file_one_block",
173 		  .size = INCFS_DATA_FILE_BLOCK_SIZE },
174 		{ .index = 2,
175 		  .name = "file_one_and_a_half_blocks",
176 		  .size = INCFS_DATA_FILE_BLOCK_SIZE +
177 			  INCFS_DATA_FILE_BLOCK_SIZE / 2 },
178 		{ .index = 3,
179 		  .name = "file_three",
180 		  .size = 300 * INCFS_DATA_FILE_BLOCK_SIZE + 3 },
181 		{ .index = 4,
182 		  .name = "file_four",
183 		  .size = 400 * INCFS_DATA_FILE_BLOCK_SIZE + 7 },
184 		{ .index = 5,
185 		  .name = "file_five",
186 		  .size = 500 * INCFS_DATA_FILE_BLOCK_SIZE + 7 },
187 		{ .index = 6,
188 		  .name = "file_six",
189 		  .size = 600 * INCFS_DATA_FILE_BLOCK_SIZE + 7 },
190 		{ .index = 7,
191 		  .name = "file_seven",
192 		  .size = 700 * INCFS_DATA_FILE_BLOCK_SIZE + 7 },
193 		{ .index = 8,
194 		  .name = "file_eight",
195 		  .size = 800 * INCFS_DATA_FILE_BLOCK_SIZE + 7 },
196 		{ .index = 9,
197 		  .name = "file_nine",
198 		  .size = 900 * INCFS_DATA_FILE_BLOCK_SIZE + 7 },
199 		{ .index = 10, .name = "file_big", .size = 500 * 1024 * 1024 }
200 	};
201 	return (struct test_files_set){ .files = files,
202 					.files_count = ARRAY_SIZE(files) };
203 }
204 
get_small_test_files_set(void)205 struct test_files_set get_small_test_files_set(void)
206 {
207 	static struct test_file files[] = {
208 		{ .index = 0, .name = "file_one_byte", .size = 1 },
209 		{ .index = 1,
210 		  .name = "file_one_block",
211 		  .size = INCFS_DATA_FILE_BLOCK_SIZE },
212 		{ .index = 2,
213 		  .name = "file_one_and_a_half_blocks",
214 		  .size = INCFS_DATA_FILE_BLOCK_SIZE +
215 			  INCFS_DATA_FILE_BLOCK_SIZE / 2 },
216 		{ .index = 3,
217 		  .name = "file_three",
218 		  .size = 300 * INCFS_DATA_FILE_BLOCK_SIZE + 3 },
219 		{ .index = 4,
220 		  .name = "file_four",
221 		  .size = 400 * INCFS_DATA_FILE_BLOCK_SIZE + 7 }
222 	};
223 	return (struct test_files_set){ .files = files,
224 					.files_count = ARRAY_SIZE(files) };
225 }
226 
get_file_block_seed(int file,int block)227 static int get_file_block_seed(int file, int block)
228 {
229 	return 7919 * file + block;
230 }
231 
min(loff_t a,loff_t b)232 static loff_t min(loff_t a, loff_t b)
233 {
234 	return a < b ? a : b;
235 }
236 
flush_and_fork(void)237 static pid_t flush_and_fork(void)
238 {
239 	fflush(stdout);
240 	return fork();
241 }
242 
print_error(char * msg)243 static void print_error(char *msg)
244 {
245 	ksft_print_msg("%s: %s\n", msg, strerror(errno));
246 }
247 
wait_for_process(pid_t pid)248 static int wait_for_process(pid_t pid)
249 {
250 	int status;
251 	int wait_res;
252 
253 	wait_res = waitpid(pid, &status, 0);
254 	if (wait_res <= 0) {
255 		print_error("Can't wait for the child");
256 		return -EINVAL;
257 	}
258 	if (!WIFEXITED(status)) {
259 		ksft_print_msg("Unexpected child status pid=%d\n", pid);
260 		return -EINVAL;
261 	}
262 	status = WEXITSTATUS(status);
263 	if (status != 0)
264 		return status;
265 	return 0;
266 }
267 
rnd_buf(uint8_t * data,size_t len,unsigned int seed)268 static void rnd_buf(uint8_t *data, size_t len, unsigned int seed)
269 {
270 	int i;
271 
272 	for (i = 0; i < len; i++) {
273 		seed = 1103515245 * seed + 12345;
274 		data[i] = (uint8_t)(seed >> (i % 13));
275 	}
276 }
277 
bin2hex(char * dst,const void * src,size_t count)278 char *bin2hex(char *dst, const void *src, size_t count)
279 {
280 	const unsigned char *_src = src;
281 	static const char hex_asc[] = "0123456789abcdef";
282 
283 	while (count--) {
284 		unsigned char x = *_src++;
285 
286 		*dst++ = hex_asc[(x & 0xf0) >> 4];
287 		*dst++ = hex_asc[(x & 0x0f)];
288 	}
289 	*dst = 0;
290 	return dst;
291 }
292 
get_index_filename(char * mnt_dir,incfs_uuid_t id)293 static char *get_index_filename(char *mnt_dir, incfs_uuid_t id)
294 {
295 	char path[FILENAME_MAX];
296 	char str_id[1 + 2 * sizeof(id)];
297 
298 	bin2hex(str_id, id.bytes, sizeof(id.bytes));
299 	snprintf(path, ARRAY_SIZE(path), "%s/.index/%s", mnt_dir, str_id);
300 
301 	return strdup(path);
302 }
303 
open_file_by_id(char * mnt_dir,incfs_uuid_t id)304 int open_file_by_id(char *mnt_dir, incfs_uuid_t id)
305 {
306 	char *path = get_index_filename(mnt_dir, id);
307 	int fd = open(path, O_RDWR);
308 
309 	free(path);
310 	if (fd < 0) {
311 		print_error("Can't open file by id.");
312 		return -errno;
313 	}
314 
315 	return fd;
316 }
317 
get_file_attr(char * mnt_dir,incfs_uuid_t id,char * value,int size)318 int get_file_attr(char *mnt_dir, incfs_uuid_t id, char *value, int size)
319 {
320 	char *path = get_index_filename(mnt_dir, id);
321 	int res;
322 
323 	res = getxattr(path, INCFS_XATTR_METADATA_NAME, value, size);
324 	if (res < 0)
325 		res = -errno;
326 
327 	free(path);
328 	return res;
329 }
330 
same_id(incfs_uuid_t * id1,incfs_uuid_t * id2)331 static bool same_id(incfs_uuid_t *id1, incfs_uuid_t *id2)
332 {
333 	return !memcmp(id1->bytes, id2->bytes, sizeof(id1->bytes));
334 }
335 
emit_test_blocks(char * mnt_dir,struct test_file * file,int blocks[],int count)336 static int emit_test_blocks(char *mnt_dir, struct test_file *file,
337 			int blocks[], int count)
338 {
339 	uint8_t data[INCFS_DATA_FILE_BLOCK_SIZE];
340 	uint8_t comp_data[2 * INCFS_DATA_FILE_BLOCK_SIZE];
341 	int block_count = (count > 32) ? 32 : count;
342 	int data_buf_size = 2 * INCFS_DATA_FILE_BLOCK_SIZE * block_count;
343 	uint8_t *data_buf = malloc(data_buf_size);
344 	uint8_t *current_data = data_buf;
345 	uint8_t *data_end = data_buf + data_buf_size;
346 	struct incfs_new_data_block *block_buf =
347 		calloc(block_count, sizeof(*block_buf));
348 	ssize_t write_res = 0;
349 	int fd;
350 	int error = 0;
351 	int i = 0;
352 	int blocks_written = 0;
353 
354 	fd = open_file_by_id(mnt_dir, file->id);
355 	if (fd <= 0) {
356 		error = -errno;
357 		goto out;
358 	}
359 
360 	for (i = 0; i < block_count; i++) {
361 		int block_index = blocks[i];
362 		bool compress = (file->index + block_index) % 2 == 0;
363 		int seed = get_file_block_seed(file->index, block_index);
364 		off_t block_offset =
365 			((off_t)block_index) * INCFS_DATA_FILE_BLOCK_SIZE;
366 		size_t block_size = 0;
367 
368 		if (block_offset > file->size) {
369 			error = -EINVAL;
370 			break;
371 		}
372 		if (file->size - block_offset >
373 			INCFS_DATA_FILE_BLOCK_SIZE)
374 			block_size = INCFS_DATA_FILE_BLOCK_SIZE;
375 		else
376 			block_size = file->size - block_offset;
377 
378 		rnd_buf(data, block_size, seed);
379 		if (compress) {
380 			size_t comp_size = LZ4_compress_default(
381 				(char *)data, (char *)comp_data, block_size,
382 				ARRAY_SIZE(comp_data));
383 
384 			if (comp_size <= 0) {
385 				error = -EBADMSG;
386 				break;
387 			}
388 			if (current_data + comp_size > data_end) {
389 				error = -ENOMEM;
390 				break;
391 			}
392 			memcpy(current_data, comp_data, comp_size);
393 			block_size = comp_size;
394 			block_buf[i].compression = COMPRESSION_LZ4;
395 		} else {
396 			if (current_data + block_size > data_end) {
397 				error = -ENOMEM;
398 				break;
399 			}
400 			memcpy(current_data, data, block_size);
401 			block_buf[i].compression = COMPRESSION_NONE;
402 		}
403 
404 		block_buf[i].block_index = block_index;
405 		block_buf[i].data_len = block_size;
406 		block_buf[i].data = ptr_to_u64(current_data);
407 		block_buf[i].compression =
408 			compress ? COMPRESSION_LZ4 : COMPRESSION_NONE;
409 		current_data += block_size;
410 	}
411 
412 	if (!error) {
413 		write_res = write(fd, block_buf, sizeof(*block_buf) * i);
414 		if (write_res < 0)
415 			error = -errno;
416 		else
417 			blocks_written = write_res / sizeof(*block_buf);
418 	}
419 	if (error) {
420 		ksft_print_msg(
421 			"Writing data block error. Write returned: %d. Error:%s\n",
422 			write_res, strerror(-error));
423 	}
424 
425 out:
426 	free(block_buf);
427 	free(data_buf);
428 	close(fd);
429 	return (error < 0) ? error : blocks_written;
430 }
431 
emit_test_block(char * mnt_dir,struct test_file * file,int block_index)432 static int emit_test_block(char *mnt_dir, struct test_file *file,
433 				int block_index)
434 {
435 	int res = emit_test_blocks(mnt_dir, file, &block_index, 1);
436 
437 	if (res == 0)
438 		return -EINVAL;
439 	if (res == 1)
440 		return 0;
441 	return res;
442 }
443 
shuffle(int array[],int count,unsigned int seed)444 static void shuffle(int array[], int count, unsigned int seed)
445 {
446 	int i;
447 
448 	for (i = 0; i < count - 1; i++) {
449 		int items_left = count - i;
450 		int shuffle_index;
451 		int v;
452 
453 		seed = 1103515245 * seed + 12345;
454 		shuffle_index = i + seed % items_left;
455 
456 		v = array[shuffle_index];
457 		array[shuffle_index] = array[i];
458 		array[i] = v;
459 	}
460 }
461 
emit_test_file_data(char * mount_dir,struct test_file * file)462 static int emit_test_file_data(char *mount_dir, struct test_file *file)
463 {
464 	int i;
465 	int block_cnt = 1 + (file->size - 1) / INCFS_DATA_FILE_BLOCK_SIZE;
466 	int *block_indexes = NULL;
467 	int result = 0;
468 	int blocks_written = 0;
469 
470 	if (file->size == 0)
471 		return 0;
472 
473 	block_indexes = calloc(block_cnt, sizeof(*block_indexes));
474 	for (i = 0; i < block_cnt; i++)
475 		block_indexes[i] = i;
476 	shuffle(block_indexes, block_cnt, file->index);
477 
478 	for (i = 0; i < block_cnt; i += blocks_written) {
479 		blocks_written = emit_test_blocks(mount_dir, file,
480 					block_indexes + i, block_cnt - i);
481 		if (blocks_written < 0) {
482 			result = blocks_written;
483 			goto out;
484 		}
485 		if (blocks_written == 0) {
486 			result = -EIO;
487 			goto out;
488 		}
489 	}
490 out:
491 	free(block_indexes);
492 	return result;
493 }
494 
read_whole_file(char * filename)495 static loff_t read_whole_file(char *filename)
496 {
497 	int fd = -1;
498 	loff_t result;
499 	loff_t bytes_read = 0;
500 	uint8_t buff[16 * 1024];
501 
502 	fd = open(filename, O_RDONLY);
503 	if (fd <= 0)
504 		return fd;
505 
506 	while (1) {
507 		int read_result = read(fd, buff, ARRAY_SIZE(buff));
508 
509 		if (read_result < 0) {
510 			print_error("Error during reading from a file.");
511 			result = -errno;
512 			goto cleanup;
513 		} else if (read_result == 0)
514 			break;
515 
516 		bytes_read += read_result;
517 	}
518 	result = bytes_read;
519 
520 cleanup:
521 	close(fd);
522 	return result;
523 }
524 
read_test_file(uint8_t * buf,size_t len,char * filename,int block_idx)525 static int read_test_file(uint8_t *buf, size_t len, char *filename,
526 			  int block_idx)
527 {
528 	int fd = -1;
529 	int result;
530 	int bytes_read = 0;
531 	size_t bytes_to_read = len;
532 	off_t offset = ((off_t)block_idx) * INCFS_DATA_FILE_BLOCK_SIZE;
533 
534 	fd = open(filename, O_RDONLY);
535 	if (fd <= 0)
536 		return fd;
537 
538 	if (lseek(fd, offset, SEEK_SET) != offset) {
539 		print_error("Seek error");
540 		return -errno;
541 	}
542 
543 	while (bytes_read < bytes_to_read) {
544 		int read_result =
545 			read(fd, buf + bytes_read, bytes_to_read - bytes_read);
546 		if (read_result < 0) {
547 			result = -errno;
548 			goto cleanup;
549 		} else if (read_result == 0)
550 			break;
551 
552 		bytes_read += read_result;
553 	}
554 	result = bytes_read;
555 
556 cleanup:
557 	close(fd);
558 	return result;
559 }
560 
create_backing_dir(char * mount_dir)561 static char *create_backing_dir(char *mount_dir)
562 {
563 	struct stat st;
564 	char backing_dir_name[255];
565 
566 	snprintf(backing_dir_name, ARRAY_SIZE(backing_dir_name), "%s-src",
567 		 mount_dir);
568 
569 	if (stat(backing_dir_name, &st) == 0) {
570 		if (S_ISDIR(st.st_mode)) {
571 			int error = delete_dir_tree(backing_dir_name);
572 
573 			if (error) {
574 				ksft_print_msg(
575 				      "Can't delete existing backing dir. %d\n",
576 				      error);
577 				return NULL;
578 			}
579 		} else {
580 			if (unlink(backing_dir_name)) {
581 				print_error("Can't clear backing dir");
582 				return NULL;
583 			}
584 		}
585 	}
586 
587 	if (mkdir(backing_dir_name, 0777)) {
588 		if (errno != EEXIST) {
589 			print_error("Can't open/create backing dir");
590 			return NULL;
591 		}
592 	}
593 
594 	return strdup(backing_dir_name);
595 }
596 
validate_test_file_content_with_seed(char * mount_dir,struct test_file * file,unsigned int shuffle_seed)597 static int validate_test_file_content_with_seed(char *mount_dir,
598 						struct test_file *file,
599 						unsigned int shuffle_seed)
600 {
601 	int error = -1;
602 	char *filename = concat_file_name(mount_dir, file->name);
603 	off_t size = file->size;
604 	loff_t actual_size = get_file_size(filename);
605 	int block_cnt = 1 + (size - 1) / INCFS_DATA_FILE_BLOCK_SIZE;
606 	int *block_indexes = NULL;
607 	int i;
608 
609 	block_indexes = alloca(sizeof(int) * block_cnt);
610 	for (i = 0; i < block_cnt; i++)
611 		block_indexes[i] = i;
612 
613 	if (shuffle_seed != 0)
614 		shuffle(block_indexes, block_cnt, shuffle_seed);
615 
616 	if (actual_size != size) {
617 		ksft_print_msg(
618 			"File size doesn't match. name: %s expected size:%ld actual size:%ld\n",
619 			filename, size, actual_size);
620 		error = -1;
621 		goto failure;
622 	}
623 
624 	for (i = 0; i < block_cnt; i++) {
625 		int block_idx = block_indexes[i];
626 		uint8_t expected_block[INCFS_DATA_FILE_BLOCK_SIZE];
627 		uint8_t actual_block[INCFS_DATA_FILE_BLOCK_SIZE];
628 		int seed = get_file_block_seed(file->index, block_idx);
629 		size_t bytes_to_compare = min(
630 			(off_t)INCFS_DATA_FILE_BLOCK_SIZE,
631 			size - ((off_t)block_idx) * INCFS_DATA_FILE_BLOCK_SIZE);
632 		int read_result =
633 			read_test_file(actual_block, INCFS_DATA_FILE_BLOCK_SIZE,
634 				       filename, block_idx);
635 		if (read_result < 0) {
636 			ksft_print_msg(
637 				"Error reading block %d from file %s. Error: %s\n",
638 				block_idx, filename, strerror(-read_result));
639 			error = read_result;
640 			goto failure;
641 		}
642 		rnd_buf(expected_block, INCFS_DATA_FILE_BLOCK_SIZE, seed);
643 		if (memcmp(expected_block, actual_block, bytes_to_compare)) {
644 			ksft_print_msg(
645 				"File contents don't match. name: %s block:%d\n",
646 				file->name, block_idx);
647 			error = -2;
648 			goto failure;
649 		}
650 	}
651 	free(filename);
652 	return 0;
653 
654 failure:
655 	free(filename);
656 	return error;
657 }
658 
validate_test_file_content(char * mount_dir,struct test_file * file)659 static int validate_test_file_content(char *mount_dir, struct test_file *file)
660 {
661 	return validate_test_file_content_with_seed(mount_dir, file, 0);
662 }
663 
data_producer(char * mount_dir,struct test_files_set * test_set)664 static int data_producer(char *mount_dir, struct test_files_set *test_set)
665 {
666 	int ret = 0;
667 	int timeout_ms = 1000;
668 	struct incfs_pending_read_info prs[100] = {};
669 	int prs_size = ARRAY_SIZE(prs);
670 	int fd = open_commands_file(mount_dir);
671 
672 	if (fd < 0)
673 		return -errno;
674 
675 	while ((ret = wait_for_pending_reads(fd, timeout_ms, prs, prs_size)) >
676 	       0) {
677 		int read_count = ret;
678 		int i;
679 
680 		for (i = 0; i < read_count; i++) {
681 			int j = 0;
682 			struct test_file *file = NULL;
683 
684 			for (j = 0; j < test_set->files_count; j++) {
685 				bool same = same_id(&(test_set->files[j].id),
686 					&(prs[i].file_id));
687 
688 				if (same) {
689 					file = &test_set->files[j];
690 					break;
691 				}
692 			}
693 			if (!file) {
694 				ksft_print_msg(
695 					"Unknown file in pending reads.\n");
696 				break;
697 			}
698 
699 			ret = emit_test_block(mount_dir, file,
700 				prs[i].block_index);
701 			if (ret < 0) {
702 				ksft_print_msg("Emitting test data error: %s\n",
703 						strerror(-ret));
704 				break;
705 			}
706 		}
707 	}
708 	close(fd);
709 	return ret;
710 }
711 
build_mtree(struct test_file * file)712 static int build_mtree(struct test_file *file)
713 {
714 	char data[INCFS_DATA_FILE_BLOCK_SIZE] = {};
715 	const int digest_size = SHA256_DIGEST_SIZE;
716 	const int hash_per_block = INCFS_DATA_FILE_BLOCK_SIZE / digest_size;
717 	int block_count = 0;
718 	int hash_block_count = 0;
719 	int total_tree_block_count = 0;
720 	int tree_lvl_index[INCFS_MAX_MTREE_LEVELS] = {};
721 	int tree_lvl_count[INCFS_MAX_MTREE_LEVELS] = {};
722 	int levels_count = 0;
723 	char data_to_sign[256] = {};
724 	int sig_data_size;
725 	int i, level;
726 
727 	if (file->size == 0)
728 		return 0;
729 
730 	block_count = 1 + (file->size - 1) / INCFS_DATA_FILE_BLOCK_SIZE;
731 	hash_block_count = block_count;
732 	for (i = 0; hash_block_count > 1; i++) {
733 		hash_block_count = (hash_block_count + hash_per_block - 1)
734 			/ hash_per_block;
735 		tree_lvl_count[i] = hash_block_count;
736 		total_tree_block_count += hash_block_count;
737 	}
738 	levels_count = i;
739 
740 	for (i = 0; i < levels_count; i++) {
741 		int prev_lvl_base = (i == 0) ? total_tree_block_count :
742 			tree_lvl_index[i - 1];
743 
744 		tree_lvl_index[i] = prev_lvl_base - tree_lvl_count[i];
745 	}
746 
747 	file->mtree_block_count = total_tree_block_count;
748 	if (block_count == 1) {
749 		int seed = get_file_block_seed(file->index, 0);
750 
751 		rnd_buf((uint8_t *)data, file->size, seed);
752 		sha256(data, file->size, file->root_hash);
753 		return 0;
754 	}
755 
756 	file->mtree = calloc(total_tree_block_count, sizeof(*file->mtree));
757 	/* Build level 0 hashes. */
758 	for (i = 0; i < block_count; i++) {
759 		off_t offset = i * INCFS_DATA_FILE_BLOCK_SIZE;
760 		size_t block_size = INCFS_DATA_FILE_BLOCK_SIZE;
761 		int block_index = tree_lvl_index[0] +
762 					i / hash_per_block;
763 		int block_off = (i % hash_per_block) * digest_size;
764 		int seed = get_file_block_seed(file->index, i);
765 		char *hash_ptr = file->mtree[block_index].data + block_off;
766 
767 		if (file->size - offset < block_size)
768 			block_size = file->size - offset;
769 
770 		rnd_buf((uint8_t *)data, block_size, seed);
771 		sha256(data, block_size, hash_ptr);
772 	}
773 
774 	/* Build higher levels of hash tree. */
775 	for (level = 1; level < levels_count; level++) {
776 		int prev_lvl_base = tree_lvl_index[level - 1];
777 		int prev_lvl_count = tree_lvl_count[level - 1];
778 
779 		for (i = 0; i < prev_lvl_count; i++) {
780 			int block_index =
781 				i / hash_per_block + tree_lvl_index[level];
782 			int block_off = (i % hash_per_block) * digest_size;
783 			char *hash_ptr =
784 				file->mtree[block_index].data + block_off;
785 
786 			sha256(file->mtree[i + prev_lvl_base].data,
787 			       INCFS_DATA_FILE_BLOCK_SIZE, hash_ptr);
788 		}
789 	}
790 
791 	/* Calculate root hash from the top block */
792 	sha256(file->mtree[0].data,
793 		INCFS_DATA_FILE_BLOCK_SIZE, file->root_hash);
794 
795 	/* Calculating digital signature */
796 	snprintf(file->sig.add_data, sizeof(file->sig.add_data), "%ld",
797 		 file->size);
798 	memcpy(data_to_sign, file->root_hash, SHA256_DIGEST_SIZE);
799 	memcpy(data_to_sign + SHA256_DIGEST_SIZE, file->sig.add_data,
800 		strlen(file->sig.add_data));
801 	sig_data_size = SHA256_DIGEST_SIZE + strlen(file->sig.add_data);
802 	if (!sign_pkcs7(data_to_sign, sig_data_size, private_key, x509_cert,
803 		       &file->sig.data, &file->sig.size)) {
804 		ksft_print_msg("Signing failed.\n");
805 		return -EINVAL;
806 	}
807 
808 	return 0;
809 }
810 
load_hash_tree(const char * mount_dir,struct test_file * file)811 static int load_hash_tree(const char *mount_dir, struct test_file *file)
812 {
813 	int err;
814 	int i;
815 	int fd;
816 
817 	size_t blocks_size =
818 		file->mtree_block_count * sizeof(struct incfs_new_data_block);
819 	struct incfs_new_data_block *blocks = NULL;
820 	char *file_path;
821 
822 	if (blocks_size == 0)
823 		return 0;
824 
825 	blocks = malloc(blocks_size);
826 	if (!blocks)
827 		return -ENOMEM;
828 
829 	for (i = 0; i < file->mtree_block_count; i++) {
830 		blocks[i] = (struct incfs_new_data_block){
831 			.block_index = i,
832 			.data_len = INCFS_DATA_FILE_BLOCK_SIZE,
833 			.data = ptr_to_u64(file->mtree[i].data),
834 			.flags = INCFS_BLOCK_FLAGS_HASH
835 		};
836 	}
837 
838 	file_path  = concat_file_name(mount_dir, file->name);
839 	fd = open(file_path, O_RDWR);
840 	free(file_path);
841 	if (fd < 0) {
842 		err = errno;
843 		goto failure;
844 	}
845 
846 	err = write(fd, blocks, blocks_size);
847 	close(fd);
848 
849 	if (err < blocks_size)
850 		err = errno;
851 	else {
852 		err = 0;
853 		free(file->mtree);
854 	}
855 
856 failure:
857 	free(blocks);
858 	return err;
859 }
860 
cant_touch_index_test(char * mount_dir)861 static int cant_touch_index_test(char *mount_dir)
862 {
863 	char *file_name = "test_file";
864 	int file_size = 123;
865 	incfs_uuid_t file_id;
866 	char *index_path = concat_file_name(mount_dir, ".index");
867 	char *subdir = concat_file_name(index_path, "subdir");
868 	char *dst_name = concat_file_name(mount_dir, "something");
869 	char *filename_in_index = NULL;
870 	char *file_path = concat_file_name(mount_dir, file_name);
871 	char *backing_dir;
872 	int cmd_fd = -1;
873 	int err;
874 
875 	backing_dir = create_backing_dir(mount_dir);
876 	if (!backing_dir)
877 		goto failure;
878 
879 	/* Mount FS and release the backing file. */
880 	if (mount_fs(mount_dir, backing_dir, 50) != 0)
881 		goto failure;
882 	free(backing_dir);
883 
884 	cmd_fd = open_commands_file(mount_dir);
885 	if (cmd_fd < 0)
886 		goto failure;
887 
888 
889 	err = mkdir(subdir, 0777);
890 	if (err == 0 || errno != EBUSY) {
891 		print_error("Shouldn't be able to crate subdir in index\n");
892 		goto failure;
893 	}
894 
895 	err = emit_file(cmd_fd, ".index", file_name, &file_id,
896 				file_size, NULL);
897 	if (err != -EBUSY) {
898 		print_error("Shouldn't be able to crate a file in index\n");
899 		goto failure;
900 	}
901 
902 	err = emit_file(cmd_fd, NULL, file_name, &file_id,
903 				file_size, NULL);
904 	if (err < 0)
905 		goto failure;
906 	filename_in_index = get_index_filename(mount_dir, file_id);
907 
908 	err = unlink(filename_in_index);
909 	if (err == 0 || errno != EBUSY) {
910 		print_error("Shouldn't be delete from index\n");
911 		goto failure;
912 	}
913 
914 
915 	err = rename(filename_in_index, dst_name);
916 	if (err == 0 || errno != EBUSY) {
917 		print_error("Shouldn't be able to move from index\n");
918 		goto failure;
919 	}
920 
921 	free(filename_in_index);
922 	filename_in_index = concat_file_name(index_path, "abc");
923 	err = link(file_path, filename_in_index);
924 	if (err == 0 || errno != EBUSY) {
925 		print_error("Shouldn't be able to link inside index\n");
926 		goto failure;
927 	}
928 
929 	close(cmd_fd);
930 	free(subdir);
931 	free(index_path);
932 	free(dst_name);
933 	free(filename_in_index);
934 	if (umount(mount_dir) != 0) {
935 		print_error("Can't unmout FS");
936 		goto failure;
937 	}
938 
939 	return TEST_SUCCESS;
940 
941 failure:
942 	free(subdir);
943 	free(dst_name);
944 	free(index_path);
945 	free(filename_in_index);
946 	close(cmd_fd);
947 	umount(mount_dir);
948 	return TEST_FAILURE;
949 }
950 
iterate_directory(char * dir_to_iterate,bool root,int file_count)951 static bool iterate_directory(char *dir_to_iterate, bool root, int file_count)
952 {
953 	struct expected_name {
954 		const char *name;
955 		bool root_only;
956 		bool found;
957 	} names[] = {
958 		{INCFS_LOG_FILENAME, true, false},
959 		{INCFS_PENDING_READS_FILENAME, true, false},
960 		{".index", true, false},
961 		{"..", false, false},
962 		{".", false, false},
963 	};
964 
965 	bool pass = true, found;
966 	int i;
967 
968 	/* Test directory iteration */
969 	int fd = open(dir_to_iterate, O_RDONLY | O_DIRECTORY);
970 
971 	if (fd < 0) {
972 		print_error("Can't open directory\n");
973 		return false;
974 	}
975 
976 	for (;;) {
977 		/* Enough space for one dirent - no name over 30 */
978 		char buf[sizeof(struct linux_dirent64) + NAME_MAX];
979 		struct linux_dirent64 *dirent = (struct linux_dirent64 *) buf;
980 		int nread;
981 		int i;
982 
983 		for (i = 0; i < NAME_MAX; ++i) {
984 			nread = syscall(__NR_getdents64, fd, buf,
985 					 sizeof(struct linux_dirent64) + i);
986 
987 			if (nread >= 0)
988 				break;
989 			if (errno != EINVAL)
990 				break;
991 		}
992 
993 		if (nread == 0)
994 			break;
995 		if (nread < 0) {
996 			print_error("Error iterating directory\n");
997 			pass = false;
998 			goto failure;
999 		}
1000 
1001 		/* Expected size is rounded up to 8 byte boundary. Not sure if
1002 		 * this is universal truth or just happenstance, but useful test
1003 		 * for the moment
1004 		 */
1005 		if (nread != (((sizeof(struct linux_dirent64)
1006 				+ strlen(dirent->d_name) + 1) + 7) & ~7)) {
1007 			print_error("Wrong dirent size");
1008 			pass = false;
1009 			goto failure;
1010 		}
1011 
1012 		found = false;
1013 		for (i = 0; i < sizeof(names) / sizeof(*names); ++i)
1014 			if (!strcmp(dirent->d_name, names[i].name)) {
1015 				if (names[i].root_only && !root) {
1016 					print_error("Root file error");
1017 					pass = false;
1018 					goto failure;
1019 				}
1020 
1021 				if (names[i].found) {
1022 					print_error("File appears twice");
1023 					pass = false;
1024 					goto failure;
1025 				}
1026 
1027 				names[i].found = true;
1028 				found = true;
1029 				break;
1030 			}
1031 
1032 		if (!found)
1033 			--file_count;
1034 	}
1035 
1036 	for (i = 0; i < sizeof(names) / sizeof(*names); ++i) {
1037 		if (!names[i].found)
1038 			if (root || !names[i].root_only) {
1039 				print_error("Expected file not present");
1040 				pass = false;
1041 				goto failure;
1042 			}
1043 	}
1044 
1045 	if (file_count) {
1046 		print_error("Wrong number of files\n");
1047 		pass = false;
1048 		goto failure;
1049 	}
1050 
1051 failure:
1052 	close(fd);
1053 	return pass;
1054 }
1055 
basic_file_ops_test(char * mount_dir)1056 static int basic_file_ops_test(char *mount_dir)
1057 {
1058 	struct test_files_set test = get_test_files_set();
1059 	const int file_num = test.files_count;
1060 	char *subdir1 = concat_file_name(mount_dir, "subdir1");
1061 	char *subdir2 = concat_file_name(mount_dir, "subdir2");
1062 	char *backing_dir;
1063 	int cmd_fd = -1;
1064 	int i, err;
1065 
1066 	backing_dir = create_backing_dir(mount_dir);
1067 	if (!backing_dir)
1068 		goto failure;
1069 
1070 	/* Mount FS and release the backing file. */
1071 	if (mount_fs(mount_dir, backing_dir, 50) != 0)
1072 		goto failure;
1073 	free(backing_dir);
1074 
1075 	cmd_fd = open_commands_file(mount_dir);
1076 	if (cmd_fd < 0)
1077 		goto failure;
1078 
1079 	err = mkdir(subdir1, 0777);
1080 	if (err < 0 && errno != EEXIST) {
1081 		print_error("Can't create subdir1\n");
1082 		goto failure;
1083 	}
1084 
1085 	err = mkdir(subdir2, 0777);
1086 	if (err < 0 && errno != EEXIST) {
1087 		print_error("Can't create subdir2\n");
1088 		goto failure;
1089 	}
1090 
1091 	/* Create all test files in subdir1 directory */
1092 	for (i = 0; i < file_num; i++) {
1093 		struct test_file *file = &test.files[i];
1094 		loff_t size;
1095 		char *file_path = concat_file_name(subdir1, file->name);
1096 
1097 		err = emit_file(cmd_fd, "subdir1", file->name, &file->id,
1098 				     file->size, NULL);
1099 		if (err < 0)
1100 			goto failure;
1101 
1102 		size = get_file_size(file_path);
1103 		free(file_path);
1104 		if (size != file->size) {
1105 			ksft_print_msg("Wrong size %lld of %s.\n",
1106 				size, file->name);
1107 			goto failure;
1108 		}
1109 	}
1110 
1111 	if (!iterate_directory(subdir1, false, file_num))
1112 		goto failure;
1113 
1114 	/* Link the files to subdir2 */
1115 	for (i = 0; i < file_num; i++) {
1116 		struct test_file *file = &test.files[i];
1117 		char *src_name = concat_file_name(subdir1, file->name);
1118 		char *dst_name = concat_file_name(subdir2, file->name);
1119 		loff_t size;
1120 
1121 		err = link(src_name, dst_name);
1122 		if (err < 0) {
1123 			print_error("Can't move file\n");
1124 			goto failure;
1125 		}
1126 
1127 		size = get_file_size(dst_name);
1128 		if (size != file->size) {
1129 			ksft_print_msg("Wrong size %lld of %s.\n",
1130 				size, file->name);
1131 			goto failure;
1132 		}
1133 		free(src_name);
1134 		free(dst_name);
1135 	}
1136 
1137 	/* Move the files from subdir2 to the mount dir */
1138 	for (i = 0; i < file_num; i++) {
1139 		struct test_file *file = &test.files[i];
1140 		char *src_name = concat_file_name(subdir2, file->name);
1141 		char *dst_name = concat_file_name(mount_dir, file->name);
1142 		loff_t size;
1143 
1144 		err = rename(src_name, dst_name);
1145 		if (err < 0) {
1146 			print_error("Can't move file\n");
1147 			goto failure;
1148 		}
1149 
1150 		size = get_file_size(dst_name);
1151 		if (size != file->size) {
1152 			ksft_print_msg("Wrong size %lld of %s.\n",
1153 				size, file->name);
1154 			goto failure;
1155 		}
1156 		free(src_name);
1157 		free(dst_name);
1158 	}
1159 
1160 	/* +2 because there are 2 subdirs */
1161 	if (!iterate_directory(mount_dir, true, file_num + 2))
1162 		goto failure;
1163 
1164 	/* Open and close all files from the mount dir */
1165 	for (i = 0; i < file_num; i++) {
1166 		struct test_file *file = &test.files[i];
1167 		char *path = concat_file_name(mount_dir, file->name);
1168 		int fd;
1169 
1170 		fd = open(path, O_RDWR);
1171 		free(path);
1172 		if (fd <= 0) {
1173 			print_error("Can't open file");
1174 			goto failure;
1175 		}
1176 		if (close(fd)) {
1177 			print_error("Can't close file");
1178 			goto failure;
1179 		}
1180 	}
1181 
1182 	/* Delete all files from the mount dir */
1183 	for (i = 0; i < file_num; i++) {
1184 		struct test_file *file = &test.files[i];
1185 		char *path = concat_file_name(mount_dir, file->name);
1186 
1187 		err = unlink(path);
1188 		free(path);
1189 		if (err < 0) {
1190 			print_error("Can't unlink file");
1191 			goto failure;
1192 		}
1193 	}
1194 
1195 	err = delete_dir_tree(subdir1);
1196 	if (err) {
1197 		ksft_print_msg("Error deleting subdir1 %d", err);
1198 		goto failure;
1199 	}
1200 
1201 	err = rmdir(subdir2);
1202 	if (err) {
1203 		print_error("Error deleting subdir2");
1204 		goto failure;
1205 	}
1206 
1207 	close(cmd_fd);
1208 	cmd_fd = -1;
1209 	if (umount(mount_dir) != 0) {
1210 		print_error("Can't unmout FS");
1211 		goto failure;
1212 	}
1213 
1214 	return TEST_SUCCESS;
1215 
1216 failure:
1217 	close(cmd_fd);
1218 	umount(mount_dir);
1219 	return TEST_FAILURE;
1220 }
1221 
dynamic_files_and_data_test(char * mount_dir)1222 static int dynamic_files_and_data_test(char *mount_dir)
1223 {
1224 	struct test_files_set test = get_test_files_set();
1225 	const int file_num = test.files_count;
1226 	const int missing_file_idx = 5;
1227 	int cmd_fd = -1;
1228 	char *backing_dir;
1229 	int i;
1230 
1231 	backing_dir = create_backing_dir(mount_dir);
1232 	if (!backing_dir)
1233 		goto failure;
1234 
1235 	/* Mount FS and release the backing file. */
1236 	if (mount_fs(mount_dir, backing_dir, 50) != 0)
1237 		goto failure;
1238 	free(backing_dir);
1239 
1240 	cmd_fd = open_commands_file(mount_dir);
1241 	if (cmd_fd < 0)
1242 		goto failure;
1243 
1244 	/* Check that test files don't exist in the filesystem. */
1245 	for (i = 0; i < file_num; i++) {
1246 		struct test_file *file = &test.files[i];
1247 		char *filename = concat_file_name(mount_dir, file->name);
1248 
1249 		if (access(filename, F_OK) != -1) {
1250 			ksft_print_msg(
1251 				"File %s somehow already exists in a clean FS.\n",
1252 				filename);
1253 			goto failure;
1254 		}
1255 		free(filename);
1256 	}
1257 
1258 	/* Write test data into the command file. */
1259 	for (i = 0; i < file_num; i++) {
1260 		struct test_file *file = &test.files[i];
1261 		int res;
1262 
1263 		build_mtree(file);
1264 		res = emit_file(cmd_fd, NULL, file->name, &file->id,
1265 				     file->size, NULL);
1266 		if (res < 0) {
1267 			ksft_print_msg("Error %s emiting file %s.\n",
1268 				       strerror(-res), file->name);
1269 			goto failure;
1270 		}
1271 
1272 		/* Skip writing data to one file so we can check */
1273 		/* that it's missing later. */
1274 		if (i == missing_file_idx)
1275 			continue;
1276 
1277 		res = load_hash_tree(mount_dir, file);
1278 		if (res) {
1279 			ksft_print_msg("Can't load hashes for %s. error: %s\n",
1280 				file->name, strerror(-res));
1281 			goto failure;
1282 		}
1283 
1284 		res = emit_test_file_data(mount_dir, file);
1285 		if (res) {
1286 			ksft_print_msg("Error %s emiting data for %s.\n",
1287 				       strerror(-res), file->name);
1288 			goto failure;
1289 		}
1290 	}
1291 
1292 	/* Validate contents of the FS */
1293 	for (i = 0; i < file_num; i++) {
1294 		struct test_file *file = &test.files[i];
1295 
1296 		if (i == missing_file_idx) {
1297 			/* No data has been written to this file. */
1298 			/* Check for read error; */
1299 			uint8_t buf;
1300 			char *filename =
1301 				concat_file_name(mount_dir, file->name);
1302 			int res = read_test_file(&buf, 1, filename, 0);
1303 
1304 			free(filename);
1305 			if (res > 0) {
1306 				ksft_print_msg(
1307 					"Data present, even though never writtern.\n");
1308 				goto failure;
1309 			}
1310 			if (res != -ETIME) {
1311 				ksft_print_msg("Wrong error code: %d.\n", res);
1312 				goto failure;
1313 			}
1314 		} else {
1315 			if (validate_test_file_content(mount_dir, file) < 0)
1316 				goto failure;
1317 		}
1318 	}
1319 
1320 	close(cmd_fd);
1321 	cmd_fd = -1;
1322 	if (umount(mount_dir) != 0) {
1323 		print_error("Can't unmout FS");
1324 		goto failure;
1325 	}
1326 
1327 	return TEST_SUCCESS;
1328 
1329 failure:
1330 	close(cmd_fd);
1331 	umount(mount_dir);
1332 	return TEST_FAILURE;
1333 }
1334 
concurrent_reads_and_writes_test(char * mount_dir)1335 static int concurrent_reads_and_writes_test(char *mount_dir)
1336 {
1337 	struct test_files_set test = get_test_files_set();
1338 	const int file_num = test.files_count;
1339 	/* Validate each file from that many child processes. */
1340 	const int child_multiplier = 3;
1341 	int cmd_fd = -1;
1342 	char *backing_dir;
1343 	int status;
1344 	int i;
1345 	pid_t producer_pid;
1346 	pid_t *child_pids = alloca(child_multiplier * file_num * sizeof(pid_t));
1347 
1348 	backing_dir = create_backing_dir(mount_dir);
1349 	if (!backing_dir)
1350 		goto failure;
1351 
1352 	/* Mount FS and release the backing file. */
1353 	if (mount_fs(mount_dir, backing_dir, 50) != 0)
1354 		goto failure;
1355 	free(backing_dir);
1356 
1357 	cmd_fd = open_commands_file(mount_dir);
1358 	if (cmd_fd < 0)
1359 		goto failure;
1360 
1361 	/* Tell FS about the files, without actually providing the data. */
1362 	for (i = 0; i < file_num; i++) {
1363 		struct test_file *file = &test.files[i];
1364 		int res;
1365 
1366 		res = emit_file(cmd_fd, NULL, file->name, &file->id,
1367 				     file->size, NULL);
1368 		if (res)
1369 			goto failure;
1370 	}
1371 
1372 	/* Start child processes acessing data in the files */
1373 	for (i = 0; i < file_num * child_multiplier; i++) {
1374 		struct test_file *file = &test.files[i / child_multiplier];
1375 		pid_t child_pid = flush_and_fork();
1376 
1377 		if (child_pid == 0) {
1378 			/* This is a child process, do the data validation. */
1379 			int ret = validate_test_file_content_with_seed(
1380 				mount_dir, file, i);
1381 			if (ret >= 0) {
1382 				/* Zero exit status if data is valid. */
1383 				exit(0);
1384 			}
1385 
1386 			/* Positive status if validation error found. */
1387 			exit(-ret);
1388 		} else if (child_pid > 0) {
1389 			child_pids[i] = child_pid;
1390 		} else {
1391 			print_error("Fork error");
1392 			goto failure;
1393 		}
1394 	}
1395 
1396 	producer_pid = flush_and_fork();
1397 	if (producer_pid == 0) {
1398 		int ret;
1399 		/*
1400 		 * This is a child that should provide data to
1401 		 * pending reads.
1402 		 */
1403 
1404 		ret = data_producer(mount_dir, &test);
1405 		exit(-ret);
1406 	} else {
1407 		status = wait_for_process(producer_pid);
1408 		if (status != 0) {
1409 			ksft_print_msg("Data produces failed. %d(%s) ", status,
1410 				       strerror(status));
1411 			goto failure;
1412 		}
1413 	}
1414 
1415 	/* Check that all children has finished with 0 exit status */
1416 	for (i = 0; i < file_num * child_multiplier; i++) {
1417 		struct test_file *file = &test.files[i / child_multiplier];
1418 
1419 		status = wait_for_process(child_pids[i]);
1420 		if (status != 0) {
1421 			ksft_print_msg(
1422 				"Validation for the file %s failed with code %d (%s)\n",
1423 				file->name, status, strerror(status));
1424 			goto failure;
1425 		}
1426 	}
1427 
1428 	/* Check that there are no pending reads left */
1429 	{
1430 		struct incfs_pending_read_info prs[1] = {};
1431 		int timeout = 0;
1432 		int read_count = wait_for_pending_reads(cmd_fd, timeout, prs,
1433 							ARRAY_SIZE(prs));
1434 
1435 		if (read_count) {
1436 			ksft_print_msg(
1437 				"Pending reads pending when all data written\n");
1438 			goto failure;
1439 		}
1440 	}
1441 
1442 	close(cmd_fd);
1443 	cmd_fd = -1;
1444 	if (umount(mount_dir) != 0) {
1445 		print_error("Can't unmout FS");
1446 		goto failure;
1447 	}
1448 
1449 	return TEST_SUCCESS;
1450 
1451 failure:
1452 	close(cmd_fd);
1453 	umount(mount_dir);
1454 	return TEST_FAILURE;
1455 }
1456 
work_after_remount_test(char * mount_dir)1457 static int work_after_remount_test(char *mount_dir)
1458 {
1459 	struct test_files_set test = get_test_files_set();
1460 	const int file_num = test.files_count;
1461 	const int file_num_stage1 = file_num / 2;
1462 	const int file_num_stage2 = file_num;
1463 	char *backing_dir = NULL;
1464 	int i = 0;
1465 	int cmd_fd = -1;
1466 
1467 	backing_dir = create_backing_dir(mount_dir);
1468 	if (!backing_dir)
1469 		goto failure;
1470 
1471 	/* Mount FS and release the backing file. */
1472 	if (mount_fs(mount_dir, backing_dir, 50) != 0)
1473 		goto failure;
1474 
1475 	cmd_fd = open_commands_file(mount_dir);
1476 	if (cmd_fd < 0)
1477 		goto failure;
1478 
1479 	/* Write first half of the data into the command file. (stage 1) */
1480 	for (i = 0; i < file_num_stage1; i++) {
1481 		struct test_file *file = &test.files[i];
1482 		int res;
1483 
1484 		build_mtree(file);
1485 		if (emit_file(cmd_fd, NULL, file->name, &file->id,
1486 				     file->size, NULL))
1487 			goto failure;
1488 
1489 		if (emit_test_file_data(mount_dir, file))
1490 			goto failure;
1491 
1492 		res = load_hash_tree(mount_dir, file);
1493 		if (res) {
1494 			ksft_print_msg("Can't load hashes for %s. error: %s\n",
1495 				file->name, strerror(-res));
1496 			goto failure;
1497 		}
1498 }
1499 
1500 	/* Unmount and mount again, to see that data is persistent. */
1501 	close(cmd_fd);
1502 	cmd_fd = -1;
1503 	if (umount(mount_dir) != 0) {
1504 		print_error("Can't unmout FS");
1505 		goto failure;
1506 	}
1507 
1508 	if (mount_fs(mount_dir, backing_dir, 50) != 0)
1509 		goto failure;
1510 
1511 	cmd_fd = open_commands_file(mount_dir);
1512 	if (cmd_fd < 0)
1513 		goto failure;
1514 
1515 	/* Write the second half of the data into the command file. (stage 2) */
1516 	for (; i < file_num_stage2; i++) {
1517 		struct test_file *file = &test.files[i];
1518 		int res = emit_file(cmd_fd, NULL, file->name, &file->id,
1519 				     file->size, NULL);
1520 
1521 		if (res)
1522 			goto failure;
1523 
1524 		if (emit_test_file_data(mount_dir, file))
1525 			goto failure;
1526 	}
1527 
1528 	/* Validate contents of the FS */
1529 	for (i = 0; i < file_num_stage2; i++) {
1530 		struct test_file *file = &test.files[i];
1531 
1532 		if (validate_test_file_content(mount_dir, file) < 0)
1533 			goto failure;
1534 	}
1535 
1536 	/* Delete all files */
1537 	for (i = 0; i < file_num; i++) {
1538 		struct test_file *file = &test.files[i];
1539 		char *filename = concat_file_name(mount_dir, file->name);
1540 		char *filename_in_index = get_index_filename(mount_dir,
1541 							file->id);
1542 
1543 		if (access(filename, F_OK) != 0) {
1544 			ksft_print_msg("File %s is not visible.\n", filename);
1545 			goto failure;
1546 		}
1547 
1548 		if (access(filename_in_index, F_OK) != 0) {
1549 			ksft_print_msg("File %s is not visible.\n",
1550 				filename_in_index);
1551 			goto failure;
1552 		}
1553 
1554 		unlink(filename);
1555 
1556 		if (access(filename, F_OK) != -1) {
1557 			ksft_print_msg("File %s is still present.\n", filename);
1558 			goto failure;
1559 		}
1560 
1561 		if (access(filename_in_index, F_OK) != 0) {
1562 			ksft_print_msg("File %s is still present.\n",
1563 				filename_in_index);
1564 			goto failure;
1565 		}
1566 		free(filename);
1567 		free(filename_in_index);
1568 	}
1569 
1570 	/* Unmount and mount again, to see that deleted files stay deleted. */
1571 	close(cmd_fd);
1572 	cmd_fd = -1;
1573 	if (umount(mount_dir) != 0) {
1574 		print_error("Can't unmout FS");
1575 		goto failure;
1576 	}
1577 
1578 	if (mount_fs(mount_dir, backing_dir, 50) != 0)
1579 		goto failure;
1580 
1581 	cmd_fd = open_commands_file(mount_dir);
1582 	if (cmd_fd < 0)
1583 		goto failure;
1584 
1585 	/* Validate all deleted files are still deleted. */
1586 	for (i = 0; i < file_num; i++) {
1587 		struct test_file *file = &test.files[i];
1588 		char *filename = concat_file_name(mount_dir, file->name);
1589 
1590 		if (access(filename, F_OK) != -1) {
1591 			ksft_print_msg("File %s is still visible.\n", filename);
1592 			goto failure;
1593 		}
1594 		free(filename);
1595 	}
1596 
1597 	/* Final unmount */
1598 	close(cmd_fd);
1599 	free(backing_dir);
1600 	cmd_fd = -1;
1601 	if (umount(mount_dir) != 0) {
1602 		print_error("Can't unmout FS");
1603 		goto failure;
1604 	}
1605 
1606 	return TEST_SUCCESS;
1607 
1608 failure:
1609 	close(cmd_fd);
1610 	free(backing_dir);
1611 	umount(mount_dir);
1612 	return TEST_FAILURE;
1613 }
1614 
attribute_test(char * mount_dir)1615 static int attribute_test(char *mount_dir)
1616 {
1617 	char file_attr[] = "metadata123123";
1618 	char attr_buf[INCFS_MAX_FILE_ATTR_SIZE] = {};
1619 	int cmd_fd = -1;
1620 	incfs_uuid_t file_id;
1621 	int attr_res = 0;
1622 	char *backing_dir;
1623 
1624 
1625 	backing_dir = create_backing_dir(mount_dir);
1626 	if (!backing_dir)
1627 		goto failure;
1628 
1629 	/* Mount FS and release the backing file. */
1630 	if (mount_fs(mount_dir, backing_dir, 50) != 0)
1631 		goto failure;
1632 
1633 
1634 	cmd_fd = open_commands_file(mount_dir);
1635 	if (cmd_fd < 0)
1636 		goto failure;
1637 
1638 	if (emit_file(cmd_fd, NULL, "file", &file_id, 12, file_attr))
1639 		goto failure;
1640 
1641 	/* Test attribute values */
1642 	attr_res = get_file_attr(mount_dir, file_id, attr_buf,
1643 		ARRAY_SIZE(attr_buf));
1644 	if (attr_res != strlen(file_attr)) {
1645 		ksft_print_msg("Get file attr error: %d\n", attr_res);
1646 		goto failure;
1647 	}
1648 	if (strcmp(attr_buf, file_attr) != 0) {
1649 		ksft_print_msg("Incorrect file attr value: '%s'", attr_buf);
1650 		goto failure;
1651 	}
1652 
1653 	/* Unmount and mount again, to see that attributes are persistent. */
1654 	close(cmd_fd);
1655 	cmd_fd = -1;
1656 	if (umount(mount_dir) != 0) {
1657 		print_error("Can't unmout FS");
1658 		goto failure;
1659 	}
1660 
1661 	if (mount_fs(mount_dir, backing_dir, 50) != 0)
1662 		goto failure;
1663 
1664 	cmd_fd = open_commands_file(mount_dir);
1665 	if (cmd_fd < 0)
1666 		goto failure;
1667 
1668 	/* Test attribute values again after remount*/
1669 	attr_res = get_file_attr(mount_dir, file_id, attr_buf,
1670 		ARRAY_SIZE(attr_buf));
1671 	if (attr_res != strlen(file_attr)) {
1672 		ksft_print_msg("Get dir attr error: %d\n", attr_res);
1673 		goto failure;
1674 	}
1675 	if (strcmp(attr_buf, file_attr) != 0) {
1676 		ksft_print_msg("Incorrect file attr value: '%s'", attr_buf);
1677 		goto failure;
1678 	}
1679 
1680 	/* Final unmount */
1681 	close(cmd_fd);
1682 	free(backing_dir);
1683 	cmd_fd = -1;
1684 	if (umount(mount_dir) != 0) {
1685 		print_error("Can't unmout FS");
1686 		goto failure;
1687 	}
1688 
1689 	return TEST_SUCCESS;
1690 
1691 failure:
1692 	close(cmd_fd);
1693 	free(backing_dir);
1694 	umount(mount_dir);
1695 	return TEST_FAILURE;
1696 }
1697 
child_procs_waiting_for_data_test(char * mount_dir)1698 static int child_procs_waiting_for_data_test(char *mount_dir)
1699 {
1700 	struct test_files_set test = get_test_files_set();
1701 	const int file_num = test.files_count;
1702 	int cmd_fd = -1;
1703 	int i;
1704 	pid_t *child_pids = alloca(file_num * sizeof(pid_t));
1705 	char *backing_dir;
1706 
1707 	backing_dir = create_backing_dir(mount_dir);
1708 	if (!backing_dir)
1709 		goto failure;
1710 
1711 	/* Mount FS and release the backing file.  (10s wait time) */
1712 	if (mount_fs(mount_dir, backing_dir, 10000) != 0)
1713 		goto failure;
1714 
1715 
1716 	cmd_fd = open_commands_file(mount_dir);
1717 	if (cmd_fd < 0)
1718 		goto failure;
1719 
1720 	/* Tell FS about the files, without actually providing the data. */
1721 	for (i = 0; i < file_num; i++) {
1722 		struct test_file *file = &test.files[i];
1723 
1724 		emit_file(cmd_fd, NULL, file->name, &file->id,
1725 				     file->size, NULL);
1726 	}
1727 
1728 	/* Start child processes acessing data in the files */
1729 	for (i = 0; i < file_num; i++) {
1730 		struct test_file *file = &test.files[i];
1731 		pid_t child_pid = flush_and_fork();
1732 
1733 		if (child_pid == 0) {
1734 			/* This is a child process, do the data validation. */
1735 			int ret = validate_test_file_content(mount_dir, file);
1736 
1737 			if (ret >= 0) {
1738 				/* Zero exit status if data is valid. */
1739 				exit(0);
1740 			}
1741 
1742 			/* Positive status if validation error found. */
1743 			exit(-ret);
1744 		} else if (child_pid > 0) {
1745 			child_pids[i] = child_pid;
1746 		} else {
1747 			print_error("Fork error");
1748 			goto failure;
1749 		}
1750 	}
1751 
1752 	/* Write test data into the command file. */
1753 	for (i = 0; i < file_num; i++) {
1754 		struct test_file *file = &test.files[i];
1755 
1756 		if (emit_test_file_data(mount_dir, file))
1757 			goto failure;
1758 	}
1759 
1760 	/* Check that all children has finished with 0 exit status */
1761 	for (i = 0; i < file_num; i++) {
1762 		struct test_file *file = &test.files[i];
1763 		int status = wait_for_process(child_pids[i]);
1764 
1765 		if (status != 0) {
1766 			ksft_print_msg(
1767 				"Validation for the file %s failed with code %d (%s)\n",
1768 				file->name, status, strerror(status));
1769 			goto failure;
1770 		}
1771 	}
1772 
1773 	close(cmd_fd);
1774 	free(backing_dir);
1775 	cmd_fd = -1;
1776 	if (umount(mount_dir) != 0) {
1777 		print_error("Can't unmout FS");
1778 		goto failure;
1779 	}
1780 
1781 	return TEST_SUCCESS;
1782 
1783 failure:
1784 	close(cmd_fd);
1785 	free(backing_dir);
1786 	umount(mount_dir);
1787 	return TEST_FAILURE;
1788 }
1789 
multiple_providers_test(char * mount_dir)1790 static int multiple_providers_test(char *mount_dir)
1791 {
1792 	struct test_files_set test = get_test_files_set();
1793 	const int file_num = test.files_count;
1794 	const int producer_count = 5;
1795 	int cmd_fd = -1;
1796 	int status;
1797 	int i;
1798 	pid_t *producer_pids = alloca(producer_count * sizeof(pid_t));
1799 	char *backing_dir;
1800 
1801 	backing_dir = create_backing_dir(mount_dir);
1802 	if (!backing_dir)
1803 		goto failure;
1804 
1805 	/* Mount FS and release the backing file.  (10s wait time) */
1806 	if (mount_fs(mount_dir, backing_dir, 10000) != 0)
1807 		goto failure;
1808 
1809 	cmd_fd = open_commands_file(mount_dir);
1810 	if (cmd_fd < 0)
1811 		goto failure;
1812 
1813 	/* Tell FS about the files, without actually providing the data. */
1814 	for (i = 0; i < file_num; i++) {
1815 		struct test_file *file = &test.files[i];
1816 
1817 		if (emit_file(cmd_fd, NULL, file->name, &file->id,
1818 				     file->size, NULL) < 0)
1819 			goto failure;
1820 	}
1821 
1822 	/* Start producer processes */
1823 	for (i = 0; i < producer_count; i++) {
1824 		pid_t producer_pid = flush_and_fork();
1825 
1826 		if (producer_pid == 0) {
1827 			int ret;
1828 			/*
1829 			 * This is a child that should provide data to
1830 			 * pending reads.
1831 			 */
1832 
1833 			ret = data_producer(mount_dir, &test);
1834 			exit(-ret);
1835 		} else if (producer_pid > 0) {
1836 			producer_pids[i] = producer_pid;
1837 		} else {
1838 			print_error("Fork error");
1839 			goto failure;
1840 		}
1841 	}
1842 
1843 	/* Validate FS content */
1844 	for (i = 0; i < file_num; i++) {
1845 		struct test_file *file = &test.files[i];
1846 		char *filename = concat_file_name(mount_dir, file->name);
1847 		loff_t read_result = read_whole_file(filename);
1848 
1849 		free(filename);
1850 		if (read_result != file->size) {
1851 			ksft_print_msg(
1852 				"Error validating file %s. Result: %ld\n",
1853 				file->name, read_result);
1854 			goto failure;
1855 		}
1856 	}
1857 
1858 	/* Check that all producers has finished with 0 exit status */
1859 	for (i = 0; i < producer_count; i++) {
1860 		status = wait_for_process(producer_pids[i]);
1861 		if (status != 0) {
1862 			ksft_print_msg("Producer %d failed with code (%s)\n", i,
1863 				       strerror(status));
1864 			goto failure;
1865 		}
1866 	}
1867 
1868 	close(cmd_fd);
1869 	free(backing_dir);
1870 	cmd_fd = -1;
1871 	if (umount(mount_dir) != 0) {
1872 		print_error("Can't unmout FS");
1873 		goto failure;
1874 	}
1875 
1876 	return TEST_SUCCESS;
1877 
1878 failure:
1879 	close(cmd_fd);
1880 	free(backing_dir);
1881 	umount(mount_dir);
1882 	return TEST_FAILURE;
1883 }
1884 
signature_test(char * mount_dir)1885 static int signature_test(char *mount_dir)
1886 {
1887 	struct test_files_set test = get_test_files_set();
1888 	const int file_num = test.files_count;
1889 	int i = 0;
1890 	unsigned char sig_buf[INCFS_MAX_SIGNATURE_SIZE];
1891 	char *backing_dir;
1892 	int cmd_fd = -1;
1893 
1894 	backing_dir = create_backing_dir(mount_dir);
1895 	if (!backing_dir)
1896 		goto failure;
1897 
1898 	/* Mount FS and release the backing file.  (10s wait time) */
1899 	if (mount_fs(mount_dir, backing_dir, 10000) != 0)
1900 		goto failure;
1901 
1902 	cmd_fd = open_commands_file(mount_dir);
1903 	if (cmd_fd < 0)
1904 		goto failure;
1905 
1906 	/* Write hashes and data. */
1907 	for (i = 0; i < file_num; i++) {
1908 		struct test_file *file = &test.files[i];
1909 		int res;
1910 
1911 		build_mtree(file);
1912 
1913 		res = crypto_emit_file(cmd_fd, NULL, file->name, &file->id,
1914 			file->size, file->root_hash,
1915 			file->sig.data, file->sig.size, file->sig.add_data);
1916 
1917 		if (res) {
1918 			ksft_print_msg("Emit failed for %s. error: %s\n",
1919 				file->name, strerror(-res));
1920 			goto failure;
1921 		}
1922 
1923 		if (emit_test_file_data(mount_dir, file))
1924 			goto failure;
1925 
1926 		res = load_hash_tree(mount_dir, file);
1927 		if (res) {
1928 			ksft_print_msg("Can't load hashes for %s. error: %s\n",
1929 				file->name, strerror(-res));
1930 			goto failure;
1931 		}
1932 	}
1933 
1934 	/* Validate data */
1935 	for (i = 0; i < file_num; i++) {
1936 		struct test_file *file = &test.files[i];
1937 		int sig_len;
1938 		char *path;
1939 		int fd;
1940 
1941 		if (validate_test_file_content(mount_dir, file) < 0)
1942 			goto failure;
1943 
1944 		path = concat_file_name(mount_dir, file->name);
1945 		fd = open(path, O_RDWR);
1946 		free(path);
1947 		if (fd < 0) {
1948 			print_error("Can't open file");
1949 			goto failure;
1950 		}
1951 
1952 		sig_len = get_file_signature(fd, sig_buf, ARRAY_SIZE(sig_buf));
1953 
1954 		if (close(fd)) {
1955 			print_error("Can't close file");
1956 			goto failure;
1957 		}
1958 
1959 		if (sig_len < 0) {
1960 			ksft_print_msg("Can't load signature %s. error: %s\n",
1961 				file->name, strerror(-sig_len));
1962 			goto failure;
1963 		}
1964 
1965 		if (sig_len != file->sig.size ||
1966 			memcmp(sig_buf, file->sig.data, sig_len)) {
1967 			ksft_print_msg("Signature mismatch %s.\n",
1968 				file->name);
1969 			goto failure;
1970 		}
1971 	}
1972 
1973 	/* Unmount and mount again, to make sure the signature is persistent. */
1974 	close(cmd_fd);
1975 	cmd_fd = -1;
1976 	if (umount(mount_dir) != 0) {
1977 		print_error("Can't unmout FS");
1978 		goto failure;
1979 	}
1980 	if (mount_fs(mount_dir, backing_dir, 50) != 0)
1981 		goto failure;
1982 
1983 	cmd_fd = open_commands_file(mount_dir);
1984 	if (cmd_fd < 0)
1985 		goto failure;
1986 
1987 	/* Validate data again */
1988 	for (i = 0; i < file_num; i++) {
1989 		struct test_file *file = &test.files[i];
1990 		int sig_len;
1991 		char *path;
1992 		int fd;
1993 
1994 		if (validate_test_file_content(mount_dir, file) < 0)
1995 			goto failure;
1996 
1997 		path = concat_file_name(mount_dir, file->name);
1998 		fd = open(path, O_RDWR);
1999 		free(path);
2000 		if (fd < 0) {
2001 			print_error("Can't open file");
2002 			goto failure;
2003 		}
2004 
2005 		sig_len = get_file_signature(fd, sig_buf, ARRAY_SIZE(sig_buf));
2006 
2007 		if (close(fd)) {
2008 			print_error("Can't close file");
2009 			goto failure;
2010 		}
2011 
2012 		if (sig_len < 0) {
2013 			ksft_print_msg("Can't load signature %s. error: %s\n",
2014 				file->name, strerror(-sig_len));
2015 			goto failure;
2016 		}
2017 		if (sig_len != file->sig.size ||
2018 			memcmp(sig_buf, file->sig.data, sig_len)) {
2019 			ksft_print_msg("Signature mismatch %s.\n",
2020 				file->name);
2021 			goto failure;
2022 		}
2023 	}
2024 
2025 	/* Final unmount */
2026 	close(cmd_fd);
2027 	cmd_fd = -1;
2028 	if (umount(mount_dir) != 0) {
2029 		print_error("Can't unmout FS");
2030 		goto failure;
2031 	}
2032 	return TEST_SUCCESS;
2033 
2034 failure:
2035 	close(cmd_fd);
2036 	free(backing_dir);
2037 	umount(mount_dir);
2038 	return TEST_FAILURE;
2039 }
2040 
hash_tree_test(char * mount_dir)2041 static int hash_tree_test(char *mount_dir)
2042 {
2043 	char *backing_dir;
2044 	struct test_files_set test = get_test_files_set();
2045 	const int file_num = test.files_count;
2046 	const int corrupted_file_idx = 5;
2047 	int i = 0;
2048 	int cmd_fd = -1;
2049 
2050 	backing_dir = create_backing_dir(mount_dir);
2051 	if (!backing_dir)
2052 		goto failure;
2053 
2054 	/* Mount FS and release the backing file. */
2055 	if (mount_fs(mount_dir, backing_dir, 50) != 0)
2056 		goto failure;
2057 
2058 	cmd_fd = open_commands_file(mount_dir);
2059 	if (cmd_fd < 0)
2060 		goto failure;
2061 
2062 	/* Write hashes and data. */
2063 	for (i = 0; i < file_num; i++) {
2064 		struct test_file *file = &test.files[i];
2065 		int res;
2066 
2067 		build_mtree(file);
2068 		res = crypto_emit_file(cmd_fd, NULL, file->name, &file->id,
2069 			file->size, file->root_hash,
2070 			file->sig.data, file->sig.size, file->sig.add_data);
2071 
2072 		if (i == corrupted_file_idx) {
2073 			/* Corrupt third blocks hash */
2074 			file->mtree[0].data[2 * SHA256_DIGEST_SIZE] ^= 0xff;
2075 		}
2076 		if (emit_test_file_data(mount_dir, file))
2077 			goto failure;
2078 
2079 		res = load_hash_tree(mount_dir, file);
2080 		if (res) {
2081 			ksft_print_msg("Can't load hashes for %s. error: %s\n",
2082 				file->name, strerror(-res));
2083 			goto failure;
2084 		}
2085 	}
2086 
2087 	/* Validate data */
2088 	for (i = 0; i < file_num; i++) {
2089 		struct test_file *file = &test.files[i];
2090 
2091 		if (i == corrupted_file_idx) {
2092 			uint8_t data[INCFS_DATA_FILE_BLOCK_SIZE];
2093 			char *filename =
2094 				concat_file_name(mount_dir, file->name);
2095 			int res;
2096 
2097 			res = read_test_file(data, INCFS_DATA_FILE_BLOCK_SIZE,
2098 					     filename, 2);
2099 			free(filename);
2100 			if (res != -EBADMSG) {
2101 				ksft_print_msg("Hash violation missed1. %d\n",
2102 					       res);
2103 				goto failure;
2104 			}
2105 		} else if (validate_test_file_content(mount_dir, file) < 0)
2106 			goto failure;
2107 	}
2108 
2109 	/* Unmount and mount again, to that hashes are persistent. */
2110 	close(cmd_fd);
2111 	cmd_fd = -1;
2112 	if (umount(mount_dir) != 0) {
2113 		print_error("Can't unmout FS");
2114 		goto failure;
2115 	}
2116 	if (mount_fs(mount_dir, backing_dir, 50) != 0)
2117 		goto failure;
2118 
2119 	cmd_fd = open_commands_file(mount_dir);
2120 	if (cmd_fd < 0)
2121 		goto failure;
2122 
2123 	/* Validate data again */
2124 	for (i = 0; i < file_num; i++) {
2125 		struct test_file *file = &test.files[i];
2126 
2127 		if (i == corrupted_file_idx) {
2128 			uint8_t data[INCFS_DATA_FILE_BLOCK_SIZE];
2129 			char *filename =
2130 				concat_file_name(mount_dir, file->name);
2131 			int res;
2132 
2133 			res = read_test_file(data, INCFS_DATA_FILE_BLOCK_SIZE,
2134 					     filename, 2);
2135 			free(filename);
2136 			if (res != -EBADMSG) {
2137 				ksft_print_msg("Hash violation missed2. %d\n",
2138 					       res);
2139 				goto failure;
2140 			}
2141 		} else if (validate_test_file_content(mount_dir, file) < 0)
2142 			goto failure;
2143 	}
2144 
2145 	/* Final unmount */
2146 	close(cmd_fd);
2147 	cmd_fd = -1;
2148 	if (umount(mount_dir) != 0) {
2149 		print_error("Can't unmout FS");
2150 		goto failure;
2151 	}
2152 	return TEST_SUCCESS;
2153 
2154 failure:
2155 	close(cmd_fd);
2156 	free(backing_dir);
2157 	umount(mount_dir);
2158 	return TEST_FAILURE;
2159 }
2160 
validate_logs(char * mount_dir,int log_fd,struct test_file * file)2161 static int validate_logs(char *mount_dir, int log_fd, struct test_file *file)
2162 {
2163 	uint8_t data[INCFS_DATA_FILE_BLOCK_SIZE];
2164 	struct incfs_pending_read_info prs[100] = {};
2165 	int prs_size = ARRAY_SIZE(prs);
2166 	int block_cnt = 1 + (file->size - 1) / INCFS_DATA_FILE_BLOCK_SIZE;
2167 	int res;
2168 	int read_count;
2169 	int i;
2170 	char *filename = concat_file_name(mount_dir, file->name);
2171 	int fd;
2172 
2173 	fd = open(filename, O_RDONLY);
2174 	free(filename);
2175 	if (fd <= 0)
2176 		return TEST_FAILURE;
2177 
2178 	if (block_cnt > prs_size)
2179 		block_cnt = prs_size;
2180 
2181 	for (i = 0; i < block_cnt; i++) {
2182 		res = pread(fd, data, sizeof(data),
2183 			    INCFS_DATA_FILE_BLOCK_SIZE * i);
2184 		if (res <= 0)
2185 			goto failure;
2186 	}
2187 
2188 	read_count = wait_for_pending_reads(log_fd, 0, prs, prs_size);
2189 	if (read_count < 0) {
2190 		ksft_print_msg("Error reading logged reads %s.\n",
2191 			       strerror(-read_count));
2192 		goto failure;
2193 	}
2194 
2195 	if (read_count != block_cnt) {
2196 		ksft_print_msg("Bad log read count %s %d %d.\n", file->name,
2197 			       read_count, block_cnt);
2198 		goto failure;
2199 	}
2200 
2201 	for (i = 0; i < read_count; i++) {
2202 		struct incfs_pending_read_info *read = &prs[i];
2203 
2204 		if (!same_id(&read->file_id, &file->id)) {
2205 			ksft_print_msg("Bad log read ino %s\n", file->name);
2206 			goto failure;
2207 		}
2208 
2209 		if (read->block_index != i) {
2210 			ksft_print_msg("Bad log read ino %s %d %d.\n",
2211 				       file->name, read->block_index, i);
2212 			goto failure;
2213 		}
2214 
2215 		if (i != 0) {
2216 			unsigned long psn = prs[i - 1].serial_number;
2217 
2218 			if (read->serial_number != psn + 1) {
2219 				ksft_print_msg("Bad log read sn %s %d %d.\n",
2220 					       file->name, read->serial_number,
2221 					       psn);
2222 				goto failure;
2223 			}
2224 		}
2225 
2226 		if (read->timestamp_us == 0) {
2227 			ksft_print_msg("Bad log read timestamp %s.\n",
2228 				       file->name);
2229 			goto failure;
2230 		}
2231 	}
2232 	close(fd);
2233 	return TEST_SUCCESS;
2234 
2235 failure:
2236 	close(fd);
2237 	return TEST_FAILURE;
2238 }
2239 
read_log_test(char * mount_dir)2240 static int read_log_test(char *mount_dir)
2241 {
2242 	struct test_files_set test = get_test_files_set();
2243 	const int file_num = test.files_count;
2244 	int i = 0;
2245 	int cmd_fd = -1, log_fd = -1;
2246 	char *backing_dir;
2247 
2248 	backing_dir = create_backing_dir(mount_dir);
2249 	if (!backing_dir)
2250 		goto failure;
2251 
2252 	if (mount_fs_opt(mount_dir, backing_dir, "readahead=0") != 0)
2253 		goto failure;
2254 
2255 	cmd_fd = open_commands_file(mount_dir);
2256 	if (cmd_fd < 0)
2257 		goto failure;
2258 
2259 	log_fd = open_log_file(mount_dir);
2260 	if (cmd_fd < 0)
2261 		ksft_print_msg("Can't open log file.\n");
2262 
2263 	/* Write data. */
2264 	for (i = 0; i < file_num; i++) {
2265 		struct test_file *file = &test.files[i];
2266 
2267 		if (emit_file(cmd_fd, NULL, file->name, &file->id,
2268 				     file->size, NULL))
2269 			goto failure;
2270 
2271 		if (emit_test_file_data(mount_dir, file))
2272 			goto failure;
2273 	}
2274 
2275 	/* Validate data */
2276 	for (i = 0; i < file_num; i++) {
2277 		struct test_file *file = &test.files[i];
2278 
2279 		if (validate_logs(mount_dir, log_fd, file))
2280 			goto failure;
2281 	}
2282 
2283 	/* Unmount and mount again, to see that logs work after remount. */
2284 	close(cmd_fd);
2285 	close(log_fd);
2286 	cmd_fd = -1;
2287 	if (umount(mount_dir) != 0) {
2288 		print_error("Can't unmout FS");
2289 		goto failure;
2290 	}
2291 
2292 	if (mount_fs_opt(mount_dir, backing_dir, "readahead=0") != 0)
2293 		goto failure;
2294 
2295 	cmd_fd = open_commands_file(mount_dir);
2296 	if (cmd_fd < 0)
2297 		goto failure;
2298 
2299 	log_fd = open_log_file(mount_dir);
2300 	if (cmd_fd < 0)
2301 		ksft_print_msg("Can't open log file.\n");
2302 
2303 	/* Validate data again */
2304 	for (i = 0; i < file_num; i++) {
2305 		struct test_file *file = &test.files[i];
2306 
2307 		if (validate_logs(mount_dir, log_fd, file))
2308 			goto failure;
2309 	}
2310 
2311 	/* Final unmount */
2312 	close(cmd_fd);
2313 	close(log_fd);
2314 	free(backing_dir);
2315 	if (umount(mount_dir) != 0) {
2316 		print_error("Can't unmout FS");
2317 		goto failure;
2318 	}
2319 
2320 	return TEST_SUCCESS;
2321 
2322 failure:
2323 	close(cmd_fd);
2324 	close(log_fd);
2325 	free(backing_dir);
2326 	umount(mount_dir);
2327 	return TEST_FAILURE;
2328 }
2329 
setup_mount_dir()2330 static char *setup_mount_dir()
2331 {
2332 	struct stat st;
2333 	char *current_dir = getcwd(NULL, 0);
2334 	char *mount_dir = concat_file_name(current_dir, "incfs-mount-dir");
2335 
2336 	free(current_dir);
2337 	if (stat(mount_dir, &st) == 0) {
2338 		if (S_ISDIR(st.st_mode))
2339 			return mount_dir;
2340 
2341 		ksft_print_msg("%s is a file, not a dir.\n", mount_dir);
2342 		return NULL;
2343 	}
2344 
2345 	if (mkdir(mount_dir, 0777)) {
2346 		print_error("Can't create mount dir.");
2347 		return NULL;
2348 	}
2349 
2350 	return mount_dir;
2351 }
2352 
main(int argc,char * argv[])2353 int main(int argc, char *argv[])
2354 {
2355 	char *mount_dir = NULL;
2356 	int fails = 0;
2357 	int i;
2358 	int fd, count;
2359 
2360 	// Seed randomness pool for testing on QEMU
2361 	// NOTE - this abuses the concept of randomness - do *not* ever do this
2362 	// on a machine for production use - the device will think it has good
2363 	// randomness when it does not.
2364 	fd = open("/dev/urandom", O_WRONLY);
2365 	count = 4096;
2366 	for (int i = 0; i < 128; ++i)
2367 		ioctl(fd, RNDADDTOENTCNT, &count);
2368 	close(fd);
2369 
2370 	ksft_print_header();
2371 
2372 	if (geteuid() != 0)
2373 		ksft_print_msg("Not a root, might fail to mount.\n");
2374 
2375 	mount_dir = setup_mount_dir();
2376 	if (mount_dir == NULL)
2377 		ksft_exit_fail_msg("Can't create a mount dir\n");
2378 
2379 #define MAKE_TEST(test)                                                        \
2380 	{                                                                      \
2381 		test, #test                                                    \
2382 	}
2383 	struct {
2384 		int (*pfunc)(char *dir);
2385 		const char *name;
2386 	} cases[] = {
2387 		MAKE_TEST(basic_file_ops_test),
2388 		MAKE_TEST(cant_touch_index_test),
2389 		MAKE_TEST(dynamic_files_and_data_test),
2390 		MAKE_TEST(concurrent_reads_and_writes_test),
2391 		MAKE_TEST(attribute_test),
2392 		MAKE_TEST(work_after_remount_test),
2393 		MAKE_TEST(child_procs_waiting_for_data_test),
2394 		MAKE_TEST(multiple_providers_test),
2395 		MAKE_TEST(signature_test),
2396 		MAKE_TEST(hash_tree_test),
2397 		MAKE_TEST(read_log_test),
2398 	};
2399 #undef MAKE_TEST
2400 
2401 	ksft_set_plan(ARRAY_SIZE(cases));
2402 
2403 	for (i = 0; i < ARRAY_SIZE(cases); ++i) {
2404 		ksft_print_msg("Running %s\n", cases[i].name);
2405 		if (cases[i].pfunc(mount_dir) == TEST_SUCCESS)
2406 			ksft_test_result_pass("%s\n", cases[i].name);
2407 		else {
2408 			ksft_test_result_fail("%s\n", cases[i].name);
2409 			fails++;
2410 		}
2411 	}
2412 
2413 	umount2(mount_dir, MNT_FORCE);
2414 	rmdir(mount_dir);
2415 
2416 	if (fails > 0)
2417 		ksft_exit_pass();
2418 	else
2419 		ksft_exit_pass();
2420 	return 0;
2421 }
2422