2 * Copyright (c) 2008 Apple Inc. All rights reserved.
4 * @APPLE_LICENSE_HEADER_START@
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. Please obtain a copy of the License at
10 * http://www.opensource.apple.com/apsl/ and read it before using this
13 * The Original Code and all software distributed under the License are
14 * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
15 * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
16 * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
17 * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT.
18 * Please see the License for the specific language governing rights and
19 * limitations under the License.
21 * @APPLE_LICENSE_HEADER_END@
27 #include "ExtentManager.h"
30 ExtentManager::Init(uint32_t theBlockSize
, uint32_t theNativeBlockSize
, off_t theTotalBytes
)
32 blockSize
= theBlockSize
;
33 nativeBlockSize
= theNativeBlockSize
;
34 totalBytes
= theTotalBytes
;
35 totalBlocks
= howmany(totalBytes
, blockSize
);
37 // add sentry empty extents at both sides so empty partition doesn't need to be handled specially
38 AddBlockRangeExtent(0, 0);
39 AddBlockRangeExtent(totalBlocks
, 0);
43 ExtentManager::MergeExtent(const ExtentInfo
&a
, const ExtentInfo
&b
, ExtentInfo
*c
)
45 // merge ext into *curIt
46 c
->blockAddr
= min(a
.blockAddr
, b
.blockAddr
);
47 c
->numBlocks
= max(a
.blockAddr
+ a
.numBlocks
, b
.blockAddr
+ b
.numBlocks
) - c
->blockAddr
;
51 ExtentManager::AddBlockRangeExtent(off_t blockAddr
, off_t numBlocks
)
53 struct ExtentInfo ext
, newExt
;
54 ListExtIt curIt
, newIt
;
57 // make the range a valid range
58 if ((blockAddr
> totalBlocks
) || (blockAddr
+ numBlocks
< 0)) { // totally out of range, do nothing
62 numBlocks
= blockAddr
+ numBlocks
;
65 if (blockAddr
+ numBlocks
> totalBlocks
) {
66 numBlocks
= totalBlocks
- blockAddr
;
69 ext
.blockAddr
= blockAddr
;
70 ext
.numBlocks
= numBlocks
;
72 for (curIt
= extentList
.begin(); curIt
!= extentList
.end(); curIt
++) {
73 if (BeforeExtent(ext
, *curIt
))
75 if (!BeforeExtent(*curIt
, ext
)) { // overlapped extents
76 MergeExtent(ext
, *curIt
, &newExt
);
83 // insert ext before curIt
85 curIt
= extentList
.insert(curIt
, ext
); // throws bad_alloc when out of memory
90 curIt
= extentList
.begin();
91 while (curIt
!= extentList
.end()) {
92 if (curIt
== newIt
|| BeforeExtent(*curIt
, *newIt
)) { // curIt is before newIt
96 if (BeforeExtent(*newIt
, *curIt
)) { // curIt is after newIt now, we are done
99 // merge the two extents
100 MergeExtent(*curIt
, *newIt
, &newExt
);
102 curIt
= extentList
.erase(curIt
);
104 // printf("After %s(%lld, %lld)\n", __func__, blockAddr, numBlocks); DebugPrint();
105 } // ExtentManager::AddBlockRangeExtent
108 ExtentManager::RemoveBlockRangeExtent(off_t blockAddr
, off_t numBlocks
)
110 struct ExtentInfo ext
, newExt
;
113 ext
.blockAddr
= blockAddr
;
114 ext
.numBlocks
= numBlocks
;
116 curIt
= extentList
.begin();
117 while (curIt
!= extentList
.end()) {
118 if (BeforeExtent(*curIt
, ext
)) {
122 if (BeforeExtent(ext
, *curIt
)) // we are done
124 // overlapped extents
125 if (curIt
->blockAddr
>= ext
.blockAddr
&&
126 curIt
->blockAddr
+ curIt
->numBlocks
<= ext
.blockAddr
+ ext
.numBlocks
) {
127 // *curIt is totally within ext, remove curIt
128 curIt
= extentList
.erase(curIt
);
129 } else if (curIt
->blockAddr
< ext
.blockAddr
&&
130 curIt
->blockAddr
+ curIt
->numBlocks
> ext
.blockAddr
+ ext
.numBlocks
) {
131 // ext is totally within *curIt, split ext into two
132 newExt
.blockAddr
= ext
.blockAddr
+ ext
.numBlocks
;
133 newExt
.numBlocks
= curIt
->blockAddr
+ curIt
->numBlocks
- newExt
.blockAddr
;
134 curIt
->numBlocks
= ext
.blockAddr
- curIt
->blockAddr
;
136 extentList
.insert(curIt
, newExt
); // throws bad_alloc when out of memory
138 } else { // remove part of ext
139 if (curIt
->blockAddr
>= ext
.blockAddr
) { // remove the former part of *curIt
140 assert(curIt
->blockAddr
+ curIt
->numBlocks
> newExt
.blockAddr
);
141 newExt
.blockAddr
= ext
.blockAddr
+ ext
.numBlocks
;
142 newExt
.numBlocks
= curIt
->blockAddr
+ curIt
->numBlocks
- newExt
.blockAddr
;
144 } else { // remove the latter part of *curIt
145 curIt
->numBlocks
= ext
.blockAddr
- curIt
->blockAddr
;
150 //printf("After %s(%lld, %lld)\n", __func__, blockAddr, numBlocks); DebugPrint();
154 ExtentManager::AddByteRangeExtent(off_t byteAddr
, off_t numBytes
)
156 off_t blockAddr
= byteAddr
/ blockSize
;
157 off_t blockAddrOfLastByte
= (byteAddr
+ numBytes
- 1) / blockSize
;
158 off_t numBlocks
= blockAddrOfLastByte
- blockAddr
+ 1;
159 AddBlockRangeExtent(blockAddr
, numBlocks
);
163 ExtentManager::DebugPrint()
167 for (it
= extentList
.begin(); it
!= extentList
.end(); it
++) {
168 printf("[%lld, %lld] ", it
->blockAddr
, it
->numBlocks
);