00053 :
00054
00055 Grows either
the Stable or
Volatile storage of a hive by adding
00056 a
new bin.
Bin will be allocated space in
Stable store (e.g. file)
00057 if Type == Stable. Memory image will be allocated and initialized.
00058 Map will be grown and filled in to describe the new bin.
00059
00060 Arguments:
00061
00062 Hive - supplies a pointer to the hive control structure for the
00063 hive of interest
00064
00065 NewSize - size of the object caller wishes to put in the hive. New
00066 bin will be at least large enough to hold this.
00067
00068 Type - Stable or Volatile
00069
00070 Return Value:
00071
00072 Pointer to the new BIN if we succeeded, NULL if we failed.
00073
00074 --*/
00075 {
00076 BOOLEAN UseForIo;
00077
PHBIN NewBin;
00078 ULONG OldLength;
00079 ULONG NewLength;
00080 ULONG OldMap;
00081 ULONG NewMap;
00082 ULONG OldTable;
00083 ULONG NewTable;
00084
PHMAP_DIRECTORY Dir;
00085
PHMAP_TABLE newt;
00086
PHMAP_ENTRY Me;
00087
PHCELL t;
00088 ULONG i;
00089 ULONG j;
00090 PULONG NewVector;
00091 PLIST_ENTRY Entry;
00092
PFREE_HBIN FreeBin;
00093 ULONG TotalDiscardedSize;
00094
00095
00096
CMLOG(CML_FLOW, CMS_HIVE) {
00097 KdPrint((
"HvpAddBin:\n"));
00098 KdPrint((
"\tHive=%08lx NewSize=%08lx\n",Hive,NewSize));
00099 }
00100
00101
00102
00103
00104
00105 NewSize +=
sizeof(
HBIN);
00106
if ((NewSize <
HCELL_BIG_ROUND) &&
00107 ((NewSize %
HBLOCK_SIZE) >
HBIN_THRESHOLD)) {
00108 NewSize +=
HBLOCK_SIZE;
00109 }
00110
00111
00112
00113
00114
00115
00116 NewSize =
ROUND_UP(NewSize, ((HBLOCK_SIZE >= PAGE_SIZE) ? HBLOCK_SIZE : PAGE_SIZE));
00117
00118
00119
00120
00121 TotalDiscardedSize = 0;
00122
00123 Retry:
00124
00125 Entry =
Hive->Storage[Type].FreeBins.Flink;
00126
while (Entry != &
Hive->Storage[Type].FreeBins) {
00127 FreeBin = CONTAINING_RECORD(Entry,
00128
FREE_HBIN,
00129 ListEntry);
00130 TotalDiscardedSize += FreeBin->
Size;
00131
if (FreeBin->
Size >= NewSize) {
00132
00133
if (!
HvMarkDirty(Hive,
00134 FreeBin->
FileOffset + (Type * HCELL_TYPE_MASK),
00135 FreeBin->
Size)) {
00136
goto ErrorExit1;
00137 }
00138 NewSize = FreeBin->
Size;
00139
ASSERT_LISTENTRY(&FreeBin->
ListEntry);
00140 RemoveEntryList(&FreeBin->
ListEntry);
00141
if (FreeBin->
Flags &
FREE_HBIN_DISCARDABLE) {
00142
00143
00144
00145
00146
for (i=0;i<NewSize;i+=
HBLOCK_SIZE) {
00147 Me =
HvpGetCellMap(Hive, FreeBin->
FileOffset+i+(Type*HCELL_TYPE_MASK));
00148
VALIDATE_CELL_MAP(__LINE__,Me,Hive,FreeBin->
FileOffset+i+(Type*HCELL_TYPE_MASK));
00149 Me->
BlockAddress = (Me->
BinAddress &
HMAP_BASE)+i;
00150 Me->
BinAddress &= ~
HMAP_DISCARDABLE;
00151 }
00152 (
Hive->
Free)(FreeBin,
sizeof(
FREE_HBIN));
00153
return((
PHBIN)(Me->
BinAddress &
HMAP_BASE));
00154 }
00155
break;
00156 }
00157 Entry = Entry->Flink;
00158 }
00159
00160
if ((Entry == &
Hive->Storage[Type].FreeBins) &&
00161 (TotalDiscardedSize >= NewSize)) {
00162
00163
00164
00165
00166
00167
00168
if (
HvpCoalesceDiscardedBins(Hive, NewSize, Type)) {
00169
goto Retry;
00170 }
00171 }
00172
00173
00174
00175
00176 UseForIo = (BOOLEAN)((Type ==
Stable) ?
TRUE :
FALSE);
00177
if (Entry != &
Hive->Storage[Type].FreeBins) {
00178
00179
00180
00181
00182
00183
00184
00185 NewBin =
ExAllocatePoolWithTag((UseForIo) ? PagedPoolCacheAligned : PagedPool,
00186 NewSize,
00187 CM_POOL_TAG);
00188
if (NewBin ==
NULL) {
00189 InsertHeadList(&
Hive->Storage[Type].FreeBins, Entry);
00190
HvMarkClean(Hive, FreeBin->
FileOffset, FreeBin->
Size);
00191
goto ErrorExit1;
00192 }
00193 }
else {
00194 NewBin = (
Hive->
Allocate)(NewSize, UseForIo);
00195
if (NewBin ==
NULL) {
00196
goto ErrorExit1;
00197 }
00198 }
00199
00200
00201
00202
00203 NewBin->
Signature =
HBIN_SIGNATURE;
00204 NewBin->
Size = NewSize;
00205 NewBin->
MemAlloc = NewSize;
00206
00207
t = (
PHCELL)((PUCHAR)NewBin +
sizeof(
HBIN));
00208
t->Size = NewSize -
sizeof(
HBIN);
00209
if (
USE_OLD_CELL(Hive)) {
00210
t->u.OldCell.Last = (ULONG)
HBIN_NIL;
00211 }
00212
00213
if (Entry != &
Hive->Storage[Type].FreeBins) {
00214
00215
00216
00217
00218
for (i=0;i<NewSize;i+=
HBLOCK_SIZE) {
00219 Me =
HvpGetCellMap(Hive, FreeBin->
FileOffset+i+(Type*HCELL_TYPE_MASK));
00220
VALIDATE_CELL_MAP(__LINE__,Me,Hive,FreeBin->
FileOffset+i+(Type*HCELL_TYPE_MASK));
00221 Me->
BlockAddress = (ULONG_PTR)NewBin + i;
00222 Me->
BinAddress = (ULONG_PTR)NewBin;
00223
if (i==0) {
00224 Me->
BinAddress |=
HMAP_NEWALLOC;
00225 }
00226 }
00227
00228 NewBin->
FileOffset = FreeBin->
FileOffset;
00229
00230 (
Hive->
Free)(FreeBin,
sizeof(
FREE_HBIN));
00231
00232
return(NewBin);
00233 }
00234
00235
00236
00237
00238
00239 OldLength =
Hive->Storage[Type].Length;
00240 NewLength = OldLength + NewSize;
00241
00242
00243 NewBin->
FileOffset = OldLength;
00244
00245
ASSERT((OldLength % HBLOCK_SIZE) == 0);
00246
ASSERT((NewLength % HBLOCK_SIZE) == 0);
00247
00248
if (OldLength == 0) {
00249
00250
00251
00252 newt = (PVOID)((
Hive->
Allocate)(
sizeof(
HMAP_TABLE),
FALSE));
00253
if (newt ==
NULL) {
00254
goto ErrorExit2;
00255 }
00256 RtlZeroMemory(newt,
sizeof(
HMAP_TABLE));
00257
Hive->Storage[Type].SmallDir = newt;
00258
Hive->Storage[Type].Map = (
PHMAP_DIRECTORY)&(
Hive->Storage[Type].SmallDir);
00259 }
00260
00261
if (OldLength > 0) {
00262 OldMap = (OldLength-1) /
HBLOCK_SIZE;
00263 }
else {
00264 OldMap = 0;
00265 }
00266 NewMap = (NewLength-1) /
HBLOCK_SIZE;
00267
00268 OldTable = OldMap /
HTABLE_SLOTS;
00269 NewTable = NewMap /
HTABLE_SLOTS;
00270
00271
if (NewTable != OldTable) {
00272
00273
00274
00275
00276
if (OldTable == 0) {
00277
00278
00279
00280
00281
00282
00283
if (
Hive->Storage[Type].Map == (
PHMAP_DIRECTORY)&
Hive->Storage[Type].SmallDir) {
00284
ASSERT(
Hive->Storage[Type].SmallDir != NULL);
00285
00286
00287
00288
00289 Dir = (
Hive->
Allocate)(
sizeof(
HMAP_DIRECTORY),
FALSE);
00290
if (Dir ==
NULL) {
00291
goto ErrorExit2;
00292 }
00293 RtlZeroMemory(Dir,
sizeof(
HMAP_DIRECTORY));
00294
00295 Dir->
Directory[0] =
Hive->Storage[Type].SmallDir;
00296
Hive->Storage[Type].SmallDir =
NULL;
00297
00298
Hive->Storage[Type].Map = Dir;
00299 }
else {
00300
ASSERT(
Hive->Storage[Type].SmallDir == NULL);
00301 }
00302
00303 }
00304 Dir =
Hive->Storage[Type].Map;
00305
00306
00307
00308
00309
if (
HvpAllocateMap(Hive, Dir, OldTable+1, NewTable) ==
FALSE) {
00310
goto ErrorExit3;
00311 }
00312 }
00313
00314
00315
00316
00317
00318
Hive->Storage[Type].Length = NewLength;
00319
if ((Type ==
Stable) && (!(
Hive->
HiveFlags &
HIVE_VOLATILE))) {
00320
00321
00322
00323
00324 NewVector = (PULONG)(
Hive->
Allocate)(
ROUND_UP(NewMap+1,
sizeof(ULONG)),
TRUE);
00325
if (NewVector ==
NULL) {
00326
goto ErrorExit3;
00327 }
00328
00329 RtlZeroMemory(NewVector, NewMap+1);
00330
00331
if (
Hive->
DirtyVector.Buffer !=
NULL) {
00332
00333 RtlCopyMemory(
00334 (PVOID)NewVector,
00335 (PVOID)
Hive->
DirtyVector.Buffer,
00336 OldMap+1
00337 );
00338 (
Hive->
Free)(
Hive->
DirtyVector.Buffer,
Hive->
DirtyAlloc);
00339 }
00340
00341
RtlInitializeBitMap(
00342 &(
Hive->
DirtyVector),
00343 NewVector,
00344 NewLength / HSECTOR_SIZE
00345 );
00346
Hive->
DirtyAlloc = NewMap+1;
00347
00348
00349
00350
00351
if ( ! (
HvpGrowLog2(Hive, NewSize))) {
00352
goto ErrorExit4;
00353 }
00354
00355
00356
00357
00358
if ( ! (
Hive->
FileSetSize)(
00359
Hive,
00360
HFILE_TYPE_PRIMARY,
00361 NewLength+
HBLOCK_SIZE
00362 ) )
00363 {
00364
goto ErrorExit4;
00365 }
00366
00367
00368
00369
00370
if (
Hive->
Alternate ==
TRUE) {
00371
if ( ! (
Hive->
FileSetSize)(
00372
Hive,
00373
HFILE_TYPE_ALTERNATE,
00374 NewLength+
HBLOCK_SIZE
00375 ) )
00376 {
00377 (
Hive->
FileSetSize)(
00378
Hive,
00379
HFILE_TYPE_PRIMARY,
00380 OldLength+
HBLOCK_SIZE
00381 );
00382
goto ErrorExit4;
00383 }
00384 }
00385
00386
00387
00388
00389
if ( !
HvMarkDirty(Hive, OldLength, NewSize)) {
00390
goto ErrorExit4;
00391 }
00392 }
00393
00394
00395
00396
00397 j = 0;
00398
for (i = OldLength; i < NewLength; i +=
HBLOCK_SIZE) {
00399 Me =
HvpGetCellMap(Hive, i + (Type*HCELL_TYPE_MASK));
00400
VALIDATE_CELL_MAP(__LINE__,Me,Hive,i + (Type*HCELL_TYPE_MASK));
00401 Me->
BlockAddress = (ULONG_PTR)NewBin + j;
00402 Me->
BinAddress = (ULONG_PTR)NewBin;
00403
00404
if (j == 0) {
00405
00406
00407
00408 Me->
BinAddress |=
HMAP_NEWALLOC;
00409 }
00410 j +=
HBLOCK_SIZE;
00411 }
00412
00413
return NewBin;
00414
00415 ErrorExit4:
00416
RtlInitializeBitMap(&
Hive->
DirtyVector,
00417 NewVector,
00418 OldLength / HSECTOR_SIZE);
00419
Hive->
DirtyCount =
RtlNumberOfSetBits(&
Hive->
DirtyVector);
00420
00421 ErrorExit3:
00422
Hive->Storage[Type].Length = OldLength;
00423
HvpFreeMap(Hive, Dir, OldTable+1, NewTable);
00424
00425 ErrorExit2:
00426 (
Hive->
Free)(NewBin, NewSize);
00427
00428 ErrorExit1:
00429
return NULL;
00430 }