Commit 2d902671 authored by Miklos Szeredi's avatar Miklos Szeredi

vfs: merge .d_select_inode() into .d_real()

The two methods essentially do the same: find the real dentry/inode
belonging to an overlay dentry.  The difference is in the usage:

vfs_open() uses ->d_select_inode() and expects the function to perform
copy-up if necessary based on the open flags argument.

file_dentry() uses ->d_real() passing in the overlay dentry as well as the
underlying inode.

vfs_rename() uses ->d_select_inode() but passes zero flags.  ->d_real()
with a zero inode would have worked just as well here.

This patch merges the functionality of ->d_select_inode() into ->d_real()
by adding an 'open_flags' argument to the latter.

[Al Viro] Make the signature of d_real() match that of ->d_real() again.
And constify the inode argument, while we are at it.
Signed-off-by: default avatarMiklos Szeredi <mszeredi@redhat.com>
parent 4c2e07c6
...@@ -1729,7 +1729,6 @@ void d_set_d_op(struct dentry *dentry, const struct dentry_operations *op) ...@@ -1729,7 +1729,6 @@ void d_set_d_op(struct dentry *dentry, const struct dentry_operations *op)
DCACHE_OP_REVALIDATE | DCACHE_OP_REVALIDATE |
DCACHE_OP_WEAK_REVALIDATE | DCACHE_OP_WEAK_REVALIDATE |
DCACHE_OP_DELETE | DCACHE_OP_DELETE |
DCACHE_OP_SELECT_INODE |
DCACHE_OP_REAL)); DCACHE_OP_REAL));
dentry->d_op = op; dentry->d_op = op;
if (!op) if (!op)
...@@ -1746,8 +1745,6 @@ void d_set_d_op(struct dentry *dentry, const struct dentry_operations *op) ...@@ -1746,8 +1745,6 @@ void d_set_d_op(struct dentry *dentry, const struct dentry_operations *op)
dentry->d_flags |= DCACHE_OP_DELETE; dentry->d_flags |= DCACHE_OP_DELETE;
if (op->d_prune) if (op->d_prune)
dentry->d_flags |= DCACHE_OP_PRUNE; dentry->d_flags |= DCACHE_OP_PRUNE;
if (op->d_select_inode)
dentry->d_flags |= DCACHE_OP_SELECT_INODE;
if (op->d_real) if (op->d_real)
dentry->d_flags |= DCACHE_OP_REAL; dentry->d_flags |= DCACHE_OP_REAL;
......
...@@ -4328,7 +4328,7 @@ int vfs_rename(struct inode *old_dir, struct dentry *old_dentry, ...@@ -4328,7 +4328,7 @@ int vfs_rename(struct inode *old_dir, struct dentry *old_dentry,
* Check source == target. * Check source == target.
* On overlayfs need to look at underlying inodes. * On overlayfs need to look at underlying inodes.
*/ */
if (vfs_select_inode(old_dentry, 0) == vfs_select_inode(new_dentry, 0)) if (d_real_inode(old_dentry) == d_real_inode(new_dentry))
return 0; return 0;
error = may_delete(old_dir, old_dentry, is_dir); error = may_delete(old_dir, old_dentry, is_dir);
......
...@@ -840,13 +840,13 @@ EXPORT_SYMBOL(file_path); ...@@ -840,13 +840,13 @@ EXPORT_SYMBOL(file_path);
int vfs_open(const struct path *path, struct file *file, int vfs_open(const struct path *path, struct file *file,
const struct cred *cred) const struct cred *cred)
{ {
struct inode *inode = vfs_select_inode(path->dentry, file->f_flags); struct dentry *dentry = d_real(path->dentry, NULL, file->f_flags);
if (IS_ERR(inode)) if (IS_ERR(dentry))
return PTR_ERR(inode); return PTR_ERR(dentry);
file->f_path = *path; file->f_path = *path;
return do_dentry_open(file, inode, NULL, cred); return do_dentry_open(file, d_backing_inode(dentry), NULL, cred);
} }
struct file *dentry_open(const struct path *path, int flags, struct file *dentry_open(const struct path *path, int flags,
......
...@@ -325,36 +325,25 @@ static bool ovl_open_need_copy_up(int flags, enum ovl_path_type type, ...@@ -325,36 +325,25 @@ static bool ovl_open_need_copy_up(int flags, enum ovl_path_type type,
return true; return true;
} }
struct inode *ovl_d_select_inode(struct dentry *dentry, unsigned file_flags) int ovl_open_maybe_copy_up(struct dentry *dentry, unsigned int file_flags)
{ {
int err; int err = 0;
struct path realpath; struct path realpath;
enum ovl_path_type type; enum ovl_path_type type;
if (d_is_dir(dentry))
return d_backing_inode(dentry);
type = ovl_path_real(dentry, &realpath); type = ovl_path_real(dentry, &realpath);
if (ovl_open_need_copy_up(file_flags, type, realpath.dentry)) { if (ovl_open_need_copy_up(file_flags, type, realpath.dentry)) {
err = ovl_want_write(dentry); err = ovl_want_write(dentry);
if (err) if (!err) {
return ERR_PTR(err); if (file_flags & O_TRUNC)
err = ovl_copy_up_truncate(dentry);
if (file_flags & O_TRUNC) else
err = ovl_copy_up_truncate(dentry); err = ovl_copy_up(dentry);
else ovl_drop_write(dentry);
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 err;
return realpath.dentry->d_op->d_select_inode(realpath.dentry, file_flags);
return d_backing_inode(realpath.dentry);
} }
static const struct inode_operations ovl_file_inode_operations = { static const struct inode_operations ovl_file_inode_operations = {
......
...@@ -179,7 +179,7 @@ ssize_t ovl_getxattr(struct dentry *dentry, struct inode *inode, ...@@ -179,7 +179,7 @@ ssize_t ovl_getxattr(struct dentry *dentry, struct inode *inode,
const char *name, void *value, size_t size); const char *name, void *value, size_t size);
ssize_t ovl_listxattr(struct dentry *dentry, char *list, size_t size); ssize_t ovl_listxattr(struct dentry *dentry, char *list, size_t size);
int ovl_removexattr(struct dentry *dentry, const char *name); int ovl_removexattr(struct dentry *dentry, const char *name);
struct inode *ovl_d_select_inode(struct dentry *dentry, unsigned file_flags); int ovl_open_maybe_copy_up(struct dentry *dentry, unsigned int file_flags);
struct inode *ovl_new_inode(struct super_block *sb, umode_t mode, struct inode *ovl_new_inode(struct super_block *sb, umode_t mode,
struct ovl_entry *oe); struct ovl_entry *oe);
......
...@@ -304,7 +304,9 @@ static void ovl_dentry_release(struct dentry *dentry) ...@@ -304,7 +304,9 @@ static void ovl_dentry_release(struct dentry *dentry)
} }
} }
static struct dentry *ovl_d_real(struct dentry *dentry, struct inode *inode) static struct dentry *ovl_d_real(struct dentry *dentry,
const struct inode *inode,
unsigned int open_flags)
{ {
struct dentry *real; struct dentry *real;
...@@ -314,6 +316,16 @@ static struct dentry *ovl_d_real(struct dentry *dentry, struct inode *inode) ...@@ -314,6 +316,16 @@ static struct dentry *ovl_d_real(struct dentry *dentry, struct inode *inode)
goto bug; goto bug;
} }
if (d_is_negative(dentry))
return dentry;
if (open_flags) {
int err = ovl_open_maybe_copy_up(dentry, open_flags);
if (err)
return ERR_PTR(err);
}
real = ovl_dentry_upper(dentry); real = ovl_dentry_upper(dentry);
if (real && (!inode || inode == d_inode(real))) if (real && (!inode || inode == d_inode(real)))
return real; return real;
...@@ -326,9 +338,7 @@ static struct dentry *ovl_d_real(struct dentry *dentry, struct inode *inode) ...@@ -326,9 +338,7 @@ static struct dentry *ovl_d_real(struct dentry *dentry, struct inode *inode)
return real; return real;
/* Handle recursion */ /* Handle recursion */
if (real->d_flags & DCACHE_OP_REAL) return d_real(real, inode, open_flags);
return real->d_op->d_real(real, inode);
bug: bug:
WARN(1, "ovl_d_real(%pd4, %s:%lu\n): real dentry not found\n", dentry, WARN(1, "ovl_d_real(%pd4, %s:%lu\n): real dentry not found\n", dentry,
inode ? inode->i_sb->s_id : "NULL", inode ? inode->i_ino : 0); inode ? inode->i_sb->s_id : "NULL", inode ? inode->i_ino : 0);
...@@ -378,13 +388,11 @@ static int ovl_dentry_weak_revalidate(struct dentry *dentry, unsigned int flags) ...@@ -378,13 +388,11 @@ static int ovl_dentry_weak_revalidate(struct dentry *dentry, unsigned int flags)
static const struct dentry_operations ovl_dentry_operations = { static const struct dentry_operations ovl_dentry_operations = {
.d_release = ovl_dentry_release, .d_release = ovl_dentry_release,
.d_select_inode = ovl_d_select_inode,
.d_real = ovl_d_real, .d_real = ovl_d_real,
}; };
static const struct dentry_operations ovl_reval_dentry_operations = { static const struct dentry_operations ovl_reval_dentry_operations = {
.d_release = ovl_dentry_release, .d_release = ovl_dentry_release,
.d_select_inode = ovl_d_select_inode,
.d_real = ovl_d_real, .d_real = ovl_d_real,
.d_revalidate = ovl_dentry_revalidate, .d_revalidate = ovl_dentry_revalidate,
.d_weak_revalidate = ovl_dentry_weak_revalidate, .d_weak_revalidate = ovl_dentry_weak_revalidate,
......
...@@ -139,8 +139,7 @@ struct dentry_operations { ...@@ -139,8 +139,7 @@ struct dentry_operations {
char *(*d_dname)(struct dentry *, char *, int); char *(*d_dname)(struct dentry *, char *, int);
struct vfsmount *(*d_automount)(struct path *); struct vfsmount *(*d_automount)(struct path *);
int (*d_manage)(struct dentry *, bool); int (*d_manage)(struct dentry *, bool);
struct inode *(*d_select_inode)(struct dentry *, unsigned); struct dentry *(*d_real)(struct dentry *, const struct inode *, unsigned int);
struct dentry *(*d_real)(struct dentry *, struct inode *);
} ____cacheline_aligned; } ____cacheline_aligned;
/* /*
...@@ -206,10 +205,8 @@ struct dentry_operations { ...@@ -206,10 +205,8 @@ struct dentry_operations {
#define DCACHE_MAY_FREE 0x00800000 #define DCACHE_MAY_FREE 0x00800000
#define DCACHE_FALLTHRU 0x01000000 /* Fall through to lower layer */ #define DCACHE_FALLTHRU 0x01000000 /* Fall through to lower layer */
#define DCACHE_OP_SELECT_INODE 0x02000000 /* Unioned entry: dcache op selects inode */ #define DCACHE_ENCRYPTED_WITH_KEY 0x02000000 /* dir is encrypted with a valid key */
#define DCACHE_OP_REAL 0x04000000
#define DCACHE_ENCRYPTED_WITH_KEY 0x04000000 /* dir is encrypted with a valid key */
#define DCACHE_OP_REAL 0x08000000
#define DCACHE_PAR_LOOKUP 0x10000000 /* being looked up (with parent locked shared) */ #define DCACHE_PAR_LOOKUP 0x10000000 /* being looked up (with parent locked shared) */
#define DCACHE_DENTRY_CURSOR 0x20000000 #define DCACHE_DENTRY_CURSOR 0x20000000
...@@ -557,25 +554,16 @@ static inline struct dentry *d_backing_dentry(struct dentry *upper) ...@@ -557,25 +554,16 @@ static inline struct dentry *d_backing_dentry(struct dentry *upper)
return upper; return upper;
} }
static inline struct dentry *d_real(struct dentry *dentry) static inline struct dentry *d_real(struct dentry *dentry,
const struct inode *inode,
unsigned int flags)
{ {
if (unlikely(dentry->d_flags & DCACHE_OP_REAL)) if (unlikely(dentry->d_flags & DCACHE_OP_REAL))
return dentry->d_op->d_real(dentry, NULL); return dentry->d_op->d_real(dentry, inode, flags);
else else
return dentry; return dentry;
} }
static inline struct inode *vfs_select_inode(struct dentry *dentry,
unsigned open_flags)
{
struct inode *inode = d_inode(dentry);
if (inode && unlikely(dentry->d_flags & DCACHE_OP_SELECT_INODE))
inode = dentry->d_op->d_select_inode(dentry, open_flags);
return inode;
}
/** /**
* d_real_inode - Return the real inode * d_real_inode - Return the real inode
* @dentry: The dentry to query * @dentry: The dentry to query
...@@ -585,7 +573,7 @@ static inline struct inode *vfs_select_inode(struct dentry *dentry, ...@@ -585,7 +573,7 @@ static inline struct inode *vfs_select_inode(struct dentry *dentry,
*/ */
static inline struct inode *d_real_inode(struct dentry *dentry) static inline struct inode *d_real_inode(struct dentry *dentry)
{ {
return d_backing_inode(d_real(dentry)); return d_backing_inode(d_real(dentry, NULL, 0));
} }
......
...@@ -1272,12 +1272,7 @@ static inline struct inode *file_inode(const struct file *f) ...@@ -1272,12 +1272,7 @@ static inline struct inode *file_inode(const struct file *f)
static inline struct dentry *file_dentry(const struct file *file) static inline struct dentry *file_dentry(const struct file *file)
{ {
struct dentry *dentry = file->f_path.dentry; return d_real(file->f_path.dentry, file_inode(file), 0);
if (unlikely(dentry->d_flags & DCACHE_OP_REAL))
return dentry->d_op->d_real(dentry, file_inode(file));
else
return dentry;
} }
static inline int locks_lock_file_wait(struct file *filp, struct file_lock *fl) static inline int locks_lock_file_wait(struct file *filp, struct file_lock *fl)
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment