8int fr_shared(
int backend) {
9 int failed = 0, other = -1, duplicate = -1;
10 struct fr_file file = {.fd = -1};
11 const size_t page = fr_page, length = 4 * page, cut = page + 137;
12 unsigned char *shared = MAP_FAILED, *alias = MAP_FAILED, *borrowed = MAP_FAILED;
14 CHECK(!fr_create(&file, backend));
15 CHECK((other = fr_open_alias(&file)) >= 0 && (duplicate = dup(file.fd)) >= 0);
16 shared = mmap(NULL, length, PROT_READ | PROT_WRITE, MAP_SHARED, file.fd, 0);
17 alias = mmap(NULL, 3 * page, PROT_READ | PROT_WRITE, MAP_SHARED, other, page);
18 borrowed = mmap(NULL, 3 * page, PROT_READ, MAP_PRIVATE, other, page);
19 CHECK(shared != MAP_FAILED && alias != MAP_FAILED && borrowed != MAP_FAILED);
20 CHECK(fr_matches(shared, 0, length, 0) && fr_matches(alias, page, 3 * page, 0) &&
21 fr_matches(borrowed, page, 3 * page, 0));
22 CHECK(!fr_resident(shared, 4, 15,
"shared before shrink") &&
23 !fr_resident(alias, 3, 7,
"offset shared before shrink") &&
24 !fr_resident(borrowed, 3, 7,
"borrowed private before shrink"));
25 const off_t position = 3 * page + 91;
26 CHECK(lseek(file.fd, position, SEEK_SET) == position);
28 CHECK(lseek(other, 7, SEEK_SET) == 7);
29 const off_t other_position = file.path[0] ? 7 : position;
31 CHECK(!ftruncate(duplicate, cut));
33 CHECK(!fr_resident(shared, 4, 3,
"shared after partial shrink") &&
34 !fr_resident(alias, 3, 1,
"offset shared after partial shrink") &&
35 !fr_resident(borrowed, 3, 1,
"borrowed private after partial shrink"));
36 CHECK(!fr_size(file.fd, cut) && !fr_size(other, cut));
37 CHECK(lseek(file.fd, 0, SEEK_CUR) == position && lseek(duplicate, 0, SEEK_CUR) == position &&
38 lseek(other, 0, SEEK_CUR) == other_position);
39 CHECK(pread(other, &
byte, 1, cut) == 0);
40 CHECK(fr_matches(shared, 0, cut, 0) && fr_matches(shared + cut, cut, 2 * page - cut, 1));
41 CHECK(fr_matches(alias, page, 137, 0) && fr_matches(alias + 137, cut, page - 137, 1));
42 CHECK(fr_matches(borrowed, page, 137, 0) && fr_matches(borrowed + 137, cut, page - 137, 1));
43 CHECK(!fr_contents(file.fd, 0, cut, 0));
44 CHECK(!fr_fault(shared + 2 * page) && !fr_fault(alias + page) && !fr_fault(borrowed + 2 * page));
46 CHECK(!ftruncate(other, length));
47 CHECK(!fr_resident(shared, 2, 3,
"shared prefix after regrowth") &&
48 !fr_resident(alias, 1, 1,
"offset prefix after regrowth"));
49 CHECK(!fr_size(file.fd, length) && fr_matches(shared, 0, cut, 0) &&
50 fr_matches(shared + cut, cut, length - cut, 1));
51 CHECK(fr_matches(alias, page, 137, 0) && fr_matches(alias + 137, cut, length - cut, 1));
52 CHECK(fr_matches(borrowed, page, 137, 0) && fr_matches(borrowed + 137, cut, length - cut, 1));
53 CHECK(!fr_contents(file.fd, 0, cut, 0) && !fr_contents(other, cut, length - cut, 1));
55 CHECK(shared[cut] == 0xd5 && borrowed[137] == 0xd5 && pread(file.fd, &
byte, 1, cut) == 1 &&
57 CHECK(lseek(file.fd, 0, SEEK_CUR) == position && lseek(other, 0, SEEK_CUR) == other_position);
59 CHECK(!ftruncate(file.fd, page));
60 CHECK(!fr_resident(shared, 4, 1,
"shared after aligned shrink") &&
61 !fr_resident(alias, 3, 0,
"offset shared after aligned shrink"));
62 CHECK(fr_matches(shared, 0, page, 0) && !fr_fault(shared + page));
63 CHECK(!ftruncate(file.fd, length));
64 CHECK(!fr_resident(shared, 1, 1,
"aligned prefix after regrowth"));
65 CHECK(fr_matches(shared, 0, page, 0) && fr_matches(shared + page, page, 3 * page, 1));
66 CHECK(fr_matches(alias, page, 3 * page, 1) && fr_matches(borrowed, page, 3 * page, 1));
67 CHECK(!fr_contents(file.fd, page, 3 * page, 1));
69 if (borrowed != MAP_FAILED)
70 munmap(borrowed, 3 * page);
71 if (alias != MAP_FAILED)
72 munmap(alias, 3 * page);
73 if (shared != MAP_FAILED)
74 munmap(shared, length);