static void sfs_block_free(struct sfs_fs *sfs, uint32_t ino) { // kprintf("%s\n", __func__); assert(sfs_block_inuse(sfs, ino)); bitmap_free(sfs->freemap, ino); sfs->super.unused_blocks ++, sfs->super_dirty = 1; }
/* * sfs_block_alloc - check and get a free disk block */ static int sfs_block_alloc(struct sfs_fs *sfs, uint32_t *ino_store) { int ret; if ((ret = bitmap_alloc(sfs->freemap, ino_store)) != 0) { return ret; } assert(sfs->super.unused_blocks > 0); sfs->super.unused_blocks --, sfs->super_dirty = 1; assert(sfs_block_inuse(sfs, *ino_store)); return sfs_clear_block(sfs, *ino_store, 1); }
static int sfs_bmap_get_nolock(struct sfs_fs *sfs, struct sfs_inode *sin, uint32_t index, bool create, uint32_t *ino_store) { struct sfs_disk_inode *din = sin->din; int ret; uint32_t ent, ino; if (index < SFS_NDIRECT) { if ((ino = din->direct[index]) == 0 && create) { if ((ret = sfs_block_alloc(sfs, &ino)) != 0) { return ret; } din->direct[index] = ino; sin->dirty = 1; } goto out; } index -= SFS_NDIRECT; if (index < SFS_BLK_NENTRY) { ent = din->indirect; if ((ret = sfs_bmap_get_sub_nolock(sfs, &ent, index, create, &ino)) != 0) { return ret; } if (ent != din->indirect) { assert(din->indirect == 0); din->indirect = ent; sin->dirty = 1; } goto out; } index -= SFS_BLK_NENTRY; ent = din->db_indirect; if ((ret = sfs_bmap_get_sub_nolock(sfs, &ent, index / SFS_BLK_NENTRY, create, &ino)) != 0) { return ret; } if (ent != din->db_indirect) { assert(din->db_indirect == 0); din->db_indirect = ent; sin->dirty = 1; } if ((ent = ino) != 0) { if ((ret = sfs_bmap_get_sub_nolock(sfs, &ent, index % SFS_BLK_NENTRY, create, &ino)) != 0) { return ret; } } out: assert(ino == 0 || sfs_block_inuse(sfs, ino)); *ino_store = ino; return 0; }
static int sfs_dirent_read_nolock(struct sfs_fs *sfs, struct sfs_inode *sin, int slot, struct sfs_disk_entry *entry) { assert(_SFS_INODE_GET_TYPE(sin->din) == SFS_TYPE_DIR && (slot >= 0 && slot < sin->din->blocks)); int ret; uint32_t ino; if ((ret = sfs_bmap_load_nolock(sfs, sin, slot, &ino)) != 0) { return ret; } assert(sfs_block_inuse(sfs, ino)); if ((ret = sfs_rbuf(sfs, entry, sizeof(struct sfs_disk_entry), ino, 0)) != 0) { return ret; } entry->name[SFS_MAX_FNAME_LEN] = '\0'; return 0; }
/* * sfs_dirent_read_nolock - read the file entry from disk block which contains this entry * @sfs: sfs file system * @sin: sfs inode in memory * @slot: the index of file entry * @entry: file entry */ static int sfs_dirent_read_nolock(struct sfs_fs *sfs, struct sfs_inode *sin, int slot, struct sfs_disk_entry *entry) { assert(sin->din->type == SFS_TYPE_DIR && (slot >= 0 && slot < sin->din->blocks)); int ret; uint32_t ino; // according to the DIR's inode and the slot of file entry, find the index of disk block which contains this file entry if ((ret = sfs_bmap_load_nolock(sfs, sin, slot, &ino)) != 0) { return ret; } assert(sfs_block_inuse(sfs, ino)); // read the content of file entry in the disk block if ((ret = sfs_rbuf(sfs, entry, sizeof(struct sfs_disk_entry), ino, 0)) != 0) { return ret; } entry->name[SFS_MAX_FNAME_LEN] = '\0'; return 0; }
/* * sfs_bmap_free_sub_nolock - set the entry item to 0 (free) in the indirect block */ static int sfs_bmap_free_sub_nolock(struct sfs_fs *sfs, uint32_t ent, uint32_t index) { assert(sfs_block_inuse(sfs, ent) && index < SFS_BLK_NENTRY); int ret; uint32_t ino, zero = 0; off_t offset = index * sizeof(uint32_t); if ((ret = sfs_rbuf(sfs, &ino, sizeof(uint32_t), ent, offset)) != 0) { return ret; } if (ino != 0) { if ((ret = sfs_wbuf(sfs, &zero, sizeof(uint32_t), ent, offset)) != 0) { return ret; } sfs_block_free(sfs, ino); } return 0; }
/* * sfs_bmap_load_nolock - according to the DIR's inode and the logical index of block in inode, find the NO. of disk block. * @sfs: sfs file system * @sin: sfs inode in memory * @index: the logical index of disk block in inode * @ino_store:the NO. of disk block */ static int sfs_bmap_load_nolock(struct sfs_fs *sfs, struct sfs_inode *sin, uint32_t index, uint32_t *ino_store) { struct sfs_disk_inode *din = sin->din; assert(index <= din->blocks); int ret; uint32_t ino; bool create = (index == din->blocks); if ((ret = sfs_bmap_get_nolock(sfs, sin, index, create, &ino)) != 0) { return ret; } assert(sfs_block_inuse(sfs, ino)); if (create) { din->blocks ++; } if (ino_store != NULL) { *ino_store = ino; } 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_dirent_read_nolock(struct sfs_fs *sfs, struct sfs_inode *sin, int slot, struct sfs_disk_entry *entry) { assert(_SFS_INODE_GET_TYPE(sin->din) == SFS_TYPE_DIR && (slot >= 0 && slot < sin->din->blocks)); // kprintf("%s\n", __func__); int ret; uint32_t ino; if ((ret = sfs_bmap_load_nolock(sfs, sin, slot, &ino)) != 0) { return ret; } // kprintf("%s and ino is %d\n", __func__, ino); // if (ino == -1) { // kprintf("%d\n", __LINE__); // } assert(sfs_block_inuse(sfs, ino)); if ((ret = sfs_rbuf(sfs, entry, sizeof(struct sfs_disk_entry), ino, 0)) != 0) { return ret; } entry->name[SFS_MAX_FNAME_LEN] = '\0'; // kprintf("%s finish inner\n", __func__); return 0; }
static int sfs_dirent_write_nolock(struct sfs_fs *sfs, struct sfs_inode *sin, int slot, uint32_t ino, const char *name) { assert(sin->din->type == SFS_TYPE_DIR && (slot >= 0 && slot <= sin->din->blocks)); struct sfs_disk_entry *entry; if ((entry = kmalloc(sizeof(struct sfs_disk_entry))) == NULL) { return -E_NO_MEM; } memset(entry, 0, sizeof(struct sfs_disk_entry)); if (ino != 0) { assert(strlen(name) <= SFS_MAX_FNAME_LEN); entry->ino = ino, strcpy(entry->name, name); } int ret; if ((ret = sfs_bmap_load_nolock(sfs, sin, slot, &ino)) != 0) { goto out; } assert(sfs_block_inuse(sfs, ino)); ret = sfs_wbuf(sfs, entry, sizeof(struct sfs_disk_entry), ino, 0); out: kfree(entry); return ret; }
/* * sfs_bmap_get_nolock - according sfs_inode and index of block, find the NO. of disk block * no lock protect * @sfs: sfs file system * @sin: sfs inode in memory * @index: the index of block in inode * @create: BOOL, if the block isn't allocated, if create = 1 the alloc a block, otherwise just do nothing * @ino_store: 0 OR the index of already inused block or new allocated block. */ static int sfs_bmap_get_nolock(struct sfs_fs *sfs, struct sfs_inode *sin, uint32_t index, bool create, uint32_t *ino_store) { struct sfs_disk_inode *din = sin->din; int ret; uint32_t ent, ino; // the index of disk block is in the fist SFS_NDIRECT direct blocks if (index < SFS_NDIRECT) { if ((ino = din->direct[index]) == 0 && create) { if ((ret = sfs_block_alloc(sfs, &ino)) != 0) { return ret; } din->direct[index] = ino; sin->dirty = 1; } goto out; } // the index of disk block is in the indirect blocks. index -= SFS_NDIRECT; if (index < SFS_BLK_NENTRY) { ent = din->indirect; if ((ret = sfs_bmap_get_sub_nolock(sfs, &ent, index, create, &ino)) != 0) { return ret; } if (ent != din->indirect) { assert(din->indirect == 0); din->indirect = ent; sin->dirty = 1; } goto out; } else { panic ("sfs_bmap_get_nolock - index out of range"); } out: assert(ino == 0 || sfs_block_inuse(sfs, ino)); *ino_store = ino; return 0; }
/* * 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; }
/* * sfs_block_free - set related bits for ino block to 1(means free) in bitmap, add sfs->super.unused_blocks, set superblock dirty * */ static void sfs_block_free(struct sfs_fs *sfs, uint32_t ino) { assert(sfs_block_inuse(sfs, ino)); bitmap_free(sfs->freemap, ino); sfs->super.unused_blocks ++, sfs->super_dirty = 1; }