static ssize_t unionfs_splice_write(struct pipe_inode_info *pipe, struct file *file, loff_t *ppos, size_t len, unsigned int flags) { ssize_t err = 0; struct file *lower_file; struct dentry *dentry = file->f_path.dentry; struct dentry *parent; unionfs_read_lock(dentry->d_sb, UNIONFS_SMUTEX_PARENT); parent = unionfs_lock_parent(dentry, UNIONFS_DMUTEX_PARENT); unionfs_lock_dentry(dentry, UNIONFS_DMUTEX_CHILD); err = unionfs_file_revalidate(file, parent, true); if (unlikely(err)) goto out; lower_file = unionfs_lower_file(file); err = vfs_splice_from(pipe, lower_file, ppos, len, flags); /* update our inode times+sizes upon a successful lower write */ if (err >= 0) { fsstack_copy_inode_size(dentry->d_inode, lower_file->f_path.dentry->d_inode); fsstack_copy_attr_times(dentry->d_inode, lower_file->f_path.dentry->d_inode); unionfs_check_file(file); } out: unionfs_unlock_dentry(dentry); unionfs_unlock_parent(dentry, parent); unionfs_read_unlock(dentry->d_sb); return err; }
long do_vfsub_splice_from(struct pipe_inode_info *pipe, struct file *out, loff_t *ppos, size_t len, unsigned int flags) { long err; LKTRTrace("%.*s, pos %lld, len %zu, 0x%x\n", AuDLNPair(out->f_dentry), *ppos, len, flags); lockdep_off(); err = vfs_splice_from(pipe, out, ppos, len, flags); lockdep_on(); if (err >= 0) au_update_fuse_h_inode(out->f_vfsmnt, out->f_dentry); /*ignore*/ return err; }