]>
git.saurik.com Git - apple/hfs.git/blob - tests/cases/test-msync-16k.c
2 * For some background: this unit test was created for a bug where
3 * during page-out, we captured the file size without any locks and
4 * then if a change happened to come in before we took the locks, we
5 * would lose the remainder of the page. The following illustrates
10 * +-------------+--------+----
12 * +-------------+--------+----
17 * A page-out is requested for the page starting at @a and ending at
18 * @c. The end of the file is at @b and is captured before any locks
19 * are taken. After that, another thread writes something between @b
20 * and @c. The page-out then continues, but it thinks the end of the
21 * file is at @b, so it will only write up to @b and then it will mark
22 * the entire page as clean. That will cause us to lose the data that
23 * was written between @b and @c. This would only occur if there is
24 * an extent boundary at @b (which is the reason for the F_PREALLOCATE
25 * calls below). The syncer thread below is simulating what we do in
26 * page-out: we write 1 MB chunks.
36 #include <sys/errno.h>
41 #include "hfs-tests.h"
42 #include "test-utils.h"
43 #include "disk-image.h"
47 static disk_image_t
*di
;
49 volatile off_t size
= 0;
63 void *p
= mmap(NULL
, 0x100000, PROT_READ
| PROT_WRITE
, MAP_SHARED
,
66 assert_with_errno(p
!= MAP_FAILED
);
68 while ((size
& ~0xfffff) == sz
) {
69 assert_no_err(msync(p
, 0x100000, MS_SYNC
));
73 assert_no_err(munmap(p
, 0x100000));
77 int run_msync_16k(__unused test_ctx_t
*ctx
)
79 di
= disk_image_get();
82 asprintf(&file
, "%s/msync-16k.data", di
->mount_point
);
84 char *buf
= malloc(1024 * 1024);
85 memset(buf
, 0xaf, 1024 * 1024);
89 fd
= open(file
, O_CREAT
| O_RDWR
, 0666);
90 assert_with_errno(fd
>= 0);
93 pthread_create(&thr
, NULL
, (void *(*)(void *))syncer
, NULL
);
95 assert_no_err(fcntl(fd
, F_NOCACHE
, 1));
97 check_io(write(fd
, buf
, 8192), 8192);
100 while (size
< 100 * 1024 * 1024ll) {
101 // Force an extent boundary
102 struct log2phys l2p
= {
103 .l2p_contigbytes
= 4096,
104 .l2p_devoffset
= size
- 4096,
106 assert(!fcntl(fd
, F_LOG2PHYS_EXT
, &l2p
));
108 struct fstore fst
= {
109 .fst_posmode
= F_VOLPOSMODE
,
110 .fst_offset
= l2p
.l2p_devoffset
+ 4096,
111 .fst_length
= size
+ 16384,
113 assert(!fcntl(fd
, F_PREALLOCATE
, &fst
));
115 check_io(pwrite(fd
, buf
, 16384, size
), 16384);
122 pthread_join(thr
, NULL
);
123 assert_no_err(close(fd
));
125 fd
= open(file
, O_RDWR
);
127 assert_with_errno(fd
>= 0);
129 char *cmp_buf
= malloc(1024 * 1024);
132 void *p
= mmap(NULL
, 1024 * 1024, PROT_READ
| PROT_WRITE
, MAP_SHARED
, fd
, done
);
133 assert_with_errno(p
!= MAP_FAILED
);
134 assert_no_err(msync(p
, 1024 * 1024, MS_INVALIDATE
| MS_SYNC
));
135 assert_no_err(munmap(p
, 1024 * 1024));
137 bzero(cmp_buf
, 1024 * 1024);
138 ssize_t amt
= read(fd
, cmp_buf
, 1024 * 1024);
140 assert(!memcmp(cmp_buf
, buf
, amt
));
144 assert_no_err(close(fd
));
146 assert_no_err(unlink(file
));