static int scfs_inode_test(struct inode *inode, void *lower_inode) { if (scfs_lower_inode(inode) == (struct inode *)lower_inode) return 1; return 0; }
static int scfs_do_unlink(struct inode *dir, struct dentry *dentry, struct inode *inode) { struct dentry *lower_dentry = scfs_lower_dentry(dentry); struct inode *lower_dir_inode = scfs_lower_inode(dir); struct dentry *lower_dir_dentry; int ret; dget(lower_dentry); lower_dir_dentry = lock_parent(lower_dentry); ret = vfs_unlink(lower_dir_inode, lower_dentry); if (ret) { SCFS_PRINT_ERROR("error in vfs_unlink, ret : %d\n", ret); goto out; } fsstack_copy_attr_times(dir, lower_dir_inode); set_nlink(inode, scfs_lower_inode(inode)->i_nlink); inode->i_ctime = dir->i_ctime; d_drop(dentry); out: unlock_dir(lower_dir_dentry); dput(lower_dentry); return ret; }
static void scfs_evict_inode(struct inode *inode) { struct inode *lower_inode; struct scfs_inode_info *sii = SCFS_I(inode); truncate_inode_pages(&inode->i_data, 0); #if LINUX_VERSION_CODE >= KERNEL_VERSION(3,10,0) clear_inode(inode); #else end_writeback(inode); #endif /* to conserve memory, evicted inode will throw out the cluster info */ if (sii->cinfo_array) { scfs_cinfo_free(sii, sii->cinfo_array); sii->cinfo_array = NULL; } if (!list_empty(&sii->cinfo_list)) SCFS_PRINT_ERROR("cinfo list is not empty!\n"); lower_inode = scfs_lower_inode(inode); scfs_set_lower_inode(inode, NULL); iput(lower_inode); }
static int scfs_open(struct inode *inode, struct file *file) { struct scfs_sb_info *sbi = SCFS_S(inode->i_sb); struct scfs_inode_info *sii = SCFS_I(inode); struct scfs_file_info *fi; int ret = 0; struct file *lower_file; if (IS_WROPENED(sii)) { SCFS_PRINT("This file is already opened with 'WRITE' flag\n"); return -EPERM; } fi = kmem_cache_zalloc(scfs_file_info_cache, GFP_KERNEL); if (!fi) return -ENOMEM; profile_add_kmcached(sizeof(struct scfs_file_info), sbi); file->private_data = fi; mutex_lock(&sii->cinfo_mutex); if (IS_INVALID_META(sii)) { SCFS_PRINT("meta is invalid, so we should re-load it\n"); ret = scfs_reload_meta(file); if (ret) { SCFS_PRINT_ERROR("error in re-reading footer, err : %d\n", ret); goto out; } } else if (sii->compressed && !sii->cinfo_array) { /* 1st lower-open is for getting cinfo */ ret = scfs_initialize_lower_file(file->f_dentry, &lower_file, O_RDONLY); if (ret) { SCFS_PRINT_ERROR("err in get_lower_file %s\n", file->f_dentry->d_name.name); goto out; } scfs_set_lower_file(file, lower_file); SCFS_PRINT("info size = %d \n", sii->cinfo_array_size); ret = scfs_load_cinfo(sii, lower_file); if (ret) { SCFS_PRINT_ERROR("err in loading cinfo, ret : %d\n", file->f_dentry->d_name.name); fput(lower_file); goto out; } fput(lower_file); } ret = scfs_initialize_lower_file(file->f_dentry, &lower_file, file->f_flags); if (ret) { SCFS_PRINT_ERROR("err in get_lower_file %s\n", file->f_dentry->d_name.name); goto out; } scfs_set_lower_file(file, lower_file); out: if (!ret) { fsstack_copy_attr_all(inode, scfs_lower_inode(inode)); if (file->f_flags & (O_RDWR | O_WRONLY)) MAKE_WROPENED(sii); } else { scfs_set_lower_file(file, NULL); kmem_cache_free(scfs_file_info_cache, file->private_data); profile_sub_kmcached(sizeof(struct scfs_file_info), sbi); sii->cinfo_array = NULL; } mutex_unlock(&sii->cinfo_mutex); SCFS_PRINT("lower, dentry name : %s, count : %d, ret : %d\n", file->f_dentry->d_name.name, file->f_dentry->d_count, ret); return ret; }