master
c 3,454 lines 117 KB
Raw
1 /*++
2
3 Copyright (c) Microsoft. All rights reserved.
4
5 Module Name:
6
7 OverlayFs.c
8
9 Abstract:
10
11 This file is a overlayfs test.
12
13 N.B. This test depends on libmount, which is part of the libmount-dev
14 apt package.
15
16 N.B. In addition to this unit test, the official overlay test on github
17 should be run when changes are made.
18
19 --*/
20
21 #include "lxtcommon.h"
22 #include "unittests.h"
23 #include <sys/mount.h>
24 #include <linux/capability.h>
25 #include <libgen.h>
26 #include <fcntl.h>
27 #include <stdlib.h>
28 #include <libmount/libmount.h>
29 #include <sys/mman.h>
30 #include <sys/time.h>
31 #include <sys/prctl.h>
32 #include <sys/xattr.h>
33 #include "lxtmount.h"
34 #include <unistd.h>
35 #include <dirent.h>
36 #include <fcntl.h>
37 #include <string.h>
38 #include <utime.h>
39 #include <sys/cdefs.h>
40 #include <linux/capability.h>
41
42 #define LXT_NAME "OverlayFs"
43
44 #define OVFS_TEST_PATH "/data"
45
46 #define OVFS_TEST_MOUNT_PATH OVFS_TEST_PATH "/" OVFS_TEST_MERGED_DIR
47
48 #define OVFS_TEST_MOUNT_NAME "overlay"
49
50 #define OVFS_TEST_LOWER_DIR "ovfs_test_lower"
51 #define OVFS_TEST_LOWER2_DIR "ovfs_test_lower2"
52 #define OVFS_TEST_LOWER3_DIR "ovfs_test_lower3"
53 #define OVFS_TEST_UPPER_DIR "ovfs_test_upper"
54 #define OVFS_TEST_WORK_DIR "ovfs_test_work"
55 #define OVFS_TEST_MERGED_DIR "ovfs_test_merged"
56
57 #define OVFS_TEST_MOUNT_DEFAULT "lowerdir=" OVFS_TEST_LOWER_DIR ",upperdir=" OVFS_TEST_UPPER_DIR ",workdir=" OVFS_TEST_WORK_DIR
58
59 #define OVFS_TEST_MOUNT_MULTI_LOWER \
60 "lowerdir=" OVFS_TEST_LOWER_DIR ":" OVFS_TEST_LOWER2_DIR ":" OVFS_TEST_LOWER3_DIR ",upperdir=" OVFS_TEST_UPPER_DIR \
61 ",workdir=" OVFS_TEST_WORK_DIR
62
63 #define OVFS_TEST_MOUNT_FS_OPTS "rw," OVFS_TEST_MOUNT_DEFAULT
64 #define OVFS_TEST_MOUNT_COMBINED_OPTS "rw,relatime," OVFS_TEST_MOUNT_DEFAULT
65
66 const char* g_OvFsTestDirs[] = {
67 OVFS_TEST_LOWER_DIR, OVFS_TEST_LOWER2_DIR, OVFS_TEST_LOWER3_DIR, OVFS_TEST_UPPER_DIR, OVFS_TEST_WORK_DIR, OVFS_TEST_MOUNT_PATH};
68
69 //
70 // N.B. This data must be kept in sync with OvFsTestDirsPopulate.
71 //
72
73 struct
74 {
75 char* Path;
76 char* Name;
77 mode_t Mode;
78 int Hydrates;
79 } g_OvFsMergedContents[] = {
80 {OVFS_TEST_MOUNT_PATH "/OnlyInLowerDir", "OnlyInLowerDir", S_IFDIR | 0222, 1},
81 {OVFS_TEST_MOUNT_PATH "/OnlyInLowerFile", "OnlyInLowerFile", S_IFREG | 0222, 1},
82 {OVFS_TEST_MOUNT_PATH "/OnlyInLowerSym", "OnlyInLowerSym", S_IFLNK | 0222, 1},
83 {OVFS_TEST_MOUNT_PATH "/OnlyInUpperDir", "OnlyInUpperDir", S_IFDIR | 0777, 0},
84 {OVFS_TEST_MOUNT_PATH "/OnlyInUpperFile", "OnlyInUpperFile", S_IFREG | 0777, 0},
85 {OVFS_TEST_MOUNT_PATH "/OnlyInUpperSym", "OnlyInUpperSym", S_IFLNK | 0777, 0},
86 {OVFS_TEST_MOUNT_PATH "/InBothDir", "InBothDir", S_IFDIR | 0777, 0},
87 {OVFS_TEST_MOUNT_PATH "/InBothFile", "InBothFile", S_IFREG | 0777, 0},
88 {OVFS_TEST_MOUNT_PATH "/InBothSym", "InBothSym", S_IFLNK | 0777, 0}};
89
90 struct
91 {
92 char* Path;
93 char* Name;
94 mode_t Mode;
95 int Hydrates;
96 } g_OvFsMergedMultiContents[] = {
97 {OVFS_TEST_MOUNT_PATH "/OnlyInLowerDir", "OnlyInLowerDir", S_IFDIR | 0222, 1},
98 {OVFS_TEST_MOUNT_PATH "/OnlyInLowerFile", "OnlyInLowerFile", S_IFREG | 0222, 1},
99 {OVFS_TEST_MOUNT_PATH "/OnlyInLowerSym", "OnlyInLowerSym", S_IFLNK | 0222, 1},
100 {OVFS_TEST_MOUNT_PATH "/OnlyInLower2Dir", "OnlyInLower2Dir", S_IFDIR | 0222, 1},
101 {OVFS_TEST_MOUNT_PATH "/OnlyInLower2File", "OnlyInLower2File", S_IFREG | 0222, 1},
102 {OVFS_TEST_MOUNT_PATH "/OnlyInLower23File", "OnlyInLower23File", S_IFREG | 0222, 1},
103 {OVFS_TEST_MOUNT_PATH "/OnlyInLower3Dir", "OnlyInLower3Dir", S_IFDIR | 0222, 1},
104 {OVFS_TEST_MOUNT_PATH "/OnlyInLower3File", "OnlyInLower3File", S_IFREG | 0222, 1},
105 {OVFS_TEST_MOUNT_PATH "/OnlyInUpperDir", "OnlyInUpperDir", S_IFDIR | 0777, 0},
106 {OVFS_TEST_MOUNT_PATH "/OnlyInUpperFile", "OnlyInUpperFile", S_IFREG | 0777, 0},
107 {OVFS_TEST_MOUNT_PATH "/OnlyInUpperSym", "OnlyInUpperSym", S_IFLNK | 0777, 0},
108 {OVFS_TEST_MOUNT_PATH "/InBothDir", "InBothDir", S_IFDIR | 0777, 0},
109 {OVFS_TEST_MOUNT_PATH "/InBothFile", "InBothFile", S_IFREG | 0777, 0},
110 {OVFS_TEST_MOUNT_PATH "/InBothSym", "InBothSym", S_IFLNK | 0777, 0}};
111
112 LXT_VARIATION_HANDLER OvFsTestBasicMount;
113 LXT_VARIATION_HANDLER OvFsTestFileObjectReadOps;
114 LXT_VARIATION_HANDLER OvFsTestFileObjectWriteOpsUpper;
115 LXT_VARIATION_HANDLER OvFsTestInodeOpaque;
116 LXT_VARIATION_HANDLER OvFsTestInodeReadOps;
117 LXT_VARIATION_HANDLER OvFsTestInodeRename;
118 LXT_VARIATION_HANDLER OvFsTestInodeWhiteout;
119 LXT_VARIATION_HANDLER OvFsTestInodeWriteOps;
120 LXT_VARIATION_HANDLER OvFsTestInodeWriteOpsUpper;
121 LXT_VARIATION_HANDLER OvFsTestInodeUnlink;
122 LXT_VARIATION_HANDLER OvFsTestInodeXattr;
123 LXT_VARIATION_HANDLER OvFsTestLowerWhiteout;
124 LXT_VARIATION_HANDLER OvFsTestMultipleLower;
125
126 int OvFsTestDirsPopulate(void);
127
128 int OvFsTestDirsSetup(void);
129
130 //
131 // Global constants
132 //
133
134 static const LXT_VARIATION g_LxtVariations[] = {
135 {"OverlayFs - basic mount", OvFsTestBasicMount},
136 {"OverlayFs - inode read ops", OvFsTestInodeReadOps},
137 {"OverlayFs - file object read ops", OvFsTestFileObjectReadOps},
138 {"OverlayFs - inode write ops upper", OvFsTestInodeWriteOpsUpper},
139 {"OverlayFs - file object write ops upper", OvFsTestFileObjectWriteOpsUpper},
140 {"OverlayFs - inode write ops", OvFsTestInodeWriteOps},
141 {"OverlayFs - inode unlink", OvFsTestInodeUnlink},
142 {"OverlayFs - whiteout", OvFsTestInodeWhiteout},
143 {"OverlayFs - opaque", OvFsTestInodeOpaque},
144 {"OverlayFs - rename", OvFsTestInodeRename},
145 {"OverlayFs - xattr", OvFsTestInodeXattr},
146 {"OverlayFs - multiple lower layers", OvFsTestMultipleLower},
147 {"OverlayFs - lower layer whiteouts", OvFsTestLowerWhiteout}};
148
149 static int g_TestPathMountId;
150
151 const int g_LxtUnstableInodes = 0;
152
153 int OverlayFsTestEntry(int Argc, char* Argv[])
154
155 /*++
156 --*/
157
158 {
159
160 LXT_ARGS Args;
161 int Result;
162
163 //
164 // TODO_LX: Support other filesystems than volfs.
165 //
166
167 LxtCheckResult(g_TestPathMountId = MountGetMountId(OVFS_TEST_PATH));
168 LxtCheckResult(LxtInitialize(Argc, Argv, &Args, LXT_NAME));
169 LxtCheckErrno(chdir(OVFS_TEST_PATH));
170 LxtCheckResult(LxtRunVariations(&Args, g_LxtVariations, LXT_COUNT_OF(g_LxtVariations)));
171
172 ErrorExit:
173
174 char DeleteCmd[128];
175
176 for (int Index = 0; Index < LXT_COUNT_OF(g_OvFsTestDirs); ++Index)
177 {
178 sprintf(DeleteCmd, "rm -rf %s", g_OvFsTestDirs[Index]);
179 if (system(DeleteCmd) < 0)
180 {
181 LxtLogError("Failed to delete %s", g_OvFsTestDirs[Index]);
182 }
183 }
184
185 LxtUninitialize();
186 return !LXT_SUCCESS(Result);
187 }
188
189 int OvFsTestBasicMount(PLXT_ARGS Args)
190
191 /*++
192
193 Description:
194
195 This routine tests the mount and umount system calls for overlayfs.
196
197 Arguments:
198
199 Args - Supplies the command line arguments.
200
201 Return Value:
202
203 Returns 0 on success, -1 on failure.
204
205 --*/
206
207 {
208
209 int Index;
210 struct
211 {
212 char* Options;
213 int Errno;
214 } InvalidOpts[] = {
215 {NULL, EINVAL},
216 {"", EINVAL},
217 {"lowerdir=doesNotExist"
218 ",upperdir=" OVFS_TEST_UPPER_DIR ",workdir=" OVFS_TEST_WORK_DIR,
219 ENOENT},
220 {"lowerdir=" OVFS_TEST_LOWER_DIR ",lowerdir=" OVFS_TEST_UPPER_DIR ",workdir=" OVFS_TEST_WORK_DIR, EINVAL},
221 {"lowerdir=" OVFS_TEST_LOWER_DIR ",workdir=" OVFS_TEST_WORK_DIR, EINVAL},
222 {"lowerdir=" OVFS_TEST_LOWER_DIR ",upperdir=" OVFS_TEST_UPPER_DIR ",workdir=" OVFS_TEST_UPPER_DIR, EINVAL},
223 {"lowerdir=" OVFS_TEST_LOWER_DIR ",upperdir=" OVFS_TEST_UPPER_DIR ",workdir=" OVFS_TEST_UPPER_DIR "/" OVFS_TEST_WORK_DIR, EINVAL},
224 {"lowerdir=:"
225 ",upperdir=" OVFS_TEST_UPPER_DIR ",workdir=" OVFS_TEST_WORK_DIR,
226 EINVAL},
227 {"lowerdir=" OVFS_TEST_LOWER_DIR ":"
228 ",upperdir=" OVFS_TEST_UPPER_DIR ",workdir=" OVFS_TEST_WORK_DIR,
229 EINVAL},
230 {"lowerdir=" OVFS_TEST_LOWER_DIR ":" OVFS_TEST_LOWER_DIR ":" OVFS_TEST_LOWER_DIR ":"
231 ",upperdir=" OVFS_TEST_UPPER_DIR ",workdir=" OVFS_TEST_WORK_DIR,
232 EINVAL},
233 {"lowerdir=" OVFS_TEST_LOWER_DIR ":" OVFS_TEST_LOWER_DIR ":"
234 "doesNotExist"
235 ",upperdir=" OVFS_TEST_UPPER_DIR ",workdir=" OVFS_TEST_WORK_DIR,
236 ENOENT}};
237 int MountId;
238 int Result;
239
240 //
241 // Set up the directories and ensure it's not a mount point yet.
242 //
243
244 LxtCheckResult(OvFsTestDirsSetup());
245 LxtCheckResult(MountCheckIsNotMount(OVFS_TEST_MOUNT_PATH));
246
247 //
248 // Mount an overlayfs instance and check it was mounted.
249 //
250
251 LxtCheckErrnoZeroSuccess(mount("myovfsnew", OVFS_TEST_MOUNT_PATH, OVFS_TEST_MOUNT_NAME, 0, OVFS_TEST_MOUNT_DEFAULT));
252
253 LxtCheckResult(
254 MountId = MountCheckIsMount(
255 OVFS_TEST_MOUNT_PATH, g_TestPathMountId, "myovfsnew", OVFS_TEST_MOUNT_NAME, "/", "rw,relatime", OVFS_TEST_MOUNT_FS_OPTS, OVFS_TEST_MOUNT_COMBINED_OPTS, 0));
256
257 //
258 // Mounting again should succeed.
259 //
260
261 LxtCheckErrnoZeroSuccess(mount("myovfsnew", OVFS_TEST_MOUNT_PATH, OVFS_TEST_MOUNT_NAME, 0, OVFS_TEST_MOUNT_DEFAULT));
262
263 LxtCheckResult(
264 MountId = MountCheckIsMount(
265 OVFS_TEST_MOUNT_PATH, MountId, "myovfsnew", OVFS_TEST_MOUNT_NAME, "/", "rw,relatime", OVFS_TEST_MOUNT_FS_OPTS, OVFS_TEST_MOUNT_COMBINED_OPTS, 0));
266
267 LxtCheckErrnoZeroSuccess(umount(OVFS_TEST_MOUNT_PATH));
268 LxtCheckResult(
269 MountId = MountCheckIsMount(
270 OVFS_TEST_MOUNT_PATH, g_TestPathMountId, "myovfsnew", OVFS_TEST_MOUNT_NAME, "/", "rw,relatime", OVFS_TEST_MOUNT_FS_OPTS, OVFS_TEST_MOUNT_COMBINED_OPTS, 0));
271
272 //
273 // Unmount and check it was unmounted.
274 //
275
276 LxtCheckErrnoZeroSuccess(umount(OVFS_TEST_MOUNT_PATH));
277 LxtCheckResult(MountCheckIsNotMount(OVFS_TEST_MOUNT_PATH));
278
279 //
280 // Check invalid mount parameters.
281 //
282
283 LxtLogInfo("Checking invalid options...");
284 mkdir(OVFS_TEST_UPPER_DIR "/" OVFS_TEST_WORK_DIR, 0777);
285 for (Index = 0; Index < LXT_COUNT_OF(InvalidOpts); ++Index)
286 {
287 LxtCheckErrnoFailure(
288 mount("myovfsnew", OVFS_TEST_MOUNT_PATH, OVFS_TEST_MOUNT_NAME, 0, InvalidOpts[Index].Options), InvalidOpts[Index].Errno);
289 }
290
291 Result = 0;
292
293 ErrorExit:
294 umount(OVFS_TEST_MOUNT_PATH);
295 return Result;
296 }
297
298 int OvFsTestDirsPopulate(void)
299
300 /*++
301
302 Description:
303
304 This routine populates the mount directories.
305
306 N.B. This data must be kept in sync with g_OvFsMergedContents.
307
308 Arguments:
309
310 None.
311
312 Return Value:
313
314 Returns 0 on success, -1 on failure.
315
316 --*/
317
318 {
319
320 char XattrName[64];
321 int Fd;
322 char* FileName;
323 int Index;
324 struct
325 {
326 char* Name;
327 int Mode;
328 } Paths[] = {
329 {OVFS_TEST_LOWER_DIR "/OnlyInLowerDir", S_IFDIR | 0666},
330 {OVFS_TEST_LOWER_DIR "/InBothDir", S_IFDIR | 0666},
331 {OVFS_TEST_LOWER_DIR "/OnlyInLowerFile", S_IFREG | 0666},
332 {OVFS_TEST_LOWER_DIR "/InBothFile", S_IFREG | 0666},
333
334 {OVFS_TEST_LOWER2_DIR "/OnlyInLower2Dir", S_IFDIR | 0444},
335 {OVFS_TEST_LOWER2_DIR "/InBothDir", S_IFDIR | 0444},
336 {OVFS_TEST_LOWER2_DIR "/OnlyInLower2File", S_IFREG | 0444},
337 {OVFS_TEST_LOWER2_DIR "/OnlyInLower23File", S_IFREG | 0444},
338 {OVFS_TEST_LOWER2_DIR "/InBothFile", S_IFREG | 0444},
339
340 {OVFS_TEST_LOWER3_DIR "/OnlyInLower3Dir", S_IFDIR | 0111},
341 {OVFS_TEST_LOWER3_DIR "/InBothDir", S_IFDIR | 0111},
342 {OVFS_TEST_LOWER3_DIR "/OnlyInLower3File", S_IFREG | 0111},
343 {OVFS_TEST_LOWER3_DIR "/OnlyInLower23File", S_IFREG | 0111},
344 {OVFS_TEST_LOWER3_DIR "/InBothFile", S_IFREG | 0111},
345
346 {OVFS_TEST_UPPER_DIR "/OnlyInUpperDir", S_IFDIR | 0777},
347 {OVFS_TEST_UPPER_DIR "/InBothDir", S_IFDIR | 0777},
348 {OVFS_TEST_UPPER_DIR "/OnlyInUpperFile", S_IFREG | 0777},
349 {OVFS_TEST_UPPER_DIR "/InBothFile", S_IFREG | 0777}};
350 int Result;
351
352 Fd = -1;
353
354 for (Index = 0; Index < LXT_COUNT_OF(Paths); ++Index)
355 {
356 FileName = strrchr(Paths[Index].Name, '/') + 1;
357 if (S_ISREG(Paths[Index].Mode))
358 {
359 LxtCheckErrno(Fd = creat(Paths[Index].Name, Paths[Index].Mode));
360 LxtCheckErrno(write(Fd, FileName, strlen(FileName) + 1));
361 LxtClose(Fd);
362 Fd = -1;
363 }
364 else
365 {
366 LxtCheckErrno(mkdir(Paths[Index].Name, Paths[Index].Mode));
367 }
368
369 LxtCheckErrno(lsetxattr(Paths[Index].Name, "trusted.overlaytest", FileName, strlen(FileName) + 1, XATTR_CREATE));
370
371 sprintf(XattrName, "trusted.%s", FileName);
372 LxtCheckErrno(lsetxattr(Paths[Index].Name, XattrName, FileName, strlen(FileName) + 1, XATTR_CREATE));
373 }
374
375 //
376 // N.B. xattrs cannot be set on symbolic links on all filesystems.
377 //
378
379 LxtCheckErrno(symlink(OVFS_TEST_LOWER_DIR "/OnlyInLowerFile", OVFS_TEST_LOWER_DIR "/OnlyInLowerSym"));
380
381 LxtCheckErrno(symlink(OVFS_TEST_LOWER_DIR "/InBothFile", OVFS_TEST_LOWER_DIR "/InBothSym"));
382
383 LxtCheckErrno(symlink(OVFS_TEST_UPPER_DIR "/OnlyInUpperFile", OVFS_TEST_UPPER_DIR "/OnlyInUpperSym"));
384
385 LxtCheckErrno(symlink(OVFS_TEST_UPPER_DIR "/InBothFile", OVFS_TEST_UPPER_DIR "/InBothSym"));
386
387 ErrorExit:
388 if (Fd != -1)
389 {
390 LxtClose(Fd);
391 }
392
393 return Result;
394 }
395
396 int OvFsTestDirsSetup(void)
397
398 /*++
399
400 Description:
401
402 This routine prepares the mount directories.
403
404 Arguments:
405
406 None.
407
408 Return Value:
409
410 Returns 0 on success, -1 on failure.
411
412 --*/
413
414 {
415
416 char DeleteCmd[128];
417 int Index;
418 int Result;
419
420 umount(OVFS_TEST_MOUNT_PATH);
421 sprintf(DeleteCmd, "rm -rf %s", OVFS_TEST_MOUNT_PATH);
422 system(DeleteCmd);
423 LxtCheckErrno(mkdir(OVFS_TEST_MOUNT_PATH, 0777));
424 for (Index = 0; Index < LXT_COUNT_OF(g_OvFsTestDirs); ++Index)
425 {
426 sprintf(DeleteCmd, "rm -rf %s", g_OvFsTestDirs[Index]);
427 system(DeleteCmd);
428 LxtCheckErrno(mkdir(g_OvFsTestDirs[Index], 0777));
429 }
430
431 Result = 0;
432
433 ErrorExit:
434 return Result;
435 }
436
437 int OvFsTestFileObjectReadOps(PLXT_ARGS Args)
438
439 /*++
440
441 Description:
442
443 This routine tests file object operations that do not modify state.
444
445 Arguments:
446
447 Args - Supplies the command line arguments.
448
449 Return Value:
450
451 Returns 0 on success, -1 on failure.
452
453 --*/
454
455 {
456
457 char Buffer[100];
458 int BytesRead;
459 int Count;
460 struct dirent* Entry;
461 int EntryPosition;
462 int Fd;
463 int Found[LXT_COUNT_OF(g_OvFsMergedContents) + 2];
464 int FoundIndex;
465 int Index;
466 void* Mapping;
467 void* MapResult;
468 int Result;
469 struct stat StatBuffer;
470 struct stat StatMergedBuffer;
471
472 Fd = -1;
473 Mapping = NULL;
474
475 //
476 // Set up the directories and populate some state.
477 //
478
479 LxtCheckResult(OvFsTestDirsSetup());
480 LxtCheckResult(OvFsTestDirsPopulate());
481
482 //
483 // Mount an overlayfs instance and check inode operations that do not
484 // hydrate files.
485 //
486
487 LxtCheckResult(MountCheckIsNotMount(OVFS_TEST_MOUNT_PATH));
488 LxtCheckErrnoZeroSuccess(mount("myovfsnew", OVFS_TEST_MOUNT_PATH, OVFS_TEST_MOUNT_NAME, 0, OVFS_TEST_MOUNT_DEFAULT));
489
490 //
491 // Check the behavior for VFS file object operations that support file
492 // descriptors opened for read only.
493 //
494 // N.B. All other file operations will fail the request and are verified
495 // in the VFS access test.
496 //
497
498 //
499 // Check the behavior for read directory on the root.
500 //
501
502 memset(Found, 0, sizeof(Found));
503 LxtCheckErrno(Fd = open(OVFS_TEST_MOUNT_PATH, O_RDONLY));
504 LxtCheckErrno(BytesRead = LxtGetdents64(Fd, (struct dirent*)Buffer, sizeof(Buffer)));
505
506 while (BytesRead > 0)
507 {
508 for (EntryPosition = 0; EntryPosition < BytesRead; EntryPosition += Entry->d_reclen)
509 {
510
511 Entry = (struct dirent*)&Buffer[EntryPosition];
512 if (strcmp(Entry->d_name, ".") == 0)
513 {
514 FoundIndex = 0;
515 }
516 else if (strcmp(Entry->d_name, "..") == 0)
517 {
518 FoundIndex = 1;
519 }
520 else
521 {
522 for (Index = 0; Index < LXT_COUNT_OF(g_OvFsMergedContents); ++Index)
523 {
524 if (strcmp(g_OvFsMergedContents[Index].Name, Entry->d_name) == 0)
525 {
526 FoundIndex = Index + 2;
527 break;
528 }
529 }
530
531 if (Index == LXT_COUNT_OF(g_OvFsMergedContents))
532 {
533 LxtLogError("Unexpected entry %s", Entry->d_name);
534 LxtCheckNotEqual(Index, LXT_COUNT_OF(g_OvFsMergedContents), "%d");
535 }
536 }
537
538 LxtCheckEqual(Found[FoundIndex], 0, "%d");
539 Found[FoundIndex] = 1;
540 }
541
542 Entry = (struct dirent*)Buffer;
543 LxtCheckErrno(BytesRead = LxtGetdents64(Fd, (struct dirent*)Buffer, sizeof(Buffer)));
544 }
545
546 for (Index = 0; Index < LXT_COUNT_OF(Found); ++Index)
547 {
548 LxtCheckEqual(Found[FoundIndex], 1, "%d");
549 }
550
551 LxtClose(Fd);
552 Fd = -1;
553
554 //
555 // Check the behavior for read directory on sub directories.
556 //
557
558 for (Index = 0; Index < LXT_COUNT_OF(g_OvFsMergedContents); ++Index)
559 {
560 if (S_ISDIR(g_OvFsMergedContents[Index].Mode) == FALSE)
561 {
562 continue;
563 }
564
565 LxtCheckErrno(Fd = open(g_OvFsMergedContents[Index].Path, O_RDONLY));
566 LxtCheckErrno(BytesRead = LxtGetdents64(Fd, (struct dirent*)Buffer, sizeof(Buffer)))
567
568 Count = 0;
569 for (EntryPosition = 0; EntryPosition < BytesRead; EntryPosition += Entry->d_reclen)
570 {
571
572 Entry = (struct dirent*)&Buffer[EntryPosition];
573 Count += 1;
574 }
575
576 LxtCheckEqual(Count, 2, "%d");
577 LxtClose(Fd);
578 Fd = -1;
579 }
580
581 //
582 // Check the behavior for map.
583 //
584
585 for (Index = 0; Index < LXT_COUNT_OF(g_OvFsMergedContents); ++Index)
586 {
587 if (S_ISREG(g_OvFsMergedContents[Index].Mode) == FALSE)
588 {
589 continue;
590 }
591
592 LxtCheckErrno(Fd = open(g_OvFsMergedContents[Index].Path, O_RDONLY));
593 LxtCheckMapErrno(Mapping = mmap(NULL, PAGE_SIZE, PROT_READ, MAP_SHARED, Fd, 0));
594 LxtCheckStringEqual(Mapping, g_OvFsMergedContents[Index].Name);
595 munmap(Mapping, PAGE_SIZE);
596 Mapping = MAP_FAILED;
597 LxtClose(Fd);
598 Fd = -1;
599 }
600
601 //
602 // Check the behavior for ioctl.
603 //
604
605 for (Index = 0; Index < LXT_COUNT_OF(g_OvFsMergedContents); ++Index)
606 {
607 if (S_ISREG(g_OvFsMergedContents[Index].Mode) == FALSE)
608 {
609 continue;
610 }
611
612 LxtCheckErrno(Fd = open(g_OvFsMergedContents[Index].Path, O_RDONLY));
613 LxtCheckErrno(ioctl(Fd, FIONREAD, &BytesRead));
614 LxtCheckEqual(BytesRead, strlen(g_OvFsMergedContents[Index].Name) + 1, "%d");
615 LxtClose(Fd);
616 Fd = -1;
617 }
618
619 //
620 // Check the behavior for sync.
621 //
622
623 for (Index = 0; Index < LXT_COUNT_OF(g_OvFsMergedContents); ++Index)
624 {
625 if ((S_ISDIR(g_OvFsMergedContents[Index].Mode) == FALSE) && (S_ISREG(g_OvFsMergedContents[Index].Mode) == FALSE))
626 {
627
628 continue;
629 }
630
631 LxtCheckErrno(Fd = open(g_OvFsMergedContents[Index].Path, O_RDONLY));
632 LxtCheckErrno(fsync(Fd));
633 LxtClose(Fd);
634 Fd = -1;
635 }
636
637 //
638 // Check the behavior for read file.
639 //
640
641 for (Index = 0; Index < LXT_COUNT_OF(g_OvFsMergedContents); ++Index)
642 {
643 if (S_ISREG(g_OvFsMergedContents[Index].Mode) == FALSE)
644 {
645 continue;
646 }
647
648 LxtCheckErrno(Fd = open(g_OvFsMergedContents[Index].Path, O_RDONLY));
649 LxtCheckErrno(BytesRead = read(Fd, Buffer, sizeof(Buffer) - 1));
650 Buffer[BytesRead] = 0;
651 LxtCheckStringEqual(Buffer, g_OvFsMergedContents[Index].Name);
652 LxtClose(Fd);
653 Fd = -1;
654 }
655
656 //
657 // Check the behavior for seek.
658 //
659
660 for (Index = 0; Index < LXT_COUNT_OF(g_OvFsMergedContents); ++Index)
661 {
662 if ((S_ISDIR(g_OvFsMergedContents[Index].Mode) == FALSE) && (S_ISREG(g_OvFsMergedContents[Index].Mode) == FALSE))
663 {
664
665 continue;
666 }
667
668 LxtLogInfo("%s", g_OvFsMergedContents[Index].Path);
669 LxtCheckErrno(Fd = open(g_OvFsMergedContents[Index].Path, O_RDONLY));
670 LxtCheckErrno(lseek(Fd, SEEK_SET, 1));
671 LxtClose(Fd);
672 Fd = -1;
673 }
674
675 //
676 // Check that none of the operations hydrated files from the lower
677 // directory.
678 //
679
680 LxtCheckErrnoFailure(stat(OVFS_TEST_UPPER_DIR "/OnlyInLowerDir", &StatBuffer), ENOENT);
681 LxtCheckErrnoFailure(stat(OVFS_TEST_UPPER_DIR "/OnlyInLowerFile", &StatBuffer), ENOENT);
682 LxtCheckErrnoFailure(stat(OVFS_TEST_UPPER_DIR "/OnlyInLowerSym", &StatBuffer), ENOENT);
683
684 //
685 // Unmount and check it was unmounted.
686 //
687
688 if (Fd != -1)
689 {
690 LxtClose(Fd);
691 Fd = -1;
692 }
693
694 LxtCheckErrnoZeroSuccess(umount(OVFS_TEST_MOUNT_PATH));
695 LxtCheckResult(MountCheckIsNotMount(OVFS_TEST_MOUNT_PATH));
696 Result = 0;
697
698 ErrorExit:
699 if (Mapping != MAP_FAILED)
700 {
701 munmap(Mapping, PAGE_SIZE);
702 }
703
704 if (Fd != -1)
705 {
706 LxtClose(Fd);
707 }
708
709 umount(OVFS_TEST_MOUNT_PATH);
710 return Result;
711 }
712
713 int OvFsTestFileObjectWriteOpsUpper(PLXT_ARGS Args)
714
715 /*++
716
717 Description:
718
719 This routine tests file object write operations that do not modify the
720 lower.
721
722 Arguments:
723
724 Args - Supplies the command line arguments.
725
726 Return Value:
727
728 Returns 0 on success, -1 on failure.
729
730 --*/
731
732 {
733
734 char Buffer[100];
735 char BufferExpected[100];
736 int BytesRead;
737 int BytesWritten;
738 int Count;
739 struct dirent* Entry;
740 int EntryPosition;
741 int Fd;
742 int Found[LXT_COUNT_OF(g_OvFsMergedContents) + 2];
743 int FoundIndex;
744 int Index;
745 void* Mapping;
746 void* MapResult;
747 int Result;
748 struct stat StatBuffer;
749 struct stat StatMergedBuffer;
750
751 Fd = -1;
752 Mapping = NULL;
753
754 //
755 // Set up the directories and populate some state.
756 //
757
758 LxtCheckResult(OvFsTestDirsSetup());
759 LxtCheckResult(OvFsTestDirsPopulate());
760
761 //
762 // Mount an overlayfs instance and check inode operations that modify the
763 // upper but do not hydrate files.
764 //
765 // N.B. The overlay fs mount does not need to be recreated after each
766 // variation since only the upper is modified.
767 //
768
769 LxtCheckResult(MountCheckIsNotMount(OVFS_TEST_MOUNT_PATH));
770 LxtCheckErrnoZeroSuccess(mount("myovfsnew", OVFS_TEST_MOUNT_PATH, OVFS_TEST_MOUNT_NAME, 0, OVFS_TEST_MOUNT_DEFAULT));
771
772 //
773 // Check the behavior for map.
774 //
775
776 for (Index = 0; Index < LXT_COUNT_OF(g_OvFsMergedContents); ++Index)
777 {
778 if ((S_ISREG(g_OvFsMergedContents[Index].Mode) == FALSE) || (g_OvFsMergedContents[Index].Hydrates != 0))
779 {
780
781 continue;
782 }
783
784 LxtCheckErrno(Fd = open(g_OvFsMergedContents[Index].Path, O_RDWR));
785 LxtCheckMapErrno(Mapping = mmap(NULL, PAGE_SIZE, PROT_READ | PROT_WRITE, MAP_SHARED, Fd, 0));
786 LxtCheckStringEqual(Mapping, g_OvFsMergedContents[Index].Name);
787 munmap(Mapping, PAGE_SIZE);
788 Mapping = MAP_FAILED;
789 LxtClose(Fd);
790 Fd = -1;
791 }
792
793 //
794 // Check the behavior for truncate.
795 //
796
797 for (Index = 0; Index < LXT_COUNT_OF(g_OvFsMergedContents); ++Index)
798 {
799 if ((S_ISREG(g_OvFsMergedContents[Index].Mode) == FALSE) || (g_OvFsMergedContents[Index].Hydrates != 0))
800 {
801
802 continue;
803 }
804
805 LxtCheckErrno(Fd = open(g_OvFsMergedContents[Index].Path, O_RDWR));
806 LxtCheckErrno(ftruncate(Fd, 0));
807 LxtClose(Fd);
808 Fd = -1;
809 }
810
811 //
812 // Check the behavior for fallocate.
813 //
814
815 for (Index = 0; Index < LXT_COUNT_OF(g_OvFsMergedContents); ++Index)
816 {
817 if ((S_ISREG(g_OvFsMergedContents[Index].Mode) == FALSE) || (g_OvFsMergedContents[Index].Hydrates != 0))
818 {
819
820 continue;
821 }
822
823 LxtCheckErrno(Fd = open(g_OvFsMergedContents[Index].Path, O_RDWR));
824 LxtCheckErrno(fallocate(Fd, 0, 0, strlen(g_OvFsMergedContents[Index].Name) + 1));
825 LxtClose(Fd);
826 Fd = -1;
827 }
828
829 //
830 // Check the behavior for write file.
831 //
832
833 memset(BufferExpected, 0, sizeof(BufferExpected));
834 for (Index = 0; Index < LXT_COUNT_OF(g_OvFsMergedContents); ++Index)
835 {
836 if ((S_ISREG(g_OvFsMergedContents[Index].Mode) == FALSE) || (g_OvFsMergedContents[Index].Hydrates != 0))
837 {
838
839 continue;
840 }
841
842 LxtCheckErrno(Fd = open(g_OvFsMergedContents[Index].Path, O_RDWR));
843 LxtCheckErrno(BytesRead = read(Fd, Buffer, sizeof(Buffer) - 1));
844 Buffer[BytesRead] = 0;
845 LxtCheckEqual(BytesRead, strlen(g_OvFsMergedContents[Index].Name) + 1, "%d");
846 LxtCheckMemoryEqual(Buffer, BufferExpected, BytesRead);
847 LxtCheckErrno(lseek(Fd, SEEK_SET, 0));
848 LxtCheckErrno(BytesWritten = write(Fd, g_OvFsMergedContents[Index].Name, strlen(g_OvFsMergedContents[Index].Name) + 1));
849 LxtCheckEqual(BytesWritten, strlen(g_OvFsMergedContents[Index].Name) + 1, "%d");
850 LxtCheckErrno(lseek(Fd, SEEK_SET, 0));
851 LxtCheckErrno(BytesRead = read(Fd, Buffer, sizeof(Buffer) - 1));
852 Buffer[BytesRead] = 0;
853 LxtCheckStringEqual(Buffer, g_OvFsMergedContents[Index].Name);
854 LxtClose(Fd);
855 Fd = -1;
856 }
857
858 //
859 // Check that none of the operations hydrated files from the lower
860 // directory.
861 //
862
863 LxtCheckErrnoFailure(stat(OVFS_TEST_UPPER_DIR "/OnlyInLowerDir", &StatBuffer), ENOENT);
864 LxtCheckErrnoFailure(stat(OVFS_TEST_UPPER_DIR "/OnlyInLowerFile", &StatBuffer), ENOENT);
865 LxtCheckErrnoFailure(stat(OVFS_TEST_UPPER_DIR "/OnlyInLowerSym", &StatBuffer), ENOENT);
866
867 //
868 // Unmount and check it was unmounted.
869 //
870
871 if (Fd != -1)
872 {
873 LxtClose(Fd);
874 Fd = -1;
875 }
876
877 LxtCheckErrnoZeroSuccess(umount(OVFS_TEST_MOUNT_PATH));
878 LxtCheckResult(MountCheckIsNotMount(OVFS_TEST_MOUNT_PATH));
879 Result = 0;
880
881 ErrorExit:
882 if (Mapping != MAP_FAILED)
883 {
884 munmap(Mapping, PAGE_SIZE);
885 }
886
887 if (Fd != -1)
888 {
889 LxtClose(Fd);
890 }
891
892 umount(OVFS_TEST_MOUNT_PATH);
893 return Result;
894 }
895
896 int OvFsTestInodeOpaque(PLXT_ARGS Args)
897
898 /*++
899
900 Description:
901
902 This routine tests inode opaque operations.
903
904 Arguments:
905
906 Args - Supplies the command line arguments.
907
908 Return Value:
909
910 Returns 0 on success, -1 on failure.
911
912 --*/
913
914 {
915
916 char Buffer[100];
917 int BytesRead;
918 int Count;
919 struct dirent* Entry;
920 int EntryPosition;
921 int Fd;
922 int Result;
923 struct stat StatBuffer;
924
925 Fd = -1;
926
927 //
928 // Set up the directories and populate some state.
929 //
930
931 LxtCheckResult(OvFsTestDirsSetup());
932 LxtCheckResult(OvFsTestDirsPopulate());
933
934 //
935 // Create a file in each directory.
936 //
937
938 LxtCheckErrno(Fd = creat(OVFS_TEST_LOWER_DIR "/OnlyInLowerDir/OnlyInLowerDirFile", 0777));
939 LxtClose(Fd);
940 Fd = -1;
941 LxtCheckErrno(Fd = creat(OVFS_TEST_LOWER_DIR "/InBothDir/InBothDirLowerFile", 0777));
942 LxtClose(Fd);
943 Fd = -1;
944 LxtCheckErrno(Fd = creat(OVFS_TEST_UPPER_DIR "/OnlyInUpperDir/OnlyInUpperDirFile", 0777));
945 LxtClose(Fd);
946 Fd = -1;
947 LxtCheckErrno(Fd = creat(OVFS_TEST_UPPER_DIR "/InBothDir/InBothDirUpperFile", 0777));
948 LxtClose(Fd);
949 Fd = -1;
950
951 //
952 // Mount an overlayfs instance and check for the expected file state.
953 //
954
955 LxtCheckResult(MountCheckIsNotMount(OVFS_TEST_MOUNT_PATH));
956 LxtCheckErrnoZeroSuccess(mount("myovfsnew", OVFS_TEST_MOUNT_PATH, OVFS_TEST_MOUNT_NAME, 0, OVFS_TEST_MOUNT_DEFAULT));
957
958 LxtCheckErrno(stat(OVFS_TEST_MERGED_DIR "/InBothDir/InBothDirLowerFile", &StatBuffer));
959 LxtCheckTrue(S_ISREG(StatBuffer.st_mode));
960 LxtCheckErrno(stat(OVFS_TEST_MERGED_DIR "/InBothDir/InBothDirUpperFile", &StatBuffer));
961 LxtCheckTrue(S_ISREG(StatBuffer.st_mode));
962
963 LxtCheckErrnoFailure(stat(OVFS_TEST_UPPER_DIR "/OnlyInLowerDir", &StatBuffer), ENOENT);
964 LxtCheckErrnoFailure(stat(OVFS_TEST_UPPER_DIR "/OnlyInLowerFile", &StatBuffer), ENOENT);
965 LxtCheckErrnoFailure(stat(OVFS_TEST_UPPER_DIR "/OnlyInLowerSym", &StatBuffer), ENOENT);
966 LxtCheckErrno(stat(OVFS_TEST_UPPER_DIR "/OnlyInUpperDir", &StatBuffer));
967 LxtCheckTrue(S_ISDIR(StatBuffer.st_mode));
968 LxtCheckErrno(stat(OVFS_TEST_UPPER_DIR "/OnlyInUpperFile", &StatBuffer));
969 LxtCheckTrue(S_ISREG(StatBuffer.st_mode));
970 LxtCheckErrno(lstat(OVFS_TEST_UPPER_DIR "/OnlyInUpperSym", &StatBuffer));
971 LxtCheckTrue(S_ISLNK(StatBuffer.st_mode));
972 LxtCheckErrno(stat(OVFS_TEST_UPPER_DIR "/InBothDir", &StatBuffer));
973 LxtCheckTrue(S_ISDIR(StatBuffer.st_mode));
974 LxtCheckErrno(stat(OVFS_TEST_UPPER_DIR "/InBothFile", &StatBuffer));
975 LxtCheckTrue(S_ISREG(StatBuffer.st_mode));
976 LxtCheckErrno(lstat(OVFS_TEST_UPPER_DIR "/InBothSym", &StatBuffer));
977 LxtCheckTrue(S_ISLNK(StatBuffer.st_mode));
978
979 //
980 // Remove each directory and check that it is removed, first checking for
981 // the expected failure code.
982 //
983
984 LxtCheckErrnoFailure(rmdir(OVFS_TEST_MERGED_DIR "/OnlyInLowerDir"), ENOTEMPTY);
985 LxtCheckErrno(unlink(OVFS_TEST_MERGED_DIR "/OnlyInLowerDir/OnlyInLowerDirFile"));
986 LxtCheckErrno(stat(OVFS_TEST_UPPER_DIR "/OnlyInLowerDir/OnlyInLowerDirFile", &StatBuffer));
987 LxtCheckTrue(S_ISCHR(StatBuffer.st_mode));
988 LxtCheckErrno(rmdir(OVFS_TEST_MERGED_DIR "/OnlyInLowerDir"));
989 LxtCheckErrno(stat(OVFS_TEST_UPPER_DIR "/OnlyInLowerDir", &StatBuffer));
990 LxtCheckTrue(S_ISCHR(StatBuffer.st_mode));
991
992 LxtCheckErrnoFailure(rmdir(OVFS_TEST_MERGED_DIR "/OnlyInUpperDir"), ENOTEMPTY);
993 LxtCheckErrno(unlink(OVFS_TEST_MERGED_DIR "/OnlyInUpperDir/OnlyInUpperDirFile"));
994 LxtCheckErrnoFailure(stat(OVFS_TEST_MERGED_DIR "/OnlyInUpperDir/OnlyInUpperDirFile", &StatBuffer), ENOENT);
995 LxtCheckErrno(rmdir(OVFS_TEST_MERGED_DIR "/OnlyInUpperDir"));
996 LxtCheckErrnoFailure(stat(OVFS_TEST_UPPER_DIR "/OnlyInUpperDir", &StatBuffer), ENOENT);
997
998 LxtCheckErrnoFailure(rmdir(OVFS_TEST_MERGED_DIR "/InBothDir"), ENOTEMPTY);
999 LxtCheckErrno(unlink(OVFS_TEST_MERGED_DIR "/InBothDir/InBothDirUpperFile"));
1000 LxtCheckErrnoFailure(stat(OVFS_TEST_MERGED_DIR "/OnlyInUpperDir/OnlyInUpperDirFile", &StatBuffer), ENOENT);
1001 LxtCheckErrnoFailure(rmdir(OVFS_TEST_MERGED_DIR "/InBothDir"), ENOTEMPTY);
1002 LxtCheckErrno(unlink(OVFS_TEST_MERGED_DIR "/InBothDir/InBothDirLowerFile"));
1003 LxtCheckErrnoFailure(stat(OVFS_TEST_MERGED_DIR "/OnlyInLowerDir/OnlyInLowerDirFile", &StatBuffer), ENOENT);
1004 LxtCheckErrno(rmdir(OVFS_TEST_MERGED_DIR "/InBothDir"));
1005 LxtCheckErrno(stat(OVFS_TEST_UPPER_DIR "/InBothDir", &StatBuffer));
1006 LxtCheckTrue(S_ISCHR(StatBuffer.st_mode));
1007
1008 //
1009 // Enumerate the top level and check that the three directories have been
1010 // removed.
1011 //
1012
1013 Count = 0;
1014 LxtCheckErrno(Fd = open(OVFS_TEST_MOUNT_PATH, O_RDONLY));
1015 LxtCheckErrno(BytesRead = LxtGetdents64(Fd, (struct dirent*)Buffer, sizeof(Buffer)));
1016
1017 while (BytesRead > 0)
1018 {
1019 for (EntryPosition = 0; EntryPosition < BytesRead; EntryPosition += Entry->d_reclen)
1020 {
1021
1022 Entry = (struct dirent*)&Buffer[EntryPosition];
1023 LxtLogInfo("%s", Entry->d_name);
1024 Count += 1;
1025 }
1026
1027 LxtCheckErrno(BytesRead = LxtGetdents64(Fd, (struct dirent*)Buffer, sizeof(Buffer)));
1028 }
1029
1030 LxtCheckEqual(Count - 2, LXT_COUNT_OF(g_OvFsMergedContents) - 3, "%d");
1031 LxtClose(Fd);
1032 Fd = -1;
1033
1034 //
1035 // Create entries over the whiteouts and check for the expected state.
1036 //
1037 //
1038
1039 LxtCheckErrno(mkdir(OVFS_TEST_MERGED_DIR "/OnlyInLowerDir", 0777));
1040 LxtCheckErrno(stat(OVFS_TEST_MERGED_DIR "/OnlyInLowerDir", &StatBuffer));
1041 LxtCheckTrue(S_ISDIR(StatBuffer.st_mode));
1042 LxtCheckErrno(stat(OVFS_TEST_UPPER_DIR "/OnlyInLowerDir", &StatBuffer));
1043 LxtCheckTrue(S_ISDIR(StatBuffer.st_mode));
1044 LxtCheckErrno(Fd = open(OVFS_TEST_MERGED_DIR "/OnlyInLowerDir", O_RDONLY));
1045 LxtCheckErrno(BytesRead = LxtGetdents64(Fd, (struct dirent*)Buffer, sizeof(Buffer)))
1046
1047 Count = 0;
1048 for (EntryPosition = 0; EntryPosition < BytesRead; EntryPosition += Entry->d_reclen)
1049 {
1050
1051 Entry = (struct dirent*)&Buffer[EntryPosition];
1052 LxtLogInfo("%s", Entry->d_name);
1053 Count += 1;
1054 }
1055
1056 LxtCheckEqual(Count, 2, "%d");
1057 LxtClose(Fd);
1058 Fd = -1;
1059 LxtCheckErrnoFailure(stat(OVFS_TEST_MERGED_DIR "/OnlyInLowerDir/OnlyInLowerDirFile", &StatBuffer), ENOENT);
1060
1061 LxtCheckErrno(mkdir(OVFS_TEST_MERGED_DIR "/OnlyInUpperDir", 0777));
1062 LxtCheckErrno(stat(OVFS_TEST_MERGED_DIR "/OnlyInUpperDir", &StatBuffer));
1063 LxtCheckTrue(S_ISDIR(StatBuffer.st_mode));
1064 LxtCheckErrno(stat(OVFS_TEST_UPPER_DIR "/OnlyInUpperDir", &StatBuffer));
1065 LxtCheckTrue(S_ISDIR(StatBuffer.st_mode));
1066 LxtCheckErrno(Fd = open(OVFS_TEST_MERGED_DIR "/OnlyInUpperDir", O_RDONLY));
1067 LxtCheckErrno(BytesRead = LxtGetdents64(Fd, (struct dirent*)Buffer, sizeof(Buffer)))
1068
1069 Count = 0;
1070 for (EntryPosition = 0; EntryPosition < BytesRead; EntryPosition += Entry->d_reclen)
1071 {
1072
1073 Entry = (struct dirent*)&Buffer[EntryPosition];
1074 Count += 1;
1075 }
1076
1077 LxtCheckEqual(Count, 2, "%d");
1078 LxtClose(Fd);
1079 Fd = -1;
1080 LxtCheckErrnoFailure(stat(OVFS_TEST_MERGED_DIR "/OnlyInUpperDir/OnlyInUpperDirFile", &StatBuffer), ENOENT);
1081
1082 LxtCheckErrno(Fd = mkdir(OVFS_TEST_MERGED_DIR "/InBothDir", 0777));
1083 LxtCheckErrno(stat(OVFS_TEST_MERGED_DIR "/InBothDir", &StatBuffer));
1084 LxtCheckTrue(S_ISDIR(StatBuffer.st_mode));
1085 LxtCheckErrno(stat(OVFS_TEST_UPPER_DIR "/InBothDir", &StatBuffer));
1086 LxtCheckTrue(S_ISDIR(StatBuffer.st_mode));
1087 LxtCheckErrno(Fd = open(OVFS_TEST_MERGED_DIR "/InBothDir", O_RDONLY));
1088 LxtCheckErrno(BytesRead = LxtGetdents64(Fd, (struct dirent*)Buffer, sizeof(Buffer)))
1089
1090 Count = 0;
1091 for (EntryPosition = 0; EntryPosition < BytesRead; EntryPosition += Entry->d_reclen)
1092 {
1093
1094 Entry = (struct dirent*)&Buffer[EntryPosition];
1095 Count += 1;
1096 }
1097
1098 LxtCheckEqual(Count, 2, "%d");
1099 LxtClose(Fd);
1100 Fd = -1;
1101 LxtCheckErrnoFailure(stat(OVFS_TEST_MERGED_DIR "/InBothDir/InBothDirLowerFile", &StatBuffer), ENOENT);
1102 LxtCheckErrnoFailure(stat(OVFS_TEST_MERGED_DIR "/InBothDir/InBothDirUpperFile", &StatBuffer), ENOENT);
1103
1104 //
1105 // Enumerate the top level and check that the three directories have been
1106 // replaced.
1107 //
1108
1109 Count = 0;
1110 LxtCheckErrno(Fd = open(OVFS_TEST_MOUNT_PATH, O_RDONLY));
1111 LxtCheckErrno(BytesRead = LxtGetdents64(Fd, (struct dirent*)Buffer, sizeof(Buffer)));
1112
1113 while (BytesRead > 0)
1114 {
1115 for (EntryPosition = 0; EntryPosition < BytesRead; EntryPosition += Entry->d_reclen)
1116 {
1117
1118 Entry = (struct dirent*)&Buffer[EntryPosition];
1119 Count += 1;
1120 }
1121
1122 Entry = (struct dirent*)Buffer;
1123 LxtCheckErrno(BytesRead = LxtGetdents64(Fd, (struct dirent*)Buffer, sizeof(Buffer)));
1124 }
1125
1126 LxtCheckEqual(Count - 2, LXT_COUNT_OF(g_OvFsMergedContents), "%d");
1127 LxtClose(Fd);
1128 Fd = -1;
1129
1130 //
1131 // Replace a directory with a file and back again to a directory.
1132 //
1133
1134 LxtCheckErrnoZeroSuccess(umount(OVFS_TEST_MOUNT_PATH));
1135 LxtCheckResult(MountCheckIsNotMount(OVFS_TEST_MOUNT_PATH));
1136 LxtCheckResult(OvFsTestDirsSetup());
1137 LxtCheckResult(OvFsTestDirsPopulate());
1138 LxtCheckErrnoZeroSuccess(mount("myovfsnew", OVFS_TEST_MOUNT_PATH, OVFS_TEST_MOUNT_NAME, 0, OVFS_TEST_MOUNT_DEFAULT));
1139
1140 LxtCheckErrno(rmdir(OVFS_TEST_MERGED_DIR "/InBothDir"));
1141 LxtCheckErrnoFailure(stat(OVFS_TEST_MERGED_DIR "/InBothDir", &StatBuffer), ENOENT);
1142 LxtCheckErrno(stat(OVFS_TEST_UPPER_DIR "/InBothDir", &StatBuffer));
1143 LxtCheckTrue(S_ISCHR(StatBuffer.st_mode));
1144 LxtCheckErrno(Fd = creat(OVFS_TEST_MERGED_DIR "/InBothDir", 0777));
1145 LxtClose(Fd);
1146 Fd = -1;
1147 LxtCheckErrno(stat(OVFS_TEST_MERGED_DIR "/InBothDir", &StatBuffer));
1148 LxtCheckTrue(S_ISREG(StatBuffer.st_mode));
1149 LxtCheckErrno(stat(OVFS_TEST_UPPER_DIR "/InBothDir", &StatBuffer));
1150 LxtCheckTrue(S_ISREG(StatBuffer.st_mode));
1151 LxtCheckErrno(unlink(OVFS_TEST_MERGED_DIR "/InBothDir"));
1152 LxtCheckErrnoFailure(stat(OVFS_TEST_MERGED_DIR "/InBothDir", &StatBuffer), ENOENT);
1153 LxtCheckErrno(stat(OVFS_TEST_UPPER_DIR "/InBothDir", &StatBuffer));
1154 LxtCheckTrue(S_ISCHR(StatBuffer.st_mode));
1155 LxtCheckErrno(mkdir(OVFS_TEST_MERGED_DIR "/InBothDir", 0777));
1156 LxtCheckErrno(stat(OVFS_TEST_MERGED_DIR "/InBothDir", &StatBuffer));
1157 LxtCheckTrue(S_ISDIR(StatBuffer.st_mode));
1158 LxtCheckErrno(stat(OVFS_TEST_UPPER_DIR "/InBothDir", &StatBuffer));
1159 LxtCheckTrue(S_ISDIR(StatBuffer.st_mode));
1160
1161 LxtCheckErrnoZeroSuccess(umount(OVFS_TEST_MOUNT_PATH));
1162 LxtCheckResult(MountCheckIsNotMount(OVFS_TEST_MOUNT_PATH));
1163
1164 Result = 0;
1165
1166 ErrorExit:
1167 if (Fd != -1)
1168 {
1169 LxtClose(Fd);
1170 }
1171
1172 umount(OVFS_TEST_MOUNT_PATH);
1173 return Result;
1174 }
1175
1176 int OvFsTestInodeReadOps(PLXT_ARGS Args)
1177
1178 /*++
1179
1180 Description:
1181
1182 This routine tests inode operations that do not modify state.
1183
1184 Arguments:
1185
1186 Args - Supplies the command line arguments.
1187
1188 Return Value:
1189
1190 Returns 0 on success, -1 on failure.
1191
1192 --*/
1193
1194 {
1195
1196 int Fd;
1197 char Path[128];
1198 ssize_t PathSize;
1199 int Result;
1200 struct stat StatBuffer;
1201 struct stat StatMergedBuffer;
1202
1203 Fd = -1;
1204
1205 //
1206 // Set up the directories and populate some state.
1207 //
1208
1209 LxtCheckResult(OvFsTestDirsSetup());
1210 LxtCheckResult(OvFsTestDirsPopulate());
1211
1212 //
1213 // Mount an overlayfs instance and check inode operations that do not
1214 // hydrate files.
1215 //
1216
1217 LxtCheckResult(MountCheckIsNotMount(OVFS_TEST_MOUNT_PATH));
1218 LxtCheckErrnoZeroSuccess(mount("myovfsnew", OVFS_TEST_MOUNT_PATH, OVFS_TEST_MOUNT_NAME, 0, OVFS_TEST_MOUNT_DEFAULT));
1219
1220 //
1221 // Check the behavior for open, lookup, and fstat. The inode numbers in the
1222 // merged folder should be unique for directories but match the files.
1223 //
1224
1225 if (g_LxtUnstableInodes != 0)
1226 {
1227 LxtCheckResult(Fd = open(OVFS_TEST_MOUNT_PATH "/OnlyInLowerDir", O_RDONLY, 0));
1228 LxtCheckResult(fstat(Fd, &StatMergedBuffer));
1229 LxtClose(Fd);
1230 Fd = -1;
1231 LxtCheckResult(stat(OVFS_TEST_LOWER_DIR "/OnlyInLowerDir", &StatBuffer));
1232 LxtCheckNotEqual(StatBuffer.st_ino, StatMergedBuffer.st_ino, "%d");
1233
1234 LxtCheckResult(Fd = open(OVFS_TEST_MOUNT_PATH "/InBothDir", O_RDONLY, 0));
1235 LxtCheckResult(fstat(Fd, &StatMergedBuffer));
1236 LxtClose(Fd);
1237 Fd = -1;
1238 LxtCheckResult(stat(OVFS_TEST_LOWER_DIR "/InBothDir", &StatBuffer));
1239 LxtCheckNotEqual(StatBuffer.st_ino, StatMergedBuffer.st_ino, "%d");
1240 LxtCheckResult(stat(OVFS_TEST_UPPER_DIR "/InBothDir", &StatBuffer));
1241 LxtCheckNotEqual(StatBuffer.st_ino, StatMergedBuffer.st_ino, "%d");
1242
1243 LxtCheckResult(Fd = open(OVFS_TEST_MOUNT_PATH "/OnlyInLowerFile", O_RDONLY, 0));
1244 LxtCheckResult(fstat(Fd, &StatMergedBuffer));
1245 LxtClose(Fd);
1246 Fd = -1;
1247 LxtCheckResult(stat(OVFS_TEST_LOWER_DIR "/OnlyInLowerFile", &StatBuffer));
1248 LxtCheckEqual(StatBuffer.st_ino, StatMergedBuffer.st_ino, "%d");
1249
1250 LxtCheckResult(Fd = open(OVFS_TEST_MOUNT_PATH "/InBothFile", O_RDONLY, 0));
1251 LxtCheckResult(fstat(Fd, &StatMergedBuffer));
1252 LxtClose(Fd);
1253 Fd = -1;
1254 LxtCheckResult(stat(OVFS_TEST_LOWER_DIR "/InBothFile", &StatBuffer));
1255 LxtCheckNotEqual(StatBuffer.st_ino, StatMergedBuffer.st_ino, "%d");
1256 LxtCheckResult(stat(OVFS_TEST_UPPER_DIR "/InBothFile", &StatBuffer));
1257 LxtCheckEqual(StatBuffer.st_ino, StatMergedBuffer.st_ino, "%d");
1258
1259 LxtCheckResult(Fd = open(OVFS_TEST_MOUNT_PATH "/OnlyInUpperDir", O_RDONLY, 0));
1260 LxtCheckResult(fstat(Fd, &StatMergedBuffer));
1261 LxtClose(Fd);
1262 Fd = -1;
1263 LxtCheckResult(stat(OVFS_TEST_UPPER_DIR "/OnlyInUpperDir", &StatBuffer));
1264 LxtCheckNotEqual(StatBuffer.st_ino, StatMergedBuffer.st_ino, "%d");
1265
1266 LxtCheckResult(Fd = open(OVFS_TEST_MOUNT_PATH "/OnlyInUpperFile", O_RDONLY, 0));
1267 LxtCheckResult(fstat(Fd, &StatMergedBuffer));
1268 LxtClose(Fd);
1269 Fd = -1;
1270 LxtCheckResult(stat(OVFS_TEST_UPPER_DIR "/OnlyInUpperFile", &StatBuffer));
1271 LxtCheckEqual(StatBuffer.st_ino, StatMergedBuffer.st_ino, "%d");
1272 }
1273
1274 //
1275 // Check the behavior for readlink.
1276 //
1277
1278 LxtCheckErrno(PathSize = readlink(OVFS_TEST_MOUNT_PATH "/OnlyInLowerSym", Path, sizeof(Path) - 1));
1279
1280 Path[PathSize] = 0;
1281 LxtCheckStringEqual(Path, OVFS_TEST_LOWER_DIR "/OnlyInLowerFile");
1282 LxtCheckErrno(PathSize = readlink(OVFS_TEST_MOUNT_PATH "/InBothSym", Path, sizeof(Path) - 1));
1283
1284 Path[PathSize] = 0;
1285 LxtCheckStringEqual(Path, OVFS_TEST_UPPER_DIR "/InBothFile");
1286 LxtCheckErrno(PathSize = readlink(OVFS_TEST_MOUNT_PATH "/OnlyInUpperSym", Path, sizeof(Path) - 1));
1287
1288 Path[PathSize] = 0;
1289 LxtCheckStringEqual(Path, OVFS_TEST_UPPER_DIR "/OnlyInUpperFile");
1290
1291 //
1292 //
1293 // Check the behavior for stat. The inode numbers in the merged folder
1294 // should be unique for directories but match the files.
1295 //
1296
1297 if (g_LxtUnstableInodes != 0)
1298 {
1299 LxtCheckResult(stat(OVFS_TEST_MOUNT_PATH "/OnlyInLowerDir", &StatMergedBuffer));
1300 LxtCheckResult(stat(OVFS_TEST_LOWER_DIR "/OnlyInLowerDir", &StatBuffer));
1301 LxtCheckNotEqual(StatBuffer.st_ino, StatMergedBuffer.st_ino, "%d");
1302
1303 LxtCheckResult(stat(OVFS_TEST_MOUNT_PATH "/InBothDir", &StatMergedBuffer));
1304 LxtCheckResult(stat(OVFS_TEST_LOWER_DIR "/InBothDir", &StatBuffer));
1305 LxtCheckNotEqual(StatBuffer.st_ino, StatMergedBuffer.st_ino, "%d");
1306 LxtCheckResult(stat(OVFS_TEST_UPPER_DIR "/InBothDir", &StatBuffer));
1307 LxtCheckNotEqual(StatBuffer.st_ino, StatMergedBuffer.st_ino, "%d");
1308
1309 LxtCheckResult(stat(OVFS_TEST_MOUNT_PATH "/OnlyInLowerFile", &StatMergedBuffer));
1310 LxtCheckResult(stat(OVFS_TEST_LOWER_DIR "/OnlyInLowerFile", &StatBuffer));
1311 LxtCheckEqual(StatBuffer.st_ino, StatMergedBuffer.st_ino, "%d");
1312
1313 LxtCheckResult(stat(OVFS_TEST_MOUNT_PATH "/InBothFile", &StatMergedBuffer));
1314 LxtCheckResult(stat(OVFS_TEST_LOWER_DIR "/InBothFile", &StatBuffer));
1315 LxtCheckNotEqual(StatBuffer.st_ino, StatMergedBuffer.st_ino, "%d");
1316 LxtCheckResult(stat(OVFS_TEST_UPPER_DIR "/InBothFile", &StatBuffer));
1317 LxtCheckEqual(StatBuffer.st_ino, StatMergedBuffer.st_ino, "%d");
1318
1319 LxtCheckResult(stat(OVFS_TEST_MOUNT_PATH "/OnlyInUpperDir", &StatMergedBuffer));
1320 LxtCheckResult(stat(OVFS_TEST_UPPER_DIR "/OnlyInUpperDir", &StatBuffer));
1321 LxtCheckNotEqual(StatBuffer.st_ino, StatMergedBuffer.st_ino, "%d");
1322
1323 LxtCheckResult(stat(OVFS_TEST_MOUNT_PATH "/OnlyInUpperFile", &StatMergedBuffer));
1324 LxtCheckResult(stat(OVFS_TEST_UPPER_DIR "/OnlyInUpperFile", &StatBuffer));
1325 LxtCheckEqual(StatBuffer.st_ino, StatMergedBuffer.st_ino, "%d");
1326 }
1327
1328 //
1329 // Check that none of the operations hydrated files from the lower
1330 // directory.
1331 //
1332
1333 LxtCheckErrnoFailure(stat(OVFS_TEST_UPPER_DIR "/OnlyInLowerDir", &StatBuffer), ENOENT);
1334 LxtCheckErrnoFailure(stat(OVFS_TEST_UPPER_DIR "/OnlyInLowerFile", &StatBuffer), ENOENT);
1335 LxtCheckErrnoFailure(stat(OVFS_TEST_UPPER_DIR "/OnlyInLowerSym", &StatBuffer), ENOENT);
1336
1337 //
1338 // Unmount and check it was unmounted.
1339 //
1340
1341 if (Fd != -1)
1342 {
1343 LxtClose(Fd);
1344 Fd = -1;
1345 }
1346
1347 LxtCheckErrnoZeroSuccess(umount(OVFS_TEST_MOUNT_PATH));
1348 LxtCheckResult(MountCheckIsNotMount(OVFS_TEST_MOUNT_PATH));
1349 Result = 0;
1350
1351 ErrorExit:
1352 if (Fd != -1)
1353 {
1354 LxtClose(Fd);
1355 }
1356
1357 umount(OVFS_TEST_MOUNT_PATH);
1358 return Result;
1359 }
1360
1361 int OvFsTestInodeRename(PLXT_ARGS Args)
1362
1363 /*++
1364
1365 Description:
1366
1367 This routine tests inode operations that may modify state.
1368
1369 Arguments:
1370
1371 Args - Supplies the command line arguments.
1372
1373 Return Value:
1374
1375 Returns 0 on success, -1 on failure.
1376
1377 --*/
1378
1379 {
1380
1381 ssize_t BufferSize;
1382 char Buffer;
1383 int Result;
1384 struct stat StatBuffer;
1385 struct stat StatMergedBuffer;
1386
1387 //
1388 // Set up the directories and populate some state.
1389 //
1390
1391 LxtCheckResult(OvFsTestDirsSetup());
1392 LxtCheckResult(OvFsTestDirsPopulate());
1393
1394 //
1395 // Mount an overlayfs instance.
1396 //
1397
1398 LxtCheckResult(MountCheckIsNotMount(OVFS_TEST_MOUNT_PATH));
1399 LxtCheckErrnoZeroSuccess(mount("myovfsnew", OVFS_TEST_MOUNT_PATH, OVFS_TEST_MOUNT_NAME, 0, OVFS_TEST_MOUNT_DEFAULT));
1400
1401 //
1402 // Rename each file and check for the expected state.
1403 //
1404
1405 //
1406 // When renaming a file from the lower, a whiteout and the renamed file are
1407 // set in the upper.
1408 //
1409
1410 LxtCheckErrnoFailure(stat(OVFS_TEST_UPPER_DIR "/OnlyInLowerFile", &StatBuffer), ENOENT);
1411 LxtCheckErrno(rename(OVFS_TEST_MERGED_DIR "/OnlyInLowerFile", OVFS_TEST_MERGED_DIR "/OnlyInLowerFileRenamed"));
1412
1413 LxtCheckErrno(stat(OVFS_TEST_UPPER_DIR "/OnlyInLowerFile", &StatBuffer));
1414 LxtCheckTrue(S_ISCHR(StatBuffer.st_mode));
1415 LxtCheckErrno(stat(OVFS_TEST_UPPER_DIR "/OnlyInLowerFileRenamed", &StatBuffer));
1416 LxtCheckTrue(S_ISREG(StatBuffer.st_mode));
1417 LxtCheckErrno(stat(OVFS_TEST_MERGED_DIR "/OnlyInLowerFileRenamed", &StatMergedBuffer));
1418 LxtCheckTrue(S_ISREG(StatMergedBuffer.st_mode));
1419 if (g_LxtUnstableInodes != 0)
1420 {
1421 LxtCheckEqual(StatBuffer.st_ino, StatMergedBuffer.st_ino, "%d");
1422 }
1423
1424 //
1425 // When renaming a file from the upper, the file is simply renamed.
1426 //
1427
1428 LxtCheckErrno(stat(OVFS_TEST_UPPER_DIR "/OnlyInUpperFile", &StatBuffer));
1429 LxtCheckErrno(rename(OVFS_TEST_MERGED_DIR "/OnlyInUpperFile", OVFS_TEST_MERGED_DIR "/OnlyInUpperFileRenamed"));
1430
1431 LxtCheckErrnoFailure(stat(OVFS_TEST_UPPER_DIR "/OnlyInUpperFile", &StatBuffer), ENOENT);
1432 LxtCheckErrno(stat(OVFS_TEST_UPPER_DIR "/OnlyInUpperFileRenamed", &StatBuffer));
1433 LxtCheckTrue(S_ISREG(StatBuffer.st_mode));
1434 LxtCheckErrno(stat(OVFS_TEST_MERGED_DIR "/OnlyInUpperFileRenamed", &StatMergedBuffer));
1435 LxtCheckTrue(S_ISREG(StatMergedBuffer.st_mode));
1436 if (g_LxtUnstableInodes != 0)
1437 {
1438 LxtCheckEqual(StatBuffer.st_ino, StatMergedBuffer.st_ino, "%d");
1439 }
1440
1441 //
1442 // When renaming a file from both, a whiteout and the renamed file are
1443 // set in the upper.
1444 //
1445
1446 LxtCheckErrno(stat(OVFS_TEST_UPPER_DIR "/InBothFile", &StatBuffer));
1447 LxtCheckTrue(S_ISREG(StatBuffer.st_mode));
1448 LxtCheckErrno(rename(OVFS_TEST_MERGED_DIR "/InBothFile", OVFS_TEST_MERGED_DIR "/InBothFileRenamed"));
1449
1450 LxtCheckErrno(stat(OVFS_TEST_UPPER_DIR "/InBothFile", &StatBuffer));
1451 LxtCheckTrue(S_ISCHR(StatBuffer.st_mode));
1452 LxtCheckErrno(stat(OVFS_TEST_UPPER_DIR "/InBothFileRenamed", &StatBuffer));
1453 LxtCheckTrue(S_ISREG(StatBuffer.st_mode));
1454 LxtCheckErrno(stat(OVFS_TEST_MERGED_DIR "/InBothFileRenamed", &StatMergedBuffer));
1455 LxtCheckTrue(S_ISREG(StatMergedBuffer.st_mode));
1456 if (g_LxtUnstableInodes != 0)
1457 {
1458 LxtCheckEqual(StatBuffer.st_ino, StatMergedBuffer.st_ino, "%d");
1459 }
1460
1461 //
1462 // Check the behavior for renaming a directory.
1463 //
1464
1465 //
1466 // When renaming a directory from the lower, the rename call should fail.
1467 //
1468
1469 LxtCheckErrnoFailure(stat(OVFS_TEST_UPPER_DIR "/OnlyInLowerDir", &StatBuffer), ENOENT);
1470 LxtCheckErrnoFailure(rename(OVFS_TEST_MERGED_DIR "/OnlyInLowerDir", OVFS_TEST_MERGED_DIR "/OnlyInLowerDirRenamed"), EXDEV);
1471
1472 LxtCheckErrnoFailure(stat(OVFS_TEST_UPPER_DIR "/OnlyInLowerDir", &StatBuffer), ENOENT);
1473
1474 //
1475 // When renaming a directory from the upper, directory is simply renamed.
1476 //
1477
1478 LxtCheckErrno(stat(OVFS_TEST_UPPER_DIR "/OnlyInUpperDir", &StatBuffer));
1479 LxtCheckErrno(rename(OVFS_TEST_MERGED_DIR "/OnlyInUpperDir", OVFS_TEST_MERGED_DIR "/OnlyInUpperDirRenamed"));
1480
1481 LxtCheckErrnoFailure(stat(OVFS_TEST_UPPER_DIR "/OnlyInUpperDir", &StatBuffer), ENOENT);
1482 LxtCheckErrno(stat(OVFS_TEST_UPPER_DIR "/OnlyInUpperDirRenamed", &StatBuffer));
1483 LxtCheckTrue(S_ISDIR(StatBuffer.st_mode));
1484 LxtCheckErrno(stat(OVFS_TEST_MERGED_DIR "/OnlyInUpperDirRenamed", &StatMergedBuffer));
1485 LxtCheckTrue(S_ISDIR(StatMergedBuffer.st_mode));
1486 if (g_LxtUnstableInodes != 0)
1487 {
1488 LxtCheckNotEqual(StatBuffer.st_ino, StatMergedBuffer.st_ino, "%d");
1489 }
1490
1491 //
1492 // When renaming a directory from both, the rename call should fail.
1493 //
1494
1495 LxtCheckErrno(stat(OVFS_TEST_UPPER_DIR "/InBothDir", &StatBuffer));
1496 LxtCheckErrnoFailure(rename(OVFS_TEST_MERGED_DIR "/InBothDir", OVFS_TEST_MERGED_DIR "/InBothDirRenamed"), EXDEV);
1497
1498 LxtCheckErrno(stat(OVFS_TEST_UPPER_DIR "/InBothDir", &StatBuffer));
1499 LxtCheckErrnoFailure(stat(OVFS_TEST_UPPER_DIR "/InBothDirRenamed", &StatBuffer), ENOENT);
1500
1501 //
1502 // When renaming an opaque directory, the rename call should succeed.
1503 //
1504
1505 LxtCheckErrno(rmdir(OVFS_TEST_MERGED_DIR "/InBothDir"));
1506 LxtCheckErrno(mkdir(OVFS_TEST_MERGED_DIR "/InBothDir", 0777));
1507 LxtCheckErrno(stat(OVFS_TEST_UPPER_DIR "/InBothDir", &StatBuffer));
1508 LxtCheckTrue(S_ISDIR(StatBuffer.st_mode));
1509 LxtCheckErrno(BufferSize = getxattr(OVFS_TEST_UPPER_DIR "/InBothDir", "trusted.overlay.opaque", &Buffer, sizeof(Buffer)));
1510
1511 LxtCheckEqual(Buffer, 'y', "%c");
1512 LxtCheckEqual(BufferSize, 1, "%d");
1513 LxtCheckErrno(rename(OVFS_TEST_MERGED_DIR "/InBothDir", OVFS_TEST_MERGED_DIR "/OnlyInLowerDir"));
1514
1515 LxtCheckErrno(stat(OVFS_TEST_UPPER_DIR "/InBothDir", &StatBuffer));
1516 LxtCheckTrue(S_ISCHR(StatBuffer.st_mode));
1517 LxtCheckErrno(stat(OVFS_TEST_UPPER_DIR "/OnlyInLowerDir", &StatBuffer));
1518 LxtCheckTrue(S_ISDIR(StatBuffer.st_mode));
1519 LxtCheckErrno(BufferSize = getxattr(OVFS_TEST_UPPER_DIR "/OnlyInLowerDir", "trusted.overlay.opaque", &Buffer, sizeof(Buffer)));
1520
1521 LxtCheckEqual(Buffer, 'y', "%c");
1522 LxtCheckEqual(BufferSize, 1, "%d");
1523
1524 //
1525 // Unmount.
1526 //
1527
1528 LxtCheckErrnoZeroSuccess(umount(OVFS_TEST_MOUNT_PATH));
1529 LxtCheckResult(MountCheckIsNotMount(OVFS_TEST_MOUNT_PATH));
1530
1531 Result = 0;
1532
1533 ErrorExit:
1534 umount(OVFS_TEST_MOUNT_PATH);
1535 return Result;
1536 }
1537
1538 int OvFsTestInodeWhiteout(PLXT_ARGS Args)
1539
1540 /*++
1541
1542 Description:
1543
1544 This routine tests inode whiteout operations.
1545
1546 Arguments:
1547
1548 Args - Supplies the command line arguments.
1549
1550 Return Value:
1551
1552 Returns 0 on success, -1 on failure.
1553
1554 --*/
1555
1556 {
1557
1558 int Fd;
1559 int Result;
1560 struct stat StatBuffer;
1561
1562 Fd = -1;
1563
1564 //
1565 // Set up the directories and populate some state.
1566 //
1567
1568 LxtCheckResult(OvFsTestDirsSetup());
1569 LxtCheckResult(OvFsTestDirsPopulate());
1570
1571 //
1572 // Mount an overlayfs instance and check for the expected file state.
1573 //
1574
1575 LxtCheckResult(MountCheckIsNotMount(OVFS_TEST_MOUNT_PATH));
1576 LxtCheckErrnoZeroSuccess(mount("myovfsnew", OVFS_TEST_MOUNT_PATH, OVFS_TEST_MOUNT_NAME, 0, OVFS_TEST_MOUNT_DEFAULT));
1577
1578 LxtCheckErrnoFailure(stat(OVFS_TEST_UPPER_DIR "/OnlyInLowerDir", &StatBuffer), ENOENT);
1579 LxtCheckErrnoFailure(stat(OVFS_TEST_UPPER_DIR "/OnlyInLowerFile", &StatBuffer), ENOENT);
1580 LxtCheckErrnoFailure(stat(OVFS_TEST_UPPER_DIR "/OnlyInLowerSym", &StatBuffer), ENOENT);
1581 LxtCheckErrno(stat(OVFS_TEST_UPPER_DIR "/OnlyInUpperDir", &StatBuffer));
1582 LxtCheckTrue(S_ISDIR(StatBuffer.st_mode));
1583 LxtCheckErrno(stat(OVFS_TEST_UPPER_DIR "/OnlyInUpperFile", &StatBuffer));
1584 LxtCheckTrue(S_ISREG(StatBuffer.st_mode));
1585 LxtCheckErrno(lstat(OVFS_TEST_UPPER_DIR "/OnlyInUpperSym", &StatBuffer));
1586 LxtCheckTrue(S_ISLNK(StatBuffer.st_mode));
1587 LxtCheckErrno(stat(OVFS_TEST_UPPER_DIR "/InBothDir", &StatBuffer));
1588 LxtCheckTrue(S_ISDIR(StatBuffer.st_mode));
1589 LxtCheckErrno(stat(OVFS_TEST_UPPER_DIR "/InBothFile", &StatBuffer));
1590 LxtCheckTrue(S_ISREG(StatBuffer.st_mode));
1591 LxtCheckErrno(lstat(OVFS_TEST_UPPER_DIR "/InBothSym", &StatBuffer));
1592 LxtCheckTrue(S_ISLNK(StatBuffer.st_mode));
1593
1594 //
1595 // Unlink each entry and check for the expected behavior.
1596 //
1597
1598 LxtCheckErrno(rmdir(OVFS_TEST_MERGED_DIR "/OnlyInLowerDir"));
1599 LxtCheckErrno(stat(OVFS_TEST_UPPER_DIR "/OnlyInLowerDir", &StatBuffer));
1600 LxtCheckTrue(S_ISCHR(StatBuffer.st_mode));
1601
1602 LxtCheckErrno(unlink(OVFS_TEST_MERGED_DIR "/OnlyInLowerFile"));
1603 LxtCheckErrno(stat(OVFS_TEST_UPPER_DIR "/OnlyInLowerFile", &StatBuffer));
1604 LxtCheckTrue(S_ISCHR(StatBuffer.st_mode));
1605
1606 LxtCheckErrno(unlink(OVFS_TEST_MERGED_DIR "/OnlyInLowerSym"));
1607 LxtCheckErrno(stat(OVFS_TEST_UPPER_DIR "/OnlyInLowerSym", &StatBuffer));
1608 LxtCheckTrue(S_ISCHR(StatBuffer.st_mode));
1609
1610 LxtCheckErrno(rmdir(OVFS_TEST_MERGED_DIR "/OnlyInUpperDir"));
1611 LxtCheckErrnoFailure(stat(OVFS_TEST_UPPER_DIR "/OnlyInUpperDir", &StatBuffer), ENOENT);
1612
1613 LxtCheckErrno(unlink(OVFS_TEST_MERGED_DIR "/OnlyInUpperFile"));
1614 LxtCheckErrnoFailure(stat(OVFS_TEST_UPPER_DIR "/OnlyInUpperFile", &StatBuffer), ENOENT);
1615
1616 LxtCheckErrno(unlink(OVFS_TEST_MERGED_DIR "/OnlyInUpperSym"));
1617 LxtCheckErrnoFailure(stat(OVFS_TEST_UPPER_DIR "/OnlyInUpperSym", &StatBuffer), ENOENT);
1618
1619 LxtCheckErrno(rmdir(OVFS_TEST_MERGED_DIR "/InBothDir"));
1620 LxtCheckErrno(stat(OVFS_TEST_UPPER_DIR "/InBothDir", &StatBuffer));
1621 LxtCheckTrue(S_ISCHR(StatBuffer.st_mode));
1622
1623 LxtCheckErrno(unlink(OVFS_TEST_MERGED_DIR "/InBothFile"));
1624 LxtCheckErrno(stat(OVFS_TEST_UPPER_DIR "/InBothFile", &StatBuffer));
1625 LxtCheckTrue(S_ISCHR(StatBuffer.st_mode));
1626
1627 LxtCheckErrno(unlink(OVFS_TEST_MERGED_DIR "/InBothSym"));
1628 LxtCheckErrno(stat(OVFS_TEST_UPPER_DIR "/InBothSym", &StatBuffer));
1629 LxtCheckTrue(S_ISCHR(StatBuffer.st_mode));
1630
1631 //
1632 // Create entries over the whiteouts and check for the expected state.
1633 //
1634
1635 LxtCheckErrno(mkdir(OVFS_TEST_MERGED_DIR "/OnlyInLowerDir", 0777));
1636 LxtCheckErrno(stat(OVFS_TEST_UPPER_DIR "/OnlyInLowerDir", &StatBuffer));
1637 LxtCheckTrue(S_ISDIR(StatBuffer.st_mode));
1638
1639 LxtCheckErrno(Fd = creat(OVFS_TEST_MERGED_DIR "/OnlyInLowerFile", 0777));
1640 LxtCheckErrno(stat(OVFS_TEST_UPPER_DIR "/OnlyInLowerFile", &StatBuffer));
1641 LxtCheckTrue(S_ISREG(StatBuffer.st_mode));
1642 LxtClose(Fd);
1643 Fd = -1;
1644
1645 LxtCheckErrno(Fd = creat(OVFS_TEST_MERGED_DIR "/OnlyInLowerSym", 0777));
1646 LxtCheckErrno(stat(OVFS_TEST_UPPER_DIR "/OnlyInLowerSym", &StatBuffer));
1647 LxtCheckTrue(S_ISREG(StatBuffer.st_mode));
1648 LxtClose(Fd);
1649 Fd = -1;
1650
1651 LxtCheckErrno(mkdir(OVFS_TEST_MERGED_DIR "/OnlyInUpperDir", 0777));
1652 LxtCheckErrno(stat(OVFS_TEST_UPPER_DIR "/OnlyInLowerDir", &StatBuffer));
1653 LxtCheckTrue(S_ISDIR(StatBuffer.st_mode));
1654
1655 LxtCheckErrno(Fd = creat(OVFS_TEST_MERGED_DIR "/OnlyInUpperFile", 0777));
1656 LxtCheckErrno(stat(OVFS_TEST_UPPER_DIR "/OnlyInUpperFile", &StatBuffer));
1657 LxtClose(Fd);
1658 Fd = -1;
1659
1660 LxtCheckErrno(Fd = creat(OVFS_TEST_MERGED_DIR "/OnlyInUpperSym", 0777));
1661 LxtCheckErrno(stat(OVFS_TEST_UPPER_DIR "/OnlyInUpperSym", &StatBuffer));
1662 LxtCheckTrue(S_ISREG(StatBuffer.st_mode));
1663 LxtClose(Fd);
1664 Fd = -1;
1665
1666 LxtCheckErrno(mkdir(OVFS_TEST_MERGED_DIR "/InBothDir", 0777));
1667 LxtCheckErrno(stat(OVFS_TEST_UPPER_DIR "/InBothDir", &StatBuffer));
1668 LxtCheckTrue(S_ISDIR(StatBuffer.st_mode));
1669
1670 LxtCheckErrno(mkdir(OVFS_TEST_MERGED_DIR "/InBothFile", 0777));
1671 LxtCheckErrno(stat(OVFS_TEST_UPPER_DIR "/InBothFile", &StatBuffer));
1672 LxtCheckTrue(S_ISDIR(StatBuffer.st_mode));
1673
1674 LxtCheckErrno(Fd = creat(OVFS_TEST_MERGED_DIR "/InBothSym", 0777));
1675 LxtCheckErrno(stat(OVFS_TEST_UPPER_DIR "/InBothSym", &StatBuffer));
1676 LxtCheckTrue(S_ISREG(StatBuffer.st_mode));
1677 LxtClose(Fd);
1678 Fd = -1;
1679
1680 LxtCheckErrnoZeroSuccess(umount(OVFS_TEST_MOUNT_PATH));
1681 LxtCheckResult(MountCheckIsNotMount(OVFS_TEST_MOUNT_PATH));
1682
1683 Result = 0;
1684
1685 ErrorExit:
1686 if (Fd != -1)
1687 {
1688 LxtClose(Fd);
1689 }
1690
1691 umount(OVFS_TEST_MOUNT_PATH);
1692 return Result;
1693 }
1694
1695 int OvFsTestInodeWriteOpsUpper(PLXT_ARGS Args)
1696
1697 /*++
1698
1699 Description:
1700
1701 This routine tests inode operations that do not modify state.
1702
1703 Arguments:
1704
1705 Args - Supplies the command line arguments.
1706
1707 Return Value:
1708
1709 Returns 0 on success, -1 on failure.
1710
1711 --*/
1712
1713 {
1714
1715 char Buffer[100];
1716 int BytesRead;
1717 int Count;
1718 struct dirent* Entry;
1719 int EntryPosition;
1720 int Fd;
1721 char* writeUpperCreate[] = {"writeUpperDir", "writeUpperFile", "writeUpperSymlink", "writeUpperLink"};
1722 int Found[LXT_COUNT_OF(g_OvFsMergedContents) + 2 + LXT_COUNT_OF(writeUpperCreate)];
1723 int FoundIndex;
1724 int Index;
1725 char Path[128];
1726 ssize_t PathSize;
1727 int Result;
1728 struct stat StatBuffer;
1729 struct stat StatMergedBuffer;
1730 struct utimbuf Times;
1731
1732 Fd = -1;
1733
1734 //
1735 // Set up the directories and populate some state.
1736 //
1737
1738 LxtCheckResult(OvFsTestDirsSetup());
1739 LxtCheckResult(OvFsTestDirsPopulate());
1740
1741 //
1742 // Mount an overlayfs instance and check inode operations that do not
1743 // hydrate files.
1744 //
1745 // N.B. The overlay fs mount does not need to be recreated after each
1746 // variation since only the upper is modified.
1747 //
1748
1749 LxtCheckResult(MountCheckIsNotMount(OVFS_TEST_MOUNT_PATH));
1750 LxtCheckErrnoZeroSuccess(mount("myovfsnew", OVFS_TEST_MOUNT_PATH, OVFS_TEST_MOUNT_NAME, 0, OVFS_TEST_MOUNT_DEFAULT));
1751
1752 //
1753 // Check the behavior for open, chown, chmod, create cases, set times. The
1754 // inode numbers in the merged folder should be unique for directories but
1755 // match the files.
1756 //
1757
1758 if (g_LxtUnstableInodes != 0)
1759 {
1760 LxtCheckResult(Fd = open(OVFS_TEST_MOUNT_PATH "/InBothFile", O_RDWR, 0));
1761 LxtCheckResult(fstat(Fd, &StatMergedBuffer));
1762 LxtClose(Fd);
1763 Fd = -1;
1764 LxtCheckResult(stat(OVFS_TEST_LOWER_DIR "/InBothFile", &StatBuffer));
1765 LxtCheckNotEqual(StatBuffer.st_ino, StatMergedBuffer.st_ino, "%d");
1766 LxtCheckResult(stat(OVFS_TEST_UPPER_DIR "/InBothFile", &StatBuffer));
1767 LxtCheckEqual(StatBuffer.st_ino, StatMergedBuffer.st_ino, "%d");
1768
1769 LxtCheckResult(Fd = open(OVFS_TEST_MOUNT_PATH "/OnlyInUpperFile", O_RDWR, 0));
1770 LxtCheckResult(fstat(Fd, &StatMergedBuffer));
1771 LxtClose(Fd);
1772 Fd = -1;
1773 LxtCheckResult(stat(OVFS_TEST_UPPER_DIR "/OnlyInUpperFile", &StatBuffer));
1774 LxtCheckEqual(StatBuffer.st_ino, StatMergedBuffer.st_ino, "%d");
1775
1776 LxtCheckResult(Fd = open(OVFS_TEST_MOUNT_PATH "/InBothSym", O_RDWR | O_PATH | O_NOFOLLOW, 0));
1777 LxtCheckResult(fstat(Fd, &StatMergedBuffer));
1778 LxtClose(Fd);
1779 Fd = -1;
1780 LxtCheckResult(lstat(OVFS_TEST_LOWER_DIR "/InBothSym", &StatBuffer));
1781 LxtCheckNotEqual(StatBuffer.st_ino, StatMergedBuffer.st_ino, "%d");
1782 LxtCheckResult(lstat(OVFS_TEST_UPPER_DIR "/InBothSym", &StatBuffer));
1783 LxtCheckEqual(StatBuffer.st_ino, StatMergedBuffer.st_ino, "%d");
1784
1785 LxtCheckResult(Fd = open(OVFS_TEST_MOUNT_PATH "/OnlyInUpperSym", O_RDWR | O_PATH | O_NOFOLLOW, 0));
1786 LxtCheckResult(fstat(Fd, &StatMergedBuffer));
1787 LxtClose(Fd);
1788 Fd = -1;
1789 LxtCheckResult(lstat(OVFS_TEST_UPPER_DIR "/OnlyInUpperSym", &StatBuffer));
1790 LxtCheckEqual(StatBuffer.st_ino, StatMergedBuffer.st_ino, "%d");
1791 }
1792
1793 //
1794 // Check the behavior for chown.
1795 //
1796
1797 for (Index = 0; Index < LXT_COUNT_OF(g_OvFsMergedContents); ++Index)
1798 {
1799 if (((S_ISREG(g_OvFsMergedContents[Index].Mode) == FALSE) && (S_ISDIR(g_OvFsMergedContents[Index].Mode) == FALSE)) ||
1800 (g_OvFsMergedContents[Index].Hydrates != 0))
1801 {
1802
1803 continue;
1804 }
1805
1806 LxtCheckErrno(chown(g_OvFsMergedContents[Index].Path, 111, 111));
1807 }
1808
1809 //
1810 // Check the behavior for chmod.
1811 //
1812
1813 for (Index = 0; Index < LXT_COUNT_OF(g_OvFsMergedContents); ++Index)
1814 {
1815 if (((S_ISREG(g_OvFsMergedContents[Index].Mode) == FALSE) && (S_ISDIR(g_OvFsMergedContents[Index].Mode) == FALSE)) ||
1816 (g_OvFsMergedContents[Index].Hydrates != 0))
1817 {
1818
1819 continue;
1820 }
1821
1822 LxtCheckErrno(chmod(g_OvFsMergedContents[Index].Path, 0777));
1823 }
1824
1825 //
1826 // Check the behavior for the 4 create cases.
1827 //
1828
1829 LxtCheckErrno(mkdir(OVFS_TEST_MOUNT_PATH "/writeUpperDir", 0777));
1830 LxtCheckResult(Fd = open(OVFS_TEST_MOUNT_PATH "/writeUpperDir", O_RDONLY, 0));
1831 LxtCheckResult(fstat(Fd, &StatMergedBuffer));
1832 LxtClose(Fd);
1833 Fd = -1;
1834 LxtCheckResult(stat(OVFS_TEST_UPPER_DIR "/writeUpperDir", &StatBuffer));
1835 if (g_LxtUnstableInodes != 0)
1836 {
1837 LxtCheckNotEqual(StatBuffer.st_ino, StatMergedBuffer.st_ino, "%d");
1838 }
1839
1840 LxtCheckErrnoFailure(stat(OVFS_TEST_LOWER_DIR "/writeUpperDir", &StatBuffer), ENOENT);
1841
1842 LxtCheckErrno(Fd = creat(OVFS_TEST_MOUNT_PATH "/writeUpperFile", 0777));
1843 LxtCheckResult(fstat(Fd, &StatMergedBuffer));
1844 LxtClose(Fd);
1845 Fd = -1;
1846 LxtCheckResult(stat(OVFS_TEST_UPPER_DIR "/writeUpperFile", &StatBuffer));
1847 if (g_LxtUnstableInodes != 0)
1848 {
1849 LxtCheckEqual(StatBuffer.st_ino, StatMergedBuffer.st_ino, "%d");
1850 }
1851
1852 LxtCheckErrnoFailure(stat(OVFS_TEST_LOWER_DIR "/writeUpperFile", &StatBuffer), ENOENT);
1853
1854 LxtCheckErrno(symlink("writeUpperSymlink", OVFS_TEST_MOUNT_PATH "/writeUpperSymlink"));
1855 LxtCheckResult(Fd = open(OVFS_TEST_MOUNT_PATH "/writeUpperSymlink", O_RDONLY | O_PATH | O_NOFOLLOW, 0));
1856 LxtCheckResult(fstat(Fd, &StatMergedBuffer));
1857 LxtClose(Fd);
1858 Fd = -1;
1859 LxtCheckResult(lstat(OVFS_TEST_UPPER_DIR "/writeUpperSymlink", &StatBuffer));
1860 if (g_LxtUnstableInodes != 0)
1861 {
1862 LxtCheckEqual(StatBuffer.st_ino, StatMergedBuffer.st_ino, "%d");
1863 }
1864
1865 LxtCheckErrnoFailure(lstat(OVFS_TEST_LOWER_DIR "/writeUpperSymlink", &StatBuffer), ENOENT);
1866
1867 LxtCheckErrno(link(OVFS_TEST_MOUNT_PATH "/writeUpperFile", OVFS_TEST_MOUNT_PATH "/writeUpperLink"));
1868 LxtCheckResult(Fd = open(OVFS_TEST_MOUNT_PATH "/writeUpperLink", O_RDONLY, 0));
1869 LxtCheckResult(fstat(Fd, &StatMergedBuffer));
1870 LxtClose(Fd);
1871 Fd = -1;
1872 LxtCheckResult(stat(OVFS_TEST_UPPER_DIR "/writeUpperLink", &StatBuffer));
1873 if (g_LxtUnstableInodes != 0)
1874 {
1875 LxtCheckEqual(StatBuffer.st_ino, StatMergedBuffer.st_ino, "%d");
1876 }
1877
1878 LxtCheckErrnoFailure(stat(OVFS_TEST_LOWER_DIR "/writeUpperLink", &StatBuffer), ENOENT);
1879
1880 //
1881 // Check the behavior for set times.
1882 //
1883
1884 Times.actime = time(NULL);
1885 Times.modtime = time(NULL);
1886 for (Index = 0; Index < LXT_COUNT_OF(g_OvFsMergedContents); ++Index)
1887 {
1888 if (((S_ISREG(g_OvFsMergedContents[Index].Mode) == FALSE) && (S_ISDIR(g_OvFsMergedContents[Index].Mode) == FALSE)) ||
1889 (g_OvFsMergedContents[Index].Hydrates != 0))
1890 {
1891
1892 continue;
1893 }
1894
1895 LxtCheckErrno(utime(g_OvFsMergedContents[Index].Path, &Times));
1896 }
1897
1898 //
1899 // Check the behavior for read directory on the root after new files were
1900 // added.
1901 //
1902
1903 memset(Found, 0, sizeof(Found));
1904 LxtCheckErrno(Fd = open(OVFS_TEST_MOUNT_PATH, O_RDONLY));
1905 LxtCheckErrno(BytesRead = LxtGetdents64(Fd, (struct dirent*)Buffer, sizeof(Buffer)));
1906
1907 while (BytesRead > 0)
1908 {
1909 for (EntryPosition = 0; EntryPosition < BytesRead; EntryPosition += Entry->d_reclen)
1910 {
1911
1912 Entry = (struct dirent*)&Buffer[EntryPosition];
1913 if (strcmp(Entry->d_name, ".") == 0)
1914 {
1915 FoundIndex = 0;
1916 }
1917 else if (strcmp(Entry->d_name, "..") == 0)
1918 {
1919 FoundIndex = 1;
1920 }
1921 else
1922 {
1923 for (Index = 0; Index < LXT_COUNT_OF(g_OvFsMergedContents); ++Index)
1924 {
1925 if (strcmp(g_OvFsMergedContents[Index].Name, Entry->d_name) == 0)
1926 {
1927 FoundIndex = Index + 2;
1928 break;
1929 }
1930 }
1931
1932 if (Index == LXT_COUNT_OF(g_OvFsMergedContents))
1933 {
1934 for (Index = 0; Index < LXT_COUNT_OF(writeUpperCreate); ++Index)
1935 {
1936 if (strcmp(writeUpperCreate[Index], Entry->d_name) == 0)
1937 {
1938 FoundIndex = Index + 2 + LXT_COUNT_OF(g_OvFsMergedContents);
1939 break;
1940 }
1941 }
1942
1943 if (Index == LXT_COUNT_OF(writeUpperCreate))
1944 {
1945 LxtLogError("Unexpected entry %s", Entry->d_name);
1946 LxtCheckNotEqual(Index, LXT_COUNT_OF(writeUpperCreate), "%d");
1947 }
1948 }
1949 }
1950
1951 LxtCheckEqual(Found[FoundIndex], 0, "%d");
1952 Found[FoundIndex] = 1;
1953 }
1954
1955 Entry = (struct dirent*)Buffer;
1956 LxtCheckErrno(BytesRead = LxtGetdents64(Fd, (struct dirent*)Buffer, sizeof(Buffer)));
1957 }
1958
1959 for (Index = 0; Index < LXT_COUNT_OF(Found); ++Index)
1960 {
1961 LxtCheckEqual(Found[FoundIndex], 1, "%d");
1962 }
1963
1964 LxtClose(Fd);
1965 Fd = -1;
1966
1967 //
1968 // Check the behavior for read directory on sub directories.
1969 //
1970
1971 for (Index = 0; Index < LXT_COUNT_OF(g_OvFsMergedContents); ++Index)
1972 {
1973 if (S_ISDIR(g_OvFsMergedContents[Index].Mode) == FALSE)
1974 {
1975 continue;
1976 }
1977
1978 LxtCheckErrno(Fd = open(g_OvFsMergedContents[Index].Path, O_RDONLY));
1979 LxtCheckErrno(BytesRead = LxtGetdents64(Fd, (struct dirent*)Buffer, sizeof(Buffer)))
1980
1981 Count = 0;
1982 for (EntryPosition = 0; EntryPosition < BytesRead; EntryPosition += Entry->d_reclen)
1983 {
1984
1985 Entry = (struct dirent*)&Buffer[EntryPosition];
1986 Count += 1;
1987 }
1988
1989 LxtCheckEqual(Count, 2, "%d");
1990 LxtClose(Fd);
1991 Fd = -1;
1992 }
1993
1994 //
1995 // Check that none of the operations hydrated files from the lower
1996 // directory.
1997 //
1998
1999 LxtCheckErrnoFailure(stat(OVFS_TEST_UPPER_DIR "/OnlyInLowerDir", &StatBuffer), ENOENT);
2000 LxtCheckErrnoFailure(stat(OVFS_TEST_UPPER_DIR "/OnlyInLowerFile", &StatBuffer), ENOENT);
2001 LxtCheckErrnoFailure(stat(OVFS_TEST_UPPER_DIR "/OnlyInLowerSym", &StatBuffer), ENOENT);
2002
2003 //
2004 // Unmount and check it was unmounted.
2005 //
2006
2007 if (Fd != -1)
2008 {
2009 LxtClose(Fd);
2010 Fd = -1;
2011 }
2012
2013 LxtCheckErrnoZeroSuccess(umount(OVFS_TEST_MOUNT_PATH));
2014 LxtCheckResult(MountCheckIsNotMount(OVFS_TEST_MOUNT_PATH));
2015 Result = 0;
2016
2017 ErrorExit:
2018 if (Fd != -1)
2019 {
2020 LxtClose(Fd);
2021 }
2022
2023 umount(OVFS_TEST_MOUNT_PATH);
2024 return Result;
2025 }
2026
2027 int OvFsTestInodeWriteOps(PLXT_ARGS Args)
2028
2029 /*++
2030
2031 Description:
2032
2033 This routine tests inode operations that may modify state.
2034
2035 Arguments:
2036
2037 Args - Supplies the command line arguments.
2038
2039 Return Value:
2040
2041 Returns 0 on success, -1 on failure.
2042
2043 --*/
2044
2045 {
2046
2047 char BytesRead;
2048 char Buffer[100];
2049 struct __user_cap_data_struct CapData[2];
2050 struct __user_cap_header_struct CapHeader;
2051 pid_t ChildPid;
2052 int Fd;
2053 int FdWrite;
2054 int Result;
2055 struct stat StatBuffer;
2056 struct stat StatBufferWrite;
2057
2058 ChildPid = -1;
2059 Fd = -1;
2060 FdWrite = -1;
2061
2062 //
2063 // Set up the directories and populate some state.
2064 //
2065
2066 LxtCheckResult(OvFsTestDirsSetup());
2067 LxtCheckResult(OvFsTestDirsPopulate());
2068
2069 //
2070 // Mount an overlayfs instance.
2071 //
2072
2073 LxtCheckResult(MountCheckIsNotMount(OVFS_TEST_MOUNT_PATH));
2074 LxtCheckErrnoZeroSuccess(mount("myovfsnew", OVFS_TEST_MOUNT_PATH, OVFS_TEST_MOUNT_NAME, 0, OVFS_TEST_MOUNT_DEFAULT));
2075
2076 //
2077 // Open the same file for read and write. The read file will be from the
2078 // lower layer, but opening the file for write will cause the file to be
2079 // hydrated in the upper layer and the inode updated.
2080 //
2081
2082 LxtCheckErrno(Fd = open(OVFS_TEST_MOUNT_PATH "/OnlyInLowerFile", O_RDONLY, 0));
2083 LxtCheckErrno(fstat(Fd, &StatBuffer));
2084 LxtCheckErrnoFailure(stat(OVFS_TEST_UPPER_DIR "/OnlyInLowerFile", &StatBufferWrite), ENOENT);
2085 LxtCheckErrno(FdWrite = open(OVFS_TEST_MOUNT_PATH "/OnlyInLowerFile", O_RDWR, 0));
2086 LxtCheckErrno(stat(OVFS_TEST_UPPER_DIR "/OnlyInLowerFile", &StatBufferWrite));
2087 LxtCheckErrno(fstat(FdWrite, &StatBufferWrite));
2088 if (g_LxtUnstableInodes != 0)
2089 {
2090 LxtCheckNotEqual(StatBuffer.st_ino, StatBufferWrite.st_ino, "%d");
2091 }
2092
2093 LxtCheckEqual(StatBuffer.st_mode, StatBufferWrite.st_mode, "%d");
2094
2095 //
2096 // Check that the inode numbers are the same now that both files are open.
2097 // Any open files referring to this inode will access the new inode
2098 // metadata.
2099 //
2100
2101 LxtCheckErrno(fstat(Fd, &StatBuffer));
2102 if (g_LxtUnstableInodes != 0)
2103 {
2104 LxtCheckEqual(StatBuffer.st_ino, StatBufferWrite.st_ino, "%d");
2105 }
2106
2107 LxtCheckErrno(fstat(FdWrite, &StatBufferWrite));
2108 if (g_LxtUnstableInodes != 0)
2109 {
2110 LxtCheckEqual(StatBuffer.st_ino, StatBufferWrite.st_ino, "%d");
2111 }
2112
2113 LxtCheckEqual(StatBuffer.st_mode, StatBufferWrite.st_mode, "%d");
2114
2115 //
2116 // Check that chmod on one of the file descriptors impacts both. Any open
2117 // files referring to this inode will access the new inode metadata.
2118 //
2119
2120 LxtCheckNotEqual(StatBuffer.st_mode, S_IFREG | 0111, "%d");
2121 LxtCheckErrno(fchmod(FdWrite, 0111));
2122 LxtCheckErrno(fstat(Fd, &StatBuffer));
2123 LxtCheckErrno(fstat(FdWrite, &StatBufferWrite));
2124 LxtLogInfo("%d, %d", StatBuffer.st_mode, StatBufferWrite.st_mode);
2125 LxtCheckEqual(StatBuffer.st_mode, S_IFREG | 0111, "%d");
2126 LxtCheckEqual(StatBufferWrite.st_mode, S_IFREG | 0111, "%d");
2127
2128 //
2129 // Check that writing only impacts the file object opened for write and not
2130 // the one opened for read. Any open files objects will access the old file
2131 // data.
2132 //
2133
2134 LxtCheckErrno(write(FdWrite, "OnlyInLowerFileModified", sizeof("OnlyInLowerFileModified")));
2135 LxtCheckErrno(BytesRead = read(Fd, Buffer, sizeof(Buffer) - 1));
2136 Buffer[BytesRead] = 0;
2137 LxtCheckStringEqual(Buffer, "OnlyInLowerFile") LxtCheckErrno(lseek(FdWrite, SEEK_SET, 0));
2138 LxtCheckErrno(BytesRead = read(FdWrite, Buffer, sizeof(Buffer) - 1));
2139 Buffer[BytesRead] = 0;
2140 LxtCheckStringEqual(Buffer, "OnlyInLowerFileModified")
2141
2142 //
2143 // Unmount and check it was unmounted.
2144 //
2145
2146 if (Fd != -1)
2147 {
2148 LxtClose(Fd);
2149 Fd = -1;
2150 }
2151
2152 if (FdWrite != -1)
2153 {
2154 LxtClose(FdWrite);
2155 FdWrite = -1;
2156 }
2157
2158 LxtCheckErrnoZeroSuccess(umount(OVFS_TEST_MOUNT_PATH));
2159 LxtCheckResult(MountCheckIsNotMount(OVFS_TEST_MOUNT_PATH));
2160
2161 //
2162 // Check that chmod, chown, and utime hydrate files.
2163 //
2164
2165 LxtCheckResult(OvFsTestDirsSetup());
2166 LxtCheckResult(OvFsTestDirsPopulate());
2167 LxtCheckResult(MountCheckIsNotMount(OVFS_TEST_MOUNT_PATH));
2168 LxtCheckErrnoZeroSuccess(mount("myovfsnew", OVFS_TEST_MOUNT_PATH, OVFS_TEST_MOUNT_NAME, 0, OVFS_TEST_MOUNT_DEFAULT));
2169
2170 LxtCheckErrnoFailure(stat(OVFS_TEST_UPPER_DIR "/OnlyInLowerDir", &StatBuffer), ENOENT);
2171 LxtCheckErrnoFailure(stat(OVFS_TEST_UPPER_DIR "/OnlyInLowerFile", &StatBuffer), ENOENT);
2172 LxtCheckErrnoFailure(stat(OVFS_TEST_UPPER_DIR "/OnlyInLowerSym", &StatBuffer), ENOENT);
2173 LxtCheckErrno(chmod(OVFS_TEST_MOUNT_PATH "/OnlyInLowerDir", 0777));
2174 LxtCheckErrno(stat(OVFS_TEST_UPPER_DIR "/OnlyInLowerDir", &StatBuffer));
2175 LxtCheckErrnoFailure(stat(OVFS_TEST_UPPER_DIR "/OnlyInLowerFile", &StatBuffer), ENOENT);
2176 LxtCheckErrnoFailure(lstat(OVFS_TEST_UPPER_DIR "/OnlyInLowerSym", &StatBuffer), ENOENT);
2177 LxtCheckErrnoZeroSuccess(umount(OVFS_TEST_MOUNT_PATH));
2178 LxtCheckResult(MountCheckIsNotMount(OVFS_TEST_MOUNT_PATH));
2179
2180 LxtCheckResult(OvFsTestDirsSetup());
2181 LxtCheckResult(OvFsTestDirsPopulate());
2182 LxtCheckResult(MountCheckIsNotMount(OVFS_TEST_MOUNT_PATH));
2183 LxtCheckErrnoZeroSuccess(mount("myovfsnew", OVFS_TEST_MOUNT_PATH, OVFS_TEST_MOUNT_NAME, 0, OVFS_TEST_MOUNT_DEFAULT));
2184
2185 LxtCheckErrnoFailure(stat(OVFS_TEST_UPPER_DIR "/OnlyInLowerDir", &StatBuffer), ENOENT);
2186 LxtCheckErrnoFailure(stat(OVFS_TEST_UPPER_DIR "/OnlyInLowerFile", &StatBuffer), ENOENT);
2187 LxtCheckErrnoFailure(stat(OVFS_TEST_UPPER_DIR "/OnlyInLowerSym", &StatBuffer), ENOENT);
2188 LxtCheckErrno(chown(OVFS_TEST_MOUNT_PATH "/OnlyInLowerFile", 1, 1));
2189 LxtCheckErrnoFailure(stat(OVFS_TEST_UPPER_DIR "/OnlyInLowerDir", &StatBuffer), ENOENT);
2190 LxtCheckErrno(stat(OVFS_TEST_UPPER_DIR "/OnlyInLowerFile", &StatBuffer));
2191 LxtCheckErrnoFailure(lstat(OVFS_TEST_UPPER_DIR "/OnlyInLowerSym", &StatBuffer), ENOENT);
2192 LxtCheckErrnoZeroSuccess(umount(OVFS_TEST_MOUNT_PATH));
2193 LxtCheckResult(MountCheckIsNotMount(OVFS_TEST_MOUNT_PATH));
2194
2195 LxtCheckResult(OvFsTestDirsSetup());
2196 LxtCheckResult(OvFsTestDirsPopulate());
2197 LxtCheckResult(MountCheckIsNotMount(OVFS_TEST_MOUNT_PATH));
2198 LxtCheckErrnoZeroSuccess(mount("myovfsnew", OVFS_TEST_MOUNT_PATH, OVFS_TEST_MOUNT_NAME, 0, OVFS_TEST_MOUNT_DEFAULT));
2199
2200 LxtCheckErrnoFailure(stat(OVFS_TEST_UPPER_DIR "/OnlyInLowerDir", &StatBuffer), ENOENT);
2201 LxtCheckErrnoFailure(stat(OVFS_TEST_UPPER_DIR "/OnlyInLowerFile", &StatBuffer), ENOENT);
2202 LxtCheckErrnoFailure(stat(OVFS_TEST_UPPER_DIR "/OnlyInLowerSym", &StatBuffer), ENOENT);
2203 LxtCheckErrno(utimensat(-1, OVFS_TEST_MOUNT_PATH "/OnlyInLowerSym", NULL, AT_SYMLINK_NOFOLLOW));
2204 LxtCheckErrnoFailure(stat(OVFS_TEST_UPPER_DIR "/OnlyInLowerDir", &StatBuffer), ENOENT);
2205 LxtCheckErrnoFailure(stat(OVFS_TEST_UPPER_DIR "/OnlyInLowerFile", &StatBuffer), ENOENT);
2206 LxtCheckErrno(lstat(OVFS_TEST_UPPER_DIR "/OnlyInLowerSym", &StatBuffer));
2207 LxtCheckErrnoZeroSuccess(umount(OVFS_TEST_MOUNT_PATH));
2208 LxtCheckResult(MountCheckIsNotMount(OVFS_TEST_MOUNT_PATH));
2209
2210 //
2211 // Check that the 4 types of creation hydrate paths.
2212 //
2213
2214 LxtCheckResult(OvFsTestDirsSetup());
2215 LxtCheckResult(OvFsTestDirsPopulate());
2216 LxtCheckResult(MountCheckIsNotMount(OVFS_TEST_MOUNT_PATH));
2217 LxtCheckErrnoZeroSuccess(mount("myovfsnew", OVFS_TEST_MOUNT_PATH, OVFS_TEST_MOUNT_NAME, 0, OVFS_TEST_MOUNT_DEFAULT));
2218
2219 LxtCheckErrnoFailure(stat(OVFS_TEST_UPPER_DIR "/OnlyInLowerDir", &StatBuffer), ENOENT);
2220 LxtCheckErrnoFailure(stat(OVFS_TEST_UPPER_DIR "/OnlyInLowerFile", &StatBuffer), ENOENT);
2221 LxtCheckErrnoFailure(stat(OVFS_TEST_UPPER_DIR "/OnlyInLowerSym", &StatBuffer), ENOENT);
2222 LxtCheckErrno(symlink("CreatedSymlink", OVFS_TEST_MOUNT_PATH "/OnlyInLowerDir/CreatedSymlink"));
2223 LxtCheckErrno(stat(OVFS_TEST_UPPER_DIR "/OnlyInLowerDir", &StatBuffer));
2224 LxtCheckErrno(lstat(OVFS_TEST_UPPER_DIR "/OnlyInLowerDir/CreatedSymlink", &StatBuffer));
2225 LxtCheckErrnoFailure(stat(OVFS_TEST_UPPER_DIR "/OnlyInLowerFile", &StatBuffer), ENOENT);
2226 LxtCheckErrnoFailure(lstat(OVFS_TEST_UPPER_DIR "/OnlyInLowerSym", &StatBuffer), ENOENT);
2227 LxtCheckErrnoZeroSuccess(umount(OVFS_TEST_MOUNT_PATH));
2228 LxtCheckResult(MountCheckIsNotMount(OVFS_TEST_MOUNT_PATH));
2229
2230 LxtCheckResult(OvFsTestDirsSetup());
2231 LxtCheckResult(OvFsTestDirsPopulate());
2232 LxtCheckResult(MountCheckIsNotMount(OVFS_TEST_MOUNT_PATH));
2233 LxtCheckErrnoZeroSuccess(mount("myovfsnew", OVFS_TEST_MOUNT_PATH, OVFS_TEST_MOUNT_NAME, 0, OVFS_TEST_MOUNT_DEFAULT));
2234
2235 LxtCheckErrnoFailure(stat(OVFS_TEST_UPPER_DIR "/OnlyInLowerDir", &StatBuffer), ENOENT);
2236 LxtCheckErrnoFailure(stat(OVFS_TEST_UPPER_DIR "/OnlyInLowerFile", &StatBuffer), ENOENT);
2237 LxtCheckErrnoFailure(stat(OVFS_TEST_UPPER_DIR "/OnlyInLowerSym", &StatBuffer), ENOENT);
2238 LxtCheckErrno(Fd = creat(OVFS_TEST_MOUNT_PATH "/OnlyInLowerDir/CreatedFile", 0777));
2239 LxtClose(Fd);
2240 Fd = -1;
2241 LxtCheckErrno(stat(OVFS_TEST_UPPER_DIR "/OnlyInLowerDir", &StatBuffer));
2242 LxtCheckErrno(stat(OVFS_TEST_UPPER_DIR "/OnlyInLowerDir/CreatedFile", &StatBuffer));
2243 LxtCheckErrnoFailure(stat(OVFS_TEST_UPPER_DIR "/OnlyInLowerFile", &StatBuffer), ENOENT);
2244 LxtCheckErrnoFailure(lstat(OVFS_TEST_UPPER_DIR "/OnlyInLowerSym", &StatBuffer), ENOENT);
2245 LxtCheckErrnoZeroSuccess(umount(OVFS_TEST_MOUNT_PATH));
2246 LxtCheckResult(MountCheckIsNotMount(OVFS_TEST_MOUNT_PATH));
2247
2248 LxtCheckResult(OvFsTestDirsSetup());
2249 LxtCheckResult(OvFsTestDirsPopulate());
2250 LxtCheckResult(MountCheckIsNotMount(OVFS_TEST_MOUNT_PATH));
2251 LxtCheckErrnoZeroSuccess(mount("myovfsnew", OVFS_TEST_MOUNT_PATH, OVFS_TEST_MOUNT_NAME, 0, OVFS_TEST_MOUNT_DEFAULT));
2252
2253 LxtCheckErrnoFailure(stat(OVFS_TEST_UPPER_DIR "/OnlyInLowerDir", &StatBuffer), ENOENT);
2254 LxtCheckErrnoFailure(stat(OVFS_TEST_UPPER_DIR "/OnlyInLowerFile", &StatBuffer), ENOENT);
2255 LxtCheckErrnoFailure(stat(OVFS_TEST_UPPER_DIR "/OnlyInLowerSym", &StatBuffer), ENOENT);
2256 LxtCheckErrno(mkdir(OVFS_TEST_MOUNT_PATH "/OnlyInLowerDir/CreatedDir", 0777));
2257 LxtCheckErrno(stat(OVFS_TEST_UPPER_DIR "/OnlyInLowerDir", &StatBuffer));
2258 LxtCheckErrno(stat(OVFS_TEST_UPPER_DIR "/OnlyInLowerDir/CreatedDir", &StatBuffer));
2259 LxtCheckErrnoFailure(stat(OVFS_TEST_UPPER_DIR "/OnlyInLowerFile", &StatBuffer), ENOENT);
2260 LxtCheckErrnoFailure(lstat(OVFS_TEST_UPPER_DIR "/OnlyInLowerSym", &StatBuffer), ENOENT);
2261 LxtCheckErrnoZeroSuccess(umount(OVFS_TEST_MOUNT_PATH));
2262 LxtCheckResult(MountCheckIsNotMount(OVFS_TEST_MOUNT_PATH));
2263
2264 LxtCheckResult(OvFsTestDirsSetup());
2265 LxtCheckResult(OvFsTestDirsPopulate());
2266 LxtCheckResult(MountCheckIsNotMount(OVFS_TEST_MOUNT_PATH));
2267 LxtCheckErrnoZeroSuccess(mount("myovfsnew", OVFS_TEST_MOUNT_PATH, OVFS_TEST_MOUNT_NAME, 0, OVFS_TEST_MOUNT_DEFAULT));
2268
2269 LxtCheckErrnoFailure(stat(OVFS_TEST_UPPER_DIR "/OnlyInLowerDir", &StatBuffer), ENOENT);
2270 LxtCheckErrnoFailure(stat(OVFS_TEST_UPPER_DIR "/OnlyInLowerFile", &StatBuffer), ENOENT);
2271 LxtCheckErrnoFailure(stat(OVFS_TEST_UPPER_DIR "/OnlyInLowerSym", &StatBuffer), ENOENT);
2272 LxtCheckErrno(link(OVFS_TEST_MOUNT_PATH "/OnlyInLowerFile", OVFS_TEST_MOUNT_PATH "/OnlyInLowerDir/CreatedLink"));
2273 LxtCheckErrno(stat(OVFS_TEST_UPPER_DIR "/OnlyInLowerDir", &StatBuffer));
2274 LxtCheckErrno(stat(OVFS_TEST_UPPER_DIR "/OnlyInLowerDir/CreatedLink", &StatBuffer));
2275 LxtCheckErrno(stat(OVFS_TEST_UPPER_DIR "/OnlyInLowerFile", &StatBuffer));
2276 LxtCheckErrnoFailure(lstat(OVFS_TEST_UPPER_DIR "/OnlyInLowerSym", &StatBuffer), ENOENT);
2277 LxtCheckErrnoZeroSuccess(umount(OVFS_TEST_MOUNT_PATH));
2278 LxtCheckResult(MountCheckIsNotMount(OVFS_TEST_MOUNT_PATH));
2279
2280 //
2281 // Check the undefined behavior for O_RDONLY with O_TRUNC
2282 //
2283
2284 LxtCheckResult(OvFsTestDirsSetup());
2285 LxtCheckResult(OvFsTestDirsPopulate());
2286 LxtCheckResult(MountCheckIsNotMount(OVFS_TEST_MOUNT_PATH));
2287 LxtCheckErrnoZeroSuccess(mount("myovfsnew", OVFS_TEST_MOUNT_PATH, OVFS_TEST_MOUNT_NAME, 0, OVFS_TEST_MOUNT_DEFAULT));
2288
2289 LxtCheckErrno(Fd = open(OVFS_TEST_MOUNT_PATH "/OnlyInLowerFile", O_RDONLY | O_TRUNC, 0));
2290 LxtCheckErrnoFailure(ftruncate(Fd, 0), EINVAL);
2291 LxtClose(Fd);
2292 Fd = -1;
2293 LxtCheckErrno(stat(OVFS_TEST_LOWER_DIR "/OnlyInLowerFile", &StatBuffer));
2294 LxtCheckNotEqual(StatBuffer.st_size, 0, "%d");
2295 LxtCheckErrno(stat(OVFS_TEST_UPPER_DIR "/OnlyInLowerFile", &StatBuffer));
2296 LxtCheckEqual(StatBuffer.st_size, 0, "%d");
2297
2298 LxtCheckErrno(Fd = open(OVFS_TEST_MOUNT_PATH "/OnlyInUpperFile", O_RDONLY | O_TRUNC, 0));
2299 LxtCheckErrnoFailure(ftruncate(Fd, 0), EINVAL);
2300 LxtClose(Fd);
2301 Fd = -1;
2302 LxtCheckErrnoFailure(stat(OVFS_TEST_LOWER_DIR "/OnlyInUpperFile", &StatBuffer), ENOENT);
2303 LxtCheckErrno(stat(OVFS_TEST_UPPER_DIR "/OnlyInUpperFile", &StatBuffer));
2304 LxtCheckEqual(StatBuffer.st_size, 0, "%d");
2305
2306 LxtCheckErrno(Fd = open(OVFS_TEST_MOUNT_PATH "/InBothFile", O_RDONLY | O_TRUNC, 0));
2307 LxtCheckErrnoFailure(ftruncate(Fd, 0), EINVAL);
2308 LxtClose(Fd);
2309 Fd = -1;
2310 LxtCheckErrno(stat(OVFS_TEST_LOWER_DIR "/OnlyInLowerFile", &StatBuffer));
2311 LxtCheckNotEqual(StatBuffer.st_size, 0, "%d");
2312 LxtCheckErrno(stat(OVFS_TEST_UPPER_DIR "/InBothFile", &StatBuffer));
2313 LxtCheckEqual(StatBuffer.st_size, 0, "%d");
2314
2315 LxtCheckErrnoZeroSuccess(umount(OVFS_TEST_MOUNT_PATH));
2316 LxtCheckResult(MountCheckIsNotMount(OVFS_TEST_MOUNT_PATH));
2317
2318 //
2319 // Repeat the above for a file outside of overlay.
2320 //
2321
2322 LxtCheckResult(OvFsTestDirsSetup());
2323 LxtCheckResult(OvFsTestDirsPopulate());
2324 LxtCheckResult(MountCheckIsNotMount(OVFS_TEST_MOUNT_PATH));
2325 LxtCheckErrno(stat(OVFS_TEST_LOWER_DIR "/OnlyInLowerFile", &StatBuffer));
2326 LxtCheckNotEqual(StatBuffer.st_size, 0, "%d");
2327 LxtCheckErrno(Fd = open(OVFS_TEST_LOWER_DIR "/OnlyInLowerFile", O_RDONLY | O_TRUNC, 0));
2328 LxtCheckErrnoFailure(ftruncate(Fd, 0), EINVAL);
2329 LxtClose(Fd);
2330 Fd = -1;
2331 LxtCheckErrno(stat(OVFS_TEST_LOWER_DIR "/OnlyInLowerFile", &StatBuffer));
2332 LxtCheckEqual(StatBuffer.st_size, 0, "%d");
2333
2334 //
2335 // Repeat the above for a file where write access is not granted.
2336 //
2337
2338 LxtCheckResult(OvFsTestDirsSetup());
2339 LxtCheckResult(OvFsTestDirsPopulate());
2340 LxtCheckResult(MountCheckIsNotMount(OVFS_TEST_MOUNT_PATH));
2341 LxtCheckErrno(stat(OVFS_TEST_LOWER_DIR "/OnlyInLowerFile", &StatBuffer));
2342 LxtCheckNotEqual(StatBuffer.st_size, 0, "%d");
2343 LxtCheckErrno(chmod(OVFS_TEST_LOWER_DIR "/OnlyInLowerFile", 0444));
2344 LxtCheckErrno(ChildPid = fork());
2345 if (ChildPid == 0)
2346 {
2347
2348 //
2349 // Drop privileges so the current process does not have VFS capabilities
2350 // and is in another user\group.
2351 //
2352
2353 memset(&CapData, 0, sizeof(CapData));
2354 memset(&CapHeader, 0, sizeof(CapHeader));
2355 CapHeader.version = _LINUX_CAPABILITY_VERSION_3;
2356 LxtCheckErrno(prctl(PR_SET_KEEPCAPS, 1));
2357 LxtCheckErrno(setgid(2002));
2358 LxtCheckErrno(setuid(2002));
2359 LxtCheckErrno(LxtCapSet(&CapHeader, CapData));
2360
2361 //
2362 // Open the file with different truncate variations.
2363 //
2364
2365 LxtCheckErrno(Fd = open(OVFS_TEST_LOWER_DIR "/OnlyInLowerFile", O_RDONLY, 0));
2366 LxtClose(Fd);
2367 Fd = -1;
2368 LxtCheckErrnoFailure(Fd = open(OVFS_TEST_LOWER_DIR "/OnlyInLowerFile", O_RDWR, 0), EACCES);
2369 LxtCheckErrnoFailure(Fd = open(OVFS_TEST_LOWER_DIR "/OnlyInLowerFile", O_RDONLY | O_TRUNC, 0), EACCES);
2370 _exit(0);
2371 }
2372
2373 LxtCheckResult(LxtWaitPidPoll(ChildPid, 0));
2374
2375 Result = 0;
2376
2377 ErrorExit:
2378 if (ChildPid == 0)
2379 {
2380 _exit(Result);
2381 }
2382
2383 if (Fd != -1)
2384 {
2385 LxtClose(Fd);
2386 }
2387
2388 if (FdWrite != -1)
2389 {
2390 LxtClose(FdWrite);
2391 }
2392
2393 umount(OVFS_TEST_MOUNT_PATH);
2394 return Result;
2395 }
2396
2397 int OvFsTestInodeUnlink(PLXT_ARGS Args)
2398
2399 /*++
2400
2401 Description:
2402
2403 This routine tests inode operations unlink.
2404
2405 Arguments:
2406
2407 Args - Supplies the command line arguments.
2408
2409 Return Value:
2410
2411 Returns 0 on success, -1 on failure.
2412
2413 --*/
2414
2415 {
2416
2417 int Fd;
2418 int FdLower;
2419 int Result;
2420 struct stat StatBuffer;
2421
2422 Fd = -1;
2423 FdLower = -1;
2424
2425 //
2426 // Set up the directories and populate some state.
2427 //
2428
2429 LxtCheckResult(OvFsTestDirsSetup());
2430 LxtCheckResult(OvFsTestDirsPopulate());
2431
2432 //
2433 // Mount an overlayfs instance and check for the expected file state.
2434 //
2435
2436 LxtCheckResult(MountCheckIsNotMount(OVFS_TEST_MOUNT_PATH));
2437 LxtCheckErrnoZeroSuccess(mount("myovfsnew", OVFS_TEST_MOUNT_PATH, OVFS_TEST_MOUNT_NAME, 0, OVFS_TEST_MOUNT_DEFAULT));
2438
2439 LxtCheckErrnoFailure(stat(OVFS_TEST_UPPER_DIR "/OnlyInLowerDir", &StatBuffer), ENOENT);
2440 LxtCheckErrnoFailure(stat(OVFS_TEST_UPPER_DIR "/OnlyInLowerFile", &StatBuffer), ENOENT);
2441 LxtCheckErrnoFailure(stat(OVFS_TEST_UPPER_DIR "/OnlyInLowerSym", &StatBuffer), ENOENT);
2442 LxtCheckErrno(stat(OVFS_TEST_UPPER_DIR "/OnlyInUpperDir", &StatBuffer));
2443 LxtCheckTrue(S_ISDIR(StatBuffer.st_mode));
2444 LxtCheckErrno(stat(OVFS_TEST_UPPER_DIR "/OnlyInUpperFile", &StatBuffer));
2445 LxtCheckTrue(S_ISREG(StatBuffer.st_mode));
2446 LxtCheckErrno(lstat(OVFS_TEST_UPPER_DIR "/OnlyInUpperSym", &StatBuffer));
2447 LxtCheckTrue(S_ISLNK(StatBuffer.st_mode));
2448 LxtCheckErrno(stat(OVFS_TEST_UPPER_DIR "/InBothDir", &StatBuffer));
2449 LxtCheckTrue(S_ISDIR(StatBuffer.st_mode));
2450 LxtCheckErrno(stat(OVFS_TEST_UPPER_DIR "/InBothFile", &StatBuffer));
2451 LxtCheckTrue(S_ISREG(StatBuffer.st_mode));
2452 LxtCheckErrno(lstat(OVFS_TEST_UPPER_DIR "/InBothSym", &StatBuffer));
2453 LxtCheckTrue(S_ISLNK(StatBuffer.st_mode));
2454
2455 //
2456 // Unlink each entry and check for the expected behavior.
2457 //
2458
2459 LxtCheckErrno(rmdir(OVFS_TEST_MERGED_DIR "/OnlyInLowerDir"));
2460 LxtCheckErrno(stat(OVFS_TEST_UPPER_DIR "/OnlyInLowerDir", &StatBuffer));
2461 LxtCheckTrue(S_ISCHR(StatBuffer.st_mode));
2462
2463 LxtCheckErrno(unlink(OVFS_TEST_MERGED_DIR "/OnlyInLowerFile"));
2464 LxtCheckErrno(stat(OVFS_TEST_UPPER_DIR "/OnlyInLowerFile", &StatBuffer));
2465 LxtCheckTrue(S_ISCHR(StatBuffer.st_mode));
2466
2467 LxtCheckErrno(unlink(OVFS_TEST_MERGED_DIR "/OnlyInLowerSym"));
2468 LxtCheckErrno(stat(OVFS_TEST_UPPER_DIR "/OnlyInLowerSym", &StatBuffer));
2469 LxtCheckTrue(S_ISCHR(StatBuffer.st_mode));
2470
2471 LxtCheckErrno(rmdir(OVFS_TEST_MERGED_DIR "/OnlyInUpperDir"));
2472 LxtCheckErrnoFailure(stat(OVFS_TEST_UPPER_DIR "/OnlyInUpperDir", &StatBuffer), ENOENT);
2473
2474 LxtCheckErrno(unlink(OVFS_TEST_MERGED_DIR "/OnlyInUpperFile"));
2475 LxtCheckErrnoFailure(stat(OVFS_TEST_UPPER_DIR "/OnlyInUpperFile", &StatBuffer), ENOENT);
2476
2477 LxtCheckErrno(unlink(OVFS_TEST_MERGED_DIR "/OnlyInUpperSym"));
2478 LxtCheckErrnoFailure(stat(OVFS_TEST_UPPER_DIR "/OnlyInUpperSym", &StatBuffer), ENOENT);
2479
2480 LxtCheckErrno(rmdir(OVFS_TEST_MERGED_DIR "/InBothDir"));
2481 LxtCheckErrno(stat(OVFS_TEST_UPPER_DIR "/InBothDir", &StatBuffer));
2482 LxtCheckTrue(S_ISCHR(StatBuffer.st_mode));
2483
2484 LxtCheckErrno(unlink(OVFS_TEST_MERGED_DIR "/InBothFile"));
2485 LxtCheckErrno(stat(OVFS_TEST_UPPER_DIR "/InBothFile", &StatBuffer));
2486 LxtCheckTrue(S_ISCHR(StatBuffer.st_mode));
2487
2488 LxtCheckErrno(unlink(OVFS_TEST_MERGED_DIR "/InBothSym"));
2489 LxtCheckErrno(stat(OVFS_TEST_UPPER_DIR "/InBothSym", &StatBuffer));
2490 LxtCheckTrue(S_ISCHR(StatBuffer.st_mode));
2491
2492 //
2493 // Check that the lower file is detected during open and not on unlink.
2494 //
2495
2496 LxtCheckErrnoZeroSuccess(umount(OVFS_TEST_MOUNT_PATH));
2497 LxtCheckResult(MountCheckIsNotMount(OVFS_TEST_MOUNT_PATH));
2498 LxtCheckResult(OvFsTestDirsSetup());
2499 LxtCheckResult(OvFsTestDirsPopulate());
2500 LxtCheckResult(MountCheckIsNotMount(OVFS_TEST_MOUNT_PATH));
2501 LxtCheckErrnoZeroSuccess(mount("myovfsnew", OVFS_TEST_MOUNT_PATH, OVFS_TEST_MOUNT_NAME, 0, OVFS_TEST_MOUNT_DEFAULT));
2502
2503 LxtCheckErrno(Fd = open(OVFS_TEST_MERGED_DIR "/OnlyInUpperFile", O_RDWR));
2504 LxtCheckErrno(FdLower = creat(OVFS_TEST_LOWER_DIR "/OnlyInUpperFile", 0777));
2505 LxtCheckErrno(unlink(OVFS_TEST_MERGED_DIR "/OnlyInUpperFile"));
2506 LxtCheckErrnoFailure(stat(OVFS_TEST_UPPER_DIR "/OnlyInUpperFile", &StatBuffer), ENOENT);
2507
2508 //
2509 // Repeat the above, but create the file in the lower first.
2510 //
2511
2512 LxtClose(Fd);
2513 Fd = -1;
2514 LxtClose(FdLower);
2515 FdLower = -1;
2516 LxtCheckErrnoZeroSuccess(umount(OVFS_TEST_MOUNT_PATH));
2517 LxtCheckResult(MountCheckIsNotMount(OVFS_TEST_MOUNT_PATH));
2518 LxtCheckResult(OvFsTestDirsSetup());
2519 LxtCheckResult(OvFsTestDirsPopulate());
2520 LxtCheckResult(MountCheckIsNotMount(OVFS_TEST_MOUNT_PATH));
2521 LxtCheckErrnoZeroSuccess(mount("myovfsnew", OVFS_TEST_MOUNT_PATH, OVFS_TEST_MOUNT_NAME, 0, OVFS_TEST_MOUNT_DEFAULT));
2522
2523 LxtCheckErrno(FdLower = creat(OVFS_TEST_LOWER_DIR "/OnlyInUpperFile", 0777));
2524 LxtCheckErrno(Fd = open(OVFS_TEST_MERGED_DIR "/OnlyInUpperFile", O_RDWR));
2525 LxtCheckErrno(unlink(OVFS_TEST_MERGED_DIR "/OnlyInUpperFile"));
2526 LxtCheckErrno(stat(OVFS_TEST_UPPER_DIR "/OnlyInUpperFile", &StatBuffer));
2527 LxtCheckTrue(S_ISCHR(StatBuffer.st_mode));
2528 LxtClose(Fd);
2529 Fd = -1;
2530 LxtClose(FdLower);
2531 FdLower = -1;
2532
2533 //
2534 // Check the behavior for unlink while a file is open.
2535 //
2536
2537 LxtCheckErrnoZeroSuccess(umount(OVFS_TEST_MOUNT_PATH));
2538 LxtCheckResult(MountCheckIsNotMount(OVFS_TEST_MOUNT_PATH));
2539 LxtCheckResult(OvFsTestDirsSetup());
2540 LxtCheckResult(OvFsTestDirsPopulate());
2541 LxtCheckResult(MountCheckIsNotMount(OVFS_TEST_MOUNT_PATH));
2542 LxtCheckErrnoZeroSuccess(mount("myovfsnew", OVFS_TEST_MOUNT_PATH, OVFS_TEST_MOUNT_NAME, 0, OVFS_TEST_MOUNT_DEFAULT));
2543
2544 LxtCheckErrno(FdLower = open(OVFS_TEST_MERGED_DIR "/OnlyInLowerFile", O_RDONLY));
2545 LxtCheckErrno(fstat(FdLower, &StatBuffer));
2546 LxtCheckTrue(S_ISREG(StatBuffer.st_mode));
2547 LxtCheckErrno(Fd = open(OVFS_TEST_MERGED_DIR "/OnlyInLowerFile", O_RDWR));
2548 LxtCheckErrno(fstat(Fd, &StatBuffer));
2549 LxtCheckTrue(S_ISREG(StatBuffer.st_mode));
2550 LxtCheckErrno(unlink(OVFS_TEST_MERGED_DIR "/OnlyInLowerFile"));
2551
2552 LxtCheckErrno(fstat(Fd, &StatBuffer));
2553 LxtCheckTrue(S_ISREG(StatBuffer.st_mode));
2554 LxtCheckErrno(fstat(FdLower, &StatBuffer));
2555 LxtCheckTrue(S_ISREG(StatBuffer.st_mode));
2556 LxtCheckErrno(fchmod(FdLower, 0777));
2557 LxtCheckErrno(fchmod(Fd, 0777));
2558 LxtClose(Fd);
2559 Fd = -1;
2560 LxtClose(FdLower);
2561 FdLower = -1;
2562
2563 LxtCheckErrno(Fd = open(OVFS_TEST_MERGED_DIR "/OnlyInUpperFile", O_RDONLY));
2564 LxtCheckErrno(fstat(Fd, &StatBuffer));
2565 LxtCheckTrue(S_ISREG(StatBuffer.st_mode));
2566 LxtCheckErrno(unlink(OVFS_TEST_MERGED_DIR "/OnlyInUpperFile"));
2567 LxtCheckErrno(fstat(Fd, &StatBuffer));
2568 LxtCheckTrue(S_ISREG(StatBuffer.st_mode));
2569 LxtCheckErrno(fchmod(Fd, 0777));
2570 LxtClose(Fd);
2571 Fd = -1;
2572
2573 //
2574 // Check the behavior for rmdir while a directory is open.
2575 //
2576
2577 LxtCheckErrnoZeroSuccess(umount(OVFS_TEST_MOUNT_PATH));
2578 LxtCheckResult(MountCheckIsNotMount(OVFS_TEST_MOUNT_PATH));
2579 LxtCheckResult(OvFsTestDirsSetup());
2580 LxtCheckResult(OvFsTestDirsPopulate());
2581 LxtCheckResult(MountCheckIsNotMount(OVFS_TEST_MOUNT_PATH));
2582 LxtCheckErrnoZeroSuccess(mount("myovfsnew", OVFS_TEST_MOUNT_PATH, OVFS_TEST_MOUNT_NAME, 0, OVFS_TEST_MOUNT_DEFAULT));
2583
2584 LxtCheckErrno(FdLower = open(OVFS_TEST_MERGED_DIR "/OnlyInLowerDir", O_RDONLY));
2585 LxtCheckErrno(fstat(FdLower, &StatBuffer));
2586 LxtCheckTrue(S_ISDIR(StatBuffer.st_mode));
2587 LxtCheckErrno(rmdir(OVFS_TEST_MERGED_DIR "/OnlyInLowerDir"));
2588 LxtCheckErrno(fstat(FdLower, &StatBuffer));
2589 LxtCheckTrue(S_ISDIR(StatBuffer.st_mode));
2590 LxtCheckErrnoFailure(fchmod(FdLower, 0777), ENOTDIR);
2591
2592 LxtCheckErrno(Fd = open(OVFS_TEST_MERGED_DIR "/InBothDir", O_RDONLY));
2593 LxtCheckErrno(fstat(Fd, &StatBuffer));
2594 LxtCheckTrue(S_ISDIR(StatBuffer.st_mode));
2595 LxtCheckErrno(rmdir(OVFS_TEST_MERGED_DIR "/InBothDir"));
2596 LxtCheckErrno(fstat(Fd, &StatBuffer));
2597 LxtCheckTrue(S_ISDIR(StatBuffer.st_mode));
2598 LxtCheckErrno(fchmod(Fd, 0777));
2599
2600 //
2601 // Unmount and check it was unmounted.
2602 //
2603
2604 if (Fd != -1)
2605 {
2606 LxtClose(Fd);
2607 Fd = -1;
2608 }
2609
2610 if (FdLower != -1)
2611 {
2612 LxtClose(FdLower);
2613 FdLower = -1;
2614 }
2615
2616 LxtCheckErrnoZeroSuccess(umount(OVFS_TEST_MOUNT_PATH));
2617 LxtCheckResult(MountCheckIsNotMount(OVFS_TEST_MOUNT_PATH));
2618
2619 Result = 0;
2620
2621 ErrorExit:
2622 if (Fd != -1)
2623 {
2624 LxtClose(Fd);
2625 }
2626
2627 if (FdLower != -1)
2628 {
2629 LxtClose(FdLower);
2630 }
2631
2632 umount(OVFS_TEST_MOUNT_PATH);
2633 return Result;
2634 }
2635
2636 int OvFsTestInodeXattr(PLXT_ARGS Args)
2637
2638 /*++
2639
2640 Description:
2641
2642 This routine tests inode operations that hydrate xattrs.
2643
2644 Arguments:
2645
2646 Args - Supplies the command line arguments.
2647
2648 Return Value:
2649
2650 Returns 0 on success, -1 on failure.
2651
2652 --*/
2653
2654 {
2655
2656 int Count;
2657 struct
2658 {
2659 char* Path;
2660 char* Name;
2661 } HydratedData[] = {
2662 {OVFS_TEST_UPPER_DIR "/OnlyInLowerDir", "OnlyInLowerDir"}, {OVFS_TEST_UPPER_DIR "/OnlyInLowerFile", "OnlyInLowerFile"}};
2663
2664 int Index;
2665 char* ListCurrent;
2666 char List[256];
2667 ssize_t ListSize;
2668 int Result;
2669 struct stat StatBuffer;
2670 char Value[64];
2671 ssize_t ValueSize;
2672
2673 //
2674 // Set up the directories and populate some state.
2675 //
2676
2677 LxtCheckResult(OvFsTestDirsSetup());
2678 LxtCheckResult(OvFsTestDirsPopulate());
2679
2680 //
2681 // Mount an overlayfs instance.
2682 //
2683
2684 LxtCheckResult(MountCheckIsNotMount(OVFS_TEST_MOUNT_PATH));
2685 LxtCheckErrnoZeroSuccess(mount("myovfsnew", OVFS_TEST_MOUNT_PATH, OVFS_TEST_MOUNT_NAME, 0, OVFS_TEST_MOUNT_DEFAULT));
2686
2687 //
2688 // Check the xattr state in the merged directory.
2689 //
2690
2691 for (Index = 0; Index < LXT_COUNT_OF(g_OvFsMergedContents); ++Index)
2692 {
2693 if ((S_ISDIR(g_OvFsMergedContents[Index].Mode) == FALSE) && (S_ISREG(g_OvFsMergedContents[Index].Mode) == FALSE))
2694 {
2695
2696 continue;
2697 }
2698
2699 LxtCheckErrno(ListSize = listxattr(g_OvFsMergedContents[Index].Path, List, sizeof(List)));
2700
2701 ListCurrent = List;
2702 Count = 0;
2703 for (;;)
2704 {
2705 LxtCheckErrno(ValueSize = getxattr(g_OvFsMergedContents[Index].Path, ListCurrent, Value, sizeof(Value)));
2706
2707 LxtCheckStringEqual(Value, g_OvFsMergedContents[Index].Name);
2708 ListCurrent += strlen(ListCurrent) + 1;
2709 Count += 1;
2710 if (ListCurrent >= List + ListSize)
2711 {
2712 break;
2713 }
2714 }
2715
2716 LxtCheckEqual(Count, 2, "%d");
2717 }
2718
2719 //
2720 // Hydrate files and check that the xattr state was copied.
2721 //
2722
2723 LxtCheckErrnoFailure(stat(OVFS_TEST_UPPER_DIR "/OnlyInLowerDir", &StatBuffer), ENOENT);
2724 LxtCheckErrnoFailure(stat(OVFS_TEST_UPPER_DIR "/OnlyInLowerFile", &StatBuffer), ENOENT);
2725 LxtCheckResult(chmod(OVFS_TEST_MERGED_DIR "/OnlyInLowerDir", 0111));
2726 LxtCheckResult(chmod(OVFS_TEST_MERGED_DIR "/OnlyInLowerFile", 0111));
2727
2728 for (Index = 0; Index < LXT_COUNT_OF(HydratedData); ++Index)
2729 {
2730 LxtCheckErrno(stat(HydratedData[Index].Path, &StatBuffer));
2731 LxtCheckErrno(ListSize = listxattr(HydratedData[Index].Path, List, sizeof(List)));
2732
2733 ListCurrent = List;
2734 Count = 0;
2735 for (;;)
2736 {
2737 LxtCheckErrno(ValueSize = getxattr(HydratedData[Index].Path, ListCurrent, Value, sizeof(Value)));
2738
2739 LxtCheckStringEqual(Value, HydratedData[Index].Name);
2740 ListCurrent += strlen(ListCurrent) + 1;
2741 Count += 1;
2742 if (ListCurrent >= List + ListSize)
2743 {
2744 break;
2745 }
2746 }
2747
2748 LxtCheckEqual(Count, 2, "%d");
2749 }
2750
2751 LxtCheckErrnoZeroSuccess(umount(OVFS_TEST_MOUNT_PATH));
2752 LxtCheckResult(MountCheckIsNotMount(OVFS_TEST_MOUNT_PATH));
2753
2754 //
2755 // Check the behavior for hydration of "trusted.overlay.opaque" where the
2756 // value is dropped.
2757 //
2758
2759 LxtCheckResult(OvFsTestDirsSetup());
2760 LxtCheckResult(OvFsTestDirsPopulate());
2761 Value[0] = 'y';
2762 LxtCheckErrno(setxattr(OVFS_TEST_LOWER_DIR "/OnlyInLowerDir", "trusted.overlay.opaque", Value, 1, XATTR_CREATE));
2763
2764 LxtCheckErrno(setxattr(OVFS_TEST_LOWER_DIR "/OnlyInLowerFile", "trusted.overlay.opaque", Value, 1, XATTR_CREATE));
2765
2766 LxtCheckResult(MountCheckIsNotMount(OVFS_TEST_MOUNT_PATH));
2767 LxtCheckErrnoZeroSuccess(mount("myovfsnew", OVFS_TEST_MOUNT_PATH, OVFS_TEST_MOUNT_NAME, 0, OVFS_TEST_MOUNT_DEFAULT));
2768
2769 LxtCheckErrnoFailure(stat(OVFS_TEST_UPPER_DIR "/OnlyInLowerDir", &StatBuffer), ENOENT);
2770 LxtCheckErrnoFailure(stat(OVFS_TEST_UPPER_DIR "/OnlyInLowerFile", &StatBuffer), ENOENT);
2771 LxtCheckResult(chmod(OVFS_TEST_MERGED_DIR "/OnlyInLowerDir", 0111));
2772 LxtCheckResult(chmod(OVFS_TEST_MERGED_DIR "/OnlyInLowerFile", 0111));
2773
2774 for (Index = 0; Index < LXT_COUNT_OF(HydratedData); ++Index)
2775 {
2776 LxtCheckErrno(stat(HydratedData[Index].Path, &StatBuffer));
2777 LxtCheckErrno(ListSize = listxattr(HydratedData[Index].Path, List, sizeof(List)));
2778
2779 ListCurrent = List;
2780 Count = 0;
2781 for (;;)
2782 {
2783 LxtCheckErrno(ValueSize = getxattr(HydratedData[Index].Path, ListCurrent, Value, sizeof(Value)));
2784
2785 LxtCheckStringEqual(Value, HydratedData[Index].Name);
2786 ListCurrent += strlen(ListCurrent) + 1;
2787 Count += 1;
2788 if (ListCurrent >= List + ListSize)
2789 {
2790 break;
2791 }
2792 }
2793
2794 LxtCheckEqual(Count, 2, "%d");
2795 }
2796
2797 //
2798 // Unmount and check that it was unmounted.
2799 //
2800
2801 LxtCheckErrnoZeroSuccess(umount(OVFS_TEST_MOUNT_PATH));
2802 LxtCheckResult(MountCheckIsNotMount(OVFS_TEST_MOUNT_PATH));
2803
2804 Result = 0;
2805
2806 ErrorExit:
2807 umount(OVFS_TEST_MOUNT_PATH);
2808 return Result;
2809 }
2810
2811 int OvFsTestLowerWhiteout(PLXT_ARGS Args)
2812
2813 /*++
2814
2815 Description:
2816
2817 This routine tests how whiteouts behavior when they are in the lower layer.
2818
2819 Arguments:
2820
2821 Args - Supplies the command line arguments.
2822
2823 Return Value:
2824
2825 Returns 0 on success, -1 on failure.
2826
2827 --*/
2828
2829 {
2830
2831 char Buffer[256];
2832 int BytesRead;
2833 int Count;
2834 struct dirent* Entry;
2835 int EntryPosition;
2836 int Fd;
2837 int Found[LXT_COUNT_OF(g_OvFsMergedMultiContents) + 2];
2838 int FoundIndex;
2839 int Index;
2840 void* Mapping;
2841 void* MapResult;
2842 int Result;
2843 struct stat StatBuffer;
2844 struct stat StatMergedBuffer;
2845
2846 Fd = -1;
2847 Mapping = NULL;
2848
2849 //
2850 // Set up the directories and populate some state.
2851 //
2852
2853 LxtCheckResult(OvFsTestDirsSetup());
2854 LxtCheckResult(OvFsTestDirsPopulate());
2855
2856 //
2857 // Create some whiteout files in the lower directory.
2858 //
2859
2860 LxtCheckResult(mknod(OVFS_TEST_LOWER_DIR "/OnlyInLowerDir/whiteoutFile", S_IFCHR | 0777, 0));
2861 LxtCheckResult(mknod(OVFS_TEST_LOWER_DIR "/InBothDir/whiteoutFile", S_IFCHR | 0777, 0));
2862
2863 //
2864 // Mount an overlayfs instance and check the behavior for the whiteouts
2865 // created above.
2866 //
2867
2868 LxtCheckResult(MountCheckIsNotMount(OVFS_TEST_MOUNT_PATH));
2869 LxtCheckErrnoZeroSuccess(mount("myovfsnew", OVFS_TEST_MOUNT_PATH, OVFS_TEST_MOUNT_NAME, 0, OVFS_TEST_MOUNT_DEFAULT));
2870
2871 //
2872 // Check that the whiteout cannot be opened but are reported through readdir
2873 // when the folder is not merged with the upper.
2874 //
2875
2876 LxtCheckErrno(stat(OVFS_TEST_LOWER_DIR "/OnlyInLowerDir/whiteoutFile", &StatBuffer));
2877 LxtCheckTrue(S_ISCHR(StatBuffer.st_mode));
2878 LxtCheckErrnoFailure(stat(OVFS_TEST_MOUNT_PATH "/OnlyInLowerDir/whiteoutFile", &StatMergedBuffer), ENOENT);
2879
2880 LxtCheckErrno(Fd = open(OVFS_TEST_MOUNT_PATH "/OnlyInLowerDir", O_RDONLY));
2881 LxtCheckErrno(BytesRead = LxtGetdents64(Fd, (struct dirent*)Buffer, sizeof(Buffer)))
2882
2883 Count = 0;
2884 for (EntryPosition = 0; EntryPosition < BytesRead; EntryPosition += Entry->d_reclen)
2885 {
2886
2887 Entry = (struct dirent*)&Buffer[EntryPosition];
2888 LxtLogInfo("%s", Entry->d_name);
2889 Count += 1;
2890 }
2891 LxtCheckEqual(Count, 3, "%d");
2892 LxtClose(Fd);
2893 Fd = -1;
2894
2895 //
2896 // Check that the whiteout cannot be opened and is not reported through
2897 // readdir when the folder is merged with the upper.
2898 //
2899
2900 LxtCheckErrno(stat(OVFS_TEST_LOWER_DIR "/InBothDir/whiteoutFile", &StatBuffer));
2901 LxtCheckTrue(S_ISCHR(StatBuffer.st_mode));
2902 LxtCheckErrnoFailure(stat(OVFS_TEST_MOUNT_PATH "/InBothDir/whiteoutFile", &StatMergedBuffer), ENOENT);
2903
2904 LxtCheckErrno(Fd = open(OVFS_TEST_MOUNT_PATH "/InBothDir", O_RDONLY));
2905 LxtCheckErrno(BytesRead = LxtGetdents64(Fd, (struct dirent*)Buffer, sizeof(Buffer)))
2906
2907 Count = 0;
2908 for (EntryPosition = 0; EntryPosition < BytesRead; EntryPosition += Entry->d_reclen)
2909 {
2910
2911 Entry = (struct dirent*)&Buffer[EntryPosition];
2912 LxtLogInfo("%s", Entry->d_name);
2913 Count += 1;
2914 }
2915 LxtCheckEqual(Count, 2, "%d");
2916 LxtClose(Fd);
2917 Fd = -1;
2918
2919 //
2920 // Check that the whiteout can be overwritten in the upper and that it
2921 // is not replaced by a whiteout when removed.
2922 //
2923
2924 LxtCheckErrno(mkdir(OVFS_TEST_MOUNT_PATH "/InBothDir/whiteoutFile", 0777));
2925 LxtCheckErrno(stat(OVFS_TEST_MOUNT_PATH "/InBothDir/whiteoutFile", &StatMergedBuffer));
2926 LxtCheckTrue(S_ISDIR(StatMergedBuffer.st_mode));
2927 LxtCheckErrno(stat(OVFS_TEST_UPPER_DIR "/InBothDir/whiteoutFile", &StatBuffer));
2928 LxtCheckTrue(S_ISDIR(StatBuffer.st_mode));
2929 LxtCheckErrno(rmdir(OVFS_TEST_MOUNT_PATH "/InBothDir/whiteoutFile"));
2930 LxtCheckErrnoFailure(stat(OVFS_TEST_MOUNT_PATH "/InBothDir/whiteoutFile", &StatMergedBuffer), ENOENT);
2931 LxtCheckErrnoFailure(stat(OVFS_TEST_UPPER_DIR "/InBothDir/whiteoutFile", &StatBuffer), ENOENT);
2932
2933 //
2934 // Repeat the above with multiple lowers.
2935 //
2936
2937 LxtCheckErrnoZeroSuccess(umount(OVFS_TEST_MOUNT_PATH));
2938 LxtCheckResult(MountCheckIsNotMount(OVFS_TEST_MOUNT_PATH));
2939
2940 LxtCheckResult(MountCheckIsNotMount(OVFS_TEST_MOUNT_PATH));
2941 LxtCheckErrnoZeroSuccess(mount("myovfsnew", OVFS_TEST_MOUNT_PATH, OVFS_TEST_MOUNT_NAME, 0, OVFS_TEST_MOUNT_MULTI_LOWER));
2942
2943 //
2944 // Check that the whiteout cannot be opened but are reported through readdir
2945 // when the folder is not merged with the upper.
2946 //
2947
2948 LxtCheckErrno(stat(OVFS_TEST_LOWER_DIR "/OnlyInLowerDir/whiteoutFile", &StatBuffer));
2949 LxtCheckTrue(S_ISCHR(StatBuffer.st_mode));
2950 LxtCheckErrnoFailure(stat(OVFS_TEST_MOUNT_PATH "/OnlyInLowerDir/whiteoutFile", &StatMergedBuffer), ENOENT);
2951
2952 LxtCheckErrno(Fd = open(OVFS_TEST_MOUNT_PATH "/OnlyInLowerDir", O_RDONLY));
2953 LxtCheckErrno(BytesRead = LxtGetdents64(Fd, (struct dirent*)Buffer, sizeof(Buffer)))
2954
2955 Count = 0;
2956 for (EntryPosition = 0; EntryPosition < BytesRead; EntryPosition += Entry->d_reclen)
2957 {
2958
2959 Entry = (struct dirent*)&Buffer[EntryPosition];
2960 LxtLogInfo("%s", Entry->d_name);
2961 Count += 1;
2962 }
2963
2964 LxtCheckEqual(Count, 3, "%d");
2965 LxtClose(Fd);
2966 Fd = -1;
2967
2968 //
2969 // Check that the whiteout cannot be opened and is not reported through
2970 // readdir when the folder is merged with the upper.
2971 //
2972
2973 LxtCheckErrno(stat(OVFS_TEST_LOWER_DIR "/InBothDir/whiteoutFile", &StatBuffer));
2974 LxtCheckTrue(S_ISCHR(StatBuffer.st_mode));
2975 LxtCheckErrnoFailure(stat(OVFS_TEST_MOUNT_PATH "/InBothDir/whiteoutFile", &StatMergedBuffer), ENOENT);
2976
2977 LxtCheckErrno(Fd = open(OVFS_TEST_MOUNT_PATH "/InBothDir", O_RDONLY));
2978 LxtCheckErrno(BytesRead = LxtGetdents64(Fd, (struct dirent*)Buffer, sizeof(Buffer)))
2979
2980 Count = 0;
2981 for (EntryPosition = 0; EntryPosition < BytesRead; EntryPosition += Entry->d_reclen)
2982 {
2983
2984 Entry = (struct dirent*)&Buffer[EntryPosition];
2985 LxtLogInfo("%s", Entry->d_name);
2986 Count += 1;
2987 }
2988
2989 LxtCheckEqual(Count, 2, "%d");
2990 LxtClose(Fd);
2991 Fd = -1;
2992
2993 //
2994 // Check that the whiteout can be overwritten in the upper and that it
2995 // is not replaced by a whiteout when removed.
2996 //
2997
2998 LxtCheckErrno(mkdir(OVFS_TEST_MOUNT_PATH "/InBothDir/whiteoutFile", 0777));
2999 LxtCheckErrno(stat(OVFS_TEST_MOUNT_PATH "/InBothDir/whiteoutFile", &StatMergedBuffer));
3000 LxtCheckTrue(S_ISDIR(StatMergedBuffer.st_mode));
3001 LxtCheckErrno(stat(OVFS_TEST_UPPER_DIR "/InBothDir/whiteoutFile", &StatBuffer));
3002 LxtCheckTrue(S_ISDIR(StatBuffer.st_mode));
3003 LxtCheckErrno(rmdir(OVFS_TEST_MOUNT_PATH "/InBothDir/whiteoutFile"));
3004 LxtCheckErrnoFailure(stat(OVFS_TEST_MOUNT_PATH "/InBothDir/whiteoutFile", &StatMergedBuffer), ENOENT);
3005 LxtCheckErrnoFailure(stat(OVFS_TEST_UPPER_DIR "/InBothDir/whiteoutFile", &StatBuffer), ENOENT);
3006
3007 //
3008 // Unmount and check it was unmounted.
3009 //
3010
3011 if (Fd != -1)
3012 {
3013 LxtClose(Fd);
3014 Fd = -1;
3015 }
3016
3017 LxtCheckErrnoZeroSuccess(umount(OVFS_TEST_MOUNT_PATH));
3018 LxtCheckResult(MountCheckIsNotMount(OVFS_TEST_MOUNT_PATH));
3019
3020 Result = 0;
3021
3022 ErrorExit:
3023 if (Mapping != MAP_FAILED)
3024 {
3025 munmap(Mapping, PAGE_SIZE);
3026 }
3027
3028 if (Fd != -1)
3029 {
3030 LxtClose(Fd);
3031 }
3032
3033 umount(OVFS_TEST_MOUNT_PATH);
3034 return Result;
3035 }
3036
3037 int OvFsTestMultipleLower(PLXT_ARGS Args)
3038
3039 /*++
3040
3041 Description:
3042
3043 This routine tests various operations with multiple lower layers.
3044
3045 Arguments:
3046
3047 Args - Supplies the command line arguments.
3048
3049 Return Value:
3050
3051 Returns 0 on success, -1 on failure.
3052
3053 --*/
3054
3055 {
3056
3057 char Buffer[100];
3058 int BytesRead;
3059 int Count;
3060 struct dirent* Entry;
3061 int EntryPosition;
3062 int Fd;
3063 int Found[LXT_COUNT_OF(g_OvFsMergedMultiContents) + 2];
3064 int FoundIndex;
3065 int Index;
3066 void* Mapping;
3067 void* MapResult;
3068 int Result;
3069 struct stat StatBuffer;
3070 struct stat StatMergedBuffer;
3071
3072 Fd = -1;
3073 Mapping = NULL;
3074
3075 //
3076 // Set up the directories and populate some state.
3077 //
3078
3079 LxtCheckResult(OvFsTestDirsSetup());
3080 LxtCheckResult(OvFsTestDirsPopulate());
3081
3082 //
3083 // Mount an overlayfs instance and check inode operations that do not
3084 // hydrate files.
3085 //
3086
3087 LxtCheckResult(MountCheckIsNotMount(OVFS_TEST_MOUNT_PATH));
3088 LxtCheckErrnoZeroSuccess(mount("myovfsnew", OVFS_TEST_MOUNT_PATH, OVFS_TEST_MOUNT_NAME, 0, OVFS_TEST_MOUNT_MULTI_LOWER));
3089
3090 //
3091 // Check the behavior for VFS file object operations that support file
3092 // descriptors opened for read only.
3093 //
3094 // N.B. All other file operations will fail the request and are verified
3095 // in the VFS access test.
3096 //
3097
3098 //
3099 // Check the behavior for read directory on the root.
3100 //
3101
3102 memset(Found, 0, sizeof(Found));
3103 LxtCheckErrno(Fd = open(OVFS_TEST_MOUNT_PATH, O_RDONLY));
3104 LxtCheckErrno(BytesRead = LxtGetdents64(Fd, (struct dirent*)Buffer, sizeof(Buffer)));
3105
3106 while (BytesRead > 0)
3107 {
3108 for (EntryPosition = 0; EntryPosition < BytesRead; EntryPosition += Entry->d_reclen)
3109 {
3110
3111 Entry = (struct dirent*)&Buffer[EntryPosition];
3112 if (strcmp(Entry->d_name, ".") == 0)
3113 {
3114 FoundIndex = 0;
3115 }
3116 else if (strcmp(Entry->d_name, "..") == 0)
3117 {
3118 FoundIndex = 1;
3119 }
3120 else
3121 {
3122 for (Index = 0; Index < LXT_COUNT_OF(g_OvFsMergedMultiContents); ++Index)
3123 {
3124 if (strcmp(g_OvFsMergedMultiContents[Index].Name, Entry->d_name) == 0)
3125 {
3126 FoundIndex = Index + 2;
3127 break;
3128 }
3129 }
3130
3131 if (Index == LXT_COUNT_OF(g_OvFsMergedMultiContents))
3132 {
3133 LxtLogError("Unexpected entry %s", Entry->d_name);
3134 LxtCheckNotEqual(Index, LXT_COUNT_OF(g_OvFsMergedMultiContents), "%d");
3135 }
3136 }
3137
3138 LxtCheckEqual(Found[FoundIndex], 0, "%d");
3139 Found[FoundIndex] = 1;
3140 }
3141
3142 Entry = (struct dirent*)Buffer;
3143 LxtCheckErrno(BytesRead = LxtGetdents64(Fd, (struct dirent*)Buffer, sizeof(Buffer)));
3144 }
3145
3146 for (Index = 0; Index < LXT_COUNT_OF(Found); ++Index)
3147 {
3148 LxtCheckEqual(Found[FoundIndex], 1, "%d");
3149 }
3150
3151 LxtClose(Fd);
3152 Fd = -1;
3153
3154 //
3155 // Check the behavior for read directory on sub directories.
3156 //
3157
3158 for (Index = 0; Index < LXT_COUNT_OF(g_OvFsMergedMultiContents); ++Index)
3159 {
3160 if (S_ISDIR(g_OvFsMergedMultiContents[Index].Mode) == FALSE)
3161 {
3162 continue;
3163 }
3164
3165 LxtCheckErrno(Fd = open(g_OvFsMergedMultiContents[Index].Path, O_RDONLY));
3166 LxtCheckErrno(BytesRead = LxtGetdents64(Fd, (struct dirent*)Buffer, sizeof(Buffer)))
3167
3168 Count = 0;
3169 for (EntryPosition = 0; EntryPosition < BytesRead; EntryPosition += Entry->d_reclen)
3170 {
3171
3172 Entry = (struct dirent*)&Buffer[EntryPosition];
3173 Count += 1;
3174 }
3175
3176 LxtCheckEqual(Count, 2, "%d");
3177 LxtClose(Fd);
3178 Fd = -1;
3179 }
3180
3181 //
3182 // Check the behavior for read file.
3183 //
3184
3185 for (Index = 0; Index < LXT_COUNT_OF(g_OvFsMergedMultiContents); ++Index)
3186 {
3187 if (S_ISREG(g_OvFsMergedMultiContents[Index].Mode) == FALSE)
3188 {
3189 continue;
3190 }
3191
3192 LxtCheckErrno(Fd = open(g_OvFsMergedMultiContents[Index].Path, O_RDONLY));
3193 LxtCheckErrno(BytesRead = read(Fd, Buffer, sizeof(Buffer) - 1));
3194 Buffer[BytesRead] = 0;
3195 LxtCheckStringEqual(Buffer, g_OvFsMergedMultiContents[Index].Name);
3196 LxtClose(Fd);
3197 Fd = -1;
3198 }
3199
3200 //
3201 // Check the behavior for seek.
3202 //
3203
3204 for (Index = 0; Index < LXT_COUNT_OF(g_OvFsMergedMultiContents); ++Index)
3205 {
3206 if ((S_ISDIR(g_OvFsMergedMultiContents[Index].Mode) == FALSE) && (S_ISREG(g_OvFsMergedMultiContents[Index].Mode) == FALSE))
3207 {
3208
3209 continue;
3210 }
3211
3212 LxtLogInfo("%s", g_OvFsMergedMultiContents[Index].Path);
3213 LxtCheckErrno(Fd = open(g_OvFsMergedMultiContents[Index].Path, O_RDONLY));
3214 LxtCheckErrno(lseek(Fd, SEEK_SET, 1));
3215 LxtClose(Fd);
3216 Fd = -1;
3217 }
3218
3219 //
3220 // Check that none of the operations hydrated files from the lower
3221 // directory.
3222 //
3223
3224 LxtCheckErrnoFailure(stat(OVFS_TEST_UPPER_DIR "/OnlyInLowerDir", &StatBuffer), ENOENT);
3225 LxtCheckErrnoFailure(stat(OVFS_TEST_UPPER_DIR "/OnlyInLowerFile", &StatBuffer), ENOENT);
3226 LxtCheckErrnoFailure(stat(OVFS_TEST_UPPER_DIR "/OnlyInLowerSym", &StatBuffer), ENOENT);
3227
3228 //
3229 // Check the search order for the multiple lower layers.
3230 //
3231
3232 LxtCheckErrno(stat(OVFS_TEST_MOUNT_PATH "/OnlyInLower2File", &StatMergedBuffer));
3233 LxtCheckEqual(S_IFREG | 0444, StatMergedBuffer.st_mode, "%d");
3234 LxtCheckErrno(stat(OVFS_TEST_MOUNT_PATH "/OnlyInLower23File", &StatMergedBuffer));
3235 LxtCheckEqual(S_IFREG | 0444, StatMergedBuffer.st_mode, "%d");
3236 LxtCheckErrno(stat(OVFS_TEST_MOUNT_PATH "/OnlyInLower3File", &StatMergedBuffer));
3237 LxtCheckEqual(S_IFREG | 0111, StatMergedBuffer.st_mode, "%d");
3238
3239 //
3240 // Hydrate some files from the lower layers.
3241 //
3242
3243 LxtCheckErrno(stat(OVFS_TEST_MOUNT_PATH "/OnlyInLower2File", &StatMergedBuffer));
3244 LxtCheckErrno(stat(OVFS_TEST_LOWER2_DIR "/OnlyInLower2File", &StatBuffer));
3245 if (g_LxtUnstableInodes != 0)
3246 {
3247 LxtCheckEqual(StatMergedBuffer.st_ino, StatBuffer.st_ino, "%d");
3248 }
3249
3250 LxtCheckErrnoFailure(stat(OVFS_TEST_UPPER_DIR "/OnlyInLower2File", &StatBuffer), ENOENT);
3251 LxtCheckErrno(chmod(OVFS_TEST_MOUNT_PATH "/OnlyInLower2File", 0777));
3252 LxtCheckErrno(stat(OVFS_TEST_MOUNT_PATH "/OnlyInLower2File", &StatMergedBuffer));
3253 LxtCheckErrno(stat(OVFS_TEST_UPPER_DIR "/OnlyInLower2File", &StatBuffer));
3254 if (g_LxtUnstableInodes != 0)
3255 {
3256 LxtCheckEqual(StatMergedBuffer.st_ino, StatBuffer.st_ino, "%d");
3257 }
3258
3259 LxtCheckErrno(stat(OVFS_TEST_MOUNT_PATH "/OnlyInLower3Dir", &StatMergedBuffer));
3260 LxtCheckErrno(stat(OVFS_TEST_LOWER3_DIR "/OnlyInLower3Dir", &StatBuffer));
3261 if (g_LxtUnstableInodes != 0)
3262 {
3263 LxtCheckNotEqual(StatMergedBuffer.st_ino, StatBuffer.st_ino, "%d");
3264 }
3265
3266 LxtCheckErrnoFailure(stat(OVFS_TEST_UPPER_DIR "/OnlyInLower3Dir", &StatBuffer), ENOENT);
3267 LxtCheckErrno(chown(OVFS_TEST_MOUNT_PATH "/OnlyInLower3Dir", 2001, 2001));
3268 LxtCheckErrno(stat(OVFS_TEST_MOUNT_PATH "/OnlyInLower3Dir", &StatMergedBuffer));
3269 LxtCheckErrno(stat(OVFS_TEST_UPPER_DIR "/OnlyInLower3Dir", &StatBuffer));
3270 if (g_LxtUnstableInodes != 0)
3271 {
3272 LxtCheckNotEqual(StatMergedBuffer.st_ino, StatBuffer.st_ino, "%d");
3273 }
3274
3275 LxtCheckErrno(stat(OVFS_TEST_MOUNT_PATH "/OnlyInLower23File", &StatMergedBuffer));
3276 LxtCheckErrno(stat(OVFS_TEST_LOWER2_DIR "/OnlyInLower23File", &StatBuffer));
3277 if (g_LxtUnstableInodes != 0)
3278 {
3279 LxtCheckEqual(StatMergedBuffer.st_ino, StatBuffer.st_ino, "%d");
3280 }
3281
3282 LxtCheckErrnoFailure(stat(OVFS_TEST_UPPER_DIR "/OnlyInLower23File", &StatBuffer), ENOENT);
3283 LxtCheckErrno(truncate(OVFS_TEST_MOUNT_PATH "/OnlyInLower23File", 0));
3284 LxtCheckErrno(stat(OVFS_TEST_MOUNT_PATH "/OnlyInLower23File", &StatMergedBuffer));
3285 LxtCheckErrno(stat(OVFS_TEST_UPPER_DIR "/OnlyInLower23File", &StatBuffer));
3286 if (g_LxtUnstableInodes != 0)
3287 {
3288 LxtCheckEqual(StatMergedBuffer.st_ino, StatBuffer.st_ino, "%d");
3289 }
3290
3291 //
3292 // Unmount and check it was unmounted.
3293 //
3294
3295 if (Fd != -1)
3296 {
3297 LxtClose(Fd);
3298 Fd = -1;
3299 }
3300
3301 LxtCheckErrnoZeroSuccess(umount(OVFS_TEST_MOUNT_PATH));
3302 LxtCheckResult(MountCheckIsNotMount(OVFS_TEST_MOUNT_PATH));
3303
3304 //
3305 // Check the behavior for entries with the same name but differing types in
3306 // the lower.
3307 //
3308
3309 LxtCheckResult(OvFsTestDirsSetup());
3310 LxtCheckResult(OvFsTestDirsPopulate());
3311 LxtCheckErrno(mkdir(OVFS_TEST_LOWER_DIR "/mixedType", 0777));
3312 LxtCheckErrno(Fd = creat(OVFS_TEST_LOWER_DIR "/mixedType/onlyInLower1", 0777));
3313 LxtClose(Fd);
3314 Fd = -1;
3315 LxtCheckErrno(Fd = creat(OVFS_TEST_LOWER2_DIR "/mixedType", 0777));
3316 LxtClose(Fd);
3317 Fd = -1;
3318 LxtCheckErrno(mkdir(OVFS_TEST_LOWER3_DIR "/mixedType", 0777));
3319 LxtCheckErrno(Fd = creat(OVFS_TEST_LOWER3_DIR "/mixedType/onlyInLower3", 0777));
3320 LxtClose(Fd);
3321 Fd = -1;
3322
3323 //
3324 // Mount an overlayfs instance and check for the expected lookup and readdir
3325 // behavior.
3326 //
3327
3328 LxtCheckResult(MountCheckIsNotMount(OVFS_TEST_MOUNT_PATH));
3329 LxtCheckErrnoZeroSuccess(mount("myovfsnew", OVFS_TEST_MOUNT_PATH, OVFS_TEST_MOUNT_NAME, 0, OVFS_TEST_MOUNT_MULTI_LOWER));
3330
3331 LxtCheckErrno(stat(OVFS_TEST_MOUNT_PATH "/mixedType", &StatMergedBuffer));
3332 LxtCheckTrue(S_ISDIR(StatMergedBuffer.st_mode));
3333 LxtCheckErrno(stat(OVFS_TEST_MOUNT_PATH "/mixedType/onlyInLower1", &StatMergedBuffer));
3334 LxtCheckTrue(S_ISREG(StatMergedBuffer.st_mode));
3335 LxtCheckErrnoFailure(stat(OVFS_TEST_MOUNT_PATH "/mixedType/onlyInLower3", &StatMergedBuffer), ENOENT);
3336
3337 Count = 0;
3338 LxtCheckErrno(Fd = open(OVFS_TEST_MOUNT_PATH "/mixedType", O_RDONLY));
3339 LxtCheckErrno(BytesRead = LxtGetdents64(Fd, (struct dirent*)Buffer, sizeof(Buffer)));
3340
3341 while (BytesRead > 0)
3342 {
3343 for (EntryPosition = 0; EntryPosition < BytesRead; EntryPosition += Entry->d_reclen)
3344 {
3345
3346 Entry = (struct dirent*)&Buffer[EntryPosition];
3347 LxtLogInfo("%s", Entry->d_name);
3348 Count += 1;
3349 }
3350
3351 LxtCheckErrno(BytesRead = LxtGetdents64(Fd, (struct dirent*)Buffer, sizeof(Buffer)));
3352 }
3353
3354 LxtCheckEqual(Count, 3, "%d");
3355 LxtClose(Fd);
3356 Fd = -1;
3357
3358 //
3359 // Repeat the above with the mismatch in the lowest layer.
3360 //
3361
3362 if (Fd != -1)
3363 {
3364 LxtClose(Fd);
3365 Fd = -1;
3366 }
3367
3368 LxtCheckErrnoZeroSuccess(umount(OVFS_TEST_MOUNT_PATH));
3369 LxtCheckResult(MountCheckIsNotMount(OVFS_TEST_MOUNT_PATH));
3370
3371 //
3372 // Check the behavior for entries with the same name but differing types in
3373 // the lower.
3374 //
3375
3376 LxtCheckResult(OvFsTestDirsSetup());
3377 LxtCheckResult(OvFsTestDirsPopulate());
3378 LxtCheckErrno(mkdir(OVFS_TEST_LOWER_DIR "/mixedType", 0777));
3379 LxtCheckErrno(Fd = creat(OVFS_TEST_LOWER_DIR "/mixedType/onlyInLower1", 0777));
3380 LxtClose(Fd);
3381 Fd = -1;
3382 LxtCheckErrno(mkdir(OVFS_TEST_LOWER2_DIR "/mixedType", 0777));
3383 LxtCheckErrno(Fd = creat(OVFS_TEST_LOWER2_DIR "/mixedType/onlyInLower2", 0777));
3384 LxtClose(Fd);
3385 Fd = -1;
3386 LxtCheckErrno(Fd = creat(OVFS_TEST_LOWER3_DIR "/mixedType", 0777));
3387 LxtClose(Fd);
3388 Fd = -1;
3389
3390 //
3391 // Mount an overlayfs instance and check for the expected lookup and readdir
3392 // behavior.
3393 //
3394
3395 LxtCheckResult(MountCheckIsNotMount(OVFS_TEST_MOUNT_PATH));
3396 LxtCheckErrnoZeroSuccess(mount("myovfsnew", OVFS_TEST_MOUNT_PATH, OVFS_TEST_MOUNT_NAME, 0, OVFS_TEST_MOUNT_MULTI_LOWER));
3397
3398 LxtCheckErrno(stat(OVFS_TEST_MOUNT_PATH "/mixedType", &StatMergedBuffer));
3399 LxtCheckTrue(S_ISDIR(StatMergedBuffer.st_mode));
3400 LxtCheckErrno(stat(OVFS_TEST_MOUNT_PATH "/mixedType/onlyInLower1", &StatMergedBuffer));
3401 LxtCheckTrue(S_ISREG(StatMergedBuffer.st_mode));
3402 LxtCheckErrno(stat(OVFS_TEST_MOUNT_PATH "/mixedType/onlyInLower2", &StatMergedBuffer));
3403 LxtCheckTrue(S_ISREG(StatMergedBuffer.st_mode));
3404
3405 Count = 0;
3406 LxtCheckErrno(Fd = open(OVFS_TEST_MOUNT_PATH "/mixedType", O_RDONLY));
3407 LxtCheckErrno(BytesRead = LxtGetdents64(Fd, (struct dirent*)Buffer, sizeof(Buffer)));
3408
3409 while (BytesRead > 0)
3410 {
3411 for (EntryPosition = 0; EntryPosition < BytesRead; EntryPosition += Entry->d_reclen)
3412 {
3413
3414 Entry = (struct dirent*)&Buffer[EntryPosition];
3415 LxtLogInfo("%s", Entry->d_name);
3416 Count += 1;
3417 }
3418
3419 LxtCheckErrno(BytesRead = LxtGetdents64(Fd, (struct dirent*)Buffer, sizeof(Buffer)));
3420 }
3421
3422 LxtCheckEqual(Count, 4, "%d");
3423 LxtClose(Fd);
3424 Fd = -1;
3425
3426 //
3427 // Unmount and check it was unmounted.
3428 //
3429
3430 if (Fd != -1)
3431 {
3432 LxtClose(Fd);
3433 Fd = -1;
3434 }
3435
3436 LxtCheckErrnoZeroSuccess(umount(OVFS_TEST_MOUNT_PATH));
3437 LxtCheckResult(MountCheckIsNotMount(OVFS_TEST_MOUNT_PATH));
3438
3439 Result = 0;
3440
3441 ErrorExit:
3442 if (Mapping != MAP_FAILED)
3443 {
3444 munmap(Mapping, PAGE_SIZE);
3445 }
3446
3447 if (Fd != -1)
3448 {
3449 LxtClose(Fd);
3450 }
3451
3452 umount(OVFS_TEST_MOUNT_PATH);
3453 return Result;
3454 }