📈
ucore-analysis
  • Introduction
  • lab1
    • boot
      • bootasm
      • bootmain
    • kern
      • debug
        • kmonitor
        • panic
      • init
        • init
      • libs
        • readline
      • mm
        • pmm
      • trap
        • trap
        • trapentry
        • vectors
    • libs
    • tools
  • lab解析
    • lab1
      • 练习1
      • 练习2
      • 练习3
      • 练习4
      • 练习6
      • 扩展练习
      • Piazza优质问题/笔记收集
    • lab2
      • 练习1
      • 练习2
      • 练习3
    • lab3
    • lab4
    • lab5
    • lab6
    • lab7
    • lab8
  • uCore代码
    • boot
      • asm.h
      • bootasm.S
      • bootmain.c
      • (lab1) bootasm.S
    • kern
      • debug
        • assert.h
        • kdebug.c
        • kdebug.h
        • kmonitor.c
        • kmonitor.h
        • panic.c
        • stab.h
        • (lab1) kdebug.c
      • driver
        • clock.c
        • clock.h
        • console.c
        • console.h
        • ide.c
        • ide.h
        • intr.c
        • intr.h
        • kbdreg.h
        • picirq.c
        • picirq.h
      • fs
        • devs
          • dev.c
          • dev_disk0.c
          • dev.h
          • dev_stdin.c
          • dev_stdout.c
        • sfs
          • bitmap.c
          • bitmap.h
          • sfs.c
          • sfs_fs.c
          • sfs.h
          • sfs_inode.c
          • sfs_io.c
          • sfs_lock.c
        • swap
          • swapfs.c
          • swapfs.h
        • vfs
          • inode.c
          • inode.h
          • README.md
          • vfs.c
          • vfsdev.c
          • vfsfile.c
          • vfs.h
          • vfslookup.c
          • vfspath.c
        • file.c
        • file.h
        • fs.c
        • fs.h
        • iobuf.c
        • iobuf.h
        • sysfile.c
        • sysfile.h
      • init
        • entry.S
        • init.c
        • (lab1) init.c
      • libs
        • readline.c
        • stdio.c
        • string.c
      • mm
        • default_pmm.c
        • default_pmm.h
        • kmalloc.c
        • kmalloc.h
        • memlayout.h
        • mmu.h
        • pmm.c
        • pmm.h
        • swap.c
        • swap_fifo.c
        • swap_fifo.h
        • swap.h
        • vmm.c
        • vmm.h
        • (lab2) pmm.c
        • (lab3) vmm.c
      • process
        • entry.S
        • proc.c
        • proc.h
        • switch.S
        • (lab4) proc.c
        • (lab5) proc.c
      • schedule
        • default_sched.c
        • default_sched.h
        • default_sched_stride.c
        • sched.c
        • sched.h
      • sync
        • check_sync.c
        • monitor.c
        • monitor.h
        • sem.c
        • sem.h
        • sync.h
        • wait.c
        • wait.h
      • syscall
        • syscall.c
        • syscall.h
      • trap
        • trap.c
        • trapentry.S
        • trap.h
        • vectors.S
        • (lab1) trap.c
    • libs
      • atomic.h
      • defs.h
      • dirent.h
      • elf.h
      • error.h
      • hash.c
      • list.h
      • printfmt.c
      • rand.c
      • skew_heap.h
      • stat.h
      • stdarg.h
      • stdio.h
      • stdlib.h
      • string.c
      • string.h
      • unistd.h
      • x86.h
    • tools
      • boot.ld
      • function.mk
      • gdbinit
      • grade.sh
      • kernel.ld
      • mksfs.c
      • sign.c
      • user.ld
      • vector.c
    • user
      • libs
        • dir.c
        • dir.h
        • file.c
        • file.h
        • initcode.S
        • lock.h
        • panic.c
        • stdio.c
        • syscall.c
        • syscall.h
        • ulib.c
        • ulib.h
        • umain.c
      • badarg.c
      • badsegment.c
      • divzero.c
      • exit.c
      • faultread.c
      • faultreadkernel.c
      • forktest.c
      • forktree.c
      • hello.c
      • ls.c
      • matrix.c
      • pgdir.c
      • priority.c
      • sfs_filetest1.c
      • sh.c
      • sleep.c
      • sleepkill.c
      • softint.c
      • spin.c
      • testbss.c
      • waitkill.c
      • yield.c
    • Makefile
    • (lab1) Makefile
  • 附录:工具使用
    • 如何编辑该文档
    • 讨论区的维护方法
    • 使用Travis CI自动化更新gitbook
Powered by GitBook
On this page

Was this helpful?

  1. uCore代码
  2. kern
  3. fs
  4. sfs

sfs_fs.c

#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);
}
Previoussfs.cNextsfs.h

Last updated 5 years ago

Was this helpful?