Skip to content

Commit 4edb83b

Browse files
author
Miklos Szeredi
committed
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 <[email protected]>
1 parent b5efccb commit 4edb83b

File tree

5 files changed

+266
-45
lines changed

5 files changed

+266
-45
lines changed

fs/overlayfs/dir.c

Lines changed: 6 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -155,7 +155,7 @@ static int ovl_set_opaque(struct dentry *dentry, struct dentry *upperdentry)
155155
static void ovl_instantiate(struct dentry *dentry, struct inode *inode,
156156
struct dentry *newdentry, bool hardlink)
157157
{
158-
ovl_dentry_version_inc(dentry->d_parent);
158+
ovl_dentry_version_inc(dentry->d_parent, false);
159159
ovl_dentry_set_upper_alias(dentry);
160160
if (!hardlink) {
161161
ovl_inode_update(inode, newdentry);
@@ -692,7 +692,7 @@ static int ovl_remove_and_whiteout(struct dentry *dentry, bool is_dir)
692692
if (flags)
693693
ovl_cleanup(wdir, upper);
694694

695-
ovl_dentry_version_inc(dentry->d_parent);
695+
ovl_dentry_version_inc(dentry->d_parent, true);
696696
out_d_drop:
697697
d_drop(dentry);
698698
dput(whiteout);
@@ -742,7 +742,7 @@ static int ovl_remove_upper(struct dentry *dentry, bool is_dir)
742742
err = vfs_rmdir(dir, upper);
743743
else
744744
err = vfs_unlink(dir, upper, NULL);
745-
ovl_dentry_version_inc(dentry->d_parent);
745+
ovl_dentry_version_inc(dentry->d_parent, ovl_type_origin(dentry));
746746

747747
/*
748748
* Keeping this dentry hashed would mean having to release
@@ -1089,8 +1089,9 @@ static int ovl_rename(struct inode *olddir, struct dentry *old,
10891089
drop_nlink(d_inode(new));
10901090
}
10911091

1092-
ovl_dentry_version_inc(old->d_parent);
1093-
ovl_dentry_version_inc(new->d_parent);
1092+
ovl_dentry_version_inc(old->d_parent,
1093+
!overwrite && ovl_type_origin(new));
1094+
ovl_dentry_version_inc(new->d_parent, ovl_type_origin(old));
10941095

10951096
out_dput:
10961097
dput(newdentry);

fs/overlayfs/overlayfs.h

Lines changed: 5 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -204,8 +204,8 @@ struct dentry *ovl_i_dentry_upper(struct inode *inode);
204204
struct inode *ovl_inode_upper(struct inode *inode);
205205
struct inode *ovl_inode_lower(struct inode *inode);
206206
struct inode *ovl_inode_real(struct inode *inode);
207-
struct ovl_dir_cache *ovl_dir_cache(struct dentry *dentry);
208-
void ovl_set_dir_cache(struct dentry *dentry, struct ovl_dir_cache *cache);
207+
struct ovl_dir_cache *ovl_dir_cache(struct inode *inode);
208+
void ovl_set_dir_cache(struct inode *inode, struct ovl_dir_cache *cache);
209209
bool ovl_dentry_is_opaque(struct dentry *dentry);
210210
bool ovl_dentry_is_whiteout(struct dentry *dentry);
211211
void ovl_dentry_set_opaque(struct dentry *dentry);
@@ -217,7 +217,7 @@ void ovl_dentry_set_redirect(struct dentry *dentry, const char *redirect);
217217
void ovl_inode_init(struct inode *inode, struct dentry *upperdentry,
218218
struct dentry *lowerdentry);
219219
void ovl_inode_update(struct inode *inode, struct dentry *upperdentry);
220-
void ovl_dentry_version_inc(struct dentry *dentry);
220+
void ovl_dentry_version_inc(struct dentry *dentry, bool impurity);
221221
u64 ovl_dentry_version_get(struct dentry *dentry);
222222
bool ovl_is_whiteout(struct dentry *dentry);
223223
struct file *ovl_path_open(struct path *path, int flags);
@@ -229,6 +229,7 @@ int ovl_check_setxattr(struct dentry *dentry, struct dentry *upperdentry,
229229
int xerr);
230230
int ovl_set_impure(struct dentry *dentry, struct dentry *upperdentry);
231231
void ovl_set_flag(unsigned long flag, struct inode *inode);
232+
void ovl_clear_flag(unsigned long flag, struct inode *inode);
232233
bool ovl_test_flag(unsigned long flag, struct inode *inode);
233234
bool ovl_inuse_trylock(struct dentry *dentry);
234235
void ovl_inuse_unlock(struct dentry *dentry);
@@ -256,6 +257,7 @@ extern const struct file_operations ovl_dir_operations;
256257
int ovl_check_empty_dir(struct dentry *dentry, struct list_head *list);
257258
void ovl_cleanup_whiteouts(struct dentry *upper, struct list_head *list);
258259
void ovl_cache_free(struct list_head *list);
260+
void ovl_dir_cache_free(struct inode *inode);
259261
int ovl_check_d_type_supported(struct path *realpath);
260262
void ovl_workdir_cleanup(struct inode *dir, struct vfsmount *mnt,
261263
struct dentry *dentry, int level);

0 commit comments

Comments
 (0)