From ff367a6a34587f7762ee5fefe714efa0118a8ede Mon Sep 17 00:00:00 2001 From: nbd Date: Thu, 17 Mar 2011 19:09:48 +0000 Subject: kernel: replace mini_fo with overlayfs for 2.6.37 git-svn-id: svn://svn.openwrt.org/openwrt/trunk@26209 3c298f89-4303-0410-b956-a3cf2f4a3e73 --- .../211-overlayfs_fix_readdir_deadlock.patch | 124 +++++++++++++++++++++ 1 file changed, 124 insertions(+) create mode 100644 target/linux/generic/patches-2.6.37/211-overlayfs_fix_readdir_deadlock.patch (limited to 'target/linux/generic/patches-2.6.37/211-overlayfs_fix_readdir_deadlock.patch') diff --git a/target/linux/generic/patches-2.6.37/211-overlayfs_fix_readdir_deadlock.patch b/target/linux/generic/patches-2.6.37/211-overlayfs_fix_readdir_deadlock.patch new file mode 100644 index 000000000..188be3d88 --- /dev/null +++ b/target/linux/generic/patches-2.6.37/211-overlayfs_fix_readdir_deadlock.patch @@ -0,0 +1,124 @@ +--- a/fs/overlayfs/overlayfs.c ++++ b/fs/overlayfs/overlayfs.c +@@ -248,8 +248,7 @@ static struct ovl_cache_entry *ovl_cache + } + + static struct ovl_cache_entry *ovl_cache_entry_new(const char *name, int len, +- u64 ino, unsigned int d_type, +- bool is_whiteout) ++ u64 ino, unsigned int d_type) + { + struct ovl_cache_entry *p; + +@@ -262,7 +261,7 @@ static struct ovl_cache_entry *ovl_cache + p->len = len; + p->type = d_type; + p->ino = ino; +- p->is_whiteout = is_whiteout; ++ p->is_whiteout = false; + } + + return p; +@@ -270,7 +269,7 @@ static struct ovl_cache_entry *ovl_cache + + static int ovl_cache_entry_add_rb(struct ovl_readdir_data *rdd, + const char *name, int len, u64 ino, +- unsigned int d_type, bool is_whiteout) ++ unsigned int d_type) + { + struct rb_node **newp = &rdd->root->rb_node; + struct rb_node *parent = NULL; +@@ -291,11 +290,18 @@ static int ovl_cache_entry_add_rb(struct + return 0; + } + +- p = ovl_cache_entry_new(name, len, ino, d_type, is_whiteout); ++ p = ovl_cache_entry_new(name, len, ino, d_type); + if (p == NULL) + return -ENOMEM; + +- list_add_tail(&p->l_node, rdd->list); ++ /* ++ * Add links before other types to be able to quicky mark ++ * any whiteout entries ++ */ ++ if (d_type == DT_LNK) ++ list_add(&p->l_node, rdd->list); ++ else ++ list_add_tail(&p->l_node, rdd->list); + rb_link_node(&p->node, parent, newp); + rb_insert_color(&p->node, rdd->root); + +@@ -313,7 +319,7 @@ static int ovl_fill_lower(void *buf, con + if (p) { + list_move_tail(&p->l_node, rdd->middle); + } else { +- p = ovl_cache_entry_new(name, namelen, ino, d_type, false); ++ p = ovl_cache_entry_new(name, namelen, ino, d_type); + if (p == NULL) + rdd->err = -ENOMEM; + else +@@ -338,26 +344,9 @@ static int ovl_fill_upper(void *buf, con + loff_t offset, u64 ino, unsigned int d_type) + { + struct ovl_readdir_data *rdd = buf; +- bool is_whiteout = false; + + rdd->count++; +- if (d_type == DT_LNK) { +- struct dentry *dentry; +- +- dentry = lookup_one_len(name, rdd->dir, namelen); +- if (IS_ERR(dentry)) { +- rdd->err = PTR_ERR(dentry); +- goto out; +- } +- is_whiteout = ovl_is_whiteout(dentry); +- dput(dentry); +- } +- +- rdd->err = ovl_cache_entry_add_rb(rdd, name, namelen, ino, d_type, +- is_whiteout); +- +-out: +- return rdd->err; ++ return ovl_cache_entry_add_rb(rdd, name, namelen, ino, d_type); + } + + static int ovl_dir_read(struct path *realpath, struct ovl_readdir_data *rdd, +@@ -423,6 +412,26 @@ static void ovl_dir_reset(struct file *f + } + } + ++static void ovl_dir_mark_whiteouts(struct ovl_readdir_data *rdd) ++{ ++ struct ovl_cache_entry *p; ++ struct dentry *dentry; ++ ++ mutex_lock(&rdd->dir->d_inode->i_mutex); ++ list_for_each_entry(p, rdd->list, l_node) { ++ if (p->type != DT_LNK) ++ break; ++ ++ dentry = lookup_one_len(p->name, rdd->dir, p->len); ++ if (IS_ERR(dentry)) ++ continue; ++ ++ p->is_whiteout = ovl_is_whiteout(dentry); ++ dput(dentry); ++ } ++ mutex_unlock(&rdd->dir->d_inode->i_mutex); ++} ++ + static int ovl_dir_read_merged(struct path *upperpath, struct path *lowerpath, + struct ovl_readdir_data *rdd) + { +@@ -436,6 +445,8 @@ static int ovl_dir_read_merged(struct pa + err = ovl_dir_read(upperpath, rdd, ovl_fill_upper); + if (err) + goto out; ++ ++ ovl_dir_mark_whiteouts(rdd); + } + /* + * Insert lowerpath entries before upperpath ones, this allows -- cgit v1.2.3