diff options
author | zhangyi (F) <yi.zhang@huawei.com> | 2017-10-31 22:57:00 +0200 |
---|---|---|
committer | Miklos Szeredi <mszeredi@redhat.com> | 2017-11-09 10:23:27 +0100 |
commit | 95e598e7ace2d89717cc3370c2126570667e2007 (patch) | |
tree | f11611e78df4ce99feba388f5dd8d60025d8070b /fs/overlayfs/readdir.c | |
parent | b79e05aaa166755fafbf02db275175edb5175df8 (diff) | |
download | linux-95e598e7ace2d89717cc3370c2126570667e2007.tar.gz linux-95e598e7ace2d89717cc3370c2126570667e2007.tar.bz2 linux-95e598e7ace2d89717cc3370c2126570667e2007.zip |
ovl: simplify ovl_check_empty_and_clear()
Filter out non-whiteout non-upper entries from list of merge dir entries
while checking if merge dir is empty in ovl_check_empty_dir().
The remaining work for ovl_clear_empty() is to clear all entries on the
list.
[amir: split patch from rmdir bug fix]
Signed-off-by: zhangyi (F) <yi.zhang@huawei.com>
Signed-off-by: Amir Goldstein <amir73il@gmail.com>
Signed-off-by: Miklos Szeredi <mszeredi@redhat.com>
Diffstat (limited to 'fs/overlayfs/readdir.c')
-rw-r--r-- | fs/overlayfs/readdir.c | 27 |
1 files changed, 20 insertions, 7 deletions
diff --git a/fs/overlayfs/readdir.c b/fs/overlayfs/readdir.c index 95d12755f847..a5ad5b33b599 100644 --- a/fs/overlayfs/readdir.c +++ b/fs/overlayfs/readdir.c @@ -26,6 +26,7 @@ struct ovl_cache_entry { struct list_head l_node; struct rb_node node; struct ovl_cache_entry *next_maybe_whiteout; + bool is_upper; bool is_whiteout; char name[]; }; @@ -158,6 +159,7 @@ static struct ovl_cache_entry *ovl_cache_entry_new(struct ovl_readdir_data *rdd, /* Defer setting d_ino for upper entry to ovl_iterate() */ if (ovl_calc_d_ino(rdd, p)) p->ino = 0; + p->is_upper = rdd->is_upper; p->is_whiteout = false; if (d_type == DT_CHR) { @@ -851,7 +853,7 @@ const struct file_operations ovl_dir_operations = { int ovl_check_empty_dir(struct dentry *dentry, struct list_head *list) { int err; - struct ovl_cache_entry *p; + struct ovl_cache_entry *p, *n; struct rb_root root = RB_ROOT; err = ovl_dir_read_merged(dentry, list, &root); @@ -860,18 +862,29 @@ int ovl_check_empty_dir(struct dentry *dentry, struct list_head *list) err = 0; - list_for_each_entry(p, list, l_node) { - if (p->is_whiteout) - continue; + list_for_each_entry_safe(p, n, list, l_node) { + /* + * Select whiteouts in upperdir, they should + * be cleared when deleting this directory. + */ + if (p->is_whiteout) { + if (p->is_upper) + continue; + goto del_entry; + } if (p->name[0] == '.') { if (p->len == 1) - continue; + goto del_entry; if (p->len == 2 && p->name[1] == '.') - continue; + goto del_entry; } err = -ENOTEMPTY; break; + +del_entry: + list_del(&p->l_node); + kfree(p); } return err; @@ -885,7 +898,7 @@ void ovl_cleanup_whiteouts(struct dentry *upper, struct list_head *list) list_for_each_entry(p, list, l_node) { struct dentry *dentry; - if (!p->is_whiteout) + if (WARN_ON(!p->is_whiteout || !p->is_upper)) continue; dentry = lookup_one_len(p->name, upper, p->len); |