[<prev] [next>] [<thread-prev] [thread-next>] [day] [month] [year] [list]
Message-ID: <20100906005029.20775.80833.stgit@localhost.localdomain>
Date: Mon, 06 Sep 2010 10:50:29 +1000
From: NeilBrown <neilb@...e.de>
To: Miklos Szeredi <miklos@...redi.hu>
Cc: linux-fsdevel@...r.kernel.org, linux-kernel@...r.kernel.org
Subject: [PATCH 07/10] ovl: add initial revalidate support
Add dentry_revalidate method and fail validation of either the
upper or lower dentry has been renamed or unlinked directly in the
otherlying filesystem.
This allows such changes to appear promptly in the overlay providing
the file isn't currently in use.
Signed-off-by: NeilBrown <neilb@...e.de>
---
fs/overlayfs/overlayfs.c | 55 ++++++++++++++++++++++++++++++++++++++++++++++
1 files changed, 55 insertions(+), 0 deletions(-)
diff --git a/fs/overlayfs/overlayfs.c b/fs/overlayfs/overlayfs.c
index 656cad7..cdeafa7 100644
--- a/fs/overlayfs/overlayfs.c
+++ b/fs/overlayfs/overlayfs.c
@@ -409,9 +409,64 @@ static void ovl_dentry_iput(struct dentry *dentry, struct inode *inode)
iput(inode);
}
+static int ovl_still_valid(struct dentry *dentry,
+ struct dentry *parent, struct dentry *child)
+{
+ /* dentry is in the overlay filesystem
+ * child is the corresponding dentry in the upper or lower layer
+ * parent is the corresponding dentry of dentry's parent in the same layer
+ *
+ * If child is NULL, the parent must be NULL or negative.
+ * Otherwise child must be hashed, have parent as the d_parent, and
+ * have the same name as dentry
+ *
+ */
+ struct qstr *qstr;
+ int rv;
+
+ if (child == NULL)
+ return (parent == NULL || parent->d_inode == NULL);
+
+ if (child->d_parent != parent)
+ return 0;
+ if (d_unhashed(child))
+ return 0;
+
+ /* Unfortunately we need d_lock to compare names */
+ spin_lock(&dentry->d_lock);
+ spin_lock_nested(&child->d_lock, DENTRY_D_LOCK_NESTED);
+ qstr = &child->d_name;
+ if (parent->d_op && parent->d_op->d_compare)
+ rv = ! (parent->d_op->d_compare(parent, qstr, &dentry->d_name));
+ else
+ rv = (qstr->len == dentry->d_name.len &&
+ memcmp(qstr->name, dentry->d_name.name, qstr->len) == 0);
+
+ spin_unlock(&child->d_lock);
+ spin_unlock(&dentry->d_lock);
+ return rv;
+}
+
+static int ovl_dentry_revalidate(struct dentry *dentry, struct nameidata *nd)
+{
+ /* We need to invalidate this dentry if the either upperpath or lowerpath
+ * has been changed
+ */
+ struct dentry *parent = dget_parent(dentry);
+ struct ovl_entry *ue = dentry->d_fsdata;
+ struct ovl_entry *pue = parent->d_fsdata;
+ int rv;
+
+ rv = (ovl_still_valid(dentry, pue->upperpath.dentry, ue->upperpath.dentry) &&
+ ovl_still_valid(dentry, pue->lowerpath.dentry, ue->lowerpath.dentry));
+ dput(parent);
+ return rv;
+}
+
static const struct dentry_operations ovl_dentry_operations = {
.d_release = ovl_dentry_release,
.d_iput = ovl_dentry_iput,
+ .d_revalidate = ovl_dentry_revalidate,
};
static struct inode *ovl_new_inode(struct super_block *sb, umode_t mode)
--
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to majordomo@...r.kernel.org
More majordomo info at http://vger.kernel.org/majordomo-info.html
Please read the FAQ at http://www.tux.org/lkml/
Powered by blists - more mailing lists