ext4: fix potential htree corruption when growing large_dir directories
[linux-2.6-microblaze.git] / fs / exfat / dir.c
index c452364..cb1c0d8 100644 (file)
@@ -63,7 +63,7 @@ static void exfat_get_uniname_from_ext_entry(struct super_block *sb,
 static int exfat_readdir(struct inode *inode, loff_t *cpos, struct exfat_dir_entry *dir_entry)
 {
        int i, dentries_per_clu, dentries_per_clu_bits = 0, num_ext;
-       unsigned int type, clu_offset;
+       unsigned int type, clu_offset, max_dentries;
        sector_t sector;
        struct exfat_chain dir, clu;
        struct exfat_uni_name uni_name;
@@ -86,6 +86,8 @@ static int exfat_readdir(struct inode *inode, loff_t *cpos, struct exfat_dir_ent
 
        dentries_per_clu = sbi->dentries_per_clu;
        dentries_per_clu_bits = ilog2(dentries_per_clu);
+       max_dentries = (unsigned int)min_t(u64, MAX_EXFAT_DENTRIES,
+                                          (u64)sbi->num_clusters << dentries_per_clu_bits);
 
        clu_offset = dentry >> dentries_per_clu_bits;
        exfat_chain_dup(&clu, &dir);
@@ -109,7 +111,7 @@ static int exfat_readdir(struct inode *inode, loff_t *cpos, struct exfat_dir_ent
                }
        }
 
-       while (clu.dir != EXFAT_EOF_CLUSTER) {
+       while (clu.dir != EXFAT_EOF_CLUSTER && dentry < max_dentries) {
                i = dentry & (dentries_per_clu - 1);
 
                for ( ; i < dentries_per_clu; i++, dentry++) {
@@ -245,7 +247,7 @@ static int exfat_iterate(struct file *filp, struct dir_context *ctx)
        if (err)
                goto unlock;
 get_new:
-       if (cpos >= i_size_read(inode))
+       if (ei->flags == ALLOC_NO_FAT_CHAIN && cpos >= i_size_read(inode))
                goto end_of_dir;
 
        err = exfat_readdir(inode, &cpos, &de);