[PATCH 50/74] union-mount: Add lookup_union()

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



From: Valerie Aurora <vaurora@xxxxxxxxxx>

lookup_union() checks if union lookup is actually necessary for this
dentry, and marks the dentry to show that the union lookup has been
performed.

__lookup_union() may overwrite the parent's path in the nameidata
struct for the entry being looked up.  This is because it reuses the
same nameidata to do lookups in each of the lower layer directories.
lookup_union() saves and restores the original parent's path in the
nameidata.

Signed-off-by: Valerie Aurora <valerie.aurora@xxxxxxxxx>
---
 fs/namei.c |   50 ++++++++++++++++++++++++++++++++++++++++++++++++++
 1 files changed, 50 insertions(+), 0 deletions(-)

diff --git a/fs/namei.c b/fs/namei.c
index 789015a..8257537 100644
--- a/fs/namei.c
+++ b/fs/namei.c
@@ -859,6 +859,56 @@ out_err:
 }
 
 /*
+ * lookup_union - Lookup and/or build union stack if needed
+ *
+ * @nd - nameidata for the parent of @topmost
+ * @name - name of target
+ * @topmost - path of the target on the topmost file system
+ *
+ * Check if we need to do a union lookup on this target.  Mark dentry
+ * to show lookup union has been performed.
+ *
+ * We borrow the nameidata struct from the topmost layer to do the
+ * revalidation on lower dentries, replacing the topmost parent
+ * directory's path with that of the matching parent dir in each lower
+ * layer.  This wrapper for __lookup_union() saves the topmost layer's
+ * path and restores it when we are done.
+ *
+ * Caller must hold parent i_mutex.
+ */
+static int lookup_union(struct nameidata *nd, struct qstr *name,
+			struct path *topmost)
+{
+	struct path saved_path;
+	int err = 0;
+
+	BUG_ON(!IS_MNT_UNION(nd->path.mnt) && !IS_MNT_UNION(topmost->mnt));
+	BUG_ON(!mutex_is_locked(&nd->path.dentry->d_inode->i_mutex));
+
+	/*
+	 * Initial test done outside of parent i_mutex lock, recheck
+	 * it.  We only set this flag inside parent i_mutex so it's
+	 * safe to check it here (only need d_lock when setting to
+	 * avoid squashing other flags).
+	 */
+	if (topmost->dentry->d_flags & DCACHE_UNION_LOOKUP_DONE)
+		return 0;
+
+	saved_path = nd->path;
+
+	err = __lookup_union(nd, name, topmost);
+
+	nd->path = saved_path;
+
+	/* XXX move into dcache.h */
+	spin_lock(&topmost->dentry->d_lock);
+	topmost->dentry->d_flags |= DCACHE_UNION_LOOKUP_DONE;
+	spin_unlock(&topmost->dentry->d_lock);
+
+	return err;
+}
+
+/*
  * Allocate a dentry with name and parent, and perform a parent
  * directory ->lookup on it. Returns the new dentry, or ERR_PTR
  * on error. parent->d_inode->i_mutex must be held. d_lookup must
-- 
1.7.0.4

--
To unsubscribe from this list: send the line "unsubscribe linux-fsdevel" in
the body of a message to majordomo@xxxxxxxxxxxxxxx
More majordomo info at  http://vger.kernel.org/majordomo-info.html


[Index of Archives]     [Linux Ext4 Filesystem]     [Union Filesystem]     [Filesystem Testing]     [Ceph Users]     [Ecryptfs]     [AutoFS]     [Kernel Newbies]     [Share Photos]     [Security]     [Netfilter]     [Bugtraq]     [Yosemite News]     [MIPS Linux]     [ARM Linux]     [Linux Security]     [Linux Cachefs]     [Reiser Filesystem]     [Linux RAID]     [Samba]     [Device Mapper]     [CEPH Development]
  Powered by Linux