]> git.saurik.com Git - apple/hfs.git/blob - livefiles_hfs_plugin/lf_hfs.h
hfs-556.41.1.tar.gz
[apple/hfs.git] / livefiles_hfs_plugin / lf_hfs.h
1 /* Copyright © 2017-2018 Apple Inc. All rights reserved.
2 *
3 * lf_hfs.h
4 * livefiles_hfs
5 *
6 * Created by Or Haimovich on 18/3/18.
7 */
8
9 #ifndef lf_hfs_h
10 #define lf_hfs_h
11
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"
19
20
21 #define HFS_MAX_DEFERED_ALLOC (1024*1024)
22
23 #define HFS_MAX_FILES (UINT32_MAX - kHFSFirstUserCatalogNodeID)
24
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)
29
30 enum { kMDBSize = 512 }; /* Size of I/O transfer to read entire MDB */
31
32 enum { kMasterDirectoryBlock = 2 }; /* MDB offset on disk in 512-byte blocks */
33 enum { kMDBOffset = kMasterDirectoryBlock * 512 }; /* MDB offset on disk in bytes */
34
35 #define kRootDirID kHFSRootFolderID
36
37 /* How many free extents to cache per volume */
38 #define kMaxFreeExtents 10
39
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)
43
44 #define HFS_AVERAGE_NAME_SIZE 22
45 #define AVERAGE_HFSDIRENTRY_SIZE (8+HFS_AVERAGE_NAME_SIZE+4)
46
47 /*
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.
53 */
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))
57
58 /*
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
61 * progress, but...
62 * HFS_MAX_META_DELAY is the maximum time we will allow the
63 * syncer to be delayed.
64 */
65 enum {
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
70 };
71
72 #define HFS_META_DELAY_TS ((struct timespec){ 0, HFS_META_DELAY * NSEC_PER_USEC })
73
74
75 /* This structure describes the HFS specific mount structure data. */
76 typedef struct hfsmount {
77 u_int32_t hfs_flags; /* see below */
78
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) */
83 /*
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.
88 *
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.
91 */
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 */
94
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 */
97
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 */
114
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 */
121
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 */
136
137 /* Persistent fields (on disk, static) */
138 u_int16_t vcbSigWord;
139
140 // Volume will be inconsistent if header is not flushed
141 bool hfs_header_dirty;
142
143 // Volume header is dirty, but won't be inconsistent if not flushed
144 bool hfs_header_minor_change;
145
146 u_int32_t vcbAtrb;
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 */
154 /*
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.
160 */
161 int32_t vcbClpSiz;
162 u_int32_t vcbFndrInfo[8];
163 int16_t vcbVBMSt; /* HFS only */
164 int16_t vcbAlBlSt; /* HFS only */
165
166 /* vcb stuff */
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 */
171
172 /* cache of largest known free extents */
173 u_int32_t vcbFreeExtCnt;
174 HFSPlusExtentDescriptor vcbFreeExt[kMaxFreeExtents];
175 pthread_mutex_t vcbFreeExtLock;
176
177 /* Summary Table */
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 */
181
182 u_int32_t scan_var; /* For initializing the summary table */
183
184
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 */
188
189 /*
190 * HFS+ Private system directories (two). Any access
191 * (besides looking at the cd_cnid) requires holding
192 * the Catalog File lock.
193 */
194 struct cat_desc hfs_private_desc[2];
195 struct cat_attr hfs_private_attr[2];
196
197 u_int32_t hfs_metadata_createdate;
198
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)
203 u_int64_t jnl_size;
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;
209
210 /*
211 * Notification variables
212 * See comments in hfs mount code for what the
213 * default levels are set to.
214 */
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;
220
221 /* time mounted and last mounted mod time "snapshot" */
222 time_t hfs_mount_time;
223 time_t hfs_last_mounted_mtime;
224
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;
232
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
236
237 #if HFS_SPARSE_DEV
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;
243 #endif
244 size_t hfs_max_inline_attrsize;
245
246 pthread_mutex_t hfs_mutex; /* protects access to hfsmount data */
247 pthread_mutex_t sync_mutex;
248
249 enum {
250 HFS_THAWED,
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
254 } hfs_freeze_state;
255 union {
256 /*
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.
261 */
262 pthread_t hfs_freezing_thread;
263 /*
264 * Once we have frozen (HFS_FROZEN), we record the
265 * process so that if it dies, we can automatically
266 * unfreeze.
267 */
268 proc_t hfs_freezing_proc;
269 };
270
271 pthread_t hfs_downgrading_thread; /* thread who's downgrading to rdonly */
272
273 /* Resize variables: */
274 u_int32_t hfs_resize_blocksmoved;
275 u_int32_t hfs_resize_totalblocks;
276 u_int32_t hfs_resize_progress;
277
278 /* the full UUID of the volume, not the one stored in finderinfo */
279 uuid_t hfs_full_uuid;
280
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 */
285
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 */
289
290 // Records the oldest outstanding sync request
291 struct timeval hfs_sync_req_oldest;
292
293 /* Records the syncer thread so that we can avoid the syncer
294 queing more syncs. */
295 pthread_t hfs_syncer_thread;
296
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;
300
301 enum {
302 // These are indices into the array below
303
304 // Tentative ranges can be claimed back at any time
305 HFS_TENTATIVE_BLOCKS = 0,
306
307 // Locked ranges cannot be claimed back, but the allocation
308 // won't have been written to disk yet
309 HFS_LOCKED_BLOCKS = 1,
310 };
311 // These lists are not sorted like a range list usually is
312 struct rl_head hfs_reserved_ranges[2];
313
314 //General counter of link id
315 int cur_link_id;
316
317 } hfsmount_t;
318
319 typedef hfsmount_t ExtendedVCB;
320
321
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
330
331 static inline void MarkVCBDirty(hfsmount_t *hfsmp)
332 {
333 hfsmp->hfs_header_dirty = true;
334 }
335
336 static inline void MarkVCBClean(hfsmount_t *hfsmp)
337 {
338 hfsmp->hfs_header_dirty = false;
339 hfsmp->hfs_header_minor_change = false;
340 }
341
342 static inline bool IsVCBDirty(ExtendedVCB *vcb)
343 {
344 return vcb->hfs_header_minor_change || vcb->hfs_header_dirty;
345 }
346
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)
349 {
350 hfsmp->hfs_header_minor_change = true;
351 }
352
353 // Must header be flushed for volume to be consistent?
354 static inline bool hfs_header_needs_flushing(hfsmount_t *hfsmp)
355 {
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)));
365 }
366
367 enum privdirtype {
368 FILE_HARDLINKS,
369 DIR_HARDLINKS
370 };
371
372 #define HFS_ALLOCATOR_SCAN_INFLIGHT 0x0001 /* scan started */
373 #define HFS_ALLOCATOR_SCAN_COMPLETED 0x0002 /* initial scan was completed */
374
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.
401 */
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
411
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.
415 */
416 #define HFS_UPDATE_NEXT_ALLOCATION(hfsmp, new_nextAllocation) \
417 { \
418 if ((hfsmp->hfs_flags & HFS_SKIP_UPDATE_NEXT_ALLOCATION) == 0) \
419 hfsmp->nextAllocation = new_nextAllocation; \
420 }
421
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.
426 */
427 #define INC_FOLDERCOUNT(hfsmp, cattr) \
428 if ((hfsmp->hfs_flags & HFS_FOLDERCOUNT) && \
429 (cattr.ca_recflags & kHFSHasFolderCountMask)) \
430 { \
431 cattr.ca_dircount++; \
432 } \
433
434 #define DEC_FOLDERCOUNT(hfsmp, cattr) \
435 if ((hfsmp->hfs_flags & HFS_FOLDERCOUNT) && \
436 (cattr.ca_recflags & kHFSHasFolderCountMask) && \
437 (cattr.ca_dircount > 0)) \
438 { \
439 cattr.ca_dircount--; \
440 } \
441
442 typedef struct filefork FCB;
443
444 /*
445 * Macros for creating item names for our special/private directories.
446 */
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
450
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
454
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
458
459 enum { kHFSPlusMaxFileNameBytes = kHFSPlusMaxFileNameChars * 3 };
460
461
462 /* macro to determine if hfs or hfsplus */
463 #define ISHFSPLUS(VCB) ((VCB)->vcbSigWord == kHFSPlusSigWord)
464
465 /*
466 * Various ways to acquire a VFS mount point pointer:
467 */
468 #define VTOVFS(VP) (vp->sFSParams.vnfs_mp)
469 #define HFSTOVFS(HFSMP) ((HFSMP)->hfs_mp)
470 #define VCBTOVFS(VCB) (HFSTOVFS(VCB))
471
472 /*
473 * Various ways to acquire an HFS mount point pointer:
474 */
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))
479
480 /*
481 * Various ways to acquire a VCB (legacy) pointer:
482 */
483 #define VTOVCB(VP) (VTOHFS(VP))
484 #define VFSTOVCB(MP) (VFSTOHFS(MP))
485 #define HFSTOVCB(HFSMP) (HFSMP)
486 #define FCBTOVCB(FCB) (FCBTOHFS(FCB))
487
488 #define E_NONE (0)
489 #define kHFSBlockSize (512)
490
491 /*
492 * Macros for getting the MDB/VH sector and offset
493 */
494 #define HFS_PRI_SECTOR(blksize) (1024 / (blksize))
495 #define HFS_PRI_OFFSET(blksize) ((blksize) > 1024 ? 1024 : 0)
496
497 #define HFS_ALT_SECTOR(blksize, blkcnt) (((blkcnt) - 1) - (512 / (blksize)))
498 #define HFS_ALT_OFFSET(blksize) ((blksize) > 1024 ? (blksize) - 1024 : 0)
499
500 #define HFS_PHYSBLK_ROUNDDOWN(sector_num, log_per_phys) ((sector_num / log_per_phys) * log_per_phys)
501
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)
510
511 /* If a runtime corruption is detected, mark the volume inconsistent
512 * bit in the volume attributes.
513 */
514 typedef enum {
515 HFS_INCONSISTENCY_DETECTED,
516 // Used when unable to rollback an operation that failed
517 HFS_ROLLBACK_FAILED,
518 // Used when the latter part of an operation failed, but we chose not to roll back
519 HFS_OP_INCOMPLETE,
520 // Used when someone told us to force an fsck on next mount
521 HFS_FSCK_FORCED,
522 } hfs_inconsistency_reason_t;
523
524 #define HFS_ERESERVEDNAME (-8)
525
526 typedef enum hfs_sync_mode {
527 HFS_FSYNC,
528 HFS_FSYNC_FULL,
529 HFS_FSYNC_BARRIER
530 } hfs_fsync_mode_t;
531
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
539 } hfs_flush_mode_t;
540
541 /* Number of bits used to represent maximum extended attribute size */
542 #define HFS_XATTR_SIZE_BITS 31
543
544 #define HFS_LINK_MAX 32767
545
546 typedef enum {
547 // Push all modifications to disk (including minor ones)
548 HFS_UPDATE_FORCE = 0x01,
549 } hfs_update_options_t;
550
551 /*
552 * Maximum extended attribute size supported for all extended attributes except
553 * resource fork and finder info.
554 */
555 #define HFS_XATTR_MAXSIZE INT32_MAX
556
557 #if DEBUG
558 #define HFS_CRASH_TEST 1
559 #else
560 #define HFS_CRASH_TEST 0
561 #endif
562
563 #if HFS_CRASH_TEST
564 typedef enum {
565 CRASH_ABORT_NONE,
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)
574 CRASH_ABORT_LAST
575 } CrashAbort_E;
576
577 typedef int (*CrashAbortFunction_FP)(CrashAbort_E eAbort, int iFD, UVFSFileNode psNode, pthread_t pSyncerThread);
578
579 extern CrashAbortFunction_FP gpsCrashAbortFunctionArray[];
580
581 #define CRASH_ABORT(CrashAbortCondition, psHfsmount, Vnode) \
582 { \
583 if (gpsCrashAbortFunctionArray[(CrashAbortCondition)]) { \
584 \
585 pthread_t pSyncerThread = 0; \
586 if ( ((psHfsmount)->hfs_syncer_thread) && \
587 ((psHfsmount)->hfs_syncer_thread != (void*)1) ) { \
588 pSyncerThread = (psHfsmount)->hfs_syncer_thread; \
589 } \
590 gpsCrashAbortFunctionArray[(CrashAbortCondition)]( \
591 (CrashAbortCondition), \
592 (psHfsmount)->hfs_devvp->psFSRecord->iFD, \
593 (Vnode), pSyncerThread ); \
594 } \
595 }
596
597 #endif // HFS_CRASH_TEST
598
599
600 #endif /* lf_hfs_h */