1 /* Copyright © 2017-2018 Apple Inc. All rights reserved.
6 * Created by Or Haimovich on 18/3/18.
12 #include <sys/kernel_types.h>
13 #include "lf_hfs_locks.h"
14 #include "lf_hfs_format.h"
15 #include "lf_hfs_catalog.h"
16 #include "lf_hfs_rangelist.h"
17 #include "lf_hfs_cnode.h"
18 #include "lf_hfs_defs.h"
21 #define HFS_MAX_DEFERED_ALLOC (1024*1024)
23 #define HFS_MAX_FILES (UINT32_MAX - kHFSFirstUserCatalogNodeID)
25 // 400 megs is a "big" file (i.e. one that when deleted
26 // would touch enough data that we should break it into
27 // multiple separate transactions)
28 #define HFS_BIGFILE_SIZE (400LL * 1024LL * 1024LL)
30 enum { kMDBSize
= 512 }; /* Size of I/O transfer to read entire MDB */
32 enum { kMasterDirectoryBlock
= 2 }; /* MDB offset on disk in 512-byte blocks */
33 enum { kMDBOffset
= kMasterDirectoryBlock
* 512 }; /* MDB offset on disk in bytes */
35 #define kRootDirID kHFSRootFolderID
37 /* How many free extents to cache per volume */
38 #define kMaxFreeExtents 10
40 /* Maximum file size that we're willing to defrag on open */
41 #define HFS_MAX_DEFRAG_SIZE (104857600) // 100 * 1024 * 1024 (100MB)
42 #define HFS_INITIAL_DEFRAG_SIZE (20971520) // 20 * 1024 * 1024 (20MB)
44 #define HFS_AVERAGE_NAME_SIZE 22
45 #define AVERAGE_HFSDIRENTRY_SIZE (8+HFS_AVERAGE_NAME_SIZE+4)
48 * HFS_MINFREE gives the minimum acceptable percentage
49 * of file system blocks which may be free (but this
50 * minimum will never exceed HFS_MAXRESERVE bytes). If
51 * the free block count drops below this level only the
52 * superuser may continue to allocate blocks.
54 #define HFS_MINFREE (1)
55 #define HFS_MAXRESERVE ((u_int64_t)(250*1024*1024))
56 #define HFS_BT_MAXRESERVE ((u_int64_t)(10*1024*1024))
59 * HFS_META_DELAY is a duration (in usecs) used for triggering the
60 * hfs_syncer() routine. We will back off if writes are in
62 * HFS_MAX_META_DELAY is the maximum time we will allow the
63 * syncer to be delayed.
66 HFS_META_DELAY
= 100 * 1000, // 0.1 secs
67 //HFS_META_DELAY = 10 * 1000, // 0.01 secs
68 HFS_MAX_META_DELAY
= 5000 * 1000 // 5 secs
69 //HFS_MAX_META_DELAY = 1000 * 1000 // 1 secs
72 #define HFS_META_DELAY_TS ((struct timespec){ 0, HFS_META_DELAY * NSEC_PER_USEC })
75 /* This structure describes the HFS specific mount structure data. */
76 typedef struct hfsmount
{
77 u_int32_t hfs_flags
; /* see below */
79 /* Physical Description */
80 u_int32_t hfs_logical_block_size
; /* Logical block size of the disk as reported by ioctl(DKIOCGETBLOCKSIZE), always a multiple of 512 */
81 daddr64_t hfs_logical_block_count
; /* Number of logical blocks on the disk, as reported by ioctl(DKIOCGETBLOCKCOUNT) */
82 u_int64_t hfs_logical_bytes
; /* Number of bytes on the disk device this HFS is mounted on (blockcount * blocksize) */
84 * Regarding the two AVH sector fields below:
85 * Under normal circumstances, the filesystem's notion of the "right" location for the AVH is such that
86 * the partition and filesystem's are in sync. However, during a filesystem resize, HFS proactively
87 * writes a new AVH at the end of the filesystem, assuming that the partition will be resized accordingly.
89 * However, it is not technically a corruption if the partition size is never modified. As a result, we need
90 * to keep two copies of the AVH around "just in case" the partition size is not modified.
92 daddr64_t hfs_partition_avh_sector
; /* location of Alt VH w.r.t partition size */
93 daddr64_t hfs_fs_avh_sector
; /* location of Alt VH w.r.t filesystem size */
95 u_int32_t hfs_physical_block_size
; /* Physical block size of the disk as reported by ioctl(DKIOCGETPHYSICALBLOCKSIZE) */
96 u_int32_t hfs_log_per_phys
; /* Number of logical blocks per physical block size */
98 /* Access to VFS and devices */
99 struct mount
* hfs_mp
; /* filesystem vfs structure */
100 struct vnode
* hfs_devvp
; /* block device mounted vnode */
101 struct vnode
* hfs_extents_vp
;
102 struct vnode
* hfs_catalog_vp
;
103 struct vnode
* hfs_allocation_vp
;
104 struct vnode
* hfs_attribute_vp
;
105 struct vnode
* hfs_startup_vp
;
106 struct vnode
* hfs_attrdata_vp
; /* pseudo file */
107 struct cnode
* hfs_extents_cp
;
108 struct cnode
* hfs_catalog_cp
;
109 struct cnode
* hfs_allocation_cp
;
110 struct cnode
* hfs_attribute_cp
;
111 struct cnode
* hfs_startup_cp
;
112 dev_t hfs_raw_dev
; /* device mounted */
113 u_int32_t hfs_logBlockSize
; /* Size of buffer cache buffer for I/O */
115 /* Default values for HFS standard and non-init access */
116 uid_t hfs_uid
; /* uid to set as owner of the files */
117 gid_t hfs_gid
; /* gid to set as owner of the files */
118 mode_t hfs_dir_mask
; /* mask to and with directory protection bits */
119 mode_t hfs_file_mask
; /* mask to and with file protection bits */
120 u_int32_t hfs_encoding
; /* Default encoding for non hfs+ volumes */
122 /* Persistent fields (on disk, dynamic) */
123 time_t hfs_mtime
; /* file system last modification time */
124 u_int32_t hfs_filecount
; /* number of files in file system */
125 u_int32_t hfs_dircount
; /* number of directories in file system */
126 u_int32_t freeBlocks
; /* free allocation blocks */
127 u_int32_t reclaimBlocks
; /* number of blocks we are reclaiming during resize */
128 u_int32_t tentativeBlocks
; /* tentative allocation blocks -- see note below */
129 u_int32_t nextAllocation
; /* start of next allocation search */
130 u_int32_t sparseAllocation
; /* start of allocations for sparse devices */
131 u_int32_t vcbNxtCNID
; /* next unused catalog node ID - protected by catalog lock */
132 u_int32_t vcbWrCnt
; /* file system write count */
133 u_int64_t encodingsBitmap
; /* in-use encodings */
134 u_int16_t vcbNmFls
; /* HFS Only - root dir file count */
135 u_int16_t vcbNmRtDirs
; /* HFS Only - root dir directory count */
137 /* Persistent fields (on disk, static) */
138 u_int16_t vcbSigWord
;
140 // Volume will be inconsistent if header is not flushed
141 bool hfs_header_dirty
;
143 // Volume header is dirty, but won't be inconsistent if not flushed
144 bool hfs_header_minor_change
;
147 u_int32_t vcbJinfoBlock
;
148 u_int32_t localCreateDate
;/* volume create time from volume header (For HFS+, value is in local time) */
149 time_t hfs_itime
; /* file system creation time (creation date of the root folder) */
150 time_t hfs_btime
; /* file system last backup time */
151 u_int32_t blockSize
; /* size of allocation blocks */
152 u_int32_t totalBlocks
; /* total allocation blocks */
153 u_int32_t allocLimit
; /* Do not allocate this block or beyond */
155 * NOTE: When resizing a volume to make it smaller, allocLimit is set to the allocation
156 * block number which will contain the new alternate volume header. At all other times,
157 * allocLimit is set to totalBlocks. The allocation code uses allocLimit instead of
158 * totalBlocks to limit which blocks may be allocated, so that during a resize, we don't
159 * put new content into the blocks we're trying to truncate away.
162 u_int32_t vcbFndrInfo
[8];
163 int16_t vcbVBMSt
; /* HFS only */
164 int16_t vcbAlBlSt
; /* HFS only */
167 u_int8_t vcbVN
[256]; /* volume name in UTF-8 */
168 u_int32_t volumeNameEncodingHint
;
169 u_int32_t hfsPlusIOPosOffset
; /* Disk block where HFS+ starts */
170 u_int32_t vcbVBMIOSize
; /* volume bitmap I/O size */
172 /* cache of largest known free extents */
173 u_int32_t vcbFreeExtCnt
;
174 HFSPlusExtentDescriptor vcbFreeExt
[kMaxFreeExtents
];
175 pthread_mutex_t vcbFreeExtLock
;
178 u_int8_t
*hfs_summary_table
; /* Each bit is 1 vcbVBMIOSize of bitmap, byte indexed */
179 u_int32_t hfs_summary_size
; /* number of BITS in summary table defined above (not bytes!) */
180 u_int32_t hfs_summary_bytes
; /* number of BYTES in summary table */
182 u_int32_t scan_var
; /* For initializing the summary table */
185 u_int32_t reserveBlocks
; /* free block reserve */
186 u_int32_t loanedBlocks
; /* blocks on loan for delayed allocations */
187 u_int32_t lockedBlocks
; /* blocks reserved and locked */
190 * HFS+ Private system directories (two). Any access
191 * (besides looking at the cd_cnid) requires holding
192 * the Catalog File lock.
194 struct cat_desc hfs_private_desc
[2];
195 struct cat_attr hfs_private_attr
[2];
197 u_int32_t hfs_metadata_createdate
;
199 /* Journaling variables: */
200 struct journal
*jnl
; // the journal for this volume (if one exists)
201 struct vnode
*jvp
; // device where the journal lives (may be equal to devvp)
202 u_int64_t jnl_start
; // start block of the journal file (so we don't delete it)
204 u_int64_t hfs_jnlfileid
;
205 u_int64_t hfs_jnlinfoblkid
;
206 pthread_rwlock_t hfs_global_lock
;
207 pthread_t hfs_global_lockowner
;
208 u_int32_t hfs_transaction_nesting
;
211 * Notification variables
212 * See comments in hfs mount code for what the
213 * default levels are set to.
215 u_int32_t hfs_notification_conditions
;
216 u_int32_t hfs_freespace_notify_dangerlimit
;
217 u_int32_t hfs_freespace_notify_warninglimit
;
218 u_int32_t hfs_freespace_notify_nearwarninglimit
;
219 u_int32_t hfs_freespace_notify_desiredlevel
;
221 /* time mounted and last mounted mod time "snapshot" */
222 time_t hfs_mount_time
;
223 time_t hfs_last_mounted_mtime
;
225 /* Metadata allocation zone variables: */
226 u_int32_t hfs_metazone_start
;
227 u_int32_t hfs_metazone_end
;
228 u_int32_t hfs_min_alloc_start
;
229 u_int32_t hfs_freed_block_count
;
230 int hfs_overflow_maxblks
;
231 int hfs_catalog_maxblks
;
233 /* defrag-on-open variables */
234 int hfs_defrag_nowait
; //issue defrags now, regardless of whether or not we've gone past 3 min.
235 uint64_t hfs_defrag_max
; //maximum file size we'll defragment on this mount
238 /* Sparse device variables: */
239 struct vnode
* hfs_backingvp
;
240 u_int32_t hfs_last_backingstatfs
;
241 u_int32_t hfs_sparsebandblks
;
242 u_int64_t hfs_backingfs_maxblocks
;
244 size_t hfs_max_inline_attrsize
;
246 pthread_mutex_t hfs_mutex
; /* protects access to hfsmount data */
247 pthread_mutex_t sync_mutex
;
251 HFS_WANT_TO_FREEZE
, // This state stops hfs_sync from starting
252 HFS_FREEZING
, // We're in this state whilst we're flushing
253 HFS_FROZEN
// Everything gets blocked in hfs_lock_global
257 * When we're freezing (HFS_FREEZING) but not yet
258 * frozen (HFS_FROZEN), we record the freezing thread
259 * so that we stop other threads from taking locks,
260 * but allow the freezing thread.
262 pthread_t hfs_freezing_thread
;
264 * Once we have frozen (HFS_FROZEN), we record the
265 * process so that if it dies, we can automatically
268 proc_t hfs_freezing_proc
;
271 pthread_t hfs_downgrading_thread
; /* thread who's downgrading to rdonly */
273 /* Resize variables: */
274 u_int32_t hfs_resize_blocksmoved
;
275 u_int32_t hfs_resize_totalblocks
;
276 u_int32_t hfs_resize_progress
;
278 /* the full UUID of the volume, not the one stored in finderinfo */
279 uuid_t hfs_full_uuid
;
281 /* Per mount cnode hash variables: */
282 pthread_mutex_t hfs_chash_mutex
; /* protects access to cnode hash table */
283 u_long hfs_cnodehash
; /* size of cnode hash table - 1 */
284 LIST_HEAD(cnodehashhead
, cnode
) *hfs_cnodehashtbl
; /* base of cnode hash */
286 /* Per mount fileid hash variables (protected by catalog lock!) */
287 u_long hfs_idhash
; /* size of cnid/fileid hash table -1 */
288 LIST_HEAD(idhashhead
, cat_preflightid
) *hfs_idhashtbl
; /* base of ID hash */
290 // Records the oldest outstanding sync request
291 struct timeval hfs_sync_req_oldest
;
293 /* Records the syncer thread so that we can avoid the syncer
294 queing more syncs. */
295 pthread_t hfs_syncer_thread
;
297 // Not currently used except for debugging purposes
298 // Since we pass this to OSAddAtomic, this needs to be 4-byte aligned.
299 uint32_t hfs_active_threads
;
302 // These are indices into the array below
304 // Tentative ranges can be claimed back at any time
305 HFS_TENTATIVE_BLOCKS
= 0,
307 // Locked ranges cannot be claimed back, but the allocation
308 // won't have been written to disk yet
309 HFS_LOCKED_BLOCKS
= 1,
311 // These lists are not sorted like a range list usually is
312 struct rl_head hfs_reserved_ranges
[2];
314 //General counter of link id
319 typedef hfsmount_t ExtendedVCB
;
322 /* Aliases for legacy (Mac OS 9) field names */
323 #define vcbLsMod hfs_mtime
324 #define vcbVolBkUp hfs_btime
325 #define extentsRefNum hfs_extents_vp
326 #define catalogRefNum hfs_catalog_vp
327 #define allocationsRefNum hfs_allocation_vp
328 #define vcbFilCnt hfs_filecount
329 #define vcbDirCnt hfs_dircount
331 static inline void MarkVCBDirty(hfsmount_t
*hfsmp
)
333 hfsmp
->hfs_header_dirty
= true;
336 static inline void MarkVCBClean(hfsmount_t
*hfsmp
)
338 hfsmp
->hfs_header_dirty
= false;
339 hfsmp
->hfs_header_minor_change
= false;
342 static inline bool IsVCBDirty(ExtendedVCB
*vcb
)
344 return vcb
->hfs_header_minor_change
|| vcb
->hfs_header_dirty
;
347 // Header is changed but won't be inconsistent if we don't write it
348 static inline void hfs_note_header_minor_change(hfsmount_t
*hfsmp
)
350 hfsmp
->hfs_header_minor_change
= true;
353 // Must header be flushed for volume to be consistent?
354 static inline bool hfs_header_needs_flushing(hfsmount_t
*hfsmp
)
356 return (hfsmp
->hfs_header_dirty
357 || ISSET(hfsmp
->hfs_catalog_cp
->c_flag
, C_MODIFIED
)
358 || ISSET(hfsmp
->hfs_extents_cp
->c_flag
, C_MODIFIED
)
359 || (hfsmp
->hfs_attribute_cp
360 && ISSET(hfsmp
->hfs_attribute_cp
->c_flag
, C_MODIFIED
))
361 || (hfsmp
->hfs_allocation_cp
362 && ISSET(hfsmp
->hfs_allocation_cp
->c_flag
, C_MODIFIED
))
363 || (hfsmp
->hfs_startup_cp
364 && ISSET(hfsmp
->hfs_startup_cp
->c_flag
, C_MODIFIED
)));
372 #define HFS_ALLOCATOR_SCAN_INFLIGHT 0x0001 /* scan started */
373 #define HFS_ALLOCATOR_SCAN_COMPLETED 0x0002 /* initial scan was completed */
375 /* HFS mount point flags */
376 #define HFS_READ_ONLY 0x00001
377 #define HFS_UNKNOWN_PERMS 0x00002
378 #define HFS_WRITEABLE_MEDIA 0x00004
379 #define HFS_CLEANED_ORPHANS 0x00008
380 #define HFS_X 0x00010
381 #define HFS_CASE_SENSITIVE 0x00020
382 //#define HFS_STANDARD 0x00040
383 #define HFS_METADATA_ZONE 0x00080
384 #define HFS_FRAGMENTED_FREESPACE 0x00100
385 #define HFS_NEED_JNL_RESET 0x00200
386 //#define HFS_HAS_SPARSE_DEVICE 0x00400
387 #define HFS_RESIZE_IN_PROGRESS 0x00800
388 #define HFS_QUOTAS 0x01000
389 #define HFS_CREATING_BTREE 0x02000
390 /* When set, do not update nextAllocation in the mount structure */
391 #define HFS_SKIP_UPDATE_NEXT_ALLOCATION 0x04000
392 /* When set, the file system supports extent-based extended attributes */
393 #define HFS_XATTR_EXTENTS 0x08000
394 #define HFS_FOLDERCOUNT 0x10000
395 /* When set, the file system exists on a virtual device, like disk image */
396 //#define HFS_VIRTUAL_DEVICE 0x20000
397 /* When set, we're in hfs_changefs, so hfs_sync should do nothing. */
398 #define HFS_IN_CHANGEFS 0x40000
399 /* When set, we are in process of downgrading or have downgraded to read-only,
400 * so hfs_start_transaction should return EROFS.
402 #define HFS_RDONLY_DOWNGRADE 0x80000
403 #define HFS_DID_CONTIG_SCAN 0x100000
404 #define HFS_UNMAP 0x200000
405 //#define HFS_SSD 0x400000
406 #define HFS_SUMMARY_TABLE 0x800000
407 //#define HFS_CS 0x1000000
408 //#define HFS_CS_METADATA_PIN 0x2000000
409 #define HFS_FEATURE_BARRIER 0x8000000 /* device supports barrier-only flush */
410 //#define HFS_CS_SWAPFILE_PIN 0x10000000
412 /* Macro to update next allocation block in the HFS mount structure. If
413 * the HFS_SKIP_UPDATE_NEXT_ALLOCATION is set, do not update
414 * nextAllocation block.
416 #define HFS_UPDATE_NEXT_ALLOCATION(hfsmp, new_nextAllocation) \
418 if ((hfsmp->hfs_flags & HFS_SKIP_UPDATE_NEXT_ALLOCATION) == 0) \
419 hfsmp->nextAllocation = new_nextAllocation; \
422 /* Macro for incrementing and decrementing the folder count in a cnode
423 * attribute only if the HFS_FOLDERCOUNT bit is set in the mount flags
424 * and kHFSHasFolderCount bit is set in the cnode flags. Currently these
425 * bits are only set for case sensitive HFS+ volumes.
427 #define INC_FOLDERCOUNT(hfsmp, cattr) \
428 if ((hfsmp->hfs_flags & HFS_FOLDERCOUNT) && \
429 (cattr.ca_recflags & kHFSHasFolderCountMask)) \
431 cattr.ca_dircount++; \
434 #define DEC_FOLDERCOUNT(hfsmp, cattr) \
435 if ((hfsmp->hfs_flags & HFS_FOLDERCOUNT) && \
436 (cattr.ca_recflags & kHFSHasFolderCountMask) && \
437 (cattr.ca_dircount > 0)) \
439 cattr.ca_dircount--; \
442 typedef struct filefork FCB;
445 * Macros for creating item names for our special/private directories.
447 #define MAKE_INODE_NAME(name, size, linkno) \
448 (void) snprintf((name), size, "%s%d", HFS_INODE_PREFIX, (linkno))
449 #define HFS_INODE_PREFIX_LEN 5
451 #define MAKE_DIRINODE_NAME(name, size, linkno) \
452 (void) snprintf((name), size, "%s%d", HFS_DIRINODE_PREFIX, (linkno))
453 #define HFS_DIRINODE_PREFIX_LEN 4
455 #define MAKE_DELETED_NAME(NAME, size, FID) \
456 (void) snprintf((NAME), size, "%s%d", HFS_DELETE_PREFIX, (FID))
457 #define HFS_DELETE_PREFIX_LEN 4
459 enum { kHFSPlusMaxFileNameBytes
= kHFSPlusMaxFileNameChars
* 3 };
462 /* macro to determine if hfs or hfsplus */
463 #define ISHFSPLUS(VCB) ((VCB)->vcbSigWord == kHFSPlusSigWord)
466 * Various ways to acquire a VFS mount point pointer:
468 #define VTOVFS(VP) (vp->sFSParams.vnfs_mp)
469 #define HFSTOVFS(HFSMP) ((HFSMP)->hfs_mp)
470 #define VCBTOVFS(VCB) (HFSTOVFS(VCB))
473 * Various ways to acquire an HFS mount point pointer:
475 #define VTOHFS(vp) ((struct hfsmount *)(vp->sFSParams.vnfs_mp->psHfsmount))
476 #define VFSTOHFS(mp) ((struct hfsmount *)(mp->psHfsmount))
477 #define VCBTOHFS(vcb) (vcb)
478 #define FCBTOHFS(fcb) ((struct hfsmount *)((vnode_mount((fcb)->ff_cp->c_vp))->psHfsmount))
481 * Various ways to acquire a VCB (legacy) pointer:
483 #define VTOVCB(VP) (VTOHFS(VP))
484 #define VFSTOVCB(MP) (VFSTOHFS(MP))
485 #define HFSTOVCB(HFSMP) (HFSMP)
486 #define FCBTOVCB(FCB) (FCBTOHFS(FCB))
489 #define kHFSBlockSize (512)
492 * Macros for getting the MDB/VH sector and offset
494 #define HFS_PRI_SECTOR(blksize) (1024 / (blksize))
495 #define HFS_PRI_OFFSET(blksize) ((blksize) > 1024 ? 1024 : 0)
497 #define HFS_ALT_SECTOR(blksize, blkcnt) (((blkcnt) - 1) - (512 / (blksize)))
498 #define HFS_ALT_OFFSET(blksize) ((blksize) > 1024 ? (blksize) - 1024 : 0)
500 #define HFS_PHYSBLK_ROUNDDOWN(sector_num, log_per_phys) ((sector_num / log_per_phys) * log_per_phys)
502 /* HFS System file locking */
503 #define SFL_CATALOG 0x0001
504 #define SFL_EXTENTS 0x0002
505 #define SFL_BITMAP 0x0004
506 #define SFL_ATTRIBUTE 0x0008
507 #define SFL_STARTUP 0x0010
508 #define SFL_VM_PRIV 0x0020
509 #define SFL_VALIDMASK (SFL_CATALOG | SFL_EXTENTS | SFL_BITMAP | SFL_ATTRIBUTE | SFL_STARTUP | SFL_VM_PRIV)
511 /* If a runtime corruption is detected, mark the volume inconsistent
512 * bit in the volume attributes.
515 HFS_INCONSISTENCY_DETECTED
,
516 // Used when unable to rollback an operation that failed
518 // Used when the latter part of an operation failed, but we chose not to roll back
520 // Used when someone told us to force an fsck on next mount
522 } hfs_inconsistency_reason_t
;
524 #define HFS_ERESERVEDNAME (-8)
526 typedef enum hfs_sync_mode
{
532 typedef enum hfs_flush_mode
{
533 HFS_FLUSH_JOURNAL
, // Flush journal
534 HFS_FLUSH_JOURNAL_META
, // Flush journal and metadata blocks
535 HFS_FLUSH_FULL
, // Flush journal and does a cache flush
536 HFS_FLUSH_CACHE
, // Flush track cache to media
537 HFS_FLUSH_BARRIER
, // Barrier-only flush to ensure write order
538 HFS_FLUSH_JOURNAL_BARRIER
// Flush journal with barrier
541 /* Number of bits used to represent maximum extended attribute size */
542 #define HFS_XATTR_SIZE_BITS 31
544 #define HFS_LINK_MAX 32767
547 // Push all modifications to disk (including minor ones)
548 HFS_UPDATE_FORCE
= 0x01,
549 } hfs_update_options_t
;
552 * Maximum extended attribute size supported for all extended attributes except
553 * resource fork and finder info.
555 #define HFS_XATTR_MAXSIZE INT32_MAX
558 #define HFS_CRASH_TEST 1
560 #define HFS_CRASH_TEST 0
566 CRASH_ABORT_MAKE_DIR
,
567 CRASH_ABORT_JOURNAL_BEFORE_FINISH
, // Crash driver before journal update starts
568 CRASH_ABORT_JOURNAL_AFTER_JOURNAL_DATA
, // Crash driver after the journal data has been written but before the journal header has been updated
569 CRASH_ABORT_JOURNAL_AFTER_JOURNAL_HEADER
, // Crash driver after the journal header has been updated but before blocks were written to destination
570 CRASH_ABORT_JOURNAL_IN_BLOCK_DATA
, // Crash driver while writing data blocks
571 CRASH_ABORT_JOURNAL_AFTER_BLOCK_DATA
, // Crash the driver after the data blocks were written
572 CRASH_ABORT_ON_UNMOUNT
, // Crash on unmount
573 CRASH_ABORT_RANDOM
, // Crach at random time (introduced by tester)
577 typedef int (*CrashAbortFunction_FP
)(CrashAbort_E eAbort
, int iFD
, UVFSFileNode psNode
, pthread_t pSyncerThread
);
579 extern CrashAbortFunction_FP gpsCrashAbortFunctionArray
[];
581 #define CRASH_ABORT(CrashAbortCondition, psHfsmount, Vnode) \
583 if (gpsCrashAbortFunctionArray[(CrashAbortCondition)]) { \
585 pthread_t pSyncerThread = 0; \
586 if ( ((psHfsmount)->hfs_syncer_thread) && \
587 ((psHfsmount)->hfs_syncer_thread != (void*)1) ) { \
588 pSyncerThread = (psHfsmount)->hfs_syncer_thread; \
590 gpsCrashAbortFunctionArray[(CrashAbortCondition)]( \
591 (CrashAbortCondition), \
592 (psHfsmount)->hfs_devvp->psFSRecord->iFD, \
593 (Vnode), pSyncerThread ); \
597 #endif // HFS_CRASH_TEST
600 #endif /* lf_hfs_h */