All of lore.kernel.org
 help / color / mirror / Atom feed
From: Miklos Szeredi <miklos@szeredi.hu>
To: Al Viro <viro@ZenIV.linux.org.uk>
Cc: linux-kernel@vger.kernel.org, linux-fsdevel@vger.kernel.org,
	David Howells <dhowells@redhat.com>
Subject: [PATCH 1/3] vfs: merge .d_select_inode() into .d_real()
Date: Tue, 17 May 2016 23:53:26 +0200	[thread overview]
Message-ID: <20160517215326.GA1589@veci.piliscsaba.szeredi.hu> (raw)

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.

Signed-off-by: Miklos Szeredi <mszeredi@redhat.com>
---
 fs/dcache.c              |    3 ---
 fs/namei.c               |    2 +-
 fs/open.c                |   17 +++++++++++++----
 fs/overlayfs/inode.c     |   31 ++++++++++---------------------
 fs/overlayfs/overlayfs.h |    2 +-
 fs/overlayfs/super.c     |   17 +++++++++++++----
 include/linux/dcache.h   |   22 ++++------------------
 include/linux/fs.h       |    2 +-
 8 files changed, 43 insertions(+), 53 deletions(-)

--- a/fs/dcache.c
+++ b/fs/dcache.c
@@ -1667,7 +1667,6 @@ void d_set_d_op(struct dentry *dentry, c
 				DCACHE_OP_REVALIDATE	|
 				DCACHE_OP_WEAK_REVALIDATE	|
 				DCACHE_OP_DELETE	|
-				DCACHE_OP_SELECT_INODE	|
 				DCACHE_OP_REAL));
 	dentry->d_op = op;
 	if (!op)
@@ -1684,8 +1683,6 @@ void d_set_d_op(struct dentry *dentry, c
 		dentry->d_flags |= DCACHE_OP_DELETE;
 	if (op->d_prune)
 		dentry->d_flags |= DCACHE_OP_PRUNE;
-	if (op->d_select_inode)
-		dentry->d_flags |= DCACHE_OP_SELECT_INODE;
 	if (op->d_real)
 		dentry->d_flags |= DCACHE_OP_REAL;
 
--- a/fs/namei.c
+++ b/fs/namei.c
@@ -4247,7 +4247,7 @@ int vfs_rename(struct inode *old_dir, st
 	 * Check source == target.
 	 * On overlayfs need to look at underlying inodes.
 	 */
-	if (vfs_select_inode(old_dentry, 0) == vfs_select_inode(new_dentry, 0))
+	if (d_inode(d_real(old_dentry)) == d_inode(d_real(new_dentry)))
 		return 0;
 
 	error = may_delete(old_dir, old_dentry, is_dir);
--- a/fs/open.c
+++ b/fs/open.c
@@ -831,6 +831,15 @@ char *file_path(struct file *filp, char
 }
 EXPORT_SYMBOL(file_path);
 
+static struct dentry *open_select_dentry(struct dentry *dentry,
+					 unsigned int open_flags)
+{
+	if (unlikely(dentry->d_flags & DCACHE_OP_REAL))
+		return dentry->d_op->d_real(dentry, NULL, open_flags);
+	else
+		return dentry;
+}
+
 /**
  * vfs_open - open the file at the given path
  * @path: path to open
@@ -840,13 +849,13 @@ EXPORT_SYMBOL(file_path);
 int vfs_open(const struct path *path, struct file *file,
 	     const struct cred *cred)
 {
-	struct inode *inode = vfs_select_inode(path->dentry, file->f_flags);
+	struct dentry *dentry = open_select_dentry(path->dentry, file->f_flags);
 
-	if (IS_ERR(inode))
-		return PTR_ERR(inode);
+	if (IS_ERR(dentry))
+		return PTR_ERR(dentry);
 
 	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,
--- a/fs/overlayfs/inode.c
+++ b/fs/overlayfs/inode.c
@@ -338,36 +338,25 @@ static bool ovl_open_need_copy_up(int fl
 	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;
 	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 (!err) {
+			if (file_flags & O_TRUNC)
+				err = ovl_copy_up_truncate(dentry);
+			else
+				err = ovl_copy_up(dentry);
+			ovl_drop_write(dentry);
+		}
 	}
 
-	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);
+	return err;
 }
 
 static const struct inode_operations ovl_file_inode_operations = {
--- a/fs/overlayfs/overlayfs.h
+++ b/fs/overlayfs/overlayfs.h
@@ -177,7 +177,7 @@ ssize_t ovl_getxattr(struct dentry *dent
 		     void *value, size_t size);
 ssize_t ovl_listxattr(struct dentry *dentry, char *list, size_t size);
 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 ovl_entry *oe);
--- a/fs/overlayfs/super.c
+++ b/fs/overlayfs/super.c
@@ -295,7 +295,8 @@ static void ovl_dentry_release(struct de
 	}
 }
 
-static struct dentry *ovl_d_real(struct dentry *dentry, struct inode *inode)
+static struct dentry *ovl_d_real(struct dentry *dentry, struct inode *inode,
+				 unsigned int open_flags)
 {
 	struct dentry *real;
 
@@ -305,6 +306,16 @@ static struct dentry *ovl_d_real(struct
 		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);
 	if (real && (!inode || inode == d_inode(real)))
 		return real;
@@ -318,7 +329,7 @@ static struct dentry *ovl_d_real(struct
 
 	/* Handle recursion */
 	if (real->d_flags & DCACHE_OP_REAL)
-		return real->d_op->d_real(real, inode);
+		return real->d_op->d_real(real, inode, open_flags);
 
 bug:
 	WARN(1, "ovl_d_real(%pd4, %s:%lu\n): real dentry not found\n", dentry,
@@ -369,13 +380,11 @@ static int ovl_dentry_weak_revalidate(st
 
 static const struct dentry_operations ovl_dentry_operations = {
 	.d_release = ovl_dentry_release,
-	.d_select_inode = ovl_d_select_inode,
 	.d_real = ovl_d_real,
 };
 
 static const struct dentry_operations ovl_reval_dentry_operations = {
 	.d_release = ovl_dentry_release,
-	.d_select_inode = ovl_d_select_inode,
 	.d_real = ovl_d_real,
 	.d_revalidate = ovl_dentry_revalidate,
 	.d_weak_revalidate = ovl_dentry_weak_revalidate,
--- a/include/linux/dcache.h
+++ b/include/linux/dcache.h
@@ -160,8 +160,7 @@ struct dentry_operations {
 	char *(*d_dname)(struct dentry *, char *, int);
 	struct vfsmount *(*d_automount)(struct path *);
 	int (*d_manage)(struct dentry *, bool);
-	struct inode *(*d_select_inode)(struct dentry *, unsigned);
-	struct dentry *(*d_real)(struct dentry *, struct inode *);
+	struct dentry *(*d_real)(struct dentry *, struct inode *, unsigned int);
 } ____cacheline_aligned;
 
 /*
@@ -227,10 +226,8 @@ struct dentry_operations {
 
 #define DCACHE_MAY_FREE			0x00800000
 #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	0x04000000 /* dir is encrypted with a valid key */
-#define DCACHE_OP_REAL			0x08000000
+#define DCACHE_ENCRYPTED_WITH_KEY	0x02000000 /* dir is encrypted with a valid key */
+#define DCACHE_OP_REAL			0x04000000
 
 extern seqlock_t rename_lock;
 
@@ -560,21 +557,10 @@ static inline struct dentry *d_backing_d
 static inline struct dentry *d_real(struct dentry *dentry)
 {
 	if (unlikely(dentry->d_flags & DCACHE_OP_REAL))
-		return dentry->d_op->d_real(dentry, NULL);
+		return dentry->d_op->d_real(dentry, NULL, 0);
 	else
 		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;
-}
-
 
 #endif	/* __LINUX_DCACHE_H */
--- a/include/linux/fs.h
+++ b/include/linux/fs.h
@@ -1246,7 +1246,7 @@ static inline struct dentry *file_dentry
 	struct dentry *dentry = file->f_path.dentry;
 
 	if (unlikely(dentry->d_flags & DCACHE_OP_REAL))
-		return dentry->d_op->d_real(dentry, file_inode(file));
+		return dentry->d_op->d_real(dentry, file_inode(file), 0);
 	else
 		return dentry;
 }

             reply	other threads:[~2016-05-17 21:53 UTC|newest]

Thread overview: 5+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2016-05-17 21:53 Miklos Szeredi [this message]
2016-05-17 21:55 ` [PATCH 2/3] vfs: document ->d_real() Miklos Szeredi
2016-05-17 21:57 ` [PATCH 3/3] vfs: clean up documentation Miklos Szeredi
2016-05-22 16:39 ` [PATCH 1/3] vfs: merge .d_select_inode() into .d_real() James Bottomley
2016-05-27  8:14   ` Miklos Szeredi

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=20160517215326.GA1589@veci.piliscsaba.szeredi.hu \
    --to=miklos@szeredi.hu \
    --cc=dhowells@redhat.com \
    --cc=linux-fsdevel@vger.kernel.org \
    --cc=linux-kernel@vger.kernel.org \
    --cc=viro@ZenIV.linux.org.uk \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.