static int sfs_rename2_nolock(struct sfs_fs *sfs, struct sfs_inode *sin, const char *name, struct sfs_inode *newsin, const char *new_name) { uint32_t ino; int ret, slot1, slot2; if ((ret = sfs_dirent_search_nolock(sfs, sin, name, &ino, &slot1, NULL)) != 0) { return ret; } if ((ret = sfs_dirent_search_nolock(sfs, newsin, new_name, NULL, NULL, &slot2)) != -E_NOENT) { return (ret != 0) ? ret : -E_EXISTS; } struct inode *link_node; if ((ret = sfs_load_inode(sfs, &link_node, ino)) != 0) { return ret; } struct sfs_inode *lnksin = vop_info(link_node, sfs_inode); if ((ret = sfs_dirent_unlink_nolock(sfs, sin, slot1, lnksin)) != 0) { goto out; } int isdir = (lnksin->din->type == SFS_TYPE_DIR); /* remove '..' link from old parent */ if (isdir) { sfs_nlinks_dec_nolock(sin); } /* if link fails try to recover its old link */ if ((ret = sfs_dirent_link_nolock(sfs, newsin, slot2, lnksin, new_name)) != 0) { if (sfs_dirent_link_nolock_check(sfs, sin, slot1, lnksin, name) == 0) { if (isdir) { sfs_nlinks_inc_nolock(sin); } } goto out; } if (isdir) { /* set '..' link to new directory */ sfs_nlinks_inc_nolock(newsin); /* update parent relationship */ sfs_dirinfo_set_parent(lnksin, newsin); } out: vop_ref_dec(link_node); return ret; }
static int sfs_rename1_nolock(struct sfs_fs *sfs, struct sfs_inode *sin, const char *name, const char *new_name) { if (strcmp(name, new_name) == 0) { return 0; } int ret, slot; uint32_t ino; if ((ret = sfs_dirent_search_nolock(sfs, sin, name, &ino, &slot, NULL)) != 0) { return ret; } if ((ret = sfs_dirent_search_nolock(sfs, sin, new_name, NULL, NULL, NULL)) != -E_NOENT) { return (ret != 0) ? ret : -E_EXISTS; } return sfs_dirent_write_nolock(sfs, sin, slot, ino, new_name); }
static int sfs_mkdir_nolock(struct sfs_fs *sfs, struct sfs_inode *sin, const char *name) { int ret, slot; if ((ret = sfs_dirent_search_nolock(sfs, sin, name, NULL, NULL, &slot)) != -E_NOENT) { return (ret != 0) ? ret : -E_EXISTS; } struct inode *link_node; if ((ret = sfs_dirent_create_inode(sfs, SFS_TYPE_DIR, &link_node)) != 0) { return ret; } struct sfs_inode *lnksin = vop_info(link_node, sfs_inode); if ((ret = sfs_dirent_link_nolock(sfs, sin, slot, lnksin, name)) != 0) { assert(lnksin->din->nlinks == 0); assert(inode_ref_count(link_node) == 1 && inode_open_count(link_node) == 0); goto out; } /* set parent */ sfs_dirinfo_set_parent(lnksin, sin); /* add '.' link to itself */ sfs_nlinks_inc_nolock(lnksin); /* add '..' link to parent */ sfs_nlinks_inc_nolock(sin); out: vop_ref_dec(link_node); return ret; }
static int sfs_create_nolock(struct sfs_fs *sfs, struct sfs_inode *sin, const char *name, bool excl, struct inode **node_store) { int ret, slot; uint32_t ino; struct inode *link_node; if ((ret = sfs_dirent_search_nolock(sfs, sin, name, &ino, NULL, &slot)) != -E_NOENT) { if (ret != 0) { return ret; } if (!excl) { if ((ret = sfs_load_inode(sfs, &link_node, ino)) != 0) { return ret; } if (vop_info(link_node, sfs_inode)->din->type == SFS_TYPE_FILE) { goto out; } vop_ref_dec(link_node); } return -E_EXISTS; } else { if ((ret = sfs_dirent_create_inode(sfs, SFS_TYPE_FILE, &link_node)) != 0) { return ret; } if ((ret = sfs_dirent_link_nolock(sfs, sin, slot, vop_info(link_node, sfs_inode), name)) != 0) { vop_ref_dec(link_node); return ret; } } out: *node_store = link_node; return 0; }
static int sfs_link_nolock(struct sfs_fs *sfs, struct sfs_inode *sin, struct sfs_inode *lnksin, const char *name) { int ret, slot; if ((ret = sfs_dirent_search_nolock(sfs, sin, name, NULL, NULL, &slot)) != -E_NOENT) { return (ret != 0) ? ret : -E_EXISTS; } return sfs_dirent_link_nolock(sfs, sin, slot, lnksin, name); }
static int sfs_lookup_once(struct sfs_fs *sfs, struct sfs_inode *sin, const char *name, struct inode **node_store, int *slot) { int ret; uint32_t ino; lock_sin(sin); { ret = sfs_dirent_search_nolock(sfs, sin, name, &ino, slot, NULL); } unlock_sin(sin); if (ret == 0) { ret = sfs_load_inode(sfs, node_store, ino); } return ret; }
/* * sfs_lookup_once - find inode corresponding the file name in DIR's sin inode * @sfs: sfs file system * @sin: DIR sfs inode in memory * @name: the file name in DIR * @node_store: the inode corresponding the file name in DIR * @slot: the logical index of file entry */ static int sfs_lookup_once(struct sfs_fs *sfs, struct sfs_inode *sin, const char *name, struct inode **node_store, int *slot) { int ret; uint32_t ino; lock_sin(sin); { // find the NO. of disk block and logical index of file entry ret = sfs_dirent_search_nolock(sfs, sin, name, &ino, slot, NULL); } unlock_sin(sin); if (ret == 0) { // load the content of inode with the the NO. of disk block ret = sfs_load_inode(sfs, node_store, ino); } return ret; }
static int sfs_unlink_nolock(struct sfs_fs *sfs, struct sfs_inode *sin, const char *name) { int ret, slot; uint32_t ino; if ((ret = sfs_dirent_search_nolock(sfs, sin, name, &ino, &slot, NULL)) != 0) { return ret; } struct inode *link_node; if ((ret = sfs_load_inode(sfs, &link_node, ino)) != 0) { return ret; } struct sfs_inode *lnksin = vop_info(link_node, sfs_inode); if (lnksin->din->type != SFS_TYPE_DIR) { ret = sfs_dirent_unlink_nolock(sfs, sin, slot, lnksin); } else { if ((ret = trylock_sin(lnksin)) == 0) { if (lnksin->din->dirinfo.slots != 0) { ret = -E_NOTEMPTY; } else if ((ret = sfs_dirent_unlink_nolock(sfs, sin, slot, lnksin)) == 0) { /* lnksin must be empty, so set SFS_removed bit to invalidate further trylock opts */ SetSFSInodeRemoved(lnksin); /* remove '.' link */ sfs_nlinks_dec_nolock(lnksin); /* remove '..' link */ sfs_nlinks_dec_nolock(sin); } unlock_sin(lnksin); } } vop_ref_dec(link_node); 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; }