Root/target/linux/generic/patches-2.6.38/102-overlayfs_fix_readdir_unlink_deadlock.patch

1--- a/fs/overlayfs/overlayfs.c
2+++ b/fs/overlayfs/overlayfs.c
3@@ -1700,37 +1700,56 @@ static int ovl_check_empty_dir(struct de
4     return err;
5 }
6 
7-static int ovl_unlink_whiteout(void *buf, const char *name, int namelen,
8- loff_t offset, u64 ino, unsigned int d_type)
9+static int ovl_fill_links(void *buf, const char *name, int namelen,
10+ loff_t offset, u64 ino, unsigned int d_type)
11 {
12     struct ovl_readdir_data *rdd = buf;
13+ struct ovl_cache_entry *p;
14 
15- rdd->count++;
16- /* check d_type to filter out "." and ".." */
17- if (d_type == DT_LNK) {
18- struct dentry *dentry;
19+ if (d_type != DT_LNK)
20+ return 0;
21 
22- dentry = lookup_one_len(name, rdd->dir, namelen);
23- if (IS_ERR(dentry)) {
24- rdd->err = PTR_ERR(dentry);
25- } else {
26- rdd->err = vfs_unlink(rdd->dir->d_inode, dentry);
27- dput(dentry);
28- }
29- }
30+ p = ovl_cache_entry_new(name, namelen, ino, d_type);
31+ if (!p)
32+ return -ENOMEM;
33 
34- return rdd->err;
35+ list_add(&p->l_node, rdd->list);
36+ return 0;
37 }
38 
39 static int ovl_remove_whiteouts(struct dentry *dentry)
40 {
41     struct path upperpath;
42- struct ovl_readdir_data rdd = { .list = NULL };
43+ LIST_HEAD(list);
44+ struct ovl_readdir_data rdd = { .list = &list };
45+ struct ovl_cache_entry *p, *t;
46+ int ret;
47 
48     ovl_path_upper(dentry, &upperpath);
49     rdd.dir = upperpath.dentry;
50 
51- return ovl_dir_read(&upperpath, &rdd, ovl_unlink_whiteout);
52+ ret = ovl_dir_read(&upperpath, &rdd, ovl_fill_links);
53+
54+ mutex_lock(&rdd.dir->d_inode->i_mutex);
55+ list_for_each_entry_safe(p, t, &list, l_node) {
56+ struct dentry *dentry;
57+
58+ if (!ret) {
59+ dentry = lookup_one_len(p->name, rdd.dir, p->len);
60+ if (IS_ERR(dentry)) {
61+ ret = PTR_ERR(dentry);
62+ } else {
63+ ret = vfs_unlink(rdd.dir->d_inode, dentry);
64+ dput(dentry);
65+ }
66+ }
67+
68+ list_del(&p->l_node);
69+ kfree(p);
70+ }
71+ mutex_unlock(&rdd.dir->d_inode->i_mutex);
72+
73+ return ret;
74 }
75 
76 static int ovl_rmdir(struct inode *dir, struct dentry *dentry)
77

Archive Download this file



interactive