static int ovl_dentry_open(struct dentry *dentry, struct file *file, const struct cred *cred) { int err; struct path realpath; enum ovl_path_type type; bool want_write = false; type = ovl_path_real(dentry, &realpath); if (ovl_open_need_copy_up(file->f_flags, type, realpath.dentry)) { want_write = true; err = ovl_want_write(dentry); if (err) goto out; if (file->f_flags & O_TRUNC) err = ovl_copy_up_last(dentry, NULL, true); else err = ovl_copy_up(dentry); if (err) goto out_drop_write; ovl_path_upper(dentry, &realpath); } err = vfs_open(&realpath, file, cred); out_drop_write: if (want_write) ovl_drop_write(dentry); out: return err; }
struct inode *ovl_d_select_inode(struct dentry *dentry, unsigned file_flags) { int err; struct path realpath; enum ovl_path_type type; 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_last(dentry, NULL, true); else err = ovl_copy_up(dentry); ovl_drop_write(dentry); if (err) return ERR_PTR(err); ovl_path_upper(dentry, &realpath); } return d_backing_inode(realpath.dentry); }
int ovl_setattr(struct dentry *dentry, struct iattr *attr) { int err; struct dentry *upperdentry; err = ovl_want_write(dentry); if (err) goto out; upperdentry = ovl_dentry_upper(dentry); if (upperdentry) { mutex_lock(&upperdentry->d_inode->i_mutex); err = notify_change(upperdentry, attr, NULL); mutex_unlock(&upperdentry->d_inode->i_mutex); } else { err = ovl_copy_up_last(dentry, attr, false); } ovl_drop_write(dentry); out: return err; }