📄 super.c
字号:
for (i = 0; i < fs->super->group_count; i++)
{
gd = fs->groups[i].desc;
blocks = 0;
first_block = fs->super->blocks_per_group * i;
// The first group needs blocks for the super block, reserved blocks and the group descriptors
if (i == 0) blocks = fs->super->groupdesc_table_block + fs->groupdesc_blocks;
// Next blocks in group are the block bitmap, inode bitmap and the inode table
gd->block_bitmap_block = first_block + blocks++;
gd->inode_bitmap_block = first_block + blocks++;
gd->inode_table_block = first_block + blocks;
blocks += fs->inode_blocks_per_group;
// Update block bitmap
buf = alloc_buffer(fs->cache, gd->block_bitmap_block);
if (!buf) return NULL;
set_bits(buf->data, 0, blocks);
mark_buffer_updated(fs->cache, buf);
release_buffer(fs->cache, buf);
// Determine the block count for the group. The last group may be truncated
if (fs->super->blocks_per_group * (i + 1) > fs->super->block_count)
gd->block_count = fs->super->block_count - fs->super->blocks_per_group * i;
else
gd->block_count = fs->super->blocks_per_group;
// Set the count of free blocks and inodes for group
gd->free_inode_count = fs->super->inodes_per_group;
gd->free_block_count = gd->block_count - blocks;
// Update super block
fs->super->free_block_count -= blocks;
mark_group_desc_dirty(fs, i);
}
// Zero out block and inode bitmaps and inode tables
if (fsopts->quick)
{
buffer = (char *) kmalloc(fs->blocksize);
memset(buffer, 0, fs->blocksize);
for (i = 0; i < fs->super->group_count; i++)
{
gd = fs->groups[i].desc;
dev_write(fs->devno, buffer, fs->blocksize, gd->block_bitmap_block);
dev_write(fs->devno, buffer, fs->blocksize, gd->inode_bitmap_block);
for (j = 0; j < fs->inode_blocks_per_group; j++)
{
dev_write(fs->devno, buffer, fs->blocksize, gd->inode_table_block + j);
}
}
kfree(buffer);
}
// Reserve inodes
for (i = 0; i < fs->super->reserved_inodes; i++)
{
ino = new_inode(fs, 0, 0);
if (ino != i)
{
kprintf("dfs: format expected inode %d, got %d\n", i, ino);
return NULL;
}
}
// Create root directory
root = get_inode(fs, DFS_INODE_ROOT);
if (!root) return NULL;
root->desc->flags = DFS_INODE_FLAG_DIRECTORY;
root->desc->ctime = root->desc->mtime = time(NULL);
root->desc->linkcount = 1;
mark_buffer_updated(fs->cache, root->buf);
release_inode(root);
// Reenable buffer cache sync
fs->cache->nosync = 0;
return fs;
}
static struct filsys *open_filesystem(char *devname, struct fsoptions *fsopts)
{
struct filsys *fs;
devno_t devno;
struct groupdesc *gd;
unsigned int i;
unsigned int cache_buffers;
// Check device
devno = dev_open(devname);
if (devno == NODEV) return NULL;
if (device(devno)->driver->type != DEV_TYPE_BLOCK) return NULL;
// Allocate file system
fs = (struct filsys *) kmalloc(sizeof(struct filsys));
memset(fs, 0, sizeof(struct filsys));
// Allocate and read super block
fs->super = (struct superblock *) kmalloc(SECTORSIZE);
memset(fs->super, 0, SECTORSIZE);
if (dev_read(devno, fs->super, SECTORSIZE, 1) != SECTORSIZE)
{
kprintf("dfs: unable to read superblock on device %s\n", device(devno)->name);
free(fs->super);
free(fs);
return NULL;
}
fs->super_dirty = 0;
// Check signature and version
if (fs->super->signature != DFS_SIGNATURE)
{
kprintf("dfs: invalid DFS signature on device %s\n", device(devno)->name);
free(fs->super);
free(fs);
return NULL;
}
if (fs->super->version != DFS_VERSION)
{
kprintf("dfs: invalid DFS version on device %s\n", device(devno)->name);
free(fs->super);
free(fs);
return NULL;
}
// Set device number and block size
fs->devno = devno;
fs->blocksize = 1 << fs->super->log_block_size;
fs->inodes_per_block = fs->blocksize / sizeof(struct inodedesc);
// Initialize buffer cache
cache_buffers = (unsigned int) fsopts->cache;
if (cache_buffers == 0) cache_buffers = fs->super->cache_buffers;
if (cache_buffers == 0) cache_buffers = DEFAULT_CACHE_BUFFERS;
if (cache_buffers > fs->super->block_count) cache_buffers = fs->super->block_count;
fs->cache = init_buffer_pool(devno, cache_buffers, fs->blocksize, dfs_sync, fs);
if (!fs->cache) return NULL;
// Calculate the number of group descriptors blocks
fs->groupdescs_per_block = fs->blocksize / sizeof(struct groupdesc);
fs->groupdesc_blocks = (fs->super->group_count * sizeof(struct groupdesc) + fs->blocksize - 1) / fs->blocksize;
// Calculate the number of block pointers per block directory page
fs->log_blkptrs_per_block = fs->super->log_block_size - 2;
// Read group descriptors
fs->groupdesc_buffers = (struct buf **) kmalloc(sizeof(struct buf *) * fs->groupdesc_blocks);
fs->groups = (struct group *) kmalloc(sizeof(struct group) * fs->super->group_count);
for (i = 0; i < fs->groupdesc_blocks; i++)
{
fs->groupdesc_buffers[i] = get_buffer(fs->cache, fs->super->groupdesc_table_block + i);
if (!fs->groupdesc_buffers[i]) return NULL;
}
for (i = 0; i < fs->super->group_count; i++)
{
gd = (struct groupdesc *) fs->groupdesc_buffers[i / fs->groupdescs_per_block]->data;
gd += (i % fs->groupdescs_per_block);
fs->groups[i].desc = gd;
fs->groups[i].first_free_block = -1;
fs->groups[i].first_free_inode = -1;
}
return fs;
}
static void close_filesystem(struct filsys *fs)
{
unsigned int i;
// Release all group descriptors
for (i = 0; i < fs->groupdesc_blocks; i++) release_buffer(fs->cache, fs->groupdesc_buffers[i]);
kfree(fs->groupdesc_buffers);
kfree(fs->groups);
// Flush and sync buffer cache
flush_buffers(fs->cache, 0);
sync_buffers(fs->cache, 0);
// Free cache
free_buffer_pool(fs->cache);
// Write super block
if (fs->super_dirty) dev_write(fs->devno, fs->super, SECTORSIZE, 1);
kfree(fs->super);
// Close device
dev_close(fs->devno);
// Deallocate file system
kfree(fs);
}
static void get_filesystem_status(struct filsys *fs, struct statfs *buf)
{
buf->bsize = fs->blocksize;
buf->iosize = fs->blocksize;
buf->blocks = fs->super->block_count;
buf->bfree = fs->super->free_block_count;
buf->files = fs->super->inode_count;
buf->ffree = fs->super->free_inode_count;
buf->cachesize = fs->cache->poolsize * fs->cache->bufsize;
}
int dfs_format(char *devname, char *opts)
{
struct fsoptions fsopts;
struct filsys *fs;
if (parse_options(opts, &fsopts) != 0) return -EINVAL;
fs = create_filesystem(devname, &fsopts);
if (!fs) return -EIO;
close_filesystem(fs);
return 0;
}
int dfs_mount(struct fs *fs, char *opts)
{
struct fsoptions fsopts;
if (parse_options(opts, &fsopts) != 0) return -EINVAL;
fs->data = open_filesystem(fs->mntfrom, &fsopts);
if (!fs->data) return -EIO;
return 0;
}
int dfs_umount(struct fs *fs)
{
close_filesystem((struct filsys *) fs->data);
return 0;
}
int dfs_statfs(struct fs *fs, struct statfs *buf)
{
get_filesystem_status((struct filsys *) fs->data, buf);
return 0;
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -