static int scfs_statfs(struct dentry *dentry, struct kstatfs *buf) { int ret; struct dentry *lower_dentry = scfs_lower_dentry(dentry); ret = lower_dentry->d_sb->s_op->statfs(lower_dentry, buf); if (ret) return ret; buf->f_type = SCFS_SUPER_MAGIC; return ret; }
static struct inode * scfs_do_create(struct inode *parent_inode, struct dentry *scfs_dentry, umode_t mode) { struct dentry *lower_file_dentry; struct dentry *lower_parent_dentry; struct inode *inode; int ret; SCFS_DEBUG_START; lower_file_dentry = scfs_lower_dentry(scfs_dentry); lower_parent_dentry = lock_parent(lower_file_dentry); if (IS_ERR(lower_parent_dentry)) { SCFS_PRINT_ERROR("lower_parent_dentry is invalid\n"); inode = ERR_CAST(lower_parent_dentry); goto out; } #if LINUX_VERSION_CODE >= KERNEL_VERSION(3,10,0) ret = vfs_create(lower_parent_dentry->d_inode, lower_file_dentry, mode, true); #else ret = vfs_create(lower_parent_dentry->d_inode, lower_file_dentry, mode, NULL); #endif if (ret) { SCFS_PRINT_ERROR("error in vfs_create, lower create, ret : %d\n", ret); inode = ERR_PTR(ret); goto unlock; } inode = _scfs_get_inode(lower_file_dentry->d_inode, parent_inode->i_sb); if (IS_ERR(inode)) { SCFS_PRINT_ERROR("error in get_inode, so lower thing will be unlinked\n"); vfs_unlink(lower_parent_dentry->d_inode, lower_file_dentry); goto unlock; } fsstack_copy_attr_times(parent_inode, lower_parent_dentry->d_inode); fsstack_copy_inode_size(parent_inode, lower_parent_dentry->d_inode); unlock: unlock_dir(lower_parent_dentry); out: SCFS_DEBUG_END; return inode; }
/* * scfs_mkdir * * Parameters: * @*dir: inode of the dir to create * @*scfs_dentry: dentry of the dir to create * @mode: * * Return: * SCFS_SUCCESS if success, otherwise if error * * Description: * mkdir() for SCFS. */ static int scfs_mkdir(struct inode *dir, struct dentry *dentry, umode_t mode) { struct dentry *lower_dir_dentry; struct dentry *lower_parent_dentry; int ret; SCFS_DEBUG_START; lower_dir_dentry = scfs_lower_dentry(dentry); lower_parent_dentry = lock_parent(lower_dir_dentry); ret = vfs_mkdir(lower_parent_dentry->d_inode, lower_dir_dentry, mode); if (ret || !lower_dir_dentry->d_inode) { SCFS_PRINT_ERROR("dir %s vfs_mkdir failed, " "lower_dir %s lower_parent %s mode %x\n", dentry->d_name.name, lower_dir_dentry->d_name.name, lower_parent_dentry->d_name.name, mode); goto out; } ret = scfs_interpose(lower_dir_dentry, dentry, dir->i_sb); if (ret) { SCFS_PRINT_ERROR("dir %s interpose failed, " "lower_dir %s lower_parent %s mode %x\n", dentry->d_name.name, lower_dir_dentry->d_name.name, lower_parent_dentry->d_name.name, mode); vfs_rmdir(lower_parent_dentry->d_inode, lower_dir_dentry); goto out; } fsstack_copy_attr_times(dir, lower_parent_dentry->d_inode); fsstack_copy_inode_size(dir, lower_parent_dentry->d_inode); set_nlink(dir, lower_parent_dentry->d_inode->i_nlink); out: unlock_dir(lower_parent_dentry); if (!dentry->d_inode) d_drop(dentry); SCFS_DEBUG_END; return ret; }
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; }