summaryrefslogtreecommitdiff
path: root/fs/overlayfs/util.c
diff options
context:
space:
mode:
authorMiklos Szeredi <mszeredi@redhat.com>2017-07-27 21:54:06 +0200
committerMiklos Szeredi <mszeredi@redhat.com>2017-07-27 21:54:06 +0200
commit4edb83bb1041e2f946ce36ea93f6bcd06d984bf4 (patch)
tree832e3e3138db090fcbecbef9324116469834f62b /fs/overlayfs/util.c
parentb5efccbe0a12a9d5c65c1a60b4270837c7fdb900 (diff)
ovl: constant d_ino for non-merge dirs
Impure directories are ones which contain objects with origins (i.e. those that have been copied up). These are relevant to readdir operation only because of the d_ino field, no other transformation is necessary. Also a directory can become impure between two getdents(2) calls. This patch creates a cache for impure directories. Unlike the cache for merged directories, this one only contains entries with origin and is not refcounted but has a its lifetime tied to that of the dentry. Similarly to the merged cache, the impure cache is invalidated based on a version number. This version number is incremented when an entry with origin is added or removed from the directory. If the cache is empty, then the impure xattr is removed from the directory. This patch also fixes up handling of d_ino for the ".." entry if the parent directory is merged. Signed-off-by: Miklos Szeredi <mszeredi@redhat.com>
Diffstat (limited to 'fs/overlayfs/util.c')
-rw-r--r--fs/overlayfs/util.c24
1 files changed, 18 insertions, 6 deletions
diff --git a/fs/overlayfs/util.c b/fs/overlayfs/util.c
index f46ad75dc96a..117794582f9f 100644
--- a/fs/overlayfs/util.c
+++ b/fs/overlayfs/util.c
@@ -180,14 +180,14 @@ struct inode *ovl_inode_real(struct inode *inode)
}
-struct ovl_dir_cache *ovl_dir_cache(struct dentry *dentry)
+struct ovl_dir_cache *ovl_dir_cache(struct inode *inode)
{
- return OVL_I(d_inode(dentry))->cache;
+ return OVL_I(inode)->cache;
}
-void ovl_set_dir_cache(struct dentry *dentry, struct ovl_dir_cache *cache)
+void ovl_set_dir_cache(struct inode *inode, struct ovl_dir_cache *cache)
{
- OVL_I(d_inode(dentry))->cache = cache;
+ OVL_I(inode)->cache = cache;
}
bool ovl_dentry_is_opaque(struct dentry *dentry)
@@ -275,12 +275,19 @@ void ovl_inode_update(struct inode *inode, struct dentry *upperdentry)
}
}
-void ovl_dentry_version_inc(struct dentry *dentry)
+void ovl_dentry_version_inc(struct dentry *dentry, bool impurity)
{
struct inode *inode = d_inode(dentry);
WARN_ON(!inode_is_locked(inode));
- OVL_I(inode)->version++;
+ /*
+ * Version is used by readdir code to keep cache consistent. For merge
+ * dirs all changes need to be noted. For non-merge dirs, cache only
+ * contains impure (ones which have been copied up and have origins)
+ * entries, so only need to note changes to impure entries.
+ */
+ if (OVL_TYPE_MERGE(ovl_path_type(dentry)) || impurity)
+ OVL_I(inode)->version++;
}
u64 ovl_dentry_version_get(struct dentry *dentry)
@@ -382,6 +389,11 @@ void ovl_set_flag(unsigned long flag, struct inode *inode)
set_bit(flag, &OVL_I(inode)->flags);
}
+void ovl_clear_flag(unsigned long flag, struct inode *inode)
+{
+ clear_bit(flag, &OVL_I(inode)->flags);
+}
+
bool ovl_test_flag(unsigned long flag, struct inode *inode)
{
return test_bit(flag, &OVL_I(inode)->flags);