source: trunk/target/linux/generic/patches-2.6.37/212-overlayfs_fix_readdir_unlink_deadlock.patch @ 26215

Last change on this file since 26215 was 26215, checked in by nbd, 6 years ago

kernel: fix an overlayfs deadlock on rmdir

File size: 1.9 KB
  • fs/overlayfs/overlayfs.c

    a b static int ovl_check_empty_dir(struct de 
    16861686        return err; 
    16871687} 
    16881688 
    1689 static int ovl_unlink_whiteout(void *buf, const char *name, int namelen, 
    1690                                 loff_t offset, u64 ino, unsigned int d_type) 
     1689static int ovl_fill_links(void *buf, const char *name, int namelen, 
     1690                          loff_t offset, u64 ino, unsigned int d_type) 
    16911691{ 
    16921692        struct ovl_readdir_data *rdd = buf; 
     1693        struct ovl_cache_entry *p; 
    16931694 
    1694         rdd->count++; 
    1695         /* check d_type to filter out "." and ".." */ 
    1696         if (d_type == DT_LNK) { 
    1697                 struct dentry *dentry; 
     1695        if (d_type != DT_LNK) 
     1696                return 0; 
    16981697 
    1699                 dentry = lookup_one_len(name, rdd->dir, namelen); 
    1700                 if (IS_ERR(dentry)) { 
    1701                         rdd->err = PTR_ERR(dentry); 
    1702                 } else { 
    1703                         rdd->err = vfs_unlink(rdd->dir->d_inode, dentry); 
    1704                         dput(dentry); 
    1705                 } 
    1706         } 
     1698        p = ovl_cache_entry_new(name, namelen, ino, d_type); 
     1699        if (!p) 
     1700                return -ENOMEM; 
    17071701 
    1708         return rdd->err; 
     1702        list_add(&p->l_node, rdd->list); 
     1703        return 0; 
    17091704} 
    17101705 
    17111706static int ovl_remove_whiteouts(struct dentry *dentry) 
    17121707{ 
    17131708        struct path upperpath; 
    1714         struct ovl_readdir_data rdd = { .list = NULL }; 
     1709        LIST_HEAD(list); 
     1710        struct ovl_readdir_data rdd = { .list = &list }; 
     1711        struct ovl_cache_entry *p, *t; 
     1712        int ret; 
    17151713 
    17161714        ovl_path_upper(dentry, &upperpath); 
    17171715        rdd.dir = upperpath.dentry; 
    17181716 
    1719         return ovl_dir_read(&upperpath, &rdd, ovl_unlink_whiteout); 
     1717        ret = ovl_dir_read(&upperpath, &rdd, ovl_fill_links); 
     1718 
     1719        mutex_lock(&rdd.dir->d_inode->i_mutex); 
     1720        list_for_each_entry_safe(p, t, &list, l_node) { 
     1721                struct dentry *dentry; 
     1722 
     1723                if (!ret) { 
     1724                        dentry = lookup_one_len(p->name, rdd.dir, p->len); 
     1725                        if (IS_ERR(dentry)) { 
     1726                                ret = PTR_ERR(dentry); 
     1727                        } else { 
     1728                                ret = vfs_unlink(rdd.dir->d_inode, dentry); 
     1729                                dput(dentry); 
     1730                        } 
     1731                } 
     1732 
     1733                list_del(&p->l_node); 
     1734                kfree(p); 
     1735        } 
     1736        mutex_unlock(&rdd.dir->d_inode->i_mutex); 
     1737 
     1738        return ret; 
    17201739} 
    17211740 
    17221741static int ovl_rmdir(struct inode *dir, struct dentry *dentry) 
Note: See TracBrowser for help on using the repository browser.