int release(fs_context& fs, const char* path, fuse_file_info* fi) { if (ffsp::is_debug_path(fs, path)) return ffsp::debug_release(fs, path) ? 0 : -EIO; set_inode(fi, nullptr); return 0; }
int open(fs_context& fs, const char* path, fuse_file_info* fi) { if (ffsp::is_debug_path(fs, path)) return ffsp::debug_open(fs, path) ? 0 : -EIO; inode* ino; int rc = ffsp::lookup(fs, &ino, path); if (rc < 0) return rc; // TODO: Comment on why we explicitly made open & trunc atomic if (fi->flags & O_TRUNC) { rc = ffsp::truncate(fs, *ino, 0); if (rc < 0) return rc; } set_inode(fi, ino); return 0; }
void setup_i(Oracle *oracl) { vertex vtx(oracl->new_algo(this)); vtx.iterate(0); this_t *ltI = oracl->get_by(vtx)->get_i(), *rtI = (oracl->get_by(vtx) + 1)->get_i(); const word_t idH = height(), ltH = ltI->height(), rtH = rtI->height(); if (idH > ltH && idH > rtH) set_inode(); else if (ltH < rtH) { set_i(rtI); rtI->set_l(this); } else { set_i(ltI); ltI->set_l(this); } }
/* todo: return with unlocked? */ struct inode *au_new_inode(struct dentry *dentry, int must_new) { struct inode *inode; struct dentry *h_dentry; struct super_block *sb; ino_t h_ino, ino; int err, match; aufs_bindex_t bstart; sb = dentry->d_sb; bstart = au_dbstart(dentry); h_dentry = au_h_dptr(dentry, bstart); h_ino = h_dentry->d_inode->i_ino; err = au_xino_read(sb, bstart, h_ino, &ino); inode = ERR_PTR(err); if (unlikely(err)) goto out; new_ino: if (!ino) { ino = au_xino_new_ino(sb); if (unlikely(!ino)) { inode = ERR_PTR(-EIO); goto out; } } AuDbg("i%lu\n", (unsigned long)ino); inode = au_iget_locked(sb, ino); err = PTR_ERR(inode); if (IS_ERR(inode)) goto out; AuDbg("%lx, new %d\n", inode->i_state, !!(inode->i_state & I_NEW)); if (inode->i_state & I_NEW) { ii_write_lock_new_child(inode); err = set_inode(inode, dentry); if (!err) { unlock_new_inode(inode); goto out; /* success */ } ii_write_unlock(inode); iget_failed(inode); goto out_err; } else if (!must_new) { err = reval_inode(inode, dentry, &match); if (!err) goto out; /* success */ else if (match) goto out_iput; } if (unlikely(au_test_fs_unique_ino(h_dentry->d_inode))) AuWarn1("Warning: Un-notified UDBA or repeatedly renamed dir," " b%d, %s, %.*s, hi%lu, i%lu.\n", bstart, au_sbtype(h_dentry->d_sb), AuDLNPair(dentry), (unsigned long)h_ino, (unsigned long)ino); ino = 0; err = au_xino_write(sb, bstart, h_ino, /*ino*/0); if (!err) { iput(inode); goto new_ino; } out_iput: iput(inode); out_err: inode = ERR_PTR(err); out: return inode; }
/* todo: return with unlocked? */ struct inode *au_new_inode(struct dentry *dentry, int must_new) { struct inode *inode, *h_inode; struct dentry *h_dentry; struct super_block *sb; struct mutex *mtx; ino_t h_ino, ino; int err; aufs_bindex_t bstart; sb = dentry->d_sb; bstart = au_dbstart(dentry); h_dentry = au_h_dptr(dentry, bstart); h_inode = h_dentry->d_inode; h_ino = h_inode->i_ino; /* * stop 'race'-ing between hardlinks under different * parents. */ mtx = NULL; if (!S_ISDIR(h_inode->i_mode)) mtx = &au_sbr(sb, bstart)->br_xino.xi_nondir_mtx; new_ino: if (mtx) mutex_lock(mtx); err = au_xino_read(sb, bstart, h_ino, &ino); inode = ERR_PTR(err); if (unlikely(err)) goto out; if (!ino) { ino = au_xino_new_ino(sb); if (unlikely(!ino)) { inode = ERR_PTR(-EIO); goto out; } } AuDbg("i%lu\n", (unsigned long)ino); inode = au_iget_locked(sb, ino); err = PTR_ERR(inode); if (IS_ERR(inode)) goto out; AuDbg("%lx, new %d\n", inode->i_state, !!(inode->i_state & I_NEW)); if (inode->i_state & I_NEW) { /* verbose coding for lock class name */ if (unlikely(S_ISLNK(h_inode->i_mode))) au_rw_class(&au_ii(inode)->ii_rwsem, au_lc_key + AuLcSymlink_IIINFO); else if (unlikely(S_ISDIR(h_inode->i_mode))) au_rw_class(&au_ii(inode)->ii_rwsem, au_lc_key + AuLcDir_IIINFO); else /* likely */ au_rw_class(&au_ii(inode)->ii_rwsem, au_lc_key + AuLcNonDir_IIINFO); ii_write_lock_new_child(inode); err = set_inode(inode, dentry); if (!err) { unlock_new_inode(inode); goto out; /* success */ } /* * iget_failed() calls iput(), but we need to call * ii_write_unlock() after iget_failed(). so dirty hack for * i_count. */ atomic_inc(&inode->i_count); iget_failed(inode); ii_write_unlock(inode); au_xino_write(sb, bstart, h_ino, /*ino*/0); /* ignore this error */ goto out_iput; } else if (!must_new && !IS_DEADDIR(inode) && inode->i_nlink) { /* * horrible race condition between lookup, readdir and copyup * (or something). */ if (mtx) mutex_unlock(mtx); err = reval_inode(inode, dentry); if (unlikely(err < 0)) { mtx = NULL; goto out_iput; } if (!err) { mtx = NULL; goto out; /* success */ } else if (mtx) mutex_lock(mtx); } if (unlikely(au_test_fs_unique_ino(h_dentry->d_inode))) AuWarn1("Warning: Un-notified UDBA or repeatedly renamed dir," " b%d, %s, %pd, hi%lu, i%lu.\n", bstart, au_sbtype(h_dentry->d_sb), dentry, (unsigned long)h_ino, (unsigned long)ino); ino = 0; err = au_xino_write(sb, bstart, h_ino, /*ino*/0); if (!err) { iput(inode); if (mtx) mutex_unlock(mtx); goto new_ino; } out_iput: iput(inode); inode = ERR_PTR(err); out: if (mtx) mutex_unlock(mtx); return inode; }
/* todo: return with unlocked? */ struct inode *au_new_inode(struct dentry *dentry, int must_new) { struct inode *inode, *h_inode; struct dentry *h_dentry; struct super_block *sb; struct mutex *mtx; ino_t h_ino, ino; int err, match; aufs_bindex_t bstart; sb = dentry->d_sb; bstart = au_dbstart(dentry); h_dentry = au_h_dptr(dentry, bstart); h_inode = h_dentry->d_inode; h_ino = h_inode->i_ino; /* * stop 'race'-ing between hardlinks under different * parents. */ mtx = NULL; if (!S_ISDIR(h_inode->i_mode)) mtx = &au_sbr(sb, bstart)->br_xino.xi_nondir_mtx; new_ino: if (mtx) mutex_lock(mtx); err = au_xino_read(sb, bstart, h_ino, &ino); inode = ERR_PTR(err); if (unlikely(err)) goto out; if (!ino) { ino = au_xino_new_ino(sb); if (unlikely(!ino)) { inode = ERR_PTR(-EIO); goto out; } } AuDbg("i%lu\n", (unsigned long)ino); inode = au_iget_locked(sb, ino); err = PTR_ERR(inode); if (IS_ERR(inode)) goto out; AuDbg("%lx, new %d\n", inode->i_state, !!(inode->i_state & I_NEW)); if (inode->i_state & I_NEW) { ii_write_lock_new_child(inode); err = set_inode(inode, dentry); if (!err) { unlock_new_inode(inode); goto out; /* success */ } ii_write_unlock(inode); iget_failed(inode); goto out_err; } else if (!must_new) { /* * horrible race condition between lookup, readdir and copyup * (or something). */ if (mtx) mutex_unlock(mtx); err = reval_inode(inode, dentry, &match); if (!err) { mtx = NULL; goto out; /* success */ } else if (match) { mtx = NULL; goto out_iput; } else if (mtx) mutex_lock(mtx); } if (unlikely(au_test_fs_unique_ino(h_dentry->d_inode))) AuWarn1("Warning: Un-notified UDBA or repeatedly renamed dir," " b%d, %s, %.*s, hi%lu, i%lu.\n", bstart, au_sbtype(h_dentry->d_sb), AuDLNPair(dentry), (unsigned long)h_ino, (unsigned long)ino); ino = 0; err = au_xino_write(sb, bstart, h_ino, /*ino*/0); if (!err) { iput(inode); if (mtx) mutex_unlock(mtx); goto new_ino; } out_iput: iput(inode); out_err: inode = ERR_PTR(err); out: if (mtx) mutex_unlock(mtx); return inode; }
int main(int argc, char **argv) { //Checks valid no of argument if(argc != 3) { fprintf(stderr, "Usage: ext2_mkdir <image file name> <file path on ext2 image>\n"); exit(1); } //Gets arguments int fd = open(argv[1], O_RDWR); char *path = argv[2]; char *dirName = extract_filename(argv[2]); //maps disk in memory and checks for error disk = mmap(NULL, 128 * BLOCK_SIZE, PROT_READ | PROT_WRITE, MAP_SHARED, fd, 0); if(disk == MAP_FAILED) { perror("mmap"); exit(1); } //gets superblock and groupd desc. struct ext2_super_block *sb = (struct ext2_super_block *)(disk + BLOCK_SIZE); struct ext2_group_desc *gd = (struct ext2_group_desc *) (disk + 2*BLOCK_SIZE + ((sb -> s_block_group_nr) * sizeof(struct ext2_group_desc))); // Checks if file already exists and returns if yes. char *directory = strrchr(argv[2], '/'); directory[(argv[2] == directory)? 1:0] = '\0'; if(file_exists(path, get_block(disk, gd -> bg_inode_table, BLOCK_SIZE), dirName)!=0){ fprintf(stderr, "mkdir: file exists\n"); return EEXIST; } //CHECK FOR INODE TO RESERVE int free_inode; if((free_inode = find_first_free_bit(get_block(disk, gd -> bg_inode_bitmap, BLOCK_SIZE), 0, 128)) == -1){ fprintf(stderr, "mkdir: operation failed: No free inodes"); exit(1); } unsigned int dirname_length = strlen(dirName); unsigned int dir_entry_size = (8 + dirname_length) + (4 - (8 + dirname_length) % 4) % 4; //Creates new directory entry struct ext2_dir_entry_2 * new_dir = malloc(dir_entry_size); if(!new_dir){ perror("malloc"); exit(1); } new_dir -> inode = free_inode + 1; new_dir -> name_len = strlen(dirName); new_dir -> rec_len = dir_entry_size; new_dir -> file_type = EXT2_FT_DIR; memcpy(new_dir -> name, dirName, strlen(dirName)); int new_capacity = gd -> bg_free_blocks_count; //Getting info to check that destination is a directory and not reserved struct basic_fileinfo destination = find_file(argv[2], get_block(disk, gd -> bg_inode_table, BLOCK_SIZE)); if(destination.inode < 11 && destination.inode != 2){ fprintf(stderr, "Invalid destination"); free(new_dir); return ENOENT; }//Checks if destination is a directory if(destination.type != 'd'){ fprintf(stderr, "mkdir: destination is not a directory"); free(new_dir); return ENOENT; }//Checks if directory has space for the new directory if(new_capacity < 1){ fprintf(stderr, "mkdir: not enough capacity"); return ENOSPC; } //Reserves location for new directory entry if ((new_capacity = reserve_directory_entry(get_block(disk, gd -> bg_inode_table, BLOCK_SIZE), destination.inode, new_capacity, new_dir, get_block(disk, gd -> bg_block_bitmap, BLOCK_SIZE))) == -1){ fprintf(stderr, "mkdir: Not enough capacity for file"); exit(-1); } //freeing memory and reducing the free inode count free(new_dir); gd -> bg_free_inodes_count --; set_inode(get_inode(get_block(disk, gd -> bg_inode_table, BLOCK_SIZE), free_inode + 1), free_inode, 0, NULL, 0, get_block(disk, gd -> bg_block_bitmap, BLOCK_SIZE), get_block(disk, gd -> bg_inode_bitmap, BLOCK_SIZE), EXT2_S_IFDIR); gd -> bg_free_blocks_count = new_capacity; printf("Success: Directory entry created."); //Adds . directory to the new directory entry new_dir = malloc(12); if (!new_dir){ perror("malloc"); exit(1); } new_dir -> inode = free_inode + 1; new_dir -> name_len = 1; new_dir -> rec_len = 12; new_dir -> file_type = EXT2_FT_DIR; new_dir -> name[0] = '.'; struct ext2_inode *inode = get_inode(get_block(disk, gd -> bg_inode_table, BLOCK_SIZE), free_inode + 1); inode -> i_block[0] = 0; // Adds .. to the new directory entry new_capacity = reserve_directory_entry(get_block(disk, gd -> bg_inode_table, BLOCK_SIZE), free_inode + 1, new_capacity, new_dir, get_block(disk, gd -> bg_block_bitmap, BLOCK_SIZE)); new_dir -> inode = destination.inode; new_dir -> name_len = 2; new_dir -> name[0] = '.'; new_dir -> name[1] = '.'; reserve_directory_entry(get_block(disk, gd -> bg_inode_table, BLOCK_SIZE), free_inode + 1, new_capacity, new_dir, get_block(disk, gd -> bg_block_bitmap, BLOCK_SIZE)); gd -> bg_free_blocks_count = new_capacity; gd -> bg_used_dirs_count += 3; free(new_dir); free(dirName); return 0; }