]>
Commit | Line | Data |
---|---|---|
1c79356b | 1 | /* |
04b8595b | 2 | * Copyright (c) 2000-2015 Apple Inc. All rights reserved. |
5d5c5d0d | 3 | * |
2d21ac55 | 4 | * @APPLE_OSREFERENCE_LICENSE_HEADER_START@ |
1c79356b | 5 | * |
2d21ac55 A |
6 | * This file contains Original Code and/or Modifications of Original Code |
7 | * as defined in and that are subject to the Apple Public Source License | |
8 | * Version 2.0 (the 'License'). You may not use this file except in | |
9 | * compliance with the License. The rights granted to you under the License | |
10 | * may not be used to create, or enable the creation or redistribution of, | |
11 | * unlawful or unlicensed copies of an Apple operating system, or to | |
12 | * circumvent, violate, or enable the circumvention or violation of, any | |
13 | * terms of an Apple operating system software license agreement. | |
8f6c56a5 | 14 | * |
2d21ac55 A |
15 | * Please obtain a copy of the License at |
16 | * http://www.opensource.apple.com/apsl/ and read it before using this file. | |
17 | * | |
18 | * The Original Code and all software distributed under the License are | |
19 | * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER | |
8f6c56a5 A |
20 | * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, |
21 | * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, | |
2d21ac55 A |
22 | * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT. |
23 | * Please see the License for the specific language governing rights and | |
24 | * limitations under the License. | |
8f6c56a5 | 25 | * |
2d21ac55 | 26 | * @APPLE_OSREFERENCE_LICENSE_HEADER_END@ |
1c79356b | 27 | */ |
1c79356b A |
28 | |
29 | #ifndef __HFS__ | |
30 | #define __HFS__ | |
31 | ||
6d2010ae A |
32 | /* If set to 1, enables the code to allocate blocks from the start |
33 | * of the disk instead of the nextAllocation for sparse devices like | |
34 | * sparse disk images or sparsebundle images. The free extent cache | |
35 | * for such volumes is also maintained based on the start block instead | |
36 | * of number of contiguous allocation blocks. These devices prefer | |
37 | * allocation of blocks near the start of the disk to avoid the | |
38 | * increasing the image size, but it can also result in file fragmentation. | |
39 | */ | |
55e303ae A |
40 | #define HFS_SPARSE_DEV 1 |
41 | ||
b0d623f7 | 42 | #if DEBUG |
2d21ac55 A |
43 | #define HFS_CHECK_LOCK_ORDER 1 |
44 | #endif | |
45 | ||
3e170ce0 A |
46 | #define HFS_TMPDBG 0 |
47 | ||
9bccf70c A |
48 | #include <sys/appleapiopts.h> |
49 | ||
50 | #ifdef KERNEL | |
51 | #ifdef __APPLE_API_PRIVATE | |
1c79356b | 52 | #include <sys/param.h> |
1c79356b | 53 | #include <sys/queue.h> |
9bccf70c | 54 | #include <sys/mount.h> |
9bccf70c A |
55 | #include <sys/vnode.h> |
56 | #include <sys/quota.h> | |
1c79356b | 57 | #include <sys/dirent.h> |
55e303ae | 58 | #include <sys/event.h> |
060df5ea | 59 | #include <sys/disk.h> |
e2fac8b1 | 60 | #include <kern/thread_call.h> |
1c79356b | 61 | |
91447636 A |
62 | #include <kern/locks.h> |
63 | ||
b4c24cb9 A |
64 | #include <vfs/vfs_journal.h> |
65 | ||
1c79356b | 66 | #include <hfs/hfs_format.h> |
9bccf70c A |
67 | #include <hfs/hfs_catalog.h> |
68 | #include <hfs/hfs_cnode.h> | |
1c79356b A |
69 | #include <hfs/hfs_macos_defs.h> |
70 | #include <hfs/hfs_encodings.h> | |
55e303ae | 71 | #include <hfs/hfs_hotfiles.h> |
fe8ab488 | 72 | #include <hfs/hfs_fsctl.h> |
1c79356b | 73 | |
316670eb A |
74 | #if CONFIG_PROTECT |
75 | /* Forward declare the cprotect struct */ | |
76 | struct cprotect; | |
3e170ce0 A |
77 | |
78 | ||
316670eb A |
79 | #endif |
80 | ||
1c79356b A |
81 | /* |
82 | * Just reported via MIG interface. | |
83 | */ | |
84 | #define VERSION_STRING "hfs-2 (4-12-99)" | |
85 | ||
86 | #define HFS_LINK_MAX 32767 | |
87 | ||
9bccf70c A |
88 | #define HFS_MAX_DEFERED_ALLOC (1024*1024) |
89 | ||
2d21ac55 | 90 | // 400 megs is a "big" file (i.e. one that when deleted |
55e303ae | 91 | // would touch enough data that we should break it into |
2d21ac55 | 92 | // multiple separate transactions) |
0c530ab8 | 93 | #define HFS_BIGFILE_SIZE (400LL * 1024LL * 1024LL) |
55e303ae | 94 | |
1c79356b A |
95 | |
96 | enum { kMDBSize = 512 }; /* Size of I/O transfer to read entire MDB */ | |
97 | ||
98 | enum { kMasterDirectoryBlock = 2 }; /* MDB offset on disk in 512-byte blocks */ | |
99 | enum { kMDBOffset = kMasterDirectoryBlock * 512 }; /* MDB offset on disk in bytes */ | |
100 | ||
91447636 | 101 | #define kRootDirID kHFSRootFolderID |
1c79356b | 102 | |
1c79356b | 103 | |
0b4e3aa0 A |
104 | /* number of locked buffer caches to hold for b-tree meta data */ |
105 | #define kMaxLockedMetaBuffers 32 | |
1c79356b | 106 | |
1c79356b A |
107 | extern struct timezone gTimeZone; |
108 | ||
1c79356b | 109 | |
0b4e3aa0 A |
110 | /* How many free extents to cache per volume */ |
111 | #define kMaxFreeExtents 10 | |
112 | ||
04b8595b A |
113 | /* The maximum time hfs locks can be held while performing hfs statistics gathering */ |
114 | #define HFS_FSINFO_MAX_LOCKHELD_TIME 20 * 1000000ULL /* at most 20 milliseconds. */ | |
115 | ||
9bccf70c A |
116 | /* |
117 | * HFS_MINFREE gives the minimum acceptable percentage | |
118 | * of file system blocks which may be free (but this | |
119 | * minimum will never exceed HFS_MAXRESERVE bytes). If | |
120 | * the free block count drops below this level only the | |
121 | * superuser may continue to allocate blocks. | |
122 | */ | |
123 | #define HFS_MINFREE 1 | |
55e303ae | 124 | #define HFS_MAXRESERVE ((u_int64_t)(250*1024*1024)) |
39236c6e | 125 | #define HFS_BT_MAXRESERVE ((u_int64_t)(10*1024*1024)) |
55e303ae A |
126 | |
127 | /* | |
128 | * The system distinguishes between the desirable low-disk | |
129 | * notifiaction levels for root volumes and non-root volumes. | |
130 | * The various thresholds are computed as a fraction of the | |
131 | * volume size, all capped at a certain fixed level | |
132 | */ | |
133 | ||
b0d623f7 | 134 | #define HFS_ROOTVERYLOWDISKTRIGGERFRACTION 5 |
6d2010ae | 135 | #define HFS_ROOTVERYLOWDISKTRIGGERLEVEL ((u_int64_t)(512*1024*1024)) |
b0d623f7 | 136 | #define HFS_ROOTLOWDISKTRIGGERFRACTION 10 |
6d2010ae | 137 | #define HFS_ROOTLOWDISKTRIGGERLEVEL ((u_int64_t)(1024*1024*1024)) |
b0d623f7 | 138 | #define HFS_ROOTLOWDISKSHUTOFFFRACTION 11 |
6d2010ae | 139 | #define HFS_ROOTLOWDISKSHUTOFFLEVEL ((u_int64_t)(1024*1024*1024 + 250*1024*1024)) |
55e303ae | 140 | |
b0d623f7 A |
141 | #define HFS_VERYLOWDISKTRIGGERFRACTION 1 |
142 | #define HFS_VERYLOWDISKTRIGGERLEVEL ((u_int64_t)(100*1024*1024)) | |
143 | #define HFS_LOWDISKTRIGGERFRACTION 2 | |
144 | #define HFS_LOWDISKTRIGGERLEVEL ((u_int64_t)(150*1024*1024)) | |
145 | #define HFS_LOWDISKSHUTOFFFRACTION 3 | |
146 | #define HFS_LOWDISKSHUTOFFLEVEL ((u_int64_t)(200*1024*1024)) | |
9bccf70c | 147 | |
1c79356b A |
148 | /* Internal Data structures*/ |
149 | ||
1c79356b A |
150 | /* This structure describes the HFS specific mount structure data. */ |
151 | typedef struct hfsmount { | |
91447636 A |
152 | u_int32_t hfs_flags; /* see below */ |
153 | ||
1c79356b | 154 | /* Physical Description */ |
593a1d5f | 155 | u_int32_t hfs_logical_block_size; /* Logical block size of the disk as reported by ioctl(DKIOCGETBLOCKSIZE), always a multiple of 512 */ |
fe8ab488 | 156 | daddr64_t hfs_logical_block_count; /* Number of logical blocks on the disk, as reported by ioctl(DKIOCGETBLOCKCOUNT) */ |
316670eb | 157 | u_int64_t hfs_logical_bytes; /* Number of bytes on the disk device this HFS is mounted on (blockcount * blocksize) */ |
fe8ab488 A |
158 | /* |
159 | * Regarding the two AVH sector fields below: | |
160 | * Under normal circumstances, the filesystem's notion of the "right" location for the AVH is such that | |
161 | * the partition and filesystem's are in sync. However, during a filesystem resize, HFS proactively | |
162 | * writes a new AVH at the end of the filesystem, assuming that the partition will be resized accordingly. | |
163 | * | |
164 | * However, it is not technically a corruption if the partition size is never modified. As a result, we need | |
165 | * to keep two copies of the AVH around "just in case" the partition size is not modified. | |
166 | */ | |
167 | daddr64_t hfs_partition_avh_sector; /* location of Alt VH w.r.t partition size */ | |
168 | daddr64_t hfs_fs_avh_sector; /* location of Alt VH w.r.t filesystem size */ | |
169 | ||
593a1d5f A |
170 | u_int32_t hfs_physical_block_size; /* Physical block size of the disk as reported by ioctl(DKIOCGETPHYSICALBLOCKSIZE) */ |
171 | u_int32_t hfs_log_per_phys; /* Number of logical blocks per physical block size */ | |
1c79356b A |
172 | |
173 | /* Access to VFS and devices */ | |
174 | struct mount *hfs_mp; /* filesystem vfs structure */ | |
175 | struct vnode *hfs_devvp; /* block device mounted vnode */ | |
91447636 A |
176 | struct vnode * hfs_extents_vp; |
177 | struct vnode * hfs_catalog_vp; | |
178 | struct vnode * hfs_allocation_vp; | |
179 | struct vnode * hfs_attribute_vp; | |
2d21ac55 A |
180 | struct vnode * hfs_startup_vp; |
181 | struct vnode * hfs_attrdata_vp; /* pseudo file */ | |
182 | struct cnode * hfs_extents_cp; | |
183 | struct cnode * hfs_catalog_cp; | |
184 | struct cnode * hfs_allocation_cp; | |
185 | struct cnode * hfs_attribute_cp; | |
186 | struct cnode * hfs_startup_cp; | |
91447636 A |
187 | dev_t hfs_raw_dev; /* device mounted */ |
188 | u_int32_t hfs_logBlockSize; /* Size of buffer cache buffer for I/O */ | |
1c79356b A |
189 | |
190 | /* Default values for HFS standard and non-init access */ | |
91447636 A |
191 | uid_t hfs_uid; /* uid to set as owner of the files */ |
192 | gid_t hfs_gid; /* gid to set as owner of the files */ | |
193 | mode_t hfs_dir_mask; /* mask to and with directory protection bits */ | |
194 | mode_t hfs_file_mask; /* mask to and with file protection bits */ | |
b0d623f7 | 195 | u_int32_t hfs_encoding; /* Default encoding for non hfs+ volumes */ |
91447636 A |
196 | |
197 | /* Persistent fields (on disk, dynamic) */ | |
198 | time_t hfs_mtime; /* file system last modification time */ | |
199 | u_int32_t hfs_filecount; /* number of files in file system */ | |
200 | u_int32_t hfs_dircount; /* number of directories in file system */ | |
3e170ce0 A |
201 | u_int32_t freeBlocks; /* free allocation blocks */ |
202 | u_int32_t reclaimBlocks; /* number of blocks we are reclaiming during resize */ | |
203 | u_int32_t tentativeBlocks; /* tentative allocation blocks -- see note below */ | |
91447636 | 204 | u_int32_t nextAllocation; /* start of next allocation search */ |
b0d623f7 | 205 | u_int32_t sparseAllocation; /* start of allocations for sparse devices */ |
2d21ac55 | 206 | u_int32_t vcbNxtCNID; /* next unused catalog node ID - protected by catalog lock */ |
91447636 A |
207 | u_int32_t vcbWrCnt; /* file system write count */ |
208 | u_int64_t encodingsBitmap; /* in-use encodings */ | |
209 | u_int16_t vcbNmFls; /* HFS Only - root dir file count */ | |
210 | u_int16_t vcbNmRtDirs; /* HFS Only - root dir directory count */ | |
211 | ||
212 | /* Persistent fields (on disk, static) */ | |
213 | u_int16_t vcbSigWord; | |
3e170ce0 A |
214 | |
215 | // Volume will be inconsistent if header is not flushed | |
216 | bool hfs_header_dirty; | |
217 | ||
218 | // Volume header is dirty, but won't be inconsistent if not flushed | |
219 | bool hfs_header_minor_change; | |
220 | ||
91447636 A |
221 | u_int32_t vcbAtrb; |
222 | u_int32_t vcbJinfoBlock; | |
6d2010ae A |
223 | u_int32_t localCreateDate;/* volume create time from volume header (For HFS+, value is in local time) */ |
224 | time_t hfs_itime; /* file system creation time (creation date of the root folder) */ | |
225 | time_t hfs_btime; /* file system last backup time */ | |
91447636 A |
226 | u_int32_t blockSize; /* size of allocation blocks */ |
227 | u_int32_t totalBlocks; /* total allocation blocks */ | |
2d21ac55 A |
228 | u_int32_t allocLimit; /* Do not allocate this block or beyond */ |
229 | /* | |
230 | * NOTE: When resizing a volume to make it smaller, allocLimit is set to the allocation | |
231 | * block number which will contain the new alternate volume header. At all other times, | |
232 | * allocLimit is set to totalBlocks. The allocation code uses allocLimit instead of | |
233 | * totalBlocks to limit which blocks may be allocated, so that during a resize, we don't | |
234 | * put new content into the blocks we're trying to truncate away. | |
235 | */ | |
91447636 A |
236 | int32_t vcbClpSiz; |
237 | u_int32_t vcbFndrInfo[8]; | |
238 | int16_t vcbVBMSt; /* HFS only */ | |
239 | int16_t vcbAlBlSt; /* HFS only */ | |
240 | ||
241 | /* vcb stuff */ | |
242 | u_int8_t vcbVN[256]; /* volume name in UTF-8 */ | |
243 | u_int32_t volumeNameEncodingHint; | |
244 | u_int32_t hfsPlusIOPosOffset; /* Disk block where HFS+ starts */ | |
245 | u_int32_t vcbVBMIOSize; /* volume bitmap I/O size */ | |
246 | ||
247 | /* cache of largest known free extents */ | |
248 | u_int32_t vcbFreeExtCnt; | |
249 | HFSPlusExtentDescriptor vcbFreeExt[kMaxFreeExtents]; | |
6d2010ae A |
250 | lck_spin_t vcbFreeExtLock; |
251 | ||
39236c6e A |
252 | /* Summary Table */ |
253 | u_int8_t *hfs_summary_table; /* Each bit is 1 vcbVBMIOSize of bitmap, byte indexed */ | |
254 | u_int32_t hfs_summary_size; /* number of BITS in summary table defined above (not bytes!) */ | |
255 | u_int32_t hfs_summary_bytes; /* number of BYTES in summary table */ | |
91447636 | 256 | |
39236c6e | 257 | u_int32_t scan_var; /* For initializing the summary table */ |
6d2010ae A |
258 | |
259 | ||
91447636 A |
260 | u_int32_t reserveBlocks; /* free block reserve */ |
261 | u_int32_t loanedBlocks; /* blocks on loan for delayed allocations */ | |
3e170ce0 | 262 | u_int32_t lockedBlocks; /* blocks reserved and locked */ |
2d21ac55 A |
263 | |
264 | /* | |
265 | * HFS+ Private system directories (two). Any access | |
266 | * (besides looking at the cd_cnid) requires holding | |
267 | * the Catalog File lock. | |
268 | */ | |
269 | struct cat_desc hfs_private_desc[2]; | |
270 | struct cat_attr hfs_private_attr[2]; | |
271 | ||
1c79356b A |
272 | u_int32_t hfs_metadata_createdate; |
273 | hfs_to_unicode_func_t hfs_get_unicode; | |
274 | unicode_to_hfs_func_t hfs_get_hfsname; | |
9bccf70c | 275 | |
55e303ae | 276 | /* Quota variables: */ |
9bccf70c | 277 | struct quotafile hfs_qfiles[MAXQUOTAS]; /* quota files */ |
b4c24cb9 | 278 | |
55e303ae | 279 | /* Journaling variables: */ |
fe8ab488 | 280 | struct journal *jnl; // the journal for this volume (if one exists) |
b4c24cb9 A |
281 | struct vnode *jvp; // device where the journal lives (may be equal to devvp) |
282 | u_int32_t jnl_start; // start block of the journal file (so we don't delete it) | |
55e303ae | 283 | u_int32_t jnl_size; |
b4c24cb9 A |
284 | u_int32_t hfs_jnlfileid; |
285 | u_int32_t hfs_jnlinfoblkid; | |
fe8ab488 | 286 | lck_rw_t hfs_global_lock; |
fe8ab488 | 287 | thread_t hfs_global_lockowner; |
3e170ce0 | 288 | u_int32_t hfs_transaction_nesting; |
fe8ab488 | 289 | |
55e303ae | 290 | /* Notification variables: */ |
b0d623f7 A |
291 | u_int32_t hfs_notification_conditions; |
292 | u_int32_t hfs_freespace_notify_dangerlimit; | |
55e303ae A |
293 | u_int32_t hfs_freespace_notify_warninglimit; |
294 | u_int32_t hfs_freespace_notify_desiredlevel; | |
295 | ||
91447636 A |
296 | /* time mounted and last mounted mod time "snapshot" */ |
297 | time_t hfs_mount_time; | |
298 | time_t hfs_last_mounted_mtime; | |
299 | ||
55e303ae A |
300 | /* Metadata allocation zone variables: */ |
301 | u_int32_t hfs_metazone_start; | |
302 | u_int32_t hfs_metazone_end; | |
303 | u_int32_t hfs_hotfile_start; | |
304 | u_int32_t hfs_hotfile_end; | |
b0d623f7 A |
305 | u_int32_t hfs_min_alloc_start; |
306 | u_int32_t hfs_freed_block_count; | |
3e170ce0 | 307 | u_int64_t hfs_cs_hotfile_size; // in bytes |
55e303ae | 308 | int hfs_hotfile_freeblks; |
3e170ce0 | 309 | int hfs_hotfile_blk_adjust; |
55e303ae A |
310 | int hfs_hotfile_maxblks; |
311 | int hfs_overflow_maxblks; | |
312 | int hfs_catalog_maxblks; | |
313 | ||
314 | /* Hot File Clustering variables: */ | |
91447636 | 315 | lck_mtx_t hfc_mutex; /* serialize hot file stages */ |
55e303ae A |
316 | enum hfc_stage hfc_stage; /* what are we up to... */ |
317 | time_t hfc_timebase; /* recording period start time */ | |
318 | time_t hfc_timeout; /* recording period stop time */ | |
319 | void * hfc_recdata; /* recording data (opaque) */ | |
3e170ce0 | 320 | uint32_t hfc_maxfiles; /* maximum files to track */ |
55e303ae A |
321 | struct vnode * hfc_filevp; |
322 | ||
6d2010ae | 323 | #if HFS_SPARSE_DEV |
55e303ae A |
324 | /* Sparse device variables: */ |
325 | struct vnode * hfs_backingfs_rootvp; | |
2d21ac55 | 326 | u_int32_t hfs_last_backingstatfs; |
fe8ab488 | 327 | u_int32_t hfs_sparsebandblks; |
b0d623f7 | 328 | u_int64_t hfs_backingfs_maxblocks; |
55e303ae | 329 | #endif |
91447636 A |
330 | size_t hfs_max_inline_attrsize; |
331 | ||
332 | lck_mtx_t hfs_mutex; /* protects access to hfsmount data */ | |
fe8ab488 A |
333 | |
334 | uint32_t hfs_syncers; // Count of the number of syncers running | |
335 | enum { | |
336 | HFS_THAWED, | |
337 | HFS_WANT_TO_FREEZE, // This state stops hfs_sync from starting | |
338 | HFS_FREEZING, // We're in this state whilst we're flushing | |
339 | HFS_FROZEN // Everything gets blocked in hfs_lock_global | |
340 | } hfs_freeze_state; | |
341 | union { | |
342 | /* | |
343 | * When we're freezing (HFS_FREEZING) but not yet | |
344 | * frozen (HFS_FROZEN), we record the freezing thread | |
345 | * so that we stop other threads from taking locks, | |
346 | * but allow the freezing thread. | |
347 | */ | |
348 | const struct thread *hfs_freezing_thread; | |
349 | /* | |
350 | * Once we have frozen (HFS_FROZEN), we record the | |
351 | * process so that if it dies, we can automatically | |
352 | * unfreeze. | |
353 | */ | |
354 | proc_t hfs_freezing_proc; | |
355 | }; | |
356 | ||
357 | thread_t hfs_downgrading_thread; /* thread who's downgrading to rdonly */ | |
0c530ab8 A |
358 | |
359 | /* Resize variables: */ | |
6d2010ae A |
360 | u_int32_t hfs_resize_blocksmoved; |
361 | u_int32_t hfs_resize_totalblocks; | |
362 | u_int32_t hfs_resize_progress; | |
316670eb | 363 | #if CONFIG_PROTECT |
fe8ab488 | 364 | /* Data Protection fields */ |
3e170ce0 | 365 | cpx_t hfs_resize_cpx; |
316670eb | 366 | u_int16_t hfs_running_cp_major_vers; |
fe8ab488 A |
367 | uint32_t default_cp_class; /* default effective class value */ |
368 | uint64_t cproot_flags; | |
369 | uint8_t cp_crypto_generation; | |
370 | uint8_t hfs_cp_lock_state; /* per-mount device lock state info */ | |
3e170ce0 A |
371 | #if HFS_TMPDBG |
372 | #if !SECURE_KERNEL | |
373 | boolean_t hfs_cp_verbose; | |
374 | #endif | |
316670eb A |
375 | #endif |
376 | ||
3e170ce0 | 377 | #endif |
e2fac8b1 | 378 | |
b0d623f7 A |
379 | /* Per mount cnode hash variables: */ |
380 | lck_mtx_t hfs_chash_mutex; /* protects access to cnode hash table */ | |
381 | u_long hfs_cnodehash; /* size of cnode hash table - 1 */ | |
382 | LIST_HEAD(cnodehashhead, cnode) *hfs_cnodehashtbl; /* base of cnode hash */ | |
383 | ||
39236c6e A |
384 | /* Per mount fileid hash variables (protected by catalog lock!) */ |
385 | u_long hfs_idhash; /* size of cnid/fileid hash table -1 */ | |
386 | LIST_HEAD(idhashhead, cat_preflightid) *hfs_idhashtbl; /* base of ID hash */ | |
b0d623f7 | 387 | |
22ba694c A |
388 | // Records the oldest outstanding sync request |
389 | struct timeval hfs_sync_req_oldest; | |
390 | ||
391 | // Records whether a sync has been queued or is in progress | |
392 | boolean_t hfs_sync_incomplete; | |
6d2010ae | 393 | |
22ba694c A |
394 | thread_call_t hfs_syncer; // removeable devices get sync'ed by this guy |
395 | ||
396 | /* Records the syncer thread so that we can avoid the syncer | |
397 | queing more syncs. */ | |
398 | thread_t hfs_syncer_thread; | |
399 | ||
400 | // Not currently used except for debugging purposes | |
401 | uint32_t hfs_active_threads; | |
3e170ce0 A |
402 | |
403 | enum { | |
404 | // These are indices into the array below | |
405 | ||
406 | // Tentative ranges can be claimed back at any time | |
407 | HFS_TENTATIVE_BLOCKS = 0, | |
408 | ||
409 | // Locked ranges cannot be claimed back, but the allocation | |
410 | // won't have been written to disk yet | |
411 | HFS_LOCKED_BLOCKS = 1, | |
412 | }; | |
413 | // These lists are not sorted like a range list usually is | |
414 | struct rl_head hfs_reserved_ranges[2]; | |
1c79356b A |
415 | } hfsmount_t; |
416 | ||
39236c6e | 417 | /* |
22ba694c A |
418 | * HFS_META_DELAY is a duration (in usecs) used for triggering the |
419 | * hfs_syncer() routine. We will back off if writes are in | |
420 | * progress, but... | |
421 | * HFS_MAX_META_DELAY is the maximum time we will allow the | |
422 | * syncer to be delayed. | |
39236c6e | 423 | */ |
22ba694c A |
424 | enum { |
425 | HFS_META_DELAY = 100 * 1000, // 0.1 secs | |
426 | HFS_MAX_META_DELAY = 5000 * 1000 // 5 secs | |
427 | }; | |
e2fac8b1 | 428 | |
91447636 A |
429 | typedef hfsmount_t ExtendedVCB; |
430 | ||
2d21ac55 | 431 | /* Aliases for legacy (Mac OS 9) field names */ |
91447636 A |
432 | #define vcbLsMod hfs_mtime |
433 | #define vcbVolBkUp hfs_btime | |
434 | #define extentsRefNum hfs_extents_vp | |
435 | #define catalogRefNum hfs_catalog_vp | |
436 | #define allocationsRefNum hfs_allocation_vp | |
437 | #define vcbFilCnt hfs_filecount | |
438 | #define vcbDirCnt hfs_dircount | |
439 | ||
3e170ce0 | 440 | static inline void MarkVCBDirty(hfsmount_t *hfsmp) |
2d21ac55 | 441 | { |
3e170ce0 A |
442 | hfsmp->hfs_header_dirty = true; |
443 | } | |
444 | ||
445 | static inline void MarkVCBClean(hfsmount_t *hfsmp) | |
446 | { | |
447 | hfsmp->hfs_header_dirty = false; | |
448 | hfsmp->hfs_header_minor_change = false; | |
449 | } | |
450 | ||
451 | static inline bool IsVCBDirty(ExtendedVCB *vcb) | |
452 | { | |
453 | return vcb->hfs_header_minor_change || vcb->hfs_header_dirty; | |
2d21ac55 A |
454 | } |
455 | ||
3e170ce0 A |
456 | // Header is changed but won't be inconsistent if we don't write it |
457 | static inline void hfs_note_header_minor_change(hfsmount_t *hfsmp) | |
2d21ac55 | 458 | { |
3e170ce0 | 459 | hfsmp->hfs_header_minor_change = true; |
2d21ac55 A |
460 | } |
461 | ||
3e170ce0 A |
462 | // Must header be flushed for volume to be consistent? |
463 | static inline bool hfs_header_needs_flushing(hfsmount_t *hfsmp) | |
2d21ac55 | 464 | { |
3e170ce0 A |
465 | return (hfsmp->hfs_header_dirty |
466 | || ISSET(hfsmp->hfs_catalog_cp->c_flag, C_MODIFIED) | |
467 | || ISSET(hfsmp->hfs_extents_cp->c_flag, C_MODIFIED) | |
468 | || (hfsmp->hfs_attribute_cp | |
469 | && ISSET(hfsmp->hfs_attribute_cp->c_flag, C_MODIFIED)) | |
470 | || (hfsmp->hfs_allocation_cp | |
471 | && ISSET(hfsmp->hfs_allocation_cp->c_flag, C_MODIFIED)) | |
472 | || (hfsmp->hfs_startup_cp | |
473 | && ISSET(hfsmp->hfs_startup_cp->c_flag, C_MODIFIED))); | |
2d21ac55 | 474 | } |
55e303ae | 475 | |
2d21ac55 A |
476 | /* |
477 | * There are two private directories in HFS+. | |
478 | * | |
479 | * One contains inodes for files that are hardlinked or open/unlinked. | |
480 | * The other contains inodes for directories that are hardlinked. | |
481 | */ | |
482 | enum privdirtype {FILE_HARDLINKS, DIR_HARDLINKS}; | |
55e303ae | 483 | |
39236c6e | 484 | #define HFS_ALLOCATOR_SCAN_INFLIGHT 0x0001 /* scan started */ |
fe8ab488 | 485 | #define HFS_ALLOCATOR_SCAN_COMPLETED 0x0002 /* initial scan was completed */ |
1c79356b | 486 | |
2d21ac55 A |
487 | /* HFS mount point flags */ |
488 | #define HFS_READ_ONLY 0x00001 | |
489 | #define HFS_UNKNOWN_PERMS 0x00002 | |
490 | #define HFS_WRITEABLE_MEDIA 0x00004 | |
491 | #define HFS_CLEANED_ORPHANS 0x00008 | |
492 | #define HFS_X 0x00010 | |
493 | #define HFS_CASE_SENSITIVE 0x00020 | |
494 | #define HFS_STANDARD 0x00040 | |
495 | #define HFS_METADATA_ZONE 0x00080 | |
496 | #define HFS_FRAGMENTED_FREESPACE 0x00100 | |
497 | #define HFS_NEED_JNL_RESET 0x00200 | |
498 | #define HFS_HAS_SPARSE_DEVICE 0x00400 | |
499 | #define HFS_RESIZE_IN_PROGRESS 0x00800 | |
500 | #define HFS_QUOTAS 0x01000 | |
501 | #define HFS_CREATING_BTREE 0x02000 | |
502 | /* When set, do not update nextAllocation in the mount structure */ | |
503 | #define HFS_SKIP_UPDATE_NEXT_ALLOCATION 0x04000 | |
6d2010ae | 504 | /* When set, the file system supports extent-based extended attributes */ |
2d21ac55 A |
505 | #define HFS_XATTR_EXTENTS 0x08000 |
506 | #define HFS_FOLDERCOUNT 0x10000 | |
507 | /* When set, the file system exists on a virtual device, like disk image */ | |
508 | #define HFS_VIRTUAL_DEVICE 0x20000 | |
593a1d5f A |
509 | /* When set, we're in hfs_changefs, so hfs_sync should do nothing. */ |
510 | #define HFS_IN_CHANGEFS 0x40000 | |
c910b4d9 | 511 | /* When set, we are in process of downgrading or have downgraded to read-only, |
b0d623f7 A |
512 | * so hfs_start_transaction should return EROFS. |
513 | */ | |
c910b4d9 | 514 | #define HFS_RDONLY_DOWNGRADE 0x80000 |
b0d623f7 | 515 | #define HFS_DID_CONTIG_SCAN 0x100000 |
316670eb | 516 | #define HFS_UNMAP 0x200000 |
fe8ab488 A |
517 | #define HFS_SSD 0x400000 |
518 | #define HFS_SUMMARY_TABLE 0x800000 | |
519 | #define HFS_CS 0x1000000 | |
3e170ce0 A |
520 | #define HFS_CS_METADATA_PIN 0x2000000 |
521 | #define HFS_CS_HOTFILE_PIN 0x4000000 /* cooperative fusion (enables a hotfile variant) */ | |
522 | #define HFS_FEATURE_BARRIER 0x8000000 /* device supports barrier-only flush */ | |
523 | #define HFS_CS_SWAPFILE_PIN 0x10000000 | |
316670eb | 524 | |
2d21ac55 A |
525 | /* Macro to update next allocation block in the HFS mount structure. If |
526 | * the HFS_SKIP_UPDATE_NEXT_ALLOCATION is set, do not update | |
527 | * nextAllocation block. | |
528 | */ | |
529 | #define HFS_UPDATE_NEXT_ALLOCATION(hfsmp, new_nextAllocation) \ | |
530 | { \ | |
531 | if ((hfsmp->hfs_flags & HFS_SKIP_UPDATE_NEXT_ALLOCATION) == 0)\ | |
532 | hfsmp->nextAllocation = new_nextAllocation; \ | |
533 | } \ | |
534 | ||
2d21ac55 A |
535 | /* Macro for incrementing and decrementing the folder count in a cnode |
536 | * attribute only if the HFS_FOLDERCOUNT bit is set in the mount flags | |
537 | * and kHFSHasFolderCount bit is set in the cnode flags. Currently these | |
538 | * bits are only set for case sensitive HFS+ volumes. | |
539 | */ | |
540 | #define INC_FOLDERCOUNT(hfsmp, cattr) \ | |
541 | if ((hfsmp->hfs_flags & HFS_FOLDERCOUNT) && \ | |
542 | (cattr.ca_recflags & kHFSHasFolderCountMask)) { \ | |
543 | cattr.ca_dircount++; \ | |
544 | } \ | |
545 | ||
546 | #define DEC_FOLDERCOUNT(hfsmp, cattr) \ | |
547 | if ((hfsmp->hfs_flags & HFS_FOLDERCOUNT) && \ | |
548 | (cattr.ca_recflags & kHFSHasFolderCountMask) && \ | |
549 | (cattr.ca_dircount > 0)) { \ | |
550 | cattr.ca_dircount--; \ | |
551 | } \ | |
1c79356b | 552 | |
9bccf70c | 553 | typedef struct filefork FCB; |
1c79356b | 554 | |
2d21ac55 A |
555 | /* |
556 | * Macros for creating item names for our special/private directories. | |
557 | */ | |
558 | #define MAKE_INODE_NAME(name, size, linkno) \ | |
559 | (void) snprintf((name), size, "%s%d", HFS_INODE_PREFIX, (linkno)) | |
560 | #define HFS_INODE_PREFIX_LEN 5 | |
1c79356b | 561 | |
2d21ac55 A |
562 | #define MAKE_DIRINODE_NAME(name, size, linkno) \ |
563 | (void) snprintf((name), size, "%s%d", HFS_DIRINODE_PREFIX, (linkno)) | |
564 | #define HFS_DIRINODE_PREFIX_LEN 4 | |
1c79356b | 565 | |
2d21ac55 A |
566 | #define MAKE_DELETED_NAME(NAME, size, FID) \ |
567 | (void) snprintf((NAME), size, "%s%d", HFS_DELETE_PREFIX, (FID)) | |
568 | #define HFS_DELETE_PREFIX_LEN 4 | |
1c79356b | 569 | |
1c79356b | 570 | |
9bccf70c A |
571 | #define HFS_AVERAGE_NAME_SIZE 22 |
572 | #define AVERAGE_HFSDIRENTRY_SIZE (8+HFS_AVERAGE_NAME_SIZE+4) | |
1c79356b | 573 | |
91447636 A |
574 | #define STD_DIRENT_LEN(namlen) \ |
575 | ((sizeof(struct dirent) - (NAME_MAX+1)) + (((namlen)+1 + 3) &~ 3)) | |
1c79356b | 576 | |
91447636 | 577 | #define EXT_DIRENT_LEN(namlen) \ |
39236c6e | 578 | ((sizeof(struct direntry) + (namlen) - (MAXPATHLEN-1) + 7) & ~7) |
1c79356b | 579 | |
1c79356b A |
580 | |
581 | enum { kHFSPlusMaxFileNameBytes = kHFSPlusMaxFileNameChars * 3 }; | |
582 | ||
1c79356b A |
583 | |
584 | /* macro to determine if hfs or hfsplus */ | |
585 | #define ISHFSPLUS(VCB) ((VCB)->vcbSigWord == kHFSPlusSigWord) | |
586 | #define ISHFS(VCB) ((VCB)->vcbSigWord == kHFSSigWord) | |
587 | ||
588 | ||
1c79356b A |
589 | /* |
590 | * Various ways to acquire a VFS mount point pointer: | |
591 | */ | |
91447636 | 592 | #define VTOVFS(VP) vnode_mount((VP)) |
1c79356b | 593 | #define HFSTOVFS(HFSMP) ((HFSMP)->hfs_mp) |
91447636 | 594 | #define VCBTOVFS(VCB) HFSTOVFS(VCB) |
1c79356b A |
595 | |
596 | /* | |
597 | * Various ways to acquire an HFS mount point pointer: | |
598 | */ | |
91447636 A |
599 | #define VTOHFS(VP) ((struct hfsmount *)vfs_fsprivate(vnode_mount((VP)))) |
600 | #define VFSTOHFS(MP) ((struct hfsmount *)vfs_fsprivate((MP))) | |
601 | #define VCBTOHFS(VCB) (VCB) | |
602 | #define FCBTOHFS(FCB) ((struct hfsmount *)vfs_fsprivate(vnode_mount((FCB)->ff_cp->c_vp))) | |
1c79356b A |
603 | |
604 | /* | |
91447636 | 605 | * Various ways to acquire a VCB (legacy) pointer: |
1c79356b | 606 | */ |
91447636 A |
607 | #define VTOVCB(VP) VTOHFS(VP) |
608 | #define VFSTOVCB(MP) VFSTOHFS(MP) | |
609 | #define HFSTOVCB(HFSMP) (HFSMP) | |
610 | #define FCBTOVCB(FCB) FCBTOHFS(FCB) | |
1c79356b A |
611 | |
612 | ||
613 | #define E_NONE 0 | |
614 | #define kHFSBlockSize 512 | |
1c79356b | 615 | |
9bccf70c A |
616 | /* |
617 | * Macros for getting the MDB/VH sector and offset | |
618 | */ | |
619 | #define HFS_PRI_SECTOR(blksize) (1024 / (blksize)) | |
620 | #define HFS_PRI_OFFSET(blksize) ((blksize) > 1024 ? 1024 : 0) | |
d52fe63f A |
621 | |
622 | #define HFS_ALT_SECTOR(blksize, blkcnt) (((blkcnt) - 1) - (512 / (blksize))) | |
623 | #define HFS_ALT_OFFSET(blksize) ((blksize) > 1024 ? (blksize) - 1024 : 0) | |
624 | ||
593a1d5f A |
625 | /* Convert the logical sector number to be aligned on physical block size boundary. |
626 | * We are assuming the partition is a multiple of physical block size. | |
627 | */ | |
628 | #define HFS_PHYSBLK_ROUNDDOWN(sector_num, log_per_phys) ((sector_num / log_per_phys) * log_per_phys) | |
91447636 A |
629 | |
630 | /* | |
631 | * HFS specific fcntl()'s | |
632 | */ | |
91447636 A |
633 | #define HFS_GET_BOOT_INFO (FCNTL_FS_SPECIFIC_BASE + 0x00004) |
634 | #define HFS_SET_BOOT_INFO (FCNTL_FS_SPECIFIC_BASE + 0x00005) | |
6d2010ae A |
635 | /* See HFSIOC_EXT_BULKACCESS and friends for HFS specific fsctls*/ |
636 | ||
91447636 A |
637 | |
638 | ||
1c79356b A |
639 | /* |
640 | * This is the straight GMT conversion constant: | |
641 | * 00:00:00 January 1, 1970 - 00:00:00 January 1, 1904 | |
642 | * (3600 * 24 * ((365 * (1970 - 1904)) + (((1970 - 1904) / 4) + 1))) | |
643 | */ | |
644 | #define MAC_GMT_FACTOR 2082844800UL | |
645 | ||
fe8ab488 | 646 | static inline __attribute__((const)) |
3e170ce0 | 647 | off_t hfs_blk_to_bytes(uint32_t blk, uint32_t blk_size) |
fe8ab488 | 648 | { |
3e170ce0 | 649 | return (off_t)blk * blk_size; // Avoid the overflow |
fe8ab488 | 650 | } |
1c79356b | 651 | |
3e170ce0 A |
652 | /* |
653 | * For now, we use EIO to indicate consistency issues. It is safe to | |
654 | * return or assign an error value to HFS_EINCONSISTENT but it is | |
655 | * *not* safe to compare against it because EIO can be generated for | |
656 | * other reasons. We take advantage of the fact that == has | |
657 | * left-to-right associativity and so any uses of: | |
658 | * | |
659 | * if (error == HFS_EINCONSISTENT) | |
660 | * | |
661 | * will produce a compiler warning: "comparison between pointer and | |
662 | * integer". | |
663 | * | |
664 | * Note that not everwhere is consistent with the use of | |
665 | * HFS_EINCONSISTENT. Some places return EINVAL, EIO directly or | |
666 | * other error codes. | |
667 | */ | |
668 | #define HFS_EINCONSISTENT (void *)0 == (void *)0 ? EIO : EIO | |
669 | ||
2d21ac55 A |
670 | /***************************************************************************** |
671 | FUNCTION PROTOTYPES | |
672 | ******************************************************************************/ | |
1c79356b | 673 | |
2d21ac55 A |
674 | /***************************************************************************** |
675 | hfs_vnop_xxx functions from different files | |
676 | ******************************************************************************/ | |
677 | int hfs_vnop_readdirattr(struct vnop_readdirattr_args *); /* in hfs_attrlist.c */ | |
fe8ab488 | 678 | int hfs_vnop_getattrlistbulk(struct vnop_getattrlistbulk_args *); /* in hfs_attrlist.c */ |
1c79356b | 679 | |
2d21ac55 A |
680 | int hfs_vnop_inactive(struct vnop_inactive_args *); /* in hfs_cnode.c */ |
681 | int hfs_vnop_reclaim(struct vnop_reclaim_args *); /* in hfs_cnode.c */ | |
316670eb | 682 | |
6d2010ae A |
683 | int hfs_set_backingstore (struct vnode *vp, int val); /* in hfs_cnode.c */ |
684 | int hfs_is_backingstore (struct vnode *vp, int *val); /* in hfs_cnode.c */ | |
685 | ||
2d21ac55 | 686 | int hfs_vnop_link(struct vnop_link_args *); /* in hfs_link.c */ |
9bccf70c | 687 | |
2d21ac55 | 688 | int hfs_vnop_lookup(struct vnop_lookup_args *); /* in hfs_lookup.c */ |
b4c24cb9 | 689 | |
2d21ac55 | 690 | int hfs_vnop_search(struct vnop_searchfs_args *); /* in hfs_search.c */ |
1c79356b | 691 | |
2d21ac55 A |
692 | int hfs_vnop_read(struct vnop_read_args *); /* in hfs_readwrite.c */ |
693 | int hfs_vnop_write(struct vnop_write_args *); /* in hfs_readwrite.c */ | |
694 | int hfs_vnop_ioctl(struct vnop_ioctl_args *); /* in hfs_readwrite.c */ | |
695 | int hfs_vnop_select(struct vnop_select_args *); /* in hfs_readwrite.c */ | |
696 | int hfs_vnop_strategy(struct vnop_strategy_args *); /* in hfs_readwrite.c */ | |
697 | int hfs_vnop_allocate(struct vnop_allocate_args *); /* in hfs_readwrite.c */ | |
698 | int hfs_vnop_pagein(struct vnop_pagein_args *); /* in hfs_readwrite.c */ | |
699 | int hfs_vnop_pageout(struct vnop_pageout_args *); /* in hfs_readwrite.c */ | |
700 | int hfs_vnop_bwrite(struct vnop_bwrite_args *); /* in hfs_readwrite.c */ | |
701 | int hfs_vnop_blktooff(struct vnop_blktooff_args *); /* in hfs_readwrite.c */ | |
702 | int hfs_vnop_offtoblk(struct vnop_offtoblk_args *); /* in hfs_readwrite.c */ | |
703 | int hfs_vnop_blockmap(struct vnop_blockmap_args *); /* in hfs_readwrite.c */ | |
3e170ce0 | 704 | errno_t hfs_flush_invalid_ranges(vnode_t vp); /* in hfs_readwrite.c */ |
1c79356b | 705 | |
2d21ac55 A |
706 | int hfs_vnop_getxattr(struct vnop_getxattr_args *); /* in hfs_xattr.c */ |
707 | int hfs_vnop_setxattr(struct vnop_setxattr_args *); /* in hfs_xattr.c */ | |
708 | int hfs_vnop_removexattr(struct vnop_removexattr_args *); /* in hfs_xattr.c */ | |
709 | int hfs_vnop_listxattr(struct vnop_listxattr_args *); /* in hfs_xattr.c */ | |
710 | #if NAMEDSTREAMS | |
711 | extern int hfs_vnop_getnamedstream(struct vnop_getnamedstream_args*); | |
712 | extern int hfs_vnop_makenamedstream(struct vnop_makenamedstream_args*); | |
713 | extern int hfs_vnop_removenamedstream(struct vnop_removenamedstream_args*); | |
714 | #endif | |
9bccf70c | 715 | |
1c79356b | 716 | |
2d21ac55 A |
717 | /***************************************************************************** |
718 | Functions from MacOSStubs.c | |
719 | ******************************************************************************/ | |
720 | time_t to_bsd_time(u_int32_t hfs_time); | |
9bccf70c | 721 | |
2d21ac55 | 722 | u_int32_t to_hfs_time(time_t bsd_time); |
1c79356b | 723 | |
1c79356b | 724 | |
2d21ac55 A |
725 | /***************************************************************************** |
726 | Functions from hfs_encodinghint.c | |
727 | ******************************************************************************/ | |
728 | u_int32_t hfs_pickencoding(const u_int16_t *src, int len); | |
9bccf70c | 729 | |
2d21ac55 | 730 | u_int32_t hfs_getencodingbias(void); |
1c79356b | 731 | |
2d21ac55 | 732 | void hfs_setencodingbias(u_int32_t bias); |
b4c24cb9 | 733 | |
2d21ac55 A |
734 | |
735 | /***************************************************************************** | |
736 | Functions from hfs_encodings.c | |
737 | ******************************************************************************/ | |
738 | void hfs_converterinit(void); | |
1c79356b | 739 | |
39236c6e A |
740 | int hfs_relconverter (u_int32_t encoding); |
741 | ||
1c79356b A |
742 | int hfs_getconverter(u_int32_t encoding, hfs_to_unicode_func_t *get_unicode, |
743 | unicode_to_hfs_func_t *get_hfsname); | |
744 | ||
39236c6e | 745 | #if CONFIG_HFS_STD |
2d21ac55 | 746 | int hfs_to_utf8(ExtendedVCB *vcb, const Str31 hfs_str, ByteCount maxDstLen, |
1c79356b A |
747 | ByteCount *actualDstLen, unsigned char* dstStr); |
748 | ||
749 | int utf8_to_hfs(ExtendedVCB *vcb, ByteCount srcLen, const unsigned char* srcStr, | |
750 | Str31 dstStr); | |
751 | ||
2d21ac55 | 752 | int mac_roman_to_utf8(const Str31 hfs_str, ByteCount maxDstLen, ByteCount *actualDstLen, |
1c79356b A |
753 | unsigned char* dstStr); |
754 | ||
755 | int utf8_to_mac_roman(ByteCount srcLen, const unsigned char* srcStr, Str31 dstStr); | |
756 | ||
2d21ac55 | 757 | int mac_roman_to_unicode(const Str31 hfs_str, UniChar *uni_str, u_int32_t maxCharLen, u_int32_t *usedCharLen); |
0b4e3aa0 | 758 | |
2d21ac55 | 759 | int unicode_to_hfs(ExtendedVCB *vcb, ByteCount srcLen, u_int16_t* srcStr, Str31 dstStr, int retry); |
39236c6e | 760 | #endif |
9bccf70c | 761 | |
2d21ac55 A |
762 | /***************************************************************************** |
763 | Functions from hfs_notifications.c | |
764 | ******************************************************************************/ | |
765 | void hfs_generate_volume_notifications(struct hfsmount *hfsmp); | |
9bccf70c A |
766 | |
767 | ||
2d21ac55 A |
768 | /***************************************************************************** |
769 | Functions from hfs_readwrite.c | |
770 | ******************************************************************************/ | |
771 | extern int hfs_relocate(struct vnode *, u_int32_t, kauth_cred_t, struct proc *); | |
9bccf70c | 772 | |
3e170ce0 A |
773 | /* flags for hfs_pin_block_range() and hfs_pin_vnode() */ |
774 | #define HFS_PIN_IT 0x0001 | |
775 | #define HFS_UNPIN_IT 0x0002 | |
776 | #define HFS_TEMP_PIN 0x0004 | |
777 | #define HFS_EVICT_PIN 0x0008 | |
778 | #define HFS_DATALESS_PIN 0x0010 | |
779 | ||
780 | // | |
781 | // pin/un-pin an explicit range of blocks to the "fast" (usually ssd) device | |
782 | // | |
783 | int hfs_pin_block_range(struct hfsmount *hfsmp, int pin_state, uint32_t start_block, uint32_t nblocks, vfs_context_t ctx); | |
784 | ||
785 | // | |
786 | // pin/un-pin all the extents belonging to a vnode. | |
787 | // also, if it is non-null, "num_blocks_pinned" returns the number of blocks pin/unpinned by the function | |
788 | // | |
789 | int hfs_pin_vnode(struct hfsmount *hfsmp, struct vnode *vp, int pin_state, uint32_t *num_blocks_pinned, vfs_context_t ctx); | |
790 | ||
791 | ||
792 | int hfs_pin_overflow_extents (struct hfsmount *hfsmp, uint32_t fileid, uint8_t forktype, uint32_t *pinned); | |
793 | ||
794 | ||
39236c6e | 795 | /* Flags for HFS truncate */ |
fe8ab488 A |
796 | #define HFS_TRUNCATE_SKIPTIMES 0x00000002 /* implied by skipupdate; it is a subset */ |
797 | ||
39236c6e | 798 | |
fe8ab488 | 799 | extern int hfs_truncate(struct vnode *, off_t, int, int, vfs_context_t); |
d7e50217 | 800 | |
6d2010ae A |
801 | extern int hfs_release_storage (struct hfsmount *hfsmp, struct filefork *datafork, |
802 | struct filefork *rsrcfork, u_int32_t fileid); | |
803 | ||
804 | extern int hfs_prepare_release_storage (struct hfsmount *hfsmp, struct vnode *vp); | |
805 | ||
2d21ac55 | 806 | extern int hfs_bmap(struct vnode *, daddr_t, struct vnode **, daddr64_t *, unsigned int *); |
55e303ae | 807 | |
fe8ab488 A |
808 | extern errno_t hfs_ubc_setsize(vnode_t vp, off_t len, bool have_cnode_lock); |
809 | ||
810 | ||
811 | /***************************************************************************** | |
812 | Functions from hfs_resize.c | |
813 | ******************************************************************************/ | |
814 | int hfs_extendfs(struct hfsmount *hfsmp, u_int64_t newsize, vfs_context_t context); | |
815 | int hfs_truncatefs(struct hfsmount *hfsmp, u_int64_t newsize, vfs_context_t context); | |
91447636 | 816 | |
91447636 | 817 | |
2d21ac55 A |
818 | /***************************************************************************** |
819 | Functions from hfs_vfsops.c | |
820 | ******************************************************************************/ | |
821 | int hfs_mountroot(mount_t mp, vnode_t rvp, vfs_context_t context); | |
91447636 | 822 | |
2d21ac55 A |
823 | /* used as a callback by the journaling code */ |
824 | extern void hfs_sync_metadata(void *arg); | |
91447636 | 825 | |
6d2010ae | 826 | extern int hfs_vget(struct hfsmount *, cnid_t, struct vnode **, int, int); |
91447636 | 827 | |
2d21ac55 | 828 | extern void hfs_setencodingbits(struct hfsmount *hfsmp, u_int32_t encoding); |
91447636 | 829 | |
2d21ac55 A |
830 | enum volop {VOL_UPDATE, VOL_MKDIR, VOL_RMDIR, VOL_MKFILE, VOL_RMFILE}; |
831 | extern int hfs_volupdate(struct hfsmount *hfsmp, enum volop op, int inroot); | |
832 | ||
3e170ce0 A |
833 | enum { |
834 | HFS_FVH_WAIT = 0x0001, | |
835 | HFS_FVH_WRITE_ALT = 0x0002, | |
836 | HFS_FVH_FLUSH_IF_DIRTY = 0x0004, | |
837 | }; | |
838 | typedef uint32_t hfs_flush_volume_header_options_t; | |
839 | int hfs_flushvolumeheader(struct hfsmount *hfsmp, hfs_flush_volume_header_options_t); | |
91447636 A |
840 | |
841 | extern int hfs_extendfs(struct hfsmount *, u_int64_t, vfs_context_t); | |
842 | extern int hfs_truncatefs(struct hfsmount *, u_int64_t, vfs_context_t); | |
0c530ab8 | 843 | extern int hfs_resize_progress(struct hfsmount *, u_int32_t *); |
91447636 | 844 | |
2d21ac55 A |
845 | /* If a runtime corruption is detected, mark the volume inconsistent |
846 | * bit in the volume attributes. | |
847 | */ | |
fe8ab488 A |
848 | |
849 | typedef enum { | |
850 | HFS_INCONSISTENCY_DETECTED, | |
851 | ||
852 | // Used when unable to rollback an operation that failed | |
853 | HFS_ROLLBACK_FAILED, | |
854 | ||
855 | // Used when the latter part of an operation failed, but we chose not to roll back | |
856 | HFS_OP_INCOMPLETE, | |
857 | ||
858 | // Used when someone told us to force an fsck on next mount | |
859 | HFS_FSCK_FORCED, | |
860 | } hfs_inconsistency_reason_t; | |
861 | ||
862 | void hfs_mark_inconsistent(struct hfsmount *hfsmp, | |
863 | hfs_inconsistency_reason_t reason); | |
2d21ac55 | 864 | |
39236c6e A |
865 | void hfs_scan_blocks (struct hfsmount *hfsmp); |
866 | ||
2d21ac55 A |
867 | /***************************************************************************** |
868 | Functions from hfs_vfsutils.c | |
869 | ******************************************************************************/ | |
b0d623f7 A |
870 | u_int32_t BestBlockSizeFit(u_int32_t allocationBlockSize, |
871 | u_int32_t blockSizeLimit, | |
872 | u_int32_t baseMultiple); | |
2d21ac55 | 873 | |
39236c6e | 874 | #if CONFIG_HFS_STD |
2d21ac55 A |
875 | OSErr hfs_MountHFSVolume(struct hfsmount *hfsmp, HFSMasterDirectoryBlock *mdb, |
876 | struct proc *p); | |
39236c6e | 877 | #endif |
2d21ac55 A |
878 | OSErr hfs_MountHFSPlusVolume(struct hfsmount *hfsmp, HFSPlusVolumeHeader *vhp, |
879 | off_t embeddedOffset, u_int64_t disksize, struct proc *p, void *args, kauth_cred_t cred); | |
880 | ||
c18c124e A |
881 | OSErr hfs_ValidateHFSPlusVolumeHeader(struct hfsmount *hfsmp, HFSPlusVolumeHeader *vhp); |
882 | ||
2d21ac55 A |
883 | extern int hfsUnmount(struct hfsmount *hfsmp, struct proc *p); |
884 | ||
fe8ab488 | 885 | extern bool overflow_extents(struct filefork *fp); |
2d21ac55 A |
886 | |
887 | extern int hfs_owner_rights(struct hfsmount *hfsmp, uid_t cnode_uid, kauth_cred_t cred, | |
888 | struct proc *p, int invokesuperuserstatus); | |
91447636 | 889 | |
6d2010ae A |
890 | extern int check_for_tracked_file(struct vnode *vp, time_t ctime, uint64_t op_type, void *arg); |
891 | extern int check_for_dataless_file(struct vnode *vp, uint64_t op_type); | |
22ba694c | 892 | extern int hfs_generate_document_id(struct hfsmount *hfsmp, uint32_t *docid); |
3e170ce0 | 893 | extern void hfs_pin_fs_metadata(struct hfsmount *hfsmp); |
22ba694c | 894 | |
fe8ab488 A |
895 | /* Return information about number of metadata blocks for volume */ |
896 | extern int hfs_getinfo_metadata_blocks(struct hfsmount *hfsmp, struct hfsinfo_metadata *hinfo); | |
6d2010ae A |
897 | |
898 | /* | |
899 | * Journal lock function prototypes | |
900 | */ | |
39236c6e | 901 | int hfs_lock_global (struct hfsmount *hfsmp, enum hfs_locktype locktype); |
6d2010ae A |
902 | void hfs_unlock_global (struct hfsmount *hfsmp); |
903 | ||
39236c6e A |
904 | /* HFS mount lock/unlock prototypes */ |
905 | void hfs_lock_mount (struct hfsmount *hfsmp); | |
906 | void hfs_unlock_mount (struct hfsmount *hfsmp); | |
907 | ||
91447636 A |
908 | |
909 | /* HFS System file locking */ | |
910 | #define SFL_CATALOG 0x0001 | |
911 | #define SFL_EXTENTS 0x0002 | |
912 | #define SFL_BITMAP 0x0004 | |
913 | #define SFL_ATTRIBUTE 0x0008 | |
2d21ac55 | 914 | #define SFL_STARTUP 0x0010 |
fe8ab488 A |
915 | #define SFL_VM_PRIV 0x0020 |
916 | #define SFL_VALIDMASK (SFL_CATALOG | SFL_EXTENTS | SFL_BITMAP | SFL_ATTRIBUTE | SFL_STARTUP | SFL_VM_PRIV) | |
91447636 | 917 | |
b0d623f7 | 918 | extern u_int32_t GetFileInfo(ExtendedVCB *vcb, u_int32_t dirid, const char *name, |
2d21ac55 A |
919 | struct cat_attr *fattr, struct cat_fork *forkinfo); |
920 | ||
921 | extern void hfs_remove_orphans(struct hfsmount *); | |
922 | ||
923 | u_int32_t GetLogicalBlockSize(struct vnode *vp); | |
924 | ||
925 | extern u_int32_t hfs_freeblks(struct hfsmount * hfsmp, int wantreserve); | |
926 | ||
927 | short MacToVFSError(OSErr err); | |
928 | ||
6d2010ae | 929 | void hfs_metadatazone_init(struct hfsmount *hfsmp, int disable); |
0b4c1975 | 930 | |
2d21ac55 A |
931 | /* HFS directory hint functions. */ |
932 | extern directoryhint_t * hfs_getdirhint(struct cnode *, int, int); | |
933 | extern void hfs_reldirhint(struct cnode *, directoryhint_t *); | |
934 | extern void hfs_reldirhints(struct cnode *, int); | |
935 | extern void hfs_insertdirhint(struct cnode *, directoryhint_t *); | |
936 | ||
937 | extern int hfs_namecmp(const u_int8_t *str1, size_t len1, const u_int8_t *str2, size_t len2); | |
938 | ||
939 | extern int hfs_early_journal_init(struct hfsmount *hfsmp, HFSPlusVolumeHeader *vhp, | |
940 | void *_args, off_t embeddedOffset, daddr64_t mdb_offset, | |
941 | HFSMasterDirectoryBlock *mdbp, kauth_cred_t cred); | |
942 | ||
943 | extern int hfs_virtualmetafile(struct cnode *); | |
944 | ||
945 | extern int hfs_start_transaction(struct hfsmount *hfsmp); | |
946 | extern int hfs_end_transaction(struct hfsmount *hfsmp); | |
fe8ab488 A |
947 | extern void hfs_journal_lock(struct hfsmount *hfsmp); |
948 | extern void hfs_journal_unlock(struct hfsmount *hfsmp); | |
22ba694c A |
949 | extern void hfs_syncer_lock(struct hfsmount *hfsmp); |
950 | extern void hfs_syncer_unlock(struct hfsmount *hfsmp); | |
951 | extern void hfs_syncer_wait(struct hfsmount *hfsmp); | |
952 | extern void hfs_syncer_wakeup(struct hfsmount *hfsmp); | |
953 | extern void hfs_syncer_queue(thread_call_t syncer); | |
e2fac8b1 | 954 | extern void hfs_sync_ejectable(struct hfsmount *hfsmp); |
2d21ac55 | 955 | |
3e170ce0 A |
956 | typedef enum hfs_flush_mode { |
957 | HFS_FLUSH_JOURNAL, // Flush journal | |
958 | HFS_FLUSH_JOURNAL_META, // Flush journal and metadata blocks | |
959 | HFS_FLUSH_FULL, // Flush journal and does a cache flush | |
960 | HFS_FLUSH_CACHE, // Flush track cache to media | |
961 | HFS_FLUSH_BARRIER, // Barrier-only flush to ensure write order | |
962 | HFS_FLUSH_JOURNAL_BARRIER // Flush journal with barrier | |
963 | } hfs_flush_mode_t; | |
964 | ||
965 | extern errno_t hfs_flush(struct hfsmount *hfsmp, hfs_flush_mode_t mode); | |
966 | ||
6d2010ae A |
967 | extern void hfs_trim_callback(void *arg, uint32_t extent_count, const dk_extent_t *extents); |
968 | ||
b0d623f7 A |
969 | /* Erase unused Catalog nodes due to <rdar://problem/6947811>. */ |
970 | extern int hfs_erase_unused_nodes(struct hfsmount *hfsmp); | |
971 | ||
22ba694c A |
972 | extern uint64_t hfs_usecs_to_deadline(uint64_t usecs); |
973 | ||
fe8ab488 A |
974 | extern int hfs_freeze(struct hfsmount *hfsmp); |
975 | extern int hfs_thaw(struct hfsmount *hfsmp, const struct proc *process); | |
976 | ||
2d21ac55 A |
977 | |
978 | /***************************************************************************** | |
979 | Functions from hfs_vnops.c | |
980 | ******************************************************************************/ | |
981 | int hfs_write_access(struct vnode *vp, kauth_cred_t cred, struct proc *p, Boolean considerFlags); | |
982 | ||
983 | int hfs_chmod(struct vnode *vp, int mode, kauth_cred_t cred, struct proc *p); | |
984 | ||
985 | int hfs_chown(struct vnode *vp, uid_t uid, gid_t gid, kauth_cred_t cred, struct proc *p); | |
986 | ||
987 | #define kMaxSecsForFsync 5 | |
988 | #define HFS_SYNCTRANS 1 | |
989 | extern int hfs_btsync(struct vnode *vp, int sync_transaction); | |
990 | ||
991 | extern void replace_desc(struct cnode *cp, struct cat_desc *cdp); | |
992 | ||
993 | extern int hfs_vgetrsrc(struct hfsmount *hfsmp, struct vnode *vp, | |
fe8ab488 | 994 | struct vnode **rvpp); |
2d21ac55 | 995 | |
3e170ce0 A |
996 | typedef enum { |
997 | // Push all modifications to disk (including minor ones) | |
998 | HFS_UPDATE_FORCE = 0x01, | |
999 | } hfs_update_options_t; | |
1000 | ||
1001 | extern int hfs_update(struct vnode *, int options); | |
1002 | ||
1003 | typedef enum hfs_sync_mode { | |
1004 | HFS_FSYNC, | |
1005 | HFS_FSYNC_FULL, | |
1006 | HFS_FSYNC_BARRIER | |
1007 | } hfs_fsync_mode_t; | |
1008 | ||
1009 | extern int hfs_fsync(struct vnode *, int, hfs_fsync_mode_t, struct proc *); | |
2d21ac55 | 1010 | |
3e170ce0 A |
1011 | const struct cat_fork * |
1012 | hfs_prepare_fork_for_update(filefork_t *ff, | |
1013 | const struct cat_fork *cf, | |
1014 | struct cat_fork *cf_buf, | |
1015 | uint32_t block_size); | |
2d21ac55 A |
1016 | |
1017 | /***************************************************************************** | |
1018 | Functions from hfs_xattr.c | |
1019 | ******************************************************************************/ | |
6d2010ae | 1020 | |
39236c6e A |
1021 | /* |
1022 | * Maximum extended attribute size supported for all extended attributes except | |
6d2010ae A |
1023 | * resource fork and finder info. |
1024 | */ | |
39236c6e | 1025 | #define HFS_XATTR_MAXSIZE INT32_MAX |
6d2010ae A |
1026 | |
1027 | /* Number of bits used to represent maximum extended attribute size */ | |
39236c6e | 1028 | #define HFS_XATTR_SIZE_BITS 31 |
6d2010ae | 1029 | |
2d21ac55 A |
1030 | int hfs_attrkeycompare(HFSPlusAttrKey *searchKey, HFSPlusAttrKey *trialKey); |
1031 | int hfs_buildattrkey(u_int32_t fileID, const char *attrname, HFSPlusAttrKey *key); | |
1032 | void hfs_xattr_init(struct hfsmount * hfsmp); | |
1033 | int file_attribute_exist(struct hfsmount *hfsmp, uint32_t fileID); | |
6d2010ae | 1034 | int init_attrdata_vnode(struct hfsmount *hfsmp); |
fe8ab488 A |
1035 | int hfs_xattr_read(vnode_t vp, const char *name, void *data, size_t *size); |
1036 | int hfs_getxattr_internal(cnode_t *, struct vnop_getxattr_args *, | |
1037 | struct hfsmount *, u_int32_t); | |
1038 | int hfs_xattr_write(vnode_t vp, const char *name, const void *data, size_t size); | |
1039 | int hfs_setxattr_internal(struct cnode *, const void *, size_t, | |
1040 | struct vnop_setxattr_args *, struct hfsmount *, u_int32_t); | |
3e170ce0 A |
1041 | extern int hfs_removeallattr(struct hfsmount *hfsmp, u_int32_t fileid, |
1042 | bool *open_transaction); | |
04b8595b A |
1043 | extern int hfs_set_volxattr(struct hfsmount *hfsmp, unsigned int xattrtype, int state); |
1044 | ||
2d21ac55 A |
1045 | |
1046 | ||
1047 | /***************************************************************************** | |
1048 | Functions from hfs_link.c | |
1049 | ******************************************************************************/ | |
1050 | ||
1051 | extern int hfs_unlink(struct hfsmount *hfsmp, struct vnode *dvp, struct vnode *vp, | |
1052 | struct componentname *cnp, int skip_reserve); | |
6d2010ae | 1053 | extern int hfs_lookup_siblinglinks(struct hfsmount *hfsmp, cnid_t linkfileid, |
2d21ac55 | 1054 | cnid_t *prevlinkid, cnid_t *nextlinkid); |
39236c6e A |
1055 | extern int hfs_lookup_lastlink(struct hfsmount *hfsmp, cnid_t linkfileid, |
1056 | cnid_t *nextlinkid, struct cat_desc *cdesc); | |
2d21ac55 A |
1057 | extern void hfs_privatedir_init(struct hfsmount *, enum privdirtype); |
1058 | ||
1059 | extern void hfs_savelinkorigin(cnode_t *cp, cnid_t parentcnid); | |
1060 | extern void hfs_relorigins(struct cnode *cp); | |
1061 | extern void hfs_relorigin(struct cnode *cp, cnid_t parentcnid); | |
1062 | extern int hfs_haslinkorigin(cnode_t *cp); | |
3e170ce0 | 1063 | extern cnid_t hfs_currentparent(cnode_t *cp, bool have_lock); |
2d21ac55 | 1064 | extern cnid_t hfs_currentcnid(cnode_t *cp); |
3e170ce0 | 1065 | errno_t hfs_first_link(hfsmount_t *hfsmp, cnode_t *cp, cnid_t *link_id); |
2d21ac55 A |
1066 | |
1067 | ||
04b8595b A |
1068 | /***************************************************************************** |
1069 | Functions from VolumeAllocation.c | |
1070 | ******************************************************************************/ | |
3e170ce0 | 1071 | extern int hfs_isallocated(struct hfsmount *hfsmp, u_int32_t startingBlock, u_int32_t numBlocks); |
04b8595b | 1072 | |
3e170ce0 A |
1073 | extern int hfs_count_allocated(struct hfsmount *hfsmp, u_int32_t startBlock, |
1074 | u_int32_t numBlocks, u_int32_t *alloc_count); | |
04b8595b A |
1075 | |
1076 | extern int hfs_isrbtree_active (struct hfsmount *hfsmp); | |
1077 | ||
1078 | /***************************************************************************** | |
1079 | Functions from hfs_fsinfo.c | |
1080 | ******************************************************************************/ | |
1081 | extern errno_t hfs_get_fsinfo(struct hfsmount *hfsmp, void *a_data); | |
1082 | extern void hfs_fsinfo_data_add(struct hfs_fsinfo_data *fsinfo, uint64_t entry); | |
1083 | ||
9bccf70c A |
1084 | #endif /* __APPLE_API_PRIVATE */ |
1085 | #endif /* KERNEL */ | |
1c79356b | 1086 | #endif /* __HFS__ */ |