Beispiel #1
0
/*!
 * \internal
 *
 * Flushes the itable bitmap if dirty.
 *
 * \param fs  the filesystem for which the itable bitmap
 *            should be flushed
 *
 * \throws std::invalid_argument  thrown if \a fs is null
 *
 */
void fs_flush_itable_bitmap(FS* fs)
{
	if (!fs)
		throw std::invalid_argument("fs_flush_itable_bitmap  invalid arg: fs");

	fs_guard lock(fs->lock);

	if (!fs->itable_bitmap_valid || !fs->itable_bitmap_dirty)
		return;

	debug::tracer DT;
	DT << "flushing itable group bitmap " << fs->itable_bitmap_group;

	assert(fs->itable_bitmap);

	if (0 == fs->itable_bitmap_phys) {
		DT << "allocating block for bitmap";

		// Determine the logical and physical block for our bitmap.
		uint32_t inodes_per_block = fs->blocksize / INODE_SIZE;
		uint32_t blocks_per_group = 1 + (FS_BLOCK_BITS(fs) / inodes_per_block);
		uint32_t logical = blocks_per_group * fs->itable_bitmap_group;

		fs->itable_bitmap_phys = translate_itable_blockno(
			fs->itable, logical, true);
		}

	fs_write_block(fs, fs->itable_bitmap_phys,
	               fs->itable_bitmap, fs->blocksize);
	fs->itable_bitmap_dirty = false;
}
Beispiel #2
0
/*!
 * \internal
 * Flushes internal buffers.
 * TODO: write documentation.
 */
void file_flush(file_handle* f)
{
	if (!f)
		throw std::invalid_argument("file_flush  null arg: f");
	
	assert(f->inode);
	assert(f->inode->fs);

	debug::tracer DT;
	DT << "flushing file with ino " << f->inode->ino;

	inode_guard lock(f->inode->lock);

	if (f->rw_buf_valid && f->rw_buf_dirty) {
		if (0 == f->rw_buf_pblockno) {
			f->rw_buf_pblockno = fs_inode_translate_blockno(
				f->inode, f->rw_buf_lblockno, true);
			assert(0 != f->rw_buf_pblockno);
		}

		fs_write_block(f->inode->fs, f->rw_buf_pblockno,
		               f->rw_buf.data(), f->rw_buf.size());
		f->rw_buf_dirty = false;
	}

	if (f->pos > f->inode->data.f_size) {
		f->inode->data.f_size = f->pos;
		mark_inode_dirty(f->inode);
	}

	fs_flush_inode(f->inode);
}
Beispiel #3
0
/*!
 * \ingroup lowlevel-api
 *
 * Write an inode.
 *
 * \param fs    a pointer to the filesystem handle
 * \param ino   the number of the inode to read
 * \param data  the inode data
 *
 */
void fs_write_inode(FS* fs, uint32_t ino, inode_data const& data)
{
	if (!fs)
		throw std::invalid_argument("fs_write_inode  invalid arg: fs");

	fs_guard lock(fs->lock);

	debug::tracer DT;
	DT.trace() << "writing inode " << ino;

	if (0 == ino) {
		fs->super.f_itable_data = data;
		mark_super_dirty(fs);
		return;
	}

	if (ino > FS_ITABLE_INODE_CAPACITY(fs))
		throw std::invalid_argument("fs_read_inode  invalid arg: ino");

	uint32_t logical = fs_get_inode_blockno(fs, ino);
	uint32_t physical = translate_itable_blockno(fs->itable, logical, true);
	assert(0 != physical);

	std::vector< char > buf(fs->blocksize, 0);
	fs_read_block(fs, physical, buf.data(), buf.size());

	// The arithmetic below requires ino to be 0-based!
	--ino;

	// Calculate the byte-offset in the block at which we can find
	// the requested inode.
	uint32_t inodes_per_block = fs->blocksize / INODE_SIZE;
	uint32_t offset = INODE_SIZE * (ino % inodes_per_block);

	serialize_inode(buf.data() + offset, data);
	fs_write_block(fs, physical, buf.data(), buf.size());
}
Beispiel #4
0
/*
 * Add a block to free list.
 */
int fs_block_free (fs_t *fs, unsigned int bno)
{
	int i;
	unsigned buf [BSDFS_BSIZE / 4];

        if (verbose > 1)
                printf ("free block %d, total %d\n", bno, fs->nfree);
	if (fs->nfree >= NICFREE) {
		buf[0] = fs->nfree;
		for (i=0; i<NICFREE; i++)
			buf[i+1] = fs->free[i];
		if (! fs_write_block (fs, bno, (unsigned char*) buf)) {
			fprintf (stderr, "block_free: write error at block %d\n", bno);
			return 0;
		}
		fs->nfree = 0;
	}
	fs->free [fs->nfree] = bno;
	fs->nfree++;
	fs->dirty = 1;
	if (bno)			/* Count total free blocks. */
		++fs->tfree;
	return 1;
}