|
|
- #include <defs.h>
- #include <stdio.h>
- #include <string.h>
- #include <kmalloc.h>
- #include <list.h>
- #include <fs.h>
- #include <vfs.h>
- #include <dev.h>
- #include <sfs.h>
- #include <inode.h>
- #include <iobuf.h>
- #include <bitmap.h>
- #include <error.h>
- #include <assert.h>
-
- /*
- * sfs_sync - sync sfs's superblock and freemap in memroy into disk
- */
- static int
- sfs_sync(struct fs *fs) {
- struct sfs_fs *sfs = fsop_info(fs, sfs);
- lock_sfs_fs(sfs);
- {
- list_entry_t *list = &(sfs->inode_list), *le = list;
- while ((le = list_next(le)) != list) {
- struct sfs_inode *sin = le2sin(le, inode_link);
- vop_fsync(info2node(sin, sfs_inode));
- }
- }
- unlock_sfs_fs(sfs);
-
- int ret;
- if (sfs->super_dirty) {
- sfs->super_dirty = 0;
- if ((ret = sfs_sync_super(sfs)) != 0) {
- sfs->super_dirty = 1;
- return ret;
- }
- if ((ret = sfs_sync_freemap(sfs)) != 0) {
- sfs->super_dirty = 1;
- return ret;
- }
- }
- return 0;
- }
-
- /*
- * sfs_get_root - get the root directory inode from disk (SFS_BLKN_ROOT,1)
- */
- static struct inode *
- sfs_get_root(struct fs *fs) {
- struct inode *node;
- int ret;
- if ((ret = sfs_load_inode(fsop_info(fs, sfs), &node, SFS_BLKN_ROOT)) != 0) {
- panic("load sfs root failed: %e", ret);
- }
- return node;
- }
-
- /*
- * sfs_unmount - unmount sfs, and free the memorys contain sfs->freemap/sfs_buffer/hash_liskt and sfs itself.
- */
- static int
- sfs_unmount(struct fs *fs) {
- struct sfs_fs *sfs = fsop_info(fs, sfs);
- if (!list_empty(&(sfs->inode_list))) {
- return -E_BUSY;
- }
- assert(!sfs->super_dirty);
- bitmap_destroy(sfs->freemap);
- kfree(sfs->sfs_buffer);
- kfree(sfs->hash_list);
- kfree(sfs);
- return 0;
- }
-
- /*
- * sfs_cleanup - when sfs failed, then should call this function to sync sfs by calling sfs_sync
- *
- * NOTICE: nouse now.
- */
- static void
- sfs_cleanup(struct fs *fs) {
- struct sfs_fs *sfs = fsop_info(fs, sfs);
- uint32_t blocks = sfs->super.blocks, unused_blocks = sfs->super.unused_blocks;
- cprintf("sfs: cleanup: '%s' (%d/%d/%d)\n", sfs->super.info,
- blocks - unused_blocks, unused_blocks, blocks);
- int i, ret;
- for (i = 0; i < 32; i ++) {
- if ((ret = fsop_sync(fs)) == 0) {
- break;
- }
- }
- if (ret != 0) {
- warn("sfs: sync error: '%s': %e.\n", sfs->super.info, ret);
- }
- }
-
- /*
- * sfs_init_read - used in sfs_do_mount to read disk block(blkno, 1) directly.
- *
- * @dev: the block device
- * @blkno: the NO. of disk block
- * @blk_buffer: the buffer used for read
- *
- * (1) init iobuf
- * (2) read dev into iobuf
- */
- static int
- sfs_init_read(struct device *dev, uint32_t blkno, void *blk_buffer) {
- struct iobuf __iob, *iob = iobuf_init(&__iob, blk_buffer, SFS_BLKSIZE, blkno * SFS_BLKSIZE);
- return dop_io(dev, iob, 0);
- }
-
- /*
- * sfs_init_freemap - used in sfs_do_mount to read freemap data info in disk block(blkno, nblks) directly.
- *
- * @dev: the block device
- * @bitmap: the bitmap in memroy
- * @blkno: the NO. of disk block
- * @nblks: Rd number of disk block
- * @blk_buffer: the buffer used for read
- *
- * (1) get data addr in bitmap
- * (2) read dev into iobuf
- */
- static int
- sfs_init_freemap(struct device *dev, struct bitmap *freemap, uint32_t blkno, uint32_t nblks, void *blk_buffer) {
- size_t len;
- void *data = bitmap_getdata(freemap, &len);
- assert(data != NULL && len == nblks * SFS_BLKSIZE);
- while (nblks != 0) {
- int ret;
- if ((ret = sfs_init_read(dev, blkno, data)) != 0) {
- return ret;
- }
- blkno ++, nblks --, data += SFS_BLKSIZE;
- }
- return 0;
- }
-
- /*
- * sfs_do_mount - mount sfs file system.
- *
- * @dev: the block device contains sfs file system
- * @fs_store: the fs struct in memroy
- */
- static int
- sfs_do_mount(struct device *dev, struct fs **fs_store) {
- static_assert(SFS_BLKSIZE >= sizeof(struct sfs_super));
- static_assert(SFS_BLKSIZE >= sizeof(struct sfs_disk_inode));
- static_assert(SFS_BLKSIZE >= sizeof(struct sfs_disk_entry));
-
- if (dev->d_blocksize != SFS_BLKSIZE) {
- return -E_NA_DEV;
- }
-
- /* allocate fs structure */
- struct fs *fs;
- if ((fs = alloc_fs(sfs)) == NULL) {
- return -E_NO_MEM;
- }
- struct sfs_fs *sfs = fsop_info(fs, sfs);
- sfs->dev = dev;
-
- int ret = -E_NO_MEM;
-
- void *sfs_buffer;
- if ((sfs->sfs_buffer = sfs_buffer = kmalloc(SFS_BLKSIZE)) == NULL) {
- goto failed_cleanup_fs;
- }
-
- /* load and check superblock */
- if ((ret = sfs_init_read(dev, SFS_BLKN_SUPER, sfs_buffer)) != 0) {
- goto failed_cleanup_sfs_buffer;
- }
-
- ret = -E_INVAL;
-
- struct sfs_super *super = sfs_buffer;
- if (super->magic != SFS_MAGIC) {
- cprintf("sfs: wrong magic in superblock. (%08x should be %08x).\n",
- super->magic, SFS_MAGIC);
- goto failed_cleanup_sfs_buffer;
- }
- if (super->blocks > dev->d_blocks) {
- cprintf("sfs: fs has %u blocks, device has %u blocks.\n",
- super->blocks, dev->d_blocks);
- goto failed_cleanup_sfs_buffer;
- }
- super->info[SFS_MAX_INFO_LEN] = '\0';
- sfs->super = *super;
-
- ret = -E_NO_MEM;
-
- uint32_t i;
-
- /* alloc and initialize hash list */
- list_entry_t *hash_list;
- if ((sfs->hash_list = hash_list = kmalloc(sizeof(list_entry_t) * SFS_HLIST_SIZE)) == NULL) {
- goto failed_cleanup_sfs_buffer;
- }
- for (i = 0; i < SFS_HLIST_SIZE; i ++) {
- list_init(hash_list + i);
- }
-
- /* load and check freemap */
- struct bitmap *freemap;
- uint32_t freemap_size_nbits = sfs_freemap_bits(super);
- if ((sfs->freemap = freemap = bitmap_create(freemap_size_nbits)) == NULL) {
- goto failed_cleanup_hash_list;
- }
- uint32_t freemap_size_nblks = sfs_freemap_blocks(super);
- if ((ret = sfs_init_freemap(dev, freemap, SFS_BLKN_FREEMAP, freemap_size_nblks, sfs_buffer)) != 0) {
- goto failed_cleanup_freemap;
- }
-
- uint32_t blocks = sfs->super.blocks, unused_blocks = 0;
- for (i = 0; i < freemap_size_nbits; i ++) {
- if (bitmap_test(freemap, i)) {
- unused_blocks ++;
- }
- }
- assert(unused_blocks == sfs->super.unused_blocks);
-
- /* and other fields */
- sfs->super_dirty = 0;
- sem_init(&(sfs->fs_sem), 1);
- sem_init(&(sfs->io_sem), 1);
- sem_init(&(sfs->mutex_sem), 1);
- list_init(&(sfs->inode_list));
- cprintf("sfs: mount: '%s' (%d/%d/%d)\n", sfs->super.info,
- blocks - unused_blocks, unused_blocks, blocks);
-
- /* link addr of sync/get_root/unmount/cleanup funciton fs's function pointers*/
- fs->fs_sync = sfs_sync;
- fs->fs_get_root = sfs_get_root;
- fs->fs_unmount = sfs_unmount;
- fs->fs_cleanup = sfs_cleanup;
- *fs_store = fs;
- return 0;
-
- failed_cleanup_freemap:
- bitmap_destroy(freemap);
- failed_cleanup_hash_list:
- kfree(hash_list);
- failed_cleanup_sfs_buffer:
- kfree(sfs_buffer);
- failed_cleanup_fs:
- kfree(fs);
- return ret;
- }
-
- int
- sfs_mount(const char *devname) {
- return vfs_mount(devname, sfs_do_mount);
- }
-
|