/* * sfs_bmap_get_sub_nolock - according entry pointer entp and index, find the index of indrect disk block * return the index of indrect disk block to ino_store. no lock protect * @sfs: sfs file system * @entp: the pointer of index of entry disk block * @index: the index of block in indrect block * @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_sub_nolock(struct sfs_fs *sfs, uint32_t *entp, uint32_t index, bool create, uint32_t *ino_store) { assert(index < SFS_BLK_NENTRY); int ret; uint32_t ent, ino = 0; off_t offset = index * sizeof(uint32_t); // the offset of entry in entry block // if entry block is existd, read the content of entry block into sfs->sfs_buffer if ((ent = *entp) != 0) { if ((ret = sfs_rbuf(sfs, &ino, sizeof(uint32_t), ent, offset)) != 0) { return ret; } if (ino != 0 || !create) { goto out; } } else { if (!create) { goto out; } //if entry block isn't existd, allocated a entry block (for indrect block) if ((ret = sfs_block_alloc(sfs, &ent)) != 0) { return ret; } } if ((ret = sfs_block_alloc(sfs, &ino)) != 0) { goto failed_cleanup; } if ((ret = sfs_wbuf(sfs, &ino, sizeof(uint32_t), ent, offset)) != 0) { sfs_block_free(sfs, ino); goto failed_cleanup; } out: if (ent != *entp) { *entp = ent; } *ino_store = ino; return 0; failed_cleanup: if (ent != *entp) { sfs_block_free(sfs, ent); } return ret; }
/* * 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; }
static int sfs_bmap_get_sub_nolock(struct sfs_fs *sfs, uint32_t *entp, uint32_t index, bool create, uint32_t *ino_store) { assert(index < SFS_BLK_NENTRY); int ret; uint32_t ent, ino = 0; off_t offset = index * sizeof(uint32_t); if ((ent = *entp) != 0) { if ((ret = sfs_rbuf(sfs, &ino, sizeof(uint32_t), ent, offset)) != 0) { return ret; } if (ino != 0 || !create) { goto out; } } else { if (!create) { goto out; } if ((ret = sfs_block_alloc(sfs, &ent)) != 0) { return ret; } } if ((ret = sfs_block_alloc(sfs, &ino)) != 0) { goto failed_cleanup; } if ((ret = sfs_wbuf(sfs, &ino, sizeof(uint32_t), ent, offset)) != 0) { sfs_block_free(sfs, ino); goto failed_cleanup; } out: if (ent != *entp) { *entp = ent; } *ino_store = ino; return 0; failed_cleanup: if (ent != *entp) { sfs_block_free(sfs, ent); } return ret; }
/* * sfs_fsync - Force any dirty inode info associated with this file to stable storage. */ static int sfs_fsync(struct inode *node) { struct sfs_fs *sfs = fsop_info(vop_fs(node), sfs); struct sfs_inode *sin = vop_info(node, sfs_inode); int ret = 0; if (sin->dirty) { 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); } return ret; }
static int sfs_fsync(struct inode *node) { struct sfs_fs *sfs = fsop_info(vop_fs(node), sfs); struct sfs_inode *sin = vop_info(node, sfs_inode); if (sin->din->nlinks == 0 || !sin->dirty) { return 0; } int ret; if ((ret = trylock_sin(sin)) != 0) { return ret; } 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); return ret; }
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; }
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; }
static int sfs_fsync(struct inode *node) { struct sfs_fs *sfs = fsop_info(vop_fs(node), sfs); struct sfs_inode *sin = vop_info(node, sfs_inode); int ret = 0; // if (sfs->super_dirty) { // lock_sfs_fs(sfs); // if (sfs->super_dirty) { // sfs->super_dirty = 0; // if ((ret = sfs_wbuf(sfs, sfs->freemap, sizeof(uint32_t) * 400, 1, 0)) != 0) { // // sfs_wbuf(struct sfs_fs *sfs, void *buf, size_t len, uint32_t blkno, off_t offset) // sfs->super_dirty = 1; // } // } // unlock_sfs_fs(sfs); // } if (sfs->super_dirty) { sfs_sync_super(sfs); sfs_sync_freemap(sfs); swapper_block_changed(0); } int secno = -1; if (sin->dirty) { 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; } } } // int secno = 0; // kprintf("in %s: sin->din is %d sin->ino is %d\n", __func__, sin->din, sin->ino); int tmp_din = sin->ino; while (tmp_din >= 0) { secno += 1; // start from `-1` tmp_din -= 32; } unlock_sin(sin); } // kprintf("secno is %d sfs->super_dirty is %s\n", secno, sfs->super_dirty ? "true" : "false"); // assert((secno < 0 && !sfs->super_dirty) || (secno >= 0 && sfs->super_dirty)); if (secno != 0) { // kprintf("sync is secno %d\n", secno); if (sfs->super_dirty) { sfs->super_dirty = 0; swapper_block_sync(0); } if (secno > 0) { swapper_block_sync(secno); } } if (secno == 0) { swapper_block_sync(0); } swapper_block_real_sync(); // kprintf("super->unused_blocks is %d\n", sfs->super.unused_blocks); // uint16_t *begin = (uint16_t *)_initrd_begin; // int item = 0; // for (item = 0; item < 4000; ++item) { // kprintf("0x%04x ", begin[item]); // } // kprintf("in %s: %d is %s and addr. of sfs is 0x%08x addr. of freemap is 0x%08x\n", // __func__, 436, sfs_block_inuse(sfs, 436)?"used":"free", sfs, sfs->freemap); return ret; }