/*! * \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; }
/*! * \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); }
/*! * \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()); }
/* * 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; }