> Namjae Jeon writes: > >The compatibility issue between linux exfat and exfat of some camera > >company was reported from Florian. In their exfat, if the number of > >files exceeds any limit, the DataLength in stream entry of the > >directory is no longer updated. So some files created from camera does > >not show in linux exfat. because linux exfat doesn't allow that cpos > >becomes larger than DataLength of stream entry. This patch check > >DataLength in stream entry only if the type is ALLOC_NO_FAT_CHAIN and > >add the check ensure that dentry offset does not exceed max dentries > >size(256 MB) to avoid the circular FAT chain issue. > > > >Fixes: ca06197382bd ("exfat: add directory operations") > >Cc: stable@xxxxxxxxxxxxxxx # v5.9 > >Reported-by: Florian Cramer <flrncrmr@xxxxxxxxx> > >Reviewed-by: Sungjong Seo <sj1557.seo@xxxxxxxxxxx> > >Signed-off-by: Namjae Jeon <namjae.jeon@xxxxxxxxxxx> > > Tested-by: Chris Down <chris@xxxxxxxxxxxxxx> Thanks for your test! > > Thanks, I came across this while debugging why directories produced on my Fuji > X-T4 were truncated at 2^12 dentries. > > If the other report was also Fuji, maybe this is worth asking them to fix in firmware? Well, I am not sure that they will respond to your report well. If you can reproduce same issue even when plugging your exfat into windows, I think that it is worth reporting to them. > >--- > > fs/exfat/dir.c | 8 +++++--- > > 1 file changed, 5 insertions(+), 3 deletions(-) > > > >diff --git a/fs/exfat/dir.c b/fs/exfat/dir.c index > >c4523648472a..f4e4d8d9894d 100644 > >--- a/fs/exfat/dir.c > >+++ b/fs/exfat/dir.c > >@@ -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); > >-- > >2.17.1 > >