2 * Copyright (c) 2015 Apple, Inc. All rights reserved.
4 * Test HFS fsinfo fsctls can be interrupted by pthread_kill signals.
8 #include <sys/ioccom.h>
10 #include <sys/mount.h>
15 #include <sys/errno.h>
22 #include "../../core/hfs_fsctl.h"
23 #include "hfs-tests.h"
24 #include "test-utils.h"
26 #include "disk-image.h"
28 TEST(fsinfo_sig
, .run_as_root
= true)
30 static disk_image_t
*di
;
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;
37 static char *fsinfo_srcdir
;
41 static void setup_testvolume()
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__);
52 for (unsigned i
= 0; i
< MAX_FILES
; i
++) {
53 asprintf(&path
, "%s/fsinfo_test.data.%u", fsinfo_srcdir
, getpid()+i
);
55 assert_with_errno((fd
= open(path
, O_RDWR
| O_TRUNC
| O_CREAT
, 0666)) >= 0);
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
);
64 //printf("\n%s:%d created %d files ", __func__, __LINE__, MAX_FILES);
67 static int test_fsinfo_file_extent_size(void)
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);
76 // printf("\n%s:%d error = %d errno = %d %s", __func__, __LINE__, error, errno, strerror(errno));
77 return error
!= 0 ? errno
: 0;
80 static int test_fsinfo_free_extents(void)
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);
89 // printf("\n%s:%d error = %d errno = %d %s", __func__, __LINE__, error, errno, strerror(errno));
90 return error
!= 0 ? errno
: 0;
94 void sig_handler (__unused
int signum
) {
95 thread_is_signaled
= true;
98 void *threadfunc1(__unused
void *parm
) {
99 struct sigaction action
;
100 int sig_count
= 1000;
102 action
.sa_handler
= sig_handler
;
103 sigemptyset( &action
.sa_mask
);
106 sigaction( SIGUSR1
, &action
, NULL
);
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
) {
115 if (test_ret
== EACCES
) {
116 printf("\n%s:%d got EACCESS. Failing the test. Please run as root.", __func__
, __LINE__
);
118 assert(test_ret
== 0);
120 if (thread_is_signaled
) {
121 thread_is_signaled
= false;
127 assert(done
== true);
129 while (!thread_to_exit
)
132 pthread_exit( NULL
);
135 void *threadfunc2(__unused
void *parm
) {
136 struct sigaction action
;
137 int sig_count
= 1000;
140 action
.sa_handler
= sig_handler
;
141 sigemptyset( &action
.sa_mask
);
144 sigaction( SIGUSR1
, &action
, NULL
);
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
) {
153 if (test_ret
== EACCES
) {
154 printf("\n%s:%d got EACCESS. Failing the test. Please run as root.", __func__
, __LINE__
);
156 assert(test_ret
== 0);
158 if (thread_is_signaled
) {
159 thread_is_signaled
= false;
165 assert(done
== true);
167 while (!thread_to_exit
)
170 pthread_exit( NULL
);
174 int run_fsinfo_sig(__unused test_ctx_t
*ctx
) {
175 pthread_t threadid1
, threadid2
;
176 int thread_stat1
, thread_stat2
;
178 di
= disk_image_get();
180 asprintf(&fsinfo_srcdir
, "%s/fsinfo-test", di
->mount_point
);
184 thread_is_signaled
= false;
185 /* To test traverse_btree path takes signal */
186 assert_no_err(pthread_create( &threadid1
, NULL
, threadfunc1
, NULL
));
189 //printf("\n%s:%d signalling thread ", __func__, __LINE__);
192 assert_no_err(pthread_kill( threadid1
, SIGUSR1
));
195 thread_to_exit
= true;
197 assert_no_err(pthread_join( threadid1
, (void *)&thread_stat1
));
199 thread_to_exit
= false;
201 thread_is_signaled
= false;
203 /* To test hfs_find_free_extents code path takes signal */
204 assert_no_err(pthread_create( &threadid2
, NULL
, threadfunc2
, NULL
));
207 //printf("\n%s:%d signalling thread ", __func__, __LINE__);
210 assert_no_err(pthread_kill( threadid2
, SIGUSR1
));
213 thread_to_exit
= true;
215 assert_no_err(pthread_join( threadid2
, (void *)&thread_stat2
));