5 extern void afsi_log(char *pattern, ...);
6 extern DWORD cm_ValidateCache;
9 GranularityAdjustment(DWORD size)
12 static DWORD dwGranularity = 0;
14 if ( !dwGranularity ) {
15 GetSystemInfo(&sysInfo);
16 afsi_log("Granularity - %lX", sysInfo.dwAllocationGranularity);
17 dwGranularity = sysInfo.dwAllocationGranularity;
20 size = (size + (dwGranularity - 1)) & ~(dwGranularity - 1);
25 ComputeSizeOfConfigData(void)
28 size = sizeof(cm_config_data_t);
33 ComputeSizeOfVolumes(DWORD maxvols)
36 size = maxvols * sizeof(cm_volume_t);
41 ComputeSizeOfCells(DWORD maxcells)
44 size = maxcells * sizeof(cm_cell_t);
49 ComputeSizeOfACLCache(DWORD stats)
52 size = 2 * (stats + 10) * sizeof(cm_aclent_t);
57 ComputeSizeOfSCache(DWORD stats)
60 size = (stats + 10) * sizeof(cm_scache_t);
65 ComputeSizeOfSCacheHT(DWORD stats)
68 size = (stats + 10) / 2 * sizeof(cm_scache_t *);;
73 ComputeSizeOfDNLCache(void)
76 size = NHSIZE * sizeof(cm_nc_t *) + NCSIZE * sizeof(cm_nc_t);
81 ComputeSizeOfDataBuffers(DWORD cacheBlocks, DWORD blockSize)
84 size = cacheBlocks * blockSize;
89 ComputeSizeOfDataHT(void)
92 size = osi_PrimeLessThan(CM_BUF_HASHSIZE) * sizeof(cm_buf_t *);
97 ComputeSizeOfDataHeaders(DWORD cacheBlocks)
100 size = cacheBlocks * sizeof(cm_buf_t);
105 ComputeSizeOfMappingFile(DWORD stats, DWORD maxVols, DWORD maxCells, DWORD chunkSize, DWORD cacheBlocks, DWORD blockSize)
109 size = ComputeSizeOfConfigData()
110 + ComputeSizeOfVolumes(maxVols)
111 + ComputeSizeOfCells(maxCells)
112 + ComputeSizeOfACLCache(stats)
113 + ComputeSizeOfSCache(stats)
114 + ComputeSizeOfSCacheHT(stats)
115 + ComputeSizeOfDNLCache()
116 + ComputeSizeOfDataBuffers(cacheBlocks, blockSize)
117 + 2 * ComputeSizeOfDataHT()
118 + ComputeSizeOfDataHeaders(cacheBlocks);
122 /* Create a security attribute structure suitable for use when the cache file
123 * is created. What we mainly want is that only the administrator should be
124 * able to do anything with the file. We create an ACL with only one entry,
125 * an entry that grants all rights to the administrator.
127 PSECURITY_ATTRIBUTES CreateCacheFileSA()
129 PSECURITY_ATTRIBUTES psa;
130 PSECURITY_DESCRIPTOR psd;
131 SID_IDENTIFIER_AUTHORITY authority = SECURITY_NT_AUTHORITY;
133 DWORD AdminSIDlength;
137 /* Get Administrator SID */
138 AllocateAndInitializeSid(&authority, 2,
139 SECURITY_BUILTIN_DOMAIN_RID,
140 DOMAIN_ALIAS_RID_ADMINS,
144 /* Create Administrator-only ACL */
145 AdminSIDlength = GetLengthSid(AdminSID);
146 ACLlength = sizeof(ACL) + sizeof(ACCESS_ALLOWED_ACE)
147 + AdminSIDlength - sizeof(DWORD);
148 AdminOnlyACL = GlobalAlloc(GMEM_FIXED, ACLlength);
149 InitializeAcl(AdminOnlyACL, ACLlength, ACL_REVISION);
150 AddAccessAllowedAce(AdminOnlyACL, ACL_REVISION,
151 STANDARD_RIGHTS_ALL | SPECIFIC_RIGHTS_ALL,
154 /* Create security descriptor */
155 psd = GlobalAlloc(GMEM_FIXED, sizeof(SECURITY_DESCRIPTOR));
156 InitializeSecurityDescriptor(psd, SECURITY_DESCRIPTOR_REVISION);
157 SetSecurityDescriptorDacl(psd, TRUE, AdminOnlyACL, FALSE);
159 /* Create security attributes structure */
160 psa = GlobalAlloc(GMEM_FIXED, sizeof(SECURITY_ATTRIBUTES));
161 psa->nLength = sizeof(SECURITY_ATTRIBUTES);
162 psa->lpSecurityDescriptor = psd;
163 psa->bInheritHandle = TRUE;
169 /* Free a security attribute structure created by CreateCacheFileSA() */
170 VOID FreeCacheFileSA(PSECURITY_ATTRIBUTES psa)
175 GetSecurityDescriptorDacl(psa->lpSecurityDescriptor, &b1, &pAcl, &b2);
177 GlobalFree(psa->lpSecurityDescriptor);
181 static HANDLE hMemoryMappedFile = NULL;
184 cm_IsCacheValid(void)
188 afsi_log("Validating Cache Contents");
190 if (cm_ValidateACLCache()) {
191 afsi_log("ACL Cache validation failure");
193 } else if (cm_ValidateDCache()) {
194 afsi_log("Data Cache validation failure");
196 } else if (cm_ValidateVolume()) {
197 afsi_log("Volume validation failure");
199 } else if (cm_ValidateCell()) {
200 afsi_log("Cell validation failure");
202 } else if (cm_ValidateSCache()) {
203 afsi_log("Stat Cache validation failure");
211 cm_ShutdownMappedMemory(void)
213 cm_config_data_t * config_data_p = (cm_config_data_t *)cm_data.baseAddress;
218 cm_ShutdownACLCache();
222 if (cm_ValidateCache == 2)
223 dirty = !cm_IsCacheValid();
225 *config_data_p = cm_data;
226 config_data_p->dirty = dirty;
227 UnmapViewOfFile(config_data_p);
228 CloseHandle(hMemoryMappedFile);
229 hMemoryMappedFile = NULL;
231 afsi_log("Memory Mapped File has been closed");
235 cm_ValidateMappedMemory(char * cachePath)
237 HANDLE hf = INVALID_HANDLE_VALUE, hm;
238 PSECURITY_ATTRIBUTES psa;
239 BY_HANDLE_FILE_INFORMATION fileInfo;
242 char * baseAddress = NULL;
243 cm_config_data_t * config_data_p;
245 psa = CreateCacheFileSA();
246 hf = CreateFile( cachePath,
247 GENERIC_READ | GENERIC_WRITE,
248 FILE_SHARE_READ | FILE_SHARE_WRITE,
251 FILE_ATTRIBUTE_HIDDEN | FILE_ATTRIBUTE_SYSTEM |
252 FILE_ATTRIBUTE_NOT_CONTENT_INDEXED | FILE_FLAG_RANDOM_ACCESS,
254 FreeCacheFileSA(psa);
256 if (hf == INVALID_HANDLE_VALUE) {
257 fprintf(stderr, "Error creating cache file \"%s\" error %d\n",
258 cachePath, GetLastError());
259 return CM_ERROR_INVAL;
262 /* The file is being re-used; check to see if the existing data can be reused */
263 if ( !GetFileInformationByHandle(hf, &fileInfo) ) {
265 fprintf(stderr, "Unable to obtain File Information\n");
266 return CM_ERROR_INVAL;
269 afsi_log("Existing File Size: %08X:%08X",
270 fileInfo.nFileSizeHigh,
271 fileInfo.nFileSizeLow);
273 hm = CreateFileMapping( hf,
277 sizeof(cm_config_data_t),
280 if (GetLastError() == ERROR_DISK_FULL) {
281 fprintf(stderr, "Error creating file mapping for \"%s\": disk full (%lX)\n",
282 cachePath, sizeof(cm_config_data_t));
284 hm = CreateFileMapping( hf,
288 fileInfo.nFileSizeLow,
291 if (GetLastError() == ERROR_DISK_FULL) {
293 return CM_ERROR_TOOMANYBUFS;
295 fprintf(stderr,"Error creating file mapping for \"%s\": %d\n",
296 cachePath, GetLastError());
298 return CM_ERROR_INVAL;
301 fprintf(stderr, "Retry with file size (%lX) succeeds",
302 fileInfo.nFileSizeLow);
305 afsi_log("Error creating file mapping for \"%s\": %d",
306 cachePath, GetLastError());
308 return CM_ERROR_INVAL;
312 config_data_p = MapViewOfFile( hm,
315 sizeof(cm_config_data_t));
316 if ( config_data_p == NULL ) {
317 fprintf(stderr, "Unable to MapViewOfFile\n");
318 if (hf != INVALID_HANDLE_VALUE)
321 return CM_ERROR_INVAL;
324 if ( config_data_p->dirty ) {
325 fprintf(stderr, "Previous session terminated prematurely\n");
326 UnmapViewOfFile(config_data_p);
329 return CM_ERROR_INVAL;
332 mappingSize = config_data_p->bufferSize;
333 baseAddress = config_data_p->baseAddress;
334 UnmapViewOfFile(config_data_p);
337 hm = CreateFileMapping( hf,
343 if (GetLastError() == ERROR_DISK_FULL) {
344 fprintf(stderr, "Error creating file mapping for \"%s\": disk full [2]\n",
347 return CM_ERROR_TOOMANYBUFS;
349 fprintf(stderr, "Error creating file mapping for \"%s\": %d\n",
350 cachePath, GetLastError());
352 return CM_ERROR_INVAL;
355 baseAddress = MapViewOfFileEx( hm,
360 if (baseAddress == NULL) {
361 fprintf(stderr, "Error mapping view of file: %d\n", GetLastError());
362 baseAddress = MapViewOfFile( hm,
366 if (baseAddress == NULL) {
368 if (hf != INVALID_HANDLE_VALUE)
370 return CM_ERROR_INVAL;
372 fprintf(stderr, "Unable to re-load cache file at base address\n");
374 if (hf != INVALID_HANDLE_VALUE)
376 return CM_ERROR_INVAL;
380 config_data_p = (cm_config_data_t *) baseAddress;
382 fprintf(stderr,"AFS Cache data:\n");
383 fprintf(stderr," Base Address = %lX\n",baseAddress);
384 fprintf(stderr," stats = %d\n", config_data_p->stats);
385 fprintf(stderr," chunkSize = %d\n", config_data_p->chunkSize);
386 fprintf(stderr," blockSize = %d\n", config_data_p->blockSize);
387 fprintf(stderr," bufferSize = %d\n", config_data_p->bufferSize);
388 fprintf(stderr," cacheType = %d\n", config_data_p->cacheType);
389 fprintf(stderr," currentVolumes = %d\n", config_data_p->currentVolumes);
390 fprintf(stderr," maxVolumes = %d\n", config_data_p->maxVolumes);
391 fprintf(stderr," currentCells = %d\n", config_data_p->currentCells);
392 fprintf(stderr," maxCells = %d\n", config_data_p->maxCells);
393 fprintf(stderr," hashTableSize = %d\n", config_data_p->hashTableSize );
394 fprintf(stderr," currentSCaches = %d\n", config_data_p->currentSCaches);
395 fprintf(stderr," maxSCaches = %d\n", config_data_p->maxSCaches);
396 cm_data = *config_data_p;
398 // perform validation of persisted data structures
399 // if there is a failure, start from scratch
400 if (!cm_IsCacheValid()) {
401 fprintf(stderr,"Cache file fails validation test\n");
402 UnmapViewOfFile(config_data_p);
404 return CM_ERROR_INVAL;
407 fprintf(stderr,"Cache passes validation test\n");
408 UnmapViewOfFile(config_data_p);
414 cm_InitMappedMemory(DWORD virtualCache, char * cachePath, DWORD stats, DWORD chunkSize, DWORD cacheBlocks)
416 HANDLE hf = INVALID_HANDLE_VALUE, hm;
417 PSECURITY_ATTRIBUTES psa;
420 DWORD maxVols = stats/2;
421 DWORD maxCells = stats/4;
422 char * baseAddress = NULL;
423 cm_config_data_t * config_data_p;
426 mappingSize = ComputeSizeOfMappingFile(stats, maxVols, maxCells, chunkSize, cacheBlocks, CM_CONFIGDEFAULT_BLOCKSIZE);
428 if ( !virtualCache ) {
429 psa = CreateCacheFileSA();
430 hf = CreateFile( cachePath,
431 GENERIC_READ | GENERIC_WRITE,
432 FILE_SHARE_READ | FILE_SHARE_WRITE,
435 FILE_ATTRIBUTE_HIDDEN | FILE_ATTRIBUTE_SYSTEM |
436 FILE_ATTRIBUTE_NOT_CONTENT_INDEXED | FILE_FLAG_RANDOM_ACCESS,
438 FreeCacheFileSA(psa);
440 if (hf == INVALID_HANDLE_VALUE) {
441 afsi_log("Error creating cache file \"%s\" error %d",
442 cachePath, GetLastError());
443 return CM_ERROR_INVAL;
446 if ( GetLastError() == ERROR_ALREADY_EXISTS ) {
447 BY_HANDLE_FILE_INFORMATION fileInfo;
449 /* The file is being re-used; check to see if the existing data can be reused */
450 afsi_log("Cache File \"%s\" already exists", cachePath);
452 if ( GetFileInformationByHandle(hf, &fileInfo) ) {
453 afsi_log("Existing File Size: %08X:%08X",
454 fileInfo.nFileSizeHigh,
455 fileInfo.nFileSizeLow);
456 if (fileInfo.nFileSizeLow > GranularityAdjustment(mappingSize)) {
457 psa = CreateCacheFileSA();
458 hf = CreateFile( cachePath,
459 GENERIC_READ | GENERIC_WRITE,
460 FILE_SHARE_READ | FILE_SHARE_WRITE,
463 FILE_ATTRIBUTE_HIDDEN | FILE_ATTRIBUTE_SYSTEM |
464 FILE_ATTRIBUTE_NOT_CONTENT_INDEXED | FILE_FLAG_RANDOM_ACCESS,
466 FreeCacheFileSA(psa);
468 if (hf == INVALID_HANDLE_VALUE) {
469 afsi_log("Error creating cache file \"%s\" error %d",
470 cachePath, GetLastError());
471 return CM_ERROR_INVAL;
474 GetFileInformationByHandle(hf, &fileInfo);
475 afsi_log(" New File Size: %08X:%08X",
476 fileInfo.nFileSizeHigh,
477 fileInfo.nFileSizeLow);
482 hm = CreateFileMapping( hf,
486 sizeof(cm_config_data_t),
489 if (GetLastError() == ERROR_DISK_FULL) {
490 afsi_log("Error creating file mapping for \"%s\": disk full (%lX)",
491 cachePath, sizeof(cm_config_data_t));
493 hm = CreateFileMapping( hf,
500 if (GetLastError() == ERROR_DISK_FULL) {
502 return CM_ERROR_TOOMANYBUFS;
504 afsi_log("Error creating file mapping for \"%s\": %d",
505 cachePath, GetLastError());
507 return CM_ERROR_INVAL;
510 afsi_log("Retry with mapping size (%lX) succeeds", mappingSize);
513 afsi_log("Error creating file mapping for \"%s\": %d",
514 cachePath, GetLastError());
516 return CM_ERROR_INVAL;
520 config_data_p = MapViewOfFile( hm,
523 sizeof(cm_config_data_t));
524 if ( config_data_p == NULL ) {
525 if (hf != INVALID_HANDLE_VALUE)
528 return CM_ERROR_INVAL;
531 if ( config_data_p->size == sizeof(cm_config_data_t) &&
532 config_data_p->magic == CM_CONFIG_DATA_MAGIC &&
533 config_data_p->stats == stats &&
534 config_data_p->maxVolumes == maxVols &&
535 config_data_p->maxCells == maxCells &&
536 config_data_p->chunkSize == chunkSize &&
537 config_data_p->buf_nbuffers == cacheBlocks &&
538 config_data_p->blockSize == CM_CONFIGDEFAULT_BLOCKSIZE &&
539 config_data_p->bufferSize == mappingSize)
541 if ( config_data_p->dirty ) {
542 afsi_log("Previous session terminated prematurely");
544 baseAddress = config_data_p->baseAddress;
548 afsi_log("Configuration changed or Not a persistent cache file");
550 UnmapViewOfFile(config_data_p);
555 hm = CreateFileMapping( hf,
561 if (GetLastError() == ERROR_DISK_FULL) {
562 afsi_log("Error creating file mapping for \"%s\": disk full [2]",
564 return CM_ERROR_TOOMANYBUFS;
566 afsi_log("Error creating file mapping for \"%s\": %d",
567 cachePath, GetLastError());
568 return CM_ERROR_INVAL;
570 baseAddress = MapViewOfFileEx( hm,
575 if (baseAddress == NULL) {
576 afsi_log("Error mapping view of file: %d", GetLastError());
577 baseAddress = MapViewOfFile( hm,
581 if (baseAddress == NULL) {
582 if (hf != INVALID_HANDLE_VALUE)
585 return CM_ERROR_INVAL;
591 config_data_p = (cm_config_data_t *) baseAddress;
594 afsi_log("Reusing existing AFS Cache data: Base Address = %lX",baseAddress);
595 cm_data = *config_data_p;
597 // perform validation of persisted data structures
598 // if there is a failure, start from scratch
599 if (cm_ValidateCache && !cm_IsCacheValid()) {
605 afsi_log("Building AFS Cache from scratch");
606 cm_data.size = sizeof(cm_config_data_t);
607 cm_data.magic = CM_CONFIG_DATA_MAGIC;
608 cm_data.baseAddress = baseAddress;
609 cm_data.stats = stats;
610 cm_data.chunkSize = chunkSize;
611 cm_data.blockSize = CM_CONFIGDEFAULT_BLOCKSIZE;
612 cm_data.bufferSize = mappingSize;
613 cm_data.hashTableSize = osi_PrimeLessThan(stats / 2 + 1);
615 cm_data.cacheType = CM_BUF_CACHETYPE_VIRTUAL;
617 cm_data.cacheType = CM_BUF_CACHETYPE_FILE;
620 cm_data.buf_nbuffers = cacheBlocks;
621 cm_data.buf_nOrigBuffers = 0;
622 cm_data.buf_blockSize = CM_BUF_BLOCKSIZE;
623 cm_data.buf_hashSize = CM_BUF_HASHSIZE;
625 cm_data.mountRootGen = time(NULL);
627 baseAddress += ComputeSizeOfConfigData();
628 cm_data.volumeBaseAddress = (cm_volume_t *) baseAddress;
629 baseAddress += ComputeSizeOfVolumes(maxVols);
630 cm_data.cellBaseAddress = (cm_cell_t *) baseAddress;
631 baseAddress += ComputeSizeOfCells(maxCells);
632 cm_data.aclBaseAddress = (cm_aclent_t *) baseAddress;
633 baseAddress += ComputeSizeOfACLCache(stats);
634 cm_data.scacheBaseAddress = (cm_scache_t *) baseAddress;
635 baseAddress += ComputeSizeOfSCache(stats);
636 cm_data.hashTablep = (cm_scache_t **) baseAddress;
637 baseAddress += ComputeSizeOfSCacheHT(stats);
638 cm_data.dnlcBaseAddress = (cm_nc_t *) baseAddress;
639 baseAddress += ComputeSizeOfDNLCache();
640 cm_data.buf_hashTablepp = (cm_buf_t **) baseAddress;
641 baseAddress += ComputeSizeOfDataHT();
642 cm_data.buf_fileHashTablepp = (cm_buf_t **) baseAddress;
643 baseAddress += ComputeSizeOfDataHT();
644 cm_data.bufHeaderBaseAddress = (cm_buf_t *) baseAddress;
645 baseAddress += ComputeSizeOfDataHeaders(cacheBlocks);
646 cm_data.bufDataBaseAddress = (char *) baseAddress;
647 baseAddress += ComputeSizeOfDataBuffers(cacheBlocks, CM_CONFIGDEFAULT_BLOCKSIZE);
648 cm_data.bufEndOfData = (char *) baseAddress;
650 cm_data.fakeDirVersion = 0x8;
652 UuidCreate((UUID *)&cm_data.Uuid);
655 UuidToString((UUID *)&cm_data.Uuid, &p);
656 afsi_log("Initializing Uuid to %s",p);
659 afsi_log("Initializing Volume Data");
660 cm_InitVolume(newFile, maxVols);
662 afsi_log("Initializing Cell Data");
663 cm_InitCell(newFile, maxCells);
665 afsi_log("Initializing ACL Data");
666 cm_InitACLCache(newFile, 2*stats);
668 afsi_log("Initializing Stat Data");
669 cm_InitSCache(newFile, stats);
671 afsi_log("Initializing Data Buffers");
672 cm_InitDCache(newFile, 0, cacheBlocks);
674 *config_data_p = cm_data;
675 config_data_p->dirty = 1;
677 hMemoryMappedFile = hf;
678 afsi_log("Cache Initialization Complete");