コード例 #1
0
ファイル: Volume.cpp プロジェクト: jiangxilong/haiku
status_t
Volume::SaveOrphan(Transaction& transaction, ino_t newID, ino_t& oldID)
{
	oldID = fSuperBlock.LastOrphan();
	TRACE("Volume::SaveOrphan(): Old: %d, New: %d\n", (int)oldID, (int)newID);
	fSuperBlock.SetLastOrphan(newID);

	return WriteSuperBlock(transaction);
}
コード例 #2
0
ファイル: Volume.cpp プロジェクト: jiangxilong/haiku
status_t
Volume::FreeInode(Transaction& transaction, ino_t id, bool isDirectory)
{
	status_t status = fInodeAllocator.Free(transaction, id, isDirectory);
	if (status != B_OK)
		return status;

	++fFreeInodes;

	return WriteSuperBlock(transaction);
}
コード例 #3
0
ファイル: Volume.cpp プロジェクト: jiangxilong/haiku
status_t
Volume::AllocateInode(Transaction& transaction, Inode* parent, int32 mode,
	ino_t& id)
{
	status_t status = fInodeAllocator.New(transaction, parent, mode, id);
	if (status != B_OK)
		return status;

	--fFreeInodes;

	return WriteSuperBlock(transaction);
}
コード例 #4
0
ファイル: Volume.cpp プロジェクト: jiangxilong/haiku
status_t
Volume::ActivateDirNLink(Transaction& transaction)
{
	if ((fSuperBlock.ReadOnlyFeatures() 
		& EXT2_READ_ONLY_FEATURE_DIR_NLINK) != 0)
		return B_OK;
	
	fSuperBlock.SetReadOnlyFeatures(fSuperBlock.ReadOnlyFeatures()
		| EXT2_READ_ONLY_FEATURE_DIR_NLINK);
	
	return WriteSuperBlock(transaction);
}
コード例 #5
0
ファイル: Volume.cpp プロジェクト: jiangxilong/haiku
status_t
Volume::ActivateLargeFiles(Transaction& transaction)
{
	if ((fSuperBlock.ReadOnlyFeatures() 
		& EXT2_READ_ONLY_FEATURE_LARGE_FILE) != 0)
		return B_OK;
	
	fSuperBlock.SetReadOnlyFeatures(fSuperBlock.ReadOnlyFeatures()
		| EXT2_READ_ONLY_FEATURE_LARGE_FILE);
	
	return WriteSuperBlock(transaction);
}
コード例 #6
0
ファイル: Volume.cpp プロジェクト: Sylvain78/haiku
status_t
Volume::CreateIndicesRoot(Transaction& transaction)
{
	off_t id;
	status_t status = Inode::Create(transaction, NULL, NULL,
		S_INDEX_DIR | S_STR_INDEX | S_DIRECTORY | 0700, 0, 0, NULL, &id,
		&fIndicesNode, NULL, BFS_DO_NOT_PUBLISH_VNODE);
	if (status < B_OK)
		RETURN_ERROR(status);

	fSuperBlock.indices = ToBlockRun(id);
	return WriteSuperBlock();
}
コード例 #7
0
ファイル: Volume.cpp プロジェクト: jiangxilong/haiku
status_t
Volume::FreeBlocks(Transaction& transaction, fsblock_t start, uint32 length)
{
	TRACE("Volume::FreeBlocks(%llu, %lu)\n", start, length);
	if (IsReadOnly())
		return B_READ_ONLY_DEVICE;

	status_t status = fBlockAllocator->Free(transaction, start, length);
	if (status != B_OK)
		return status;

	TRACE("Volume::FreeBlocks(): number of free blocks (before): %llu\n",
		fFreeBlocks);
	fFreeBlocks += length;
	TRACE("Volume::FreeBlocks(): number of free blocks (after): %llu\n",
		fFreeBlocks);

	return WriteSuperBlock(transaction);
}
コード例 #8
0
ファイル: Volume.cpp プロジェクト: jiangxilong/haiku
status_t
Volume::AllocateBlocks(Transaction& transaction, uint32 minimum, uint32 maximum,
	uint32& blockGroup, fsblock_t& start, uint32& length)
{
	TRACE("Volume::AllocateBlocks()\n");
	if (IsReadOnly())
		return B_READ_ONLY_DEVICE;

	TRACE("Volume::AllocateBlocks(): Calling the block allocator\n");

	status_t status = fBlockAllocator->AllocateBlocks(transaction, minimum,
		maximum, blockGroup, start, length);
	if (status != B_OK)
		return status;

	TRACE("Volume::AllocateBlocks(): Allocated %lu blocks\n", length);

	fFreeBlocks -= length;

	return WriteSuperBlock(transaction);
}
コード例 #9
0
ファイル: Volume.cpp プロジェクト: jiangxilong/haiku
status_t
Volume::RemoveOrphan(Transaction& transaction, ino_t id)
{
	ino_t currentID = fSuperBlock.LastOrphan();
	TRACE("Volume::RemoveOrphan(): ID: %d\n", (int)id);
	if (currentID == 0)
		return B_OK;

	CachedBlock cached(this);

	off_t blockNum;
	status_t status = GetInodeBlock(currentID, blockNum);
	if (status != B_OK)
		return status;

	uint8* block = cached.SetToWritable(transaction, blockNum);
	if (block == NULL)
		return B_IO_ERROR;

	ext2_inode* inode = (ext2_inode*)(block
		+ InodeBlockIndex(currentID) * InodeSize());
	
	if (currentID == id) {
		TRACE("Volume::RemoveOrphan(): First entry. Updating head to: %d\n",
			(int)inode->NextOrphan());
		fSuperBlock.SetLastOrphan(inode->NextOrphan());

		return WriteSuperBlock(transaction);
	}

	currentID = inode->NextOrphan();
	if (currentID == 0)
		return B_OK;

	do {
		off_t lastBlockNum = blockNum;
		status = GetInodeBlock(currentID, blockNum);
		if (status != B_OK)
			return status;

		if (blockNum != lastBlockNum) {
			block = cached.SetToWritable(transaction, blockNum);
			if (block == NULL)
				return B_IO_ERROR;
		}

		ext2_inode* inode = (ext2_inode*)(block
			+ InodeBlockIndex(currentID) * InodeSize());

		currentID = inode->NextOrphan();
		if (currentID == 0)
			return B_OK;
	} while(currentID != id);

	CachedBlock cachedRemoved(this);

	status = GetInodeBlock(id, blockNum);
	if (status != B_OK)
		return status;

	uint8* removedBlock = cachedRemoved.SetToWritable(transaction, blockNum);
	if (removedBlock == NULL)
		return B_IO_ERROR;

	ext2_inode* removedInode = (ext2_inode*)(removedBlock
		+ InodeBlockIndex(id) * InodeSize());

	// Next orphan is stored inside deletion time
	inode->deletion_time = removedInode->deletion_time;
	TRACE("Volume::RemoveOrphan(): Updated pointer to %d\n",
		(int)inode->NextOrphan());

	return status;
}
コード例 #10
0
ファイル: Volume.cpp プロジェクト: Sylvain78/haiku
status_t
Volume::Initialize(int fd, const char* name, uint32 blockSize,
	uint32 flags)
{
	// although there is no really good reason for it, we won't
	// accept '/' in disk names (mkbfs does this, too - and since
	// Tracker names mounted volumes like their name)
	if (strchr(name, '/') != NULL)
		return B_BAD_VALUE;

	if (blockSize != 1024 && blockSize != 2048 && blockSize != 4096
		&& blockSize != 8192)
		return B_BAD_VALUE;

	DeviceOpener opener(fd, O_RDWR);
	if (opener.Device() < B_OK)
		return B_BAD_VALUE;

	if (opener.IsReadOnly())
		return B_READ_ONLY_DEVICE;

	fDevice = opener.Device();

	uint32 deviceBlockSize;
	off_t deviceSize;
	if (opener.GetSize(&deviceSize, &deviceBlockSize) < B_OK)
		return B_ERROR;

	off_t numBlocks = deviceSize / blockSize;

	// create valid superblock

	fSuperBlock.Initialize(name, numBlocks, blockSize);

	// initialize short hands to the superblock (to save byte swapping)
	fBlockSize = fSuperBlock.BlockSize();
	fBlockShift = fSuperBlock.BlockShift();
	fAllocationGroupShift = fSuperBlock.AllocationGroupShift();

	// determine log size depending on the size of the volume
	off_t logSize = 2048;
	if (numBlocks <= 20480)
		logSize = 512;
	if (deviceSize > 1LL * 1024 * 1024 * 1024)
		logSize = 4096;

	// since the allocator has not been initialized yet, we
	// cannot use BlockAllocator::BitmapSize() here
	off_t bitmapBlocks = (numBlocks + blockSize * 8 - 1) / (blockSize * 8);

	fSuperBlock.log_blocks = ToBlockRun(bitmapBlocks + 1);
	fSuperBlock.log_blocks.length = HOST_ENDIAN_TO_BFS_INT16(logSize);
	fSuperBlock.log_start = fSuperBlock.log_end = HOST_ENDIAN_TO_BFS_INT64(
		ToBlock(Log()));

	// set the current log pointers, so that journaling will work correctly
	fLogStart = fSuperBlock.LogStart();
	fLogEnd = fSuperBlock.LogEnd();

	if (!IsValidSuperBlock())
		RETURN_ERROR(B_ERROR);

	if ((fBlockCache = opener.InitCache(NumBlocks(), fBlockSize)) == NULL)
		return B_ERROR;

	fJournal = new(std::nothrow) Journal(this);
	if (fJournal == NULL || fJournal->InitCheck() < B_OK)
		RETURN_ERROR(B_ERROR);

	// ready to write data to disk

	Transaction transaction(this, 0);

	if (fBlockAllocator.InitializeAndClearBitmap(transaction) < B_OK)
		RETURN_ERROR(B_ERROR);

	off_t id;
	status_t status = Inode::Create(transaction, NULL, NULL,
		S_DIRECTORY | 0755, 0, 0, NULL, &id, &fRootNode);
	if (status < B_OK)
		RETURN_ERROR(status);

	fSuperBlock.root_dir = ToBlockRun(id);

	if ((flags & VOLUME_NO_INDICES) == 0) {
		// The indices root directory will be created automatically
		// when the standard indices are created (or any other).
		Index index(this);
		status = index.Create(transaction, "name", B_STRING_TYPE);
		if (status < B_OK)
			return status;

		status = index.Create(transaction, "BEOS:APP_SIG", B_STRING_TYPE);
		if (status < B_OK)
			return status;

		status = index.Create(transaction, "last_modified", B_INT64_TYPE);
		if (status < B_OK)
			return status;

		status = index.Create(transaction, "size", B_INT64_TYPE);
		if (status < B_OK)
			return status;
	}

	status = CreateVolumeID(transaction);
	if (status < B_OK)
		return status;

	status = _EraseUnusedBootBlock();
	if (status < B_OK)
		return status;

	status = WriteSuperBlock();
	if (status < B_OK)
		return status;

	status = transaction.Done();
	if (status < B_OK)
		return status;

	Sync();
	opener.RemoveCache(true);
	return B_OK;
}