static int sfs_reclaim(struct inode *node) { struct sfs_fs *sfs = fsop_info(vop_fs(node), sfs); struct sfs_inode *sin = vop_info(node, sfs_inode); lock_sfs_fs(sfs); int ret = -E_BUSY; assert(sin->reclaim_count > 0); if ((-- sin->reclaim_count) != 0) { goto failed_unlock; } assert(inode_ref_count(node) == 0 && inode_open_count(node) == 0); if (sin->din->nlinks == 0) { uint32_t nblks; for (nblks = sin->din->blocks; nblks != 0; nblks --) { sfs_bmap_truncate_nolock(sfs, sin); } } else if (sin->dirty) { if ((ret = vop_fsync(node)) != 0) { goto failed_unlock; } } sfs_remove_links(sin); unlock_sfs_fs(sfs); if (sin->din->nlinks == 0) { sfs_block_free(sfs, sin->ino); uint32_t ent; if ((ent = sin->din->indirect) != 0) { sfs_block_free(sfs, ent); } if ((ent = sin->din->db_indirect) != 0) { int i; for (i = 0; i < SFS_BLK_NENTRY; i ++) { sfs_bmap_free_sub_nolock(sfs, ent, i); } sfs_block_free(sfs, ent); } } kfree(sin->din); vop_kill(node); return 0; failed_unlock: unlock_sfs_fs(sfs); return ret; }
// 同步文件块 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; }
static int sfs_dirent_create_inode(struct sfs_fs *sfs, uint16_t type, struct inode **node_store) { struct sfs_disk_inode *din; if ((din = kmalloc(sizeof(struct sfs_disk_inode))) == NULL) { return -E_NO_MEM; } memset(din, 0, sizeof(struct sfs_disk_inode)); din->type = type; int ret; uint32_t ino; if ((ret = sfs_block_alloc(sfs, &ino)) != 0) { goto failed_cleanup_din; } struct inode *node; if ((ret = sfs_create_inode(sfs, din, ino, &node)) != 0) { goto failed_cleanup_ino; } lock_sfs_fs(sfs); { sfs_set_links(sfs, vop_info(node, sfs_inode)); } unlock_sfs_fs(sfs); *node_store = node; return 0; failed_cleanup_ino: sfs_block_free(sfs, ino); failed_cleanup_din: kfree(din); return ret; }
static int sfs_sync(struct fs *fs) { struct sfs_fs *sfs = fsop_info(fs, sfs); lock_sfs_fs(sfs); /* * Get the sfs_fs from the generic abstract fs. * * Note that the abstract struct fs, which is all the VFS * layer knows about, is actually a member of struct sfs_fs. * The pointer in the struct fs points back to the top of the * struct sfs_fs - essentially the same object. This can be a * little confusing at first. * * The following diagram may help: * * struct sfs_fs <-----------------\ * : | * : sfs_absfs (struct fs) | <------\ * : : | | * : : various members | | * : : | | * : : fs_info(__sfs_info) ---/ | * : : ...|... * : . VFS . * : . layer . * : other members ....... * : * : * * This construct is repeated with inodes and devices and other * similar things all over the place in ucore, so taking the * time to straighten it out in your mind is worthwhile. */ { 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 the superblock needs to be written, write it. */ if ((ret = sfs_sync_super(sfs)) != 0) { sfs->super_dirty = 1; return ret; } /* If the free block map needs to be written, write it. */ if ((ret = sfs_sync_freemap(sfs)) != 0) { sfs->super_dirty = 1; return ret; } } return 0; }
int sfs_load_inode(struct sfs_fs *sfs, struct inode **node_store, uint32_t ino) { // while (1); lock_sfs_fs(sfs); struct inode *node; if ((node = lookup_sfs_nolock(sfs, ino)) != NULL) { goto out_unlock; } int ret = -E_NO_MEM; struct sfs_disk_inode *din; if ((din = kmalloc(sizeof(struct sfs_disk_inode))) == NULL) { goto failed_unlock; } // kprintf("in %s: ino is %d\n", __func__, ino); // while (1); // kprintf("%s\n", __func__); assert(sfs_block_inuse(sfs, ino)); if ((ret = sfs_rbuf(sfs, din, sizeof(struct sfs_disk_inode), ino, 0)) != 0) { goto failed_cleanup_din; } assert(_SFS_INODE_GET_NLINKS(din) != 0); if ((ret = sfs_create_inode(sfs, din, ino, &node)) != 0) { goto failed_cleanup_din; } sfs_set_links(sfs, vop_info(node, sfs_inode)); out_unlock: unlock_sfs_fs(sfs); *node_store = node; return 0; failed_cleanup_din: kfree(din); failed_unlock: unlock_sfs_fs(sfs); return ret; }
static int sfs_sync(struct fs *fs) { // debug // int u; // kprintf("--- %d ---\n", 1); // for (u = _initrd_begin; u < _initrd_end; ++u) { // kprintf("%02x ", *((char *)u)); // } // kprintf("\n"); 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); // kprintf("--- %d ---\n", 2); // for (u = _initrd_begin; u < _initrd_end; ++u) { // kprintf("%02x ", *((char *)u)); // } // kprintf("\n"); 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; } } // kprintf("--- %d ---\n", 3); // for (u = _initrd_begin; u < _initrd_end; ++u) { // kprintf("%02x ", *((char *)u)); // } // kprintf("\n"); swapper_all_block_sync(); return 0; }
/* * sfs_reclaim - Free all resources inode occupied . Called when inode is no longer in use. */ static int sfs_reclaim(struct inode *node) { struct sfs_fs *sfs = fsop_info(vop_fs(node), sfs); struct sfs_inode *sin = vop_info(node, sfs_inode); int ret = -E_BUSY; uint32_t ent; lock_sfs_fs(sfs); assert(sin->reclaim_count > 0); if ((-- sin->reclaim_count) != 0 || inode_ref_count(node) != 0) { goto failed_unlock; } if (sin->din->nlinks == 0) { if ((ret = vop_truncate(node, 0)) != 0) { goto failed_unlock; } } if (sin->dirty) { if ((ret = vop_fsync(node)) != 0) { goto failed_unlock; } } sfs_remove_links(sin); unlock_sfs_fs(sfs); if (sin->din->nlinks == 0) { sfs_block_free(sfs, sin->ino); if ((ent = sin->din->indirect) != 0) { sfs_block_free(sfs, ent); } } kfree(sin->din); vop_kill(node); return 0; failed_unlock: unlock_sfs_fs(sfs); return ret; }
/* * sfs_load_inode - If the inode isn't existed, load inode related ino disk block data into a new created inode. * If the inode is in memory alreadily, then do nothing */ int sfs_load_inode(struct sfs_fs *sfs, struct inode **node_store, uint32_t ino) { lock_sfs_fs(sfs); struct inode *node; if ((node = lookup_sfs_nolock(sfs, ino)) != NULL) { goto out_unlock; } int ret = -E_NO_MEM; struct sfs_disk_inode *din; if ((din = kmalloc(sizeof(struct sfs_disk_inode))) == NULL) { goto failed_unlock; } assert(sfs_block_inuse(sfs, ino)); if ((ret = sfs_rbuf(sfs, din, sizeof(struct sfs_disk_inode), ino, 0)) != 0) { goto failed_cleanup_din; } assert(din->nlinks != 0); if ((ret = sfs_create_inode(sfs, din, ino, &node)) != 0) { goto failed_cleanup_din; } sfs_set_links(sfs, vop_info(node, sfs_inode)); out_unlock: unlock_sfs_fs(sfs); *node_store = node; return 0; failed_cleanup_din: kfree(din); failed_unlock: unlock_sfs_fs(sfs); return ret; }
static int sfs_create(struct inode *node, const char *name, bool excl, struct inode **node_store) { // kprintf("ready to create a file\n"); if (strlen(name) > SFS_MAX_FNAME_LEN) { return -1; } // sfs_create_inode(struct sfs_fs *sfs, struct sfs_disk_inode *din, uint32_t ino, struct inode **node_store) struct sfs_fs *sfs = fsop_info(vop_fs(node), sfs); struct sfs_inode *sin = vop_info(node, sfs_inode); int ret; // sfs_create_inode(struct sfs_fs *sfs, struct sfs_disk_inode *din, uint32_t ino, struct inode **node_store) struct inode *node_tmp = NULL; int empty_slot = -1; lock_sfs_fs(sfs); // sfs_block_alloc(struct sfs_fs *sfs, uint32_t *ino_store) sfs_dirent_search_nolock(sfs, sin, name, node_tmp, NULL, &empty_slot); // kprintf("%s\n", __func__); if (node_tmp) { node_store = node_tmp; } else { if (empty_slot < 0) { kprintf("no slot\n"); return -1; } struct sfs_disk_inode *din = alloc_disk_inode(SFS_TYPE_FILE); int ino; sfs_block_alloc(sfs, &ino); // kprintf("%s\n", __func__); // if (sfs_block_inuse(sfs, ino)) { // kprintf("be sure use\n"); // } else { // kprintf("not used\n"); // } sfs_create_inode(sfs, din, ino, &node_tmp); ++ (din->__nlinks__); sfs_set_links(sfs, vop_info(node_tmp, sfs_inode)); // kprintf("0x%08x\n", node_tmp); // sfs_namefile(struct inode *node, struct iobuf *iob) // sfs_dirent_write_nolock(struct sfs_fs *sfs, struct sfs_inode *sin, int slot, uint32_t ino, const char *name) sfs_dirent_write_nolock(sfs, sin, empty_slot, ino, name); // ++ sin->din->blocks; int secno = ram2block(ino); swapper_block_changed(secno); swapper_block_late_sync(secno); // kprintf("sin->ino is %d\n", sin->ino); sin->dirty = 1; lock_sin(sin); { if (sin->dirty) { sin->dirty = 0; if ((ret = sfs_wbuf(sfs, sin->din, sizeof(struct sfs_disk_inode), sin->ino, 0)) != 0) { sin->dirty = 1; } } } unlock_sin(sin); secno = ram2block(sin->ino); swapper_block_changed(secno); swapper_block_late_sync(secno); vop_info(node_tmp, sfs_inode)->dirty = 1; sfs->super_dirty = 1; // if ((ret = sfs_bmap_load_nolock(sfs, sin, slot, &ino)) != 0) { // return ret; // } // assert(sfs_block_inuse(sfs, ino)); // kprintf("ino is %d\n", ino); // kprintf("empty slot is %d\n", empty_slot); // kprintf("father ino is %d\n", sin->ino); *node_store = node_tmp; } unlock_sfs_fs(sfs); // sfs_create_inode(sfs, struct sfs_disk_inode *din, uint32_t ino, struct inode **node_store) return 0; }