static int sfs_gettype(struct inode *node, uint32_t *type_store) { struct sfs_disk_inode *din = vop_info(node, sfs_inode)->din; switch (_SFS_INODE_GET_TYPE(din)) { case SFS_TYPE_DIR: *type_store = S_IFDIR; return 0; case SFS_TYPE_FILE: *type_store = S_IFREG; return 0; case SFS_TYPE_LINK: *type_store = S_IFLNK; return 0; } panic("invalid file type %d.\n", _SFS_INODE_GET_TYPE(din)); }
static int sfs_create_inode(struct sfs_fs *sfs, struct sfs_disk_inode *din, uint32_t ino, struct inode **node_store) { struct inode *node; if ((node = alloc_inode(sfs_inode)) != NULL) { vop_init(node, sfs_get_ops(_SFS_INODE_GET_TYPE(din)), info2fs(sfs, sfs)); struct sfs_inode *sin = vop_info(node, sfs_inode); sin->din = din, sin->ino = ino, sin->dirty = 0, sin->reclaim_count = 1; sem_init(&(sin->sem), 1); *node_store = node; return 0; } return -E_NO_MEM; }
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; }
static int sfs_lookup(struct inode *node, char *path, struct inode **node_store) { struct sfs_fs *sfs = fsop_info(vop_fs(node), sfs); assert(*path != '\0' && *path != '/'); vop_ref_inc(node); struct sfs_inode *sin = vop_info(node, sfs_inode); if (_SFS_INODE_GET_TYPE(sin->din) != SFS_TYPE_DIR) { vop_ref_dec(node); return -E_NOTDIR; } struct inode *subnode; int ret = sfs_lookup_once(sfs, sin, path, &subnode, NULL); vop_ref_dec(node); if (ret != 0) { return ret; } *node_store = subnode; 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)); // 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(_SFS_INODE_GET_TYPE(sin->din) == SFS_TYPE_DIR && (slot >= 0 && slot <= sin->din->blocks)); struct sfs_disk_entry *entry; if ((entry = kmalloc(sizeof(struct sfs_disk_entry))) == NULL) { return -1; } 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 wirte_out; } // kprintf("heheh\n"); assert(sfs_block_inuse(sfs, ino)); ret = sfs_wbuf(sfs, entry, sizeof(struct sfs_disk_entry), ino, 0); wirte_out: kfree(entry); return ret; }
static int sfs_namefile(struct inode *node, struct iobuf *iob) { struct sfs_disk_entry *entry; if (iob->io_resid <= 2 || (entry = kmalloc(sizeof(struct sfs_disk_entry))) == NULL) { return -E_NO_MEM; } struct sfs_fs *sfs = fsop_info(vop_fs(node), sfs); struct sfs_inode *sin = vop_info(node, sfs_inode); int ret; char *ptr = iob->io_base + iob->io_resid; size_t alen, resid = iob->io_resid - 2; vop_ref_inc(node); while (1) { struct inode *parent; if ((ret = sfs_lookup_once(sfs, sin, "..", &parent, NULL)) != 0) { goto failed; } uint32_t ino = sin->ino; vop_ref_dec(node); if (node == parent) { vop_ref_dec(node); break; } node = parent, sin = vop_info(node, sfs_inode); assert(ino != sin->ino && _SFS_INODE_GET_TYPE(sin->din) == SFS_TYPE_DIR); lock_sin(sin); { ret = sfs_dirent_findino_nolock(sfs, sin, ino, entry); } unlock_sin(sin); if (ret != 0) { goto failed; } if ((alen = strlen(entry->name) + 1) > resid) { goto failed_nomem; } resid -= alen, ptr -= alen; memcpy(ptr, entry->name, alen - 1); ptr[alen - 1] = '/'; } alen = iob->io_resid - resid - 2; ptr = memmove(iob->io_base + 1, ptr, alen); ptr[-1] = '/', ptr[alen] = '\0'; iobuf_skip(iob, alen); kfree(entry); return 0; failed_nomem: ret = -E_NO_MEM; failed: vop_ref_dec(node); kfree(entry); return ret; }
static int sfs_io_nolock(struct sfs_fs *sfs, struct sfs_inode *sin, void *buf, off_t offset, size_t *alenp, bool write) { struct sfs_disk_inode *din = sin->din; assert(_SFS_INODE_GET_TYPE(din) != SFS_TYPE_DIR); off_t endpos = offset + *alenp, blkoff; *alenp = 0; if (offset < 0 || offset >= SFS_MAX_FILE_SIZE || offset > endpos) { return -E_INVAL; } if (offset == endpos) { return 0; } if (endpos > SFS_MAX_FILE_SIZE) { endpos = SFS_MAX_FILE_SIZE; } if (!write) { if (offset >= din->size) { return 0; } if (endpos > din->size) { endpos = din->size; } } int (*sfs_buf_op)(struct sfs_fs *sfs, void *buf, size_t len, uint32_t blkno, off_t offset); int (*sfs_block_op)(struct sfs_fs *sfs, void *buf, uint32_t blkno, uint32_t nblks); if (write) { sfs_buf_op = sfs_wbuf, sfs_block_op = sfs_wblock; } else { sfs_buf_op = sfs_rbuf, sfs_block_op = sfs_rblock; } int ret = 0; size_t size, alen = 0; uint32_t ino; uint32_t blkno = offset / SFS_BLKSIZE; uint32_t nblks = endpos / SFS_BLKSIZE - blkno; //LAB8:EXERCISE1 2009010989 HINT: call sfs_bmap_load_nolock, sfs_rbuf, sfs_rblock,etc. read different kind of blocks in file if((blkoff = offset % SFS_BLKSIZE)!= 0) { if(nblks){ size = SFS_BLKSIZE - blkoff; }else{ size = endpos - offset; } if ((ret = sfs_bmap_load_nolock(sfs, sin, blkno, &ino)) != 0) { goto out; } if ((ret = sfs_buf_op(sfs, buf, size, ino, blkoff)) != 0) { goto out; } // add if (write) { // kprintf("write secno %d\n", ino); int secno = ram2block(ino); swapper_block_changed(secno); swapper_block_late_sync(secno); } alen += size; if (nblks == 0) { goto out; } buf += size, blkno ++, nblks --; } size = SFS_BLKSIZE; while(nblks != 0){ if((ret = sfs_bmap_load_nolock(sfs, sin, blkno, &ino)) != 0) { goto out; } if((ret = sfs_block_op(sfs, buf, ino, 1)) != 0) { goto out; } alen += size, buf += size, blkno ++, nblks --; // add if (write) { // kprintf("write secno %d\n", ino); int secno = ram2block(ino); swapper_block_changed(secno); swapper_block_late_sync(secno); } } if((size = endpos % SFS_BLKSIZE) != 0) { if ((ret = sfs_bmap_load_nolock(sfs, sin, blkno, &ino)) != 0) { goto out; } if ((ret = sfs_buf_op(sfs, buf, size, ino, 0)) != 0) { goto out; } alen += size; // add if (write) { // kprintf("write secno %d\n", ino); int secno = ram2block(ino); swapper_block_changed(secno); swapper_block_late_sync(secno); } } out: *alenp = alen; if (offset + alen > sin->din->size) { sin->din->size = offset + alen; sin->dirty = 1; } return ret; }