diff options
Diffstat (limited to 'fs')
-rw-r--r-- | fs/overlayfs/inode.c | 48 |
1 files changed, 11 insertions, 37 deletions
diff --git a/fs/overlayfs/inode.c b/fs/overlayfs/inode.c index d554e86abbe3..32ae8b49a72c 100644 --- a/fs/overlayfs/inode.c +++ b/fs/overlayfs/inode.c @@ -109,31 +109,12 @@ static int ovl_getattr(struct vfsmount *mnt, struct dentry *dentry, int ovl_permission(struct inode *inode, int mask) { - struct ovl_entry *oe; - struct dentry *alias = NULL; - struct inode *realinode; - struct dentry *realdentry; + struct ovl_entry *oe = inode->i_private; bool is_upper; + struct dentry *realdentry = ovl_entry_real(oe, &is_upper); + struct inode *realinode; int err; - if (S_ISDIR(inode->i_mode)) { - oe = inode->i_private; - } else if (mask & MAY_NOT_BLOCK) { - return -ECHILD; - } else { - /* - * For non-directories find an alias and get the info - * from there. - */ - alias = d_find_any_alias(inode); - if (WARN_ON(!alias)) - return -ENOENT; - - oe = alias->d_fsdata; - } - - realdentry = ovl_entry_real(oe, &is_upper); - if (ovl_is_default_permissions(inode)) { struct kstat stat; struct path realpath = { .dentry = realdentry }; @@ -145,26 +126,23 @@ int ovl_permission(struct inode *inode, int mask) err = vfs_getattr(&realpath, &stat); if (err) - goto out_dput; + return err; - err = -ESTALE; if ((stat.mode ^ inode->i_mode) & S_IFMT) - goto out_dput; + return -ESTALE; inode->i_mode = stat.mode; inode->i_uid = stat.uid; inode->i_gid = stat.gid; - err = generic_permission(inode, mask); - goto out_dput; + return generic_permission(inode, mask); } /* Careful in RCU walk mode */ - realinode = ACCESS_ONCE(realdentry->d_inode); + realinode = d_inode_rcu(realdentry); if (!realinode) { WARN_ON(!(mask & MAY_NOT_BLOCK)); - err = -ENOENT; - goto out_dput; + return -ENOENT; } if (mask & MAY_WRITE) { @@ -183,16 +161,12 @@ int ovl_permission(struct inode *inode, int mask) * constructed return EROFS to prevent modification of * upper layer. */ - err = -EROFS; if (is_upper && !IS_RDONLY(inode) && IS_RDONLY(realinode) && (S_ISREG(mode) || S_ISDIR(mode) || S_ISLNK(mode))) - goto out_dput; + return -EROFS; } - err = __inode_permission(realinode, mask); -out_dput: - dput(alias); - return err; + return __inode_permission(realinode, mask); } static const char *ovl_get_link(struct dentry *dentry, @@ -405,11 +379,11 @@ struct inode *ovl_new_inode(struct super_block *sb, umode_t mode, inode->i_ino = get_next_ino(); inode->i_mode = mode; inode->i_flags |= S_NOATIME | S_NOCMTIME; + inode->i_private = oe; mode &= S_IFMT; switch (mode) { case S_IFDIR: - inode->i_private = oe; inode->i_op = &ovl_dir_inode_operations; inode->i_fop = &ovl_dir_operations; break; |