]> git.saurik.com Git - apple/xnu.git/blame - bsd/hfs/hfscommon/Misc/FileExtentMapping.c
xnu-3247.1.106.tar.gz
[apple/xnu.git] / bsd / hfs / hfscommon / Misc / FileExtentMapping.c
CommitLineData
1c79356b 1/*
3e170ce0 2 * Copyright (c) 2000-2014 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
30#include "../../hfs.h"
31#include "../../hfs_format.h"
32#include "../../hfs_endian.h"
33
34#include "../headers/FileMgrInternal.h"
35#include "../headers/BTreesInternal.h"
1c79356b 36
1c79356b 37#include <sys/malloc.h>
3e170ce0 38#include <sys/vnode_internal.h>
1c79356b
A
39
40/*
41============================================================
42Public (Exported) Routines:
43============================================================
1c79356b
A
44
45 ExtendFileC Allocate more space to a given file.
46
47 CompareExtentKeys
48 Compare two extents file keys (a search key and a trial
49 key). Used by the BTree manager when searching for,
50 adding, or deleting keys in the extents file of an HFS
51 volume.
52
53 CompareExtentKeysPlus
54 Compare two extents file keys (a search key and a trial
55 key). Used by the BTree manager when searching for,
56 adding, or deleting keys in the extents file of an HFS+
57 volume.
58
59 MapFileBlockC Convert (map) an offset within a given file into a
60 physical disk address.
61
62 TruncateFileC Truncates the disk space allocated to a file. The file
63 space is truncated to a specified new physical EOF, rounded
64 up to the next allocation block boundry. There is an option
65 to truncate to the end of the extent containing the new EOF.
66
67 FlushExtentFile
68 Flush the extents file for a given volume.
69
3e170ce0
A
70 SearchExtentFile
71 Search the FCB and extents file for an extent record that
72 contains a given file position (in bytes).
1c79356b 73
1c79356b
A
74
75============================================================
76Internal Routines:
77============================================================
78 FindExtentRecord
79 Search the extents BTree for a particular extent record.
1c79356b
A
80 SearchExtentRecord
81 Search a given extent record to see if it contains a given
82 file position (in bytes). Used by SearchExtentFile.
83 ReleaseExtents
84 Deallocate all allocation blocks in all extents of an extent
85 data record.
86 TruncateExtents
87 Deallocate blocks and delete extent records for all allocation
88 blocks beyond a certain point in a file. The starting point
89 must be the first file allocation block for some extent record
90 for the file.
91 DeallocateFork
92 Deallocate all allocation blocks belonging to a given fork.
93 UpdateExtentRecord
94 If the extent record came from the extents file, write out
95 the updated record; otherwise, copy the updated record into
96 the FCB resident extent record. If the record has no extents,
97 and was in the extents file, then delete the record instead.
98*/
99
fe8ab488 100#if CONFIG_HFS_STD
2d21ac55 101static const int64_t kTwoGigabytes = 0x80000000LL;
fe8ab488 102#endif
9bccf70c 103
1c79356b
A
104enum
105{
1c79356b
A
106 kDataForkType = 0,
107 kResourceForkType = 0xFF,
108
d52fe63f 109 kPreviousRecord = -1
1c79356b
A
110};
111
1c79356b 112
39236c6e 113#if CONFIG_HFS_STD
55e303ae 114static OSErr HFSPlusToHFSExtents(
1c79356b
A
115 const HFSPlusExtentRecord oldExtents,
116 HFSExtentRecord newExtents);
39236c6e 117#endif
1c79356b 118
55e303ae 119static OSErr FindExtentRecord(
1c79356b 120 const ExtendedVCB *vcb,
2d21ac55
A
121 u_int8_t forkType,
122 u_int32_t fileID,
123 u_int32_t startBlock,
1c79356b
A
124 Boolean allowPrevious,
125 HFSPlusExtentKey *foundKey,
126 HFSPlusExtentRecord foundData,
2d21ac55 127 u_int32_t *foundHint);
1c79356b 128
55e303ae 129static OSErr DeleteExtentRecord(
1c79356b 130 const ExtendedVCB *vcb,
2d21ac55
A
131 u_int8_t forkType,
132 u_int32_t fileID,
133 u_int32_t startBlock);
1c79356b
A
134
135static OSErr CreateExtentRecord(
91447636 136 ExtendedVCB *vcb,
1c79356b
A
137 HFSPlusExtentKey *key,
138 HFSPlusExtentRecord extents,
2d21ac55 139 u_int32_t *hint);
1c79356b
A
140
141
55e303ae 142static OSErr GetFCBExtentRecord(
1c79356b
A
143 const FCB *fcb,
144 HFSPlusExtentRecord extents);
145
1c79356b 146static OSErr SearchExtentRecord(
91447636 147 ExtendedVCB *vcb,
2d21ac55 148 u_int32_t searchFABN,
1c79356b 149 const HFSPlusExtentRecord extentData,
2d21ac55
A
150 u_int32_t extentDataStartFABN,
151 u_int32_t *foundExtentDataOffset,
152 u_int32_t *endingFABNPlusOne,
1c79356b
A
153 Boolean *noMoreExtents);
154
155static OSErr ReleaseExtents(
156 ExtendedVCB *vcb,
157 const HFSPlusExtentRecord extentRecord,
2d21ac55 158 u_int32_t *numReleasedAllocationBlocks,
1c79356b
A
159 Boolean *releasedLastExtent);
160
161static OSErr DeallocateFork(
162 ExtendedVCB *vcb,
163 HFSCatalogNodeID fileID,
2d21ac55 164 u_int8_t forkType,
1c79356b
A
165 HFSPlusExtentRecord catalogExtents,
166 Boolean * recordDeleted);
167
168static OSErr TruncateExtents(
169 ExtendedVCB *vcb,
2d21ac55
A
170 u_int8_t forkType,
171 u_int32_t fileID,
172 u_int32_t startBlock,
1c79356b
A
173 Boolean * recordDeleted);
174
175static OSErr UpdateExtentRecord (
91447636 176 ExtendedVCB *vcb,
6d2010ae
A
177 FCB *fcb,
178 int deleted,
1c79356b
A
179 const HFSPlusExtentKey *extentFileKey,
180 const HFSPlusExtentRecord extentData,
2d21ac55 181 u_int32_t extentBTreeHint);
1c79356b 182
1c79356b
A
183static Boolean ExtentsAreIntegral(
184 const HFSPlusExtentRecord extentRecord,
2d21ac55
A
185 u_int32_t mask,
186 u_int32_t *blocksChecked,
1c79356b
A
187 Boolean *checkedLastExtent);
188
189//_________________________________________________________________________________
190//
191// Routine: FindExtentRecord
192//
193// Purpose: Search the extents BTree for an extent record matching the given
194// FileID, fork, and starting file allocation block number.
195//
196// Inputs:
197// vcb Volume to search
198// forkType 0 = data fork, -1 = resource fork
199// fileID File's FileID (CatalogNodeID)
200// startBlock Starting file allocation block number
201// allowPrevious If the desired record isn't found and this flag is set,
202// then see if the previous record belongs to the same fork.
203// If so, then return it.
204//
205// Outputs:
206// foundKey The key data for the record actually found
207// foundData The extent record actually found (NOTE: on an HFS volume, the
208// fourth entry will be zeroes.
209// foundHint The BTree hint to find the node again
210//_________________________________________________________________________________
55e303ae 211static OSErr FindExtentRecord(
1c79356b 212 const ExtendedVCB *vcb,
2d21ac55
A
213 u_int8_t forkType,
214 u_int32_t fileID,
215 u_int32_t startBlock,
1c79356b
A
216 Boolean allowPrevious,
217 HFSPlusExtentKey *foundKey,
218 HFSPlusExtentRecord foundData,
2d21ac55 219 u_int32_t *foundHint)
1c79356b
A
220{
221 FCB * fcb;
316670eb 222 struct BTreeIterator *btIterator = NULL;
1c79356b
A
223 FSBufferDescriptor btRecord;
224 OSErr err;
2d21ac55 225 u_int16_t btRecordSize;
1c79356b
A
226
227 err = noErr;
55e303ae
A
228 if (foundHint)
229 *foundHint = 0;
1c79356b 230 fcb = GetFileControlBlock(vcb->extentsRefNum);
316670eb
A
231
232 MALLOC (btIterator, struct BTreeIterator*, sizeof(struct BTreeIterator), M_TEMP, M_WAITOK);
233 if (btIterator == NULL) {
234 return memFullErr; // translates to ENOMEM
235 }
236 bzero(btIterator, sizeof(*btIterator));
1c79356b 237
39236c6e
A
238 /* HFS Plus / HFSX */
239 if (vcb->vcbSigWord != kHFSSigWord) {
240 HFSPlusExtentKey * extentKeyPtr;
241 HFSPlusExtentRecord extentData;
1c79356b 242
39236c6e
A
243 extentKeyPtr = (HFSPlusExtentKey*) &btIterator->key;
244 extentKeyPtr->keyLength = kHFSPlusExtentKeyMaximumLength;
245 extentKeyPtr->forkType = forkType;
246 extentKeyPtr->pad = 0;
247 extentKeyPtr->fileID = fileID;
1c79356b
A
248 extentKeyPtr->startBlock = startBlock;
249
250 btRecord.bufferAddress = &extentData;
39236c6e 251 btRecord.itemSize = sizeof(HFSPlusExtentRecord);
1c79356b
A
252 btRecord.itemCount = 1;
253
316670eb 254 err = BTSearchRecord(fcb, btIterator, &btRecord, &btRecordSize, btIterator);
1c79356b
A
255
256 if (err == btNotFound && allowPrevious) {
316670eb 257 err = BTIterateRecord(fcb, kBTreePrevRecord, btIterator, &btRecord, &btRecordSize);
1c79356b
A
258
259 // A previous record may not exist, so just return btNotFound (like we would if
260 // it was for the wrong file/fork).
261