]> git.saurik.com Git - apple/hfs.git/blob - tests/cases/test-fsinfo-sig.c
hfs-366.1.1.tar.gz
[apple/hfs.git] / tests / cases / test-fsinfo-sig.c
1 /*
2 * Copyright (c) 2015 Apple, Inc. All rights reserved.
3 *
4 * Test HFS fsinfo fsctls can be interrupted by pthread_kill signals.
5 */
6
7 #include <sys/ioctl.h>
8 #include <sys/ioccom.h>
9 #include <sys/param.h>
10 #include <sys/mount.h>
11 #include <stdio.h>
12 #include <unistd.h>
13 #include <stdlib.h>
14 #include <string.h>
15 #include <sys/errno.h>
16 #include <sys/stat.h>
17 #include <fcntl.h>
18 #include <pthread.h>
19 #include <signal.h>
20 #include <spawn.h>
21
22 #include "../../core/hfs_fsctl.h"
23 #include "hfs-tests.h"
24 #include "test-utils.h"
25 #include "systemx.h"
26 #include "disk-image.h"
27
28 TEST(fsinfo_sig, .run_as_root = true)
29
30 static disk_image_t *di;
31
32 static hfs_fsinfo fsinfo;
33 static volatile bool done = false;
34 static volatile bool thread_to_exit = false;
35 static volatile bool thread_is_signaled = false;
36
37 static char *fsinfo_srcdir;
38 #define MAX_FILES 100
39 #define KB *1024
40
41 static void setup_testvolume()
42 {
43 char *path;
44 int fd;
45 void *buf;
46
47 // Create a test folder with MAX_FILES files
48 assert_no_err(systemx("/bin/rm", "-rf", fsinfo_srcdir, NULL));
49 assert_no_err(mkdir(fsinfo_srcdir, 0777));
50 //printf("\n%s:%d creating files ", __func__, __LINE__);
51
52 for (unsigned i = 0; i < MAX_FILES; i++) {
53 asprintf(&path, "%s/fsinfo_test.data.%u", fsinfo_srcdir, getpid()+i);
54 unlink(path);
55 assert_with_errno((fd = open(path, O_RDWR | O_TRUNC | O_CREAT, 0666)) >= 0);
56
57 unsigned buf_size = (4 KB) * i;
58 buf = malloc(buf_size);
59 memset(buf, 0x25, buf_size);
60 check_io(write(fd, buf, buf_size), buf_size);
61 free(buf);
62 free(path);
63 }
64 //printf("\n%s:%d created %d files ", __func__, __LINE__, MAX_FILES);
65 }
66
67 static int test_fsinfo_file_extent_size(void)
68 {
69 int error = 0;
70
71 bzero(&fsinfo, sizeof(fsinfo));
72 fsinfo.header.request_type = HFS_FSINFO_FILE_EXTENT_SIZE;
73 fsinfo.header.version = HFS_FSINFO_VERSION;
74 error = fsctl(di->mount_point, HFSIOC_GET_FSINFO, &fsinfo, 0);
75 //if (error)
76 // printf("\n%s:%d error = %d errno = %d %s", __func__, __LINE__, error, errno, strerror(errno));
77 return error != 0 ? errno : 0;
78 }
79
80 static int test_fsinfo_free_extents(void)
81 {
82 int error = 0;
83
84 bzero(&fsinfo, sizeof(fsinfo));
85 fsinfo.header.version = HFS_FSINFO_VERSION;
86 fsinfo.header.request_type = HFS_FSINFO_FREE_EXTENTS;
87 error = fsctl(di->mount_point, HFSIOC_GET_FSINFO, &fsinfo, 0);
88 //if (error)
89 // printf("\n%s:%d error = %d errno = %d %s", __func__, __LINE__, error, errno, strerror(errno));
90 return error != 0 ? errno : 0;
91 }
92
93
94 void sig_handler (__unused int signum) {
95 thread_is_signaled = true;
96 }
97
98 void *threadfunc1(__unused void *parm ) {
99 struct sigaction action;
100 int sig_count = 1000;
101 int test_ret = 0;
102 action.sa_handler = sig_handler;
103 sigemptyset( &action.sa_mask );
104 action.sa_flags = 0;
105
106 sigaction( SIGUSR1, &action, NULL );
107
108 //printf("\n%s:%d starting test_fsinfo_file_extent_size in loop", __func__, __LINE__);
109 while (sig_count > 0) {
110 test_ret = test_fsinfo_file_extent_size();
111 if (test_ret == EINTR) {
112 done = true;
113 break;
114 }
115 if (test_ret == EACCES) {
116 printf("\n%s:%d got EACCESS. Failing the test. Please run as root.", __func__, __LINE__);
117 }
118 assert(test_ret == 0);
119
120 if (thread_is_signaled) {
121 thread_is_signaled = false;
122 sig_count -= 1;
123 }
124
125 }
126
127 assert(done == true);
128
129 while (!thread_to_exit)
130 ;
131
132 pthread_exit( NULL );
133 }
134
135 void *threadfunc2(__unused void *parm ) {
136 struct sigaction action;
137 int sig_count = 1000;
138 int test_ret = 0;
139
140 action.sa_handler = sig_handler;
141 sigemptyset( &action.sa_mask );
142 action.sa_flags = 0;
143
144 sigaction( SIGUSR1, &action, NULL );
145
146 //printf("\n%s:%d starting test_fsinfo_free_extents in loop", __func__, __LINE__);
147 while (sig_count > 0) {
148 test_ret = test_fsinfo_free_extents();
149 if (test_ret == EINTR) {
150 done = true;
151 break;
152 }
153 if (test_ret == EACCES) {
154 printf("\n%s:%d got EACCESS. Failing the test. Please run as root.", __func__, __LINE__);
155 }
156 assert(test_ret == 0);
157
158 if (thread_is_signaled) {
159 thread_is_signaled = false;
160 sig_count -= 1;
161 }
162
163 }
164
165 assert(done == true);
166
167 while (!thread_to_exit)
168 ;
169
170 pthread_exit( NULL );
171 }
172
173
174 int run_fsinfo_sig(__unused test_ctx_t *ctx) {
175 pthread_t threadid1, threadid2;
176 int thread_stat1, thread_stat2;
177
178 di = disk_image_get();
179
180 asprintf(&fsinfo_srcdir, "%s/fsinfo-test", di->mount_point);
181
182 setup_testvolume();
183
184 thread_is_signaled = false;
185 /* To test traverse_btree path takes signal */
186 assert_no_err(pthread_create( &threadid1, NULL, threadfunc1, NULL ));
187
188 sleep( 10 );
189 //printf("\n%s:%d signalling thread ", __func__, __LINE__);
190
191 while (!done) {
192 assert_no_err(pthread_kill( threadid1, SIGUSR1 ));
193 }
194
195 thread_to_exit = true;
196
197 assert_no_err(pthread_join( threadid1, (void *)&thread_stat1 ));
198
199 thread_to_exit = false;
200 done = false;
201 thread_is_signaled = false;
202
203 /* To test hfs_find_free_extents code path takes signal */
204 assert_no_err(pthread_create( &threadid2, NULL, threadfunc2, NULL ));
205
206 sleep( 10 );
207 //printf("\n%s:%d signalling thread ", __func__, __LINE__);
208
209 while (!done) {
210 assert_no_err(pthread_kill( threadid2, SIGUSR1 ));
211 }
212
213 thread_to_exit = true;
214
215 assert_no_err(pthread_join( threadid2, (void *)&thread_stat2 ));
216
217 free(fsinfo_srcdir);
218
219 return 0;
220 }