struct inode *ovl_d_select_inode(struct dentry *dentry, unsigned file_flags) { int err; struct path realpath; enum ovl_path_type type; if (d_is_dir(dentry)) return d_backing_inode(dentry); type = ovl_path_real(dentry, &realpath); if (ovl_open_need_copy_up(file_flags, type, realpath.dentry)) { err = ovl_want_write(dentry); if (err) return ERR_PTR(err); if (file_flags & O_TRUNC) err = ovl_copy_up_truncate(dentry); else err = ovl_copy_up(dentry); ovl_drop_write(dentry); if (err) return ERR_PTR(err); ovl_path_upper(dentry, &realpath); } if (realpath.dentry->d_flags & DCACHE_OP_SELECT_INODE) return realpath.dentry->d_op->d_select_inode(realpath.dentry, file_flags); return d_backing_inode(realpath.dentry); }
static struct file *ovl_open(struct dentry *dentry, struct file *file, const struct cred *cred) { int err; struct path realpath; enum ovl_path_type type; type = ovl_path_real(dentry, &realpath); if (ovl_open_need_copy_up(file->f_flags, type, realpath.dentry)) { if (file->f_flags & O_TRUNC) err = ovl_copy_up_truncate(dentry, 0); else err = ovl_copy_up(dentry); if (err) return ERR_PTR(err); ovl_path_upper(dentry, &realpath); } return vfs_open(&realpath, file, cred); }
int ovl_setattr(struct dentry *dentry, struct iattr *attr) { struct dentry *upperdentry; int err; if ((attr->ia_valid & ATTR_SIZE) && !ovl_dentry_upper(dentry)) err = ovl_copy_up_truncate(dentry, attr->ia_size); else err = ovl_copy_up(dentry); if (err) return err; upperdentry = ovl_dentry_upper(dentry); if (attr->ia_valid & (ATTR_KILL_SUID|ATTR_KILL_SGID)) attr->ia_valid &= ~ATTR_MODE; mutex_lock(&upperdentry->d_inode->i_mutex); err = notify_change(upperdentry, attr); mutex_unlock(&upperdentry->d_inode->i_mutex); return err; }