static pfs_aentry_t *getAentry(pfs_cache_t *clink, char *key, char *value, int mode) { int kLen, fullsize; pfs_aentry_t *aentry = clink->u.aentry; pfs_aentry_t *aentryLast = NULL; pfs_aentry_t *end; kLen = strlen(key); fullsize = (kLen + strlen(value) + 7) & ~3; for (end = (pfs_aentry_t *)((u8 *)aentry + 1024); aentry < end; aentry = (pfs_aentry_t *)((u8 *)aentry + aentry->aLen)) { //Other than critical errors, do nothing about the filesystem errors. if (aentry->aLen & 3) PFS_PRINTF(PFS_DRV_NAME " Error: aentry allocated length/4 != 0\n"); if (aentry->aLen < ((aentry->kLen + aentry->vLen + 7) & ~3)) { PFS_PRINTF(PFS_DRV_NAME " Panic: aentry is too small\n"); return NULL; } if (end < (pfs_aentry_t *)((u8 *)aentry + aentry->aLen)) PFS_PRINTF(PFS_DRV_NAME " Error: aentry too big\n"); switch (mode) { case PFS_AENTRY_MODE_LOOKUP: if (kLen == aentry->kLen) if (memcmp(key, aentry->str, kLen) == 0) return aentry; break; case PFS_AENTRY_MODE_ADD: if (aentry->kLen == 0) { if (aentry->aLen >= fullsize) return aentry; } if (aentry->aLen - ((aentry->kLen + aentry->vLen + 7) & ~3) < fullsize) continue; return aentry; case PFS_AENTRY_MODE_DELETE: default: if (kLen == aentry->kLen) { if (memcmp(key, aentry->str, kLen) == 0) { if (aentryLast != NULL) { aentryLast->aLen += aentry->aLen; return aentry; } // delete it :P aentry->kLen = 0; aentry->vLen = 0; return aentry; } } aentryLast = aentry; break; } } return NULL; }
// Sets 'blockpos' to point to the next block segment for the inode (and moves onto the // next block descriptor inode if necessary) int pfsBlockSeekNextSegment(pfs_cache_t *clink, pfs_blockpos_t *blockpos) { pfs_cache_t *nextSegment; int result=0; if (blockpos->byte_offset) { PFS_PRINTF(PFS_DRV_NAME": Panic: This is a bug!\n"); return -1; } // If we're at the end of the block descriptor array for the current // inode, then move onto the next inode if (pfsFixIndex(blockpos->block_segment+1)==0) { if ((nextSegment=pfsBlockGetNextSegment(pfsCacheUsedAdd(blockpos->inode), &result)) == NULL) return result; pfsCacheFree(blockpos->inode); blockpos->inode=nextSegment; if (clink->u.inode->number_data-1 == ++blockpos->block_segment) return -EINVAL; } blockpos->block_offset=0; blockpos->block_segment++; return result; }
int pfsCheckZoneSize(u32 zone_size) { if ((zone_size & (zone_size - 1)) || (zone_size < (2 * 1024)) || (zone_size > (128 * 1024))) { PFS_PRINTF(PFS_DRV_NAME ": Error: Invalid zone size\n"); return 0; } return 1; }
// Returns the next block descriptor inode pfs_cache_t *pfsBlockGetNextSegment(pfs_cache_t *clink, int *result) { pfsCacheFree(clink); if (clink->u.inode->next_segment.number) return pfsCacheGetData(clink->pfsMount, clink->u.inode->next_segment.subpart, clink->u.inode->next_segment.number << clink->pfsMount->inode_scale, PFS_CACHE_FLAG_SEGI, result); PFS_PRINTF(PFS_DRV_NAME": Error: There is no next segment descriptor\n"); *result=-EINVAL; return NULL; }
int pfsInodeSync(pfs_blockpos_t *blockpos, u64 size, u32 used_segments) { int result=0; u32 i; u16 count; for(i=pfsBlockSyncPos(blockpos, size); i; ) { count=blockpos->inode->u.inode->data[pfsFixIndex(blockpos->block_segment)].count; i+=blockpos->block_offset; if (i < count){ blockpos->block_offset=i; break; } i-=count; if (blockpos->block_segment + 1 == used_segments) { blockpos->block_offset=count; if (i || blockpos->byte_offset){ PFS_PRINTF(PFS_DRV_NAME": panic: fp exceeds file.\n"); return -EINVAL; } }else{ blockpos->block_offset=0; blockpos->block_segment++; } if (pfsFixIndex(blockpos->block_segment)) continue; if ((blockpos->inode = pfsBlockGetNextSegment(blockpos->inode, &result)) == 0) break; i++; } return result; }
void pfsInodePrint(pfs_inode_t *inode) { PFS_PRINTF(PFS_DRV_NAME": pfsInodePrint: Checksum = 0x%lX, Magic = 0x%lX\n", inode->checksum, inode->magic); PFS_PRINTF(PFS_DRV_NAME": Mode = 0x%X, attr = 0x%X\n", inode->mode, inode->attr); PFS_PRINTF(PFS_DRV_NAME": size = 0x%08lX%08lX\n", (u32)(inode->size >> 32), (u32)(inode->size)); }
// Attempts to allocate 'blocks' new blocks for an inode int pfsBlockAllocNewSegment(pfs_cache_t *clink, pfs_blockpos_t *blockpos, u32 blocks) { pfs_blockinfo_t bi, *bi2; int result=0; pfs_mount_t *pfsMount=clink->pfsMount; u32 i, old_blocks = blocks; if (pfsCacheIsFull()) return -ENOMEM; // create "indirect segment descriptor" if necessary if (pfsFixIndex(clink->u.inode->number_data) == 0) { pfs_cache_t *clink2; bi2 = &blockpos->inode->u.inode->data[pfsFixIndex(blockpos->block_segment)]; bi.subpart=bi2->subpart; bi.count=1; bi.number=bi2->number+bi2->count; result=pfsBitmapSearchFreeZone(pfsMount, &bi, clink->u.inode->number_blocks); if (result<0) { PFS_PRINTF(PFS_DRV_NAME": Error: Couldnt allocate zone! (1)\n"); return result; } clink2=pfsCacheGetData(pfsMount, bi.subpart, bi.number << pfsMount->inode_scale, PFS_CACHE_FLAG_SEGI | PFS_CACHE_FLAG_NOLOAD, &result); memset(clink2->u.inode, 0, sizeof(pfs_inode_t)); clink2->u.inode->magic=PFS_SEGI_MAGIC; memcpy(&clink2->u.inode->inode_block, &clink->u.inode->inode_block, sizeof(pfs_blockinfo_t)); memcpy(&clink2->u.inode->last_segment, blockpos->inode->u.inode->data, sizeof(pfs_blockinfo_t)); memcpy(clink2->u.inode->data, &bi, sizeof(pfs_blockinfo_t)); clink2->flags |= PFS_CACHE_FLAG_DIRTY; clink->u.inode->number_blocks+=bi.count; clink->u.inode->number_data++; memcpy(&clink->u.inode->last_segment, &bi, sizeof(pfs_blockinfo_t)); clink->u.inode->number_segdesg++; clink->flags |= PFS_CACHE_FLAG_DIRTY; blockpos->block_segment++; blockpos->block_offset=0; memcpy(&blockpos->inode->u.inode->next_segment, &bi, sizeof(pfs_blockinfo_t)); blockpos->inode->flags |= PFS_CACHE_FLAG_DIRTY; pfsCacheFree(blockpos->inode); blockpos->inode=clink2; } bi2 = &blockpos->inode->u.inode->data[pfsFixIndex(blockpos->block_segment)]; bi.subpart = bi2->subpart; bi.count = blocks; bi.number = bi2->number + bi2->count; result = pfsBitmapSearchFreeZone(pfsMount, &bi, clink->u.inode->number_blocks); if(result < 0) { PFS_PRINTF(PFS_DRV_NAME": Error: Couldnt allocate zone! (2)\n"); return result; } clink->u.inode->number_blocks += bi.count; clink->u.inode->number_data++; clink->flags |= PFS_CACHE_FLAG_DIRTY; blockpos->block_offset=0; blockpos->block_segment++; i = pfsFixIndex(clink->u.inode->number_data-1); memcpy(&blockpos->inode->u.inode->data[i], &bi, sizeof(pfs_blockinfo_t)); blockpos->inode->flags |= PFS_CACHE_FLAG_DIRTY; blocks -= bi.count; if (blocks) blocks -= pfsBlockExpandSegment(clink, blockpos, blocks); return old_blocks - blocks; }