Skip to content

Commit 7850f77

Browse files
author
CKI KWF Bot
committed
Merge: Rebase exFAT to v6.13 + selected fixes
MR: https://gitlab.com/redhat/centos-stream/src/kernel/centos-stream-10/-/merge_requests/1222 Rebase exFAT to v6.13 + selected fixes JIRA: https://issues.redhat.com/browse/RHEL-89708 Signed-off-by: Pavel Reichl <preichl@redhat.com> Approved-by: Andrey Albershteyn <aalbersh@redhat.com> Approved-by: Carlos Maiolino <cmaiolino@redhat.com> Approved-by: CKI KWF Bot <cki-ci-bot+kwf-gitlab-com@redhat.com> Merged-by: CKI GitLab Kmaint Pipeline Bot <26919896-cki-kmaint-pipeline-bot@users.noreply.gitlab.com>
2 parents 12eaead + 7444476 commit 7850f77

File tree

7 files changed

+157
-138
lines changed

7 files changed

+157
-138
lines changed

fs/exfat/balloc.c

Lines changed: 8 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -141,7 +141,7 @@ int exfat_set_bitmap(struct inode *inode, unsigned int clu, bool sync)
141141
return 0;
142142
}
143143

144-
void exfat_clear_bitmap(struct inode *inode, unsigned int clu, bool sync)
144+
int exfat_clear_bitmap(struct inode *inode, unsigned int clu, bool sync)
145145
{
146146
int i, b;
147147
unsigned int ent_idx;
@@ -150,13 +150,17 @@ void exfat_clear_bitmap(struct inode *inode, unsigned int clu, bool sync)
150150
struct exfat_mount_options *opts = &sbi->options;
151151

152152
if (!is_valid_cluster(sbi, clu))
153-
return;
153+
return -EIO;
154154

155155
ent_idx = CLUSTER_TO_BITMAP_ENT(clu);
156156
i = BITMAP_OFFSET_SECTOR_INDEX(sb, ent_idx);
157157
b = BITMAP_OFFSET_BIT_IN_SECTOR(sb, ent_idx);
158158

159+
if (!test_bit_le(b, sbi->vol_amap[i]->b_data))
160+
return -EIO;
161+
159162
clear_bit_le(b, sbi->vol_amap[i]->b_data);
163+
160164
exfat_update_bh(sbi->vol_amap[i], sync);
161165

162166
if (opts->discard) {
@@ -171,6 +175,8 @@ void exfat_clear_bitmap(struct inode *inode, unsigned int clu, bool sync)
171175
opts->discard = 0;
172176
}
173177
}
178+
179+
return 0;
174180
}
175181

176182
/*

fs/exfat/dir.c

Lines changed: 5 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -82,11 +82,8 @@ static int exfat_readdir(struct inode *inode, loff_t *cpos, struct exfat_dir_ent
8282
if (ei->type != TYPE_DIR)
8383
return -EPERM;
8484

85-
if (ei->entry == -1)
86-
exfat_chain_set(&dir, sbi->root_dir, 0, ALLOC_FAT_CHAIN);
87-
else
88-
exfat_chain_set(&dir, ei->start_clu,
89-
EXFAT_B_TO_CLU(i_size_read(inode), sbi), ei->flags);
85+
exfat_chain_set(&dir, ei->start_clu,
86+
EXFAT_B_TO_CLU(i_size_read(inode), sbi), ei->flags);
9087

9188
dentries_per_clu = sbi->dentries_per_clu;
9289
max_dentries = (unsigned int)min_t(u64, MAX_EXFAT_DENTRIES,
@@ -135,21 +132,6 @@ static int exfat_readdir(struct inode *inode, loff_t *cpos, struct exfat_dir_ent
135132

136133
num_ext = ep->dentry.file.num_ext;
137134
dir_entry->attr = le16_to_cpu(ep->dentry.file.attr);
138-
exfat_get_entry_time(sbi, &dir_entry->crtime,
139-
ep->dentry.file.create_tz,
140-
ep->dentry.file.create_time,
141-
ep->dentry.file.create_date,
142-
ep->dentry.file.create_time_cs);
143-
exfat_get_entry_time(sbi, &dir_entry->mtime,
144-
ep->dentry.file.modify_tz,
145-
ep->dentry.file.modify_time,
146-
ep->dentry.file.modify_date,
147-
ep->dentry.file.modify_time_cs);
148-
exfat_get_entry_time(sbi, &dir_entry->atime,
149-
ep->dentry.file.access_tz,
150-
ep->dentry.file.access_time,
151-
ep->dentry.file.access_date,
152-
0);
153135

154136
*uni_name.name = 0x0;
155137
err = exfat_get_uniname_from_ext_entry(sb, &clu, i,
@@ -166,9 +148,8 @@ static int exfat_readdir(struct inode *inode, loff_t *cpos, struct exfat_dir_ent
166148
ep = exfat_get_dentry(sb, &clu, i + 1, &bh);
167149
if (!ep)
168150
return -EIO;
169-
dir_entry->size =
170-
le64_to_cpu(ep->dentry.stream.valid_size);
171-
dir_entry->entry = dentry;
151+
dir_entry->entry = i;
152+
dir_entry->dir = clu;
172153
brelse(bh);
173154

174155
ei->hint_bmap.off = EXFAT_DEN_TO_CLU(dentry, sbi);
@@ -277,7 +258,7 @@ static int exfat_iterate(struct file *file, struct dir_context *ctx)
277258
if (!nb->lfn[0])
278259
goto end_of_dir;
279260

280-
i_pos = ((loff_t)ei->start_clu << 32) | (de.entry & 0xffffffff);
261+
i_pos = ((loff_t)de.dir.dir << 32) | (de.entry & 0xffffffff);
281262
tmp = exfat_iget(sb, i_pos);
282263
if (tmp) {
283264
inum = tmp->i_ino;

fs/exfat/exfat_fs.h

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -204,7 +204,9 @@ struct exfat_entry_set_cache {
204204
#define IS_DYNAMIC_ES(es) ((es)->__bh != (es)->bh)
205205

206206
struct exfat_dir_entry {
207+
/* the cluster where file dentry is located */
207208
struct exfat_chain dir;
209+
/* the index of file dentry in ->dir */
208210
int entry;
209211
unsigned int type;
210212
unsigned int start_clu;
@@ -290,7 +292,9 @@ struct exfat_sb_info {
290292
* EXFAT file system inode in-memory data
291293
*/
292294
struct exfat_inode_info {
295+
/* the cluster where file dentry is located */
293296
struct exfat_chain dir;
297+
/* the index of file dentry in ->dir */
294298
int entry;
295299
unsigned int type;
296300
unsigned short attr;
@@ -452,7 +456,7 @@ int exfat_count_num_clusters(struct super_block *sb,
452456
int exfat_load_bitmap(struct super_block *sb);
453457
void exfat_free_bitmap(struct exfat_sb_info *sbi);
454458
int exfat_set_bitmap(struct inode *inode, unsigned int clu, bool sync);
455-
void exfat_clear_bitmap(struct inode *inode, unsigned int clu, bool sync);
459+
int exfat_clear_bitmap(struct inode *inode, unsigned int clu, bool sync);
456460
unsigned int exfat_find_free_bitmap(struct super_block *sb, unsigned int clu);
457461
int exfat_count_used_clusters(struct super_block *sb, unsigned int *ret_count);
458462
int exfat_trim_fs(struct inode *inode, struct fstrim_range *range);
@@ -508,6 +512,8 @@ struct exfat_dentry *exfat_get_dentry_cached(struct exfat_entry_set_cache *es,
508512
int exfat_get_dentry_set(struct exfat_entry_set_cache *es,
509513
struct super_block *sb, struct exfat_chain *p_dir, int entry,
510514
unsigned int num_entries);
515+
#define exfat_get_dentry_set_by_ei(es, sb, ei) \
516+
exfat_get_dentry_set(es, sb, &(ei)->dir, (ei)->entry, ES_ALL_ENTRIES)
511517
int exfat_get_empty_dentry_set(struct exfat_entry_set_cache *es,
512518
struct super_block *sb, struct exfat_chain *p_dir, int entry,
513519
unsigned int num_entries);

fs/exfat/fatent.c

Lines changed: 18 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -175,6 +175,7 @@ static int __exfat_free_cluster(struct inode *inode, struct exfat_chain *p_chain
175175
BITMAP_OFFSET_SECTOR_INDEX(sb, CLUSTER_TO_BITMAP_ENT(clu));
176176

177177
if (p_chain->flags == ALLOC_NO_FAT_CHAIN) {
178+
int err;
178179
unsigned int last_cluster = p_chain->dir + p_chain->size - 1;
179180
do {
180181
bool sync = false;
@@ -189,7 +190,9 @@ static int __exfat_free_cluster(struct inode *inode, struct exfat_chain *p_chain
189190
cur_cmap_i = next_cmap_i;
190191
}
191192

192-
exfat_clear_bitmap(inode, clu, (sync && IS_DIRSYNC(inode)));
193+
err = exfat_clear_bitmap(inode, clu, (sync && IS_DIRSYNC(inode)));
194+
if (err)
195+
break;
193196
clu++;
194197
num_clusters++;
195198
} while (num_clusters < p_chain->size);
@@ -210,16 +213,26 @@ static int __exfat_free_cluster(struct inode *inode, struct exfat_chain *p_chain
210213
cur_cmap_i = next_cmap_i;
211214
}
212215

213-
exfat_clear_bitmap(inode, clu, (sync && IS_DIRSYNC(inode)));
216+
if (exfat_clear_bitmap(inode, clu, (sync && IS_DIRSYNC(inode))))
217+
break;
214218
clu = n_clu;
215219
num_clusters++;
216220

217221
if (err)
218-
goto dec_used_clus;
222+
break;
223+
224+
if (num_clusters >= sbi->num_clusters - EXFAT_FIRST_CLUSTER) {
225+
/*
226+
* The cluster chain includes a loop, scan the
227+
* bitmap to get the number of used clusters.
228+
*/
229+
exfat_count_used_clusters(sb, &sbi->used_clusters);
230+
231+
return 0;
232+
}
219233
} while (clu != EXFAT_EOF_CLUSTER);
220234
}
221235

222-
dec_used_clus:
223236
sbi->used_clusters -= num_clusters;
224237
return 0;
225238
}
@@ -252,7 +265,7 @@ int exfat_find_last_cluster(struct super_block *sb, struct exfat_chain *p_chain,
252265
clu = next;
253266
if (exfat_ent_get(sb, clu, &next))
254267
return -EIO;
255-
} while (next != EXFAT_EOF_CLUSTER);
268+
} while (next != EXFAT_EOF_CLUSTER && count <= p_chain->size);
256269

257270
if (p_chain->size != count) {
258271
exfat_fs_error(sb,

fs/exfat/file.c

Lines changed: 38 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -582,14 +582,27 @@ static ssize_t exfat_file_write_iter(struct kiocb *iocb, struct iov_iter *iter)
582582
loff_t pos = iocb->ki_pos;
583583
loff_t valid_size;
584584

585+
if (unlikely(exfat_forced_shutdown(inode->i_sb)))
586+
return -EIO;
587+
585588
inode_lock(inode);
586589

587590
valid_size = ei->valid_size;
588591

589592
ret = generic_write_checks(iocb, iter);
590-
if (ret < 0)
593+
if (ret <= 0)
591594
goto unlock;
592595

596+
if (iocb->ki_flags & IOCB_DIRECT) {
597+
unsigned long align = pos | iov_iter_alignment(iter);
598+
599+
if (!IS_ALIGNED(align, i_blocksize(inode)) &&
600+
!IS_ALIGNED(align, bdev_logical_block_size(inode->i_sb->s_bdev))) {
601+
ret = -EINVAL;
602+
goto unlock;
603+
}
604+
}
605+
593606
if (pos > valid_size) {
594607
ret = exfat_extend_valid_size(file, pos);
595608
if (ret < 0 && ret != -ENOSPC) {
@@ -625,6 +638,16 @@ static ssize_t exfat_file_write_iter(struct kiocb *iocb, struct iov_iter *iter)
625638
return ret;
626639
}
627640

641+
static ssize_t exfat_file_read_iter(struct kiocb *iocb, struct iov_iter *iter)
642+
{
643+
struct inode *inode = file_inode(iocb->ki_filp);
644+
645+
if (unlikely(exfat_forced_shutdown(inode->i_sb)))
646+
return -EIO;
647+
648+
return generic_file_read_iter(iocb, iter);
649+
}
650+
628651
static vm_fault_t exfat_page_mkwrite(struct vm_fault *vmf)
629652
{
630653
int err;
@@ -662,22 +685,34 @@ static const struct vm_operations_struct exfat_file_vm_ops = {
662685

663686
static int exfat_file_mmap(struct file *file, struct vm_area_struct *vma)
664687
{
688+
if (unlikely(exfat_forced_shutdown(file_inode(file)->i_sb)))
689+
return -EIO;
690+
665691
file_accessed(file);
666692
vma->vm_ops = &exfat_file_vm_ops;
667693
return 0;
668694
}
669695

696+
static ssize_t exfat_splice_read(struct file *in, loff_t *ppos,
697+
struct pipe_inode_info *pipe, size_t len, unsigned int flags)
698+
{
699+
if (unlikely(exfat_forced_shutdown(file_inode(in)->i_sb)))
700+
return -EIO;
701+
702+
return filemap_splice_read(in, ppos, pipe, len, flags);
703+
}
704+
670705
const struct file_operations exfat_file_operations = {
671706
.llseek = generic_file_llseek,
672-
.read_iter = generic_file_read_iter,
707+
.read_iter = exfat_file_read_iter,
673708
.write_iter = exfat_file_write_iter,
674709
.unlocked_ioctl = exfat_ioctl,
675710
#ifdef CONFIG_COMPAT
676711
.compat_ioctl = exfat_compat_ioctl,
677712
#endif
678713
.mmap = exfat_file_mmap,
679714
.fsync = exfat_file_fsync,
680-
.splice_read = filemap_splice_read,
715+
.splice_read = exfat_splice_read,
681716
.splice_write = iter_file_splice_write,
682717
};
683718

fs/exfat/inode.c

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -43,7 +43,7 @@ int __exfat_write_inode(struct inode *inode, int sync)
4343
exfat_set_volume_dirty(sb);
4444

4545
/* get the directory entry of given file or directory */
46-
if (exfat_get_dentry_set(&es, sb, &(ei->dir), ei->entry, ES_ALL_ENTRIES))
46+
if (exfat_get_dentry_set_by_ei(&es, sb, ei))
4747
return -EIO;
4848
ep = exfat_get_dentry_cached(&es, ES_IDX_FILE);
4949
ep2 = exfat_get_dentry_cached(&es, ES_IDX_STREAM);
@@ -391,6 +391,8 @@ static int exfat_get_block(struct inode *inode, sector_t iblock,
391391
/* Zero unwritten part of a block */
392392
memset(bh_result->b_data + size, 0,
393393
bh_result->b_size - size);
394+
395+
err = 0;
394396
} else {
395397
/*
396398
* The range has not been written, clear the mapped flag

0 commit comments

Comments
 (0)