}
 
-static void exfat_get_uniname_from_ext_entry(struct super_block *sb,
+static int exfat_get_uniname_from_ext_entry(struct super_block *sb,
                struct exfat_chain *p_dir, int entry, unsigned short *uniname)
 {
-       int i;
+       int i, err;
        struct exfat_entry_set_cache es;
 
-       if (exfat_get_dentry_set(&es, sb, p_dir, entry, ES_ALL_ENTRIES))
-               return;
+       err = exfat_get_dentry_set(&es, sb, p_dir, entry, ES_ALL_ENTRIES);
+       if (err)
+               return err;
 
        /*
         * First entry  : file entry
        }
 
        exfat_put_dentry_set(&es, false);
+       return 0;
 }
 
 /* read a directory entry from the opened directory */
 static int exfat_readdir(struct inode *inode, loff_t *cpos, struct exfat_dir_entry *dir_entry)
 {
-       int i, dentries_per_clu, num_ext;
+       int i, dentries_per_clu, num_ext, err;
        unsigned int type, clu_offset, max_dentries;
        struct exfat_chain dir, clu;
        struct exfat_uni_name uni_name;
                                        0);
 
                        *uni_name.name = 0x0;
-                       exfat_get_uniname_from_ext_entry(sb, &clu, i,
+                       err = exfat_get_uniname_from_ext_entry(sb, &clu, i,
                                uni_name.name);
+                       if (err) {
+                               brelse(bh);
+                               continue;
+                       }
                        exfat_utf16_to_nls(sb, &uni_name,
                                dir_entry->namebuf.lfn,
                                dir_entry->namebuf.lfnbuf_len);
                        return TYPE_ACL;
                return TYPE_CRITICAL_SEC;
        }
+
+       if (ep->type == EXFAT_VENDOR_EXT)
+               return TYPE_VENDOR_EXT;
+       if (ep->type == EXFAT_VENDOR_ALLOC)
+               return TYPE_VENDOR_ALLOC;
+
        return TYPE_BENIGN_SEC;
 }
 
        return ret;
 }
 
+static void exfat_free_benign_secondary_clusters(struct inode *inode,
+               struct exfat_dentry *ep)
+{
+       struct super_block *sb = inode->i_sb;
+       struct exfat_chain dir;
+       unsigned int start_clu =
+               le32_to_cpu(ep->dentry.generic_secondary.start_clu);
+       u64 size = le64_to_cpu(ep->dentry.generic_secondary.size);
+       unsigned char flags = ep->dentry.generic_secondary.flags;
+
+       if (!(flags & ALLOC_POSSIBLE) || !start_clu || !size)
+               return;
+
+       exfat_chain_set(&dir, start_clu,
+                       EXFAT_B_TO_CLU_ROUND_UP(size, EXFAT_SB(sb)),
+                       flags);
+       exfat_free_cluster(inode, &dir);
+}
+
 int exfat_init_ext_entry(struct inode *inode, struct exfat_chain *p_dir,
                int entry, int num_entries, struct exfat_uni_name *p_uniname)
 {
                if (!ep)
                        return -EIO;
 
+               if (exfat_get_entry_type(ep) & TYPE_BENIGN_SEC)
+                       exfat_free_benign_secondary_clusters(inode, ep);
+
                exfat_init_name_entry(ep, uniname);
                exfat_update_bh(bh, sync);
                brelse(bh);
                if (!ep)
                        return -EIO;
 
+               if (exfat_get_entry_type(ep) & TYPE_BENIGN_SEC)
+                       exfat_free_benign_secondary_clusters(inode, ep);
+
                exfat_set_entry_type(ep, TYPE_DELETED);
                exfat_update_bh(bh, IS_DIRSYNC(inode));
                brelse(bh);
        ES_MODE_GET_STRM_ENTRY,
        ES_MODE_GET_NAME_ENTRY,
        ES_MODE_GET_CRITICAL_SEC_ENTRY,
+       ES_MODE_GET_BENIGN_SEC_ENTRY,
 };
 
 static bool exfat_validate_entry(unsigned int type,
                if  (type != TYPE_FILE && type != TYPE_DIR)
                        return false;
                *mode = ES_MODE_GET_FILE_ENTRY;
-               return true;
+               break;
        case ES_MODE_GET_FILE_ENTRY:
                if (type != TYPE_STREAM)
                        return false;
                *mode = ES_MODE_GET_STRM_ENTRY;
-               return true;
+               break;
        case ES_MODE_GET_STRM_ENTRY:
                if (type != TYPE_EXTEND)
                        return false;
                *mode = ES_MODE_GET_NAME_ENTRY;
-               return true;
+               break;
        case ES_MODE_GET_NAME_ENTRY:
-               if (type == TYPE_STREAM)
+               if (type & TYPE_BENIGN_SEC)
+                       *mode = ES_MODE_GET_BENIGN_SEC_ENTRY;
+               else if (type != TYPE_EXTEND)
                        return false;
-               if (type != TYPE_EXTEND) {
-                       if (!(type & TYPE_CRITICAL_SEC))
-                               return false;
-                       *mode = ES_MODE_GET_CRITICAL_SEC_ENTRY;
-               }
-               return true;
-       case ES_MODE_GET_CRITICAL_SEC_ENTRY:
-               if (type == TYPE_EXTEND || type == TYPE_STREAM)
-                       return false;
-               if ((type & TYPE_CRITICAL_SEC) != TYPE_CRITICAL_SEC)
+               break;
+       case ES_MODE_GET_BENIGN_SEC_ENTRY:
+               /* Assume unreconized benign secondary entry */
+               if (!(type & TYPE_BENIGN_SEC))
                        return false;
-               return true;
+               break;
        default:
-               WARN_ON_ONCE(1);
                return false;
        }
+
+       return true;
 }
 
 struct exfat_dentry *exfat_get_dentry_cached(
 
                type = exfat_get_entry_type(ext_ep);
                brelse(bh);
-               if (type == TYPE_EXTEND || type == TYPE_STREAM)
+               if (type & TYPE_CRITICAL_SEC || type & TYPE_BENIGN_SEC)
                        count++;
-               else
-                       break;
        }
        return count;
 }
 
        ((sbi)->num_clusters - EXFAT_RESERVED_CLUSTERS)
 
 /* AllocationPossible and NoFatChain field in GeneralSecondaryFlags Field */
+#define ALLOC_POSSIBLE         0x01
 #define ALLOC_FAT_CHAIN                0x01
 #define ALLOC_NO_FAT_CHAIN     0x03
 
 #define EXFAT_STREAM           0xC0    /* stream entry */
 #define EXFAT_NAME             0xC1    /* file name entry */
 #define EXFAT_ACL              0xC2    /* stream entry */
+#define EXFAT_VENDOR_EXT       0xE0    /* vendor extension entry */
+#define EXFAT_VENDOR_ALLOC     0xE1    /* vendor allocation entry */
 
 #define IS_EXFAT_CRITICAL_PRI(x)       (x < 0xA0)
 #define IS_EXFAT_BENIGN_PRI(x)         (x < 0xC0)
                        __le32 start_clu;
                        __le64 size;
                } __packed upcase; /* up-case table directory entry */
+               struct {
+                       __u8 flags;
+                       __u8 vendor_guid[16];
+                       __u8 vendor_defined[14];
+               } __packed vendor_ext; /* vendor extension directory entry */
+               struct {
+                       __u8 flags;
+                       __u8 vendor_guid[16];
+                       __u8 vendor_defined[2];
+                       __le32 start_clu;
+                       __le64 size;
+               } __packed vendor_alloc; /* vendor allocation directory entry */
+               struct {
+                       __u8 flags;
+                       __u8 custom_defined[18];
+                       __le32 start_clu;
+                       __le64 size;
+               } __packed generic_secondary; /* generic secondary directory entry */
        } __packed dentry;
 } __packed;