From d2febfdc2b7f77d409f19af8d289a0cf7ff63dbc Mon Sep 17 00:00:00 2001 From: Matheus Alves de Almeida Date: Mon, 12 Oct 2026 14:11:05 -0300 Subject: [PATCH] fat: support adding multiple clusters fat_add_cluster() currently adds only one cluster to a file's chain, requiring multiple calls when adding more clusters. Add a fat_alloc_chain() helper that allocates a cluster chain but only returns the first cluster. Extend fat_add_cluster() to add multiple clusters in a single call and rename it to fat_add_clusters() to reflect the new behavior. Link: https://lore.kernel.org/20261012171106.146243-3-matheus.aalmeida@inf.ufrgs.br Signed-off-by: Matheus Alves de Almeida Signed-off-by: Andrew Morton Acked-by: OGAWA Hirofumi --- fs/fat/fat.h | 3 ++- fs/fat/fatent.c | 18 ++++++++++++++++-- fs/fat/file.c | 2 +- fs/fat/inode.c | 8 ++++---- 4 files changed, 23 insertions(+), 8 deletions(-) diff --git a/fs/fat/fat.h b/fs/fat/fat.h index fbd207c55859..5784ca9061b6 100644 --- a/fs/fat/fat.h +++ b/fs/fat/fat.h @@ -395,6 +395,7 @@ extern int fat_ent_write(struct inode *inode, struct fat_entry *fatent, int new, int old, int wait); extern int fat_alloc_clusters(struct inode *inode, int *cluster, int nr_cluster); +int fat_alloc_chain(struct inode *inode, int *cluster, int nr_cluster); extern int fat_free_clusters(struct inode *inode, int cluster); extern int fat_count_free_clusters(struct super_block *sb); extern int fat_trim_fs(struct inode *inode, struct fstrim_range *range); @@ -440,7 +441,7 @@ static inline unsigned long fat_dir_hash(int logstart) { return hash_32(logstart, FAT_HASH_BITS); } -extern int fat_add_cluster(struct inode *inode); +extern int fat_add_clusters(struct inode *inode, int nr_cluster); /* fat/misc.c */ extern __printf(3, 4) __cold diff --git a/fs/fat/fatent.c b/fs/fat/fatent.c index e008fb4e72e0..2d10a815a579 100644 --- a/fs/fat/fatent.c +++ b/fs/fat/fatent.c @@ -503,7 +503,8 @@ static int fat_flush_bhs(struct super_block *sb, struct buffer_head **bhs, return 0; } -int fat_alloc_clusters(struct inode *inode, int *cluster, int nr_cluster) +static int __fat_alloc_clusters(struct inode *inode, int *cluster, int nr_cluster, + bool return_all) { struct super_block *sb = inode->i_sb; struct msdos_sb_info *sbi = MSDOS_SB(sb); @@ -546,7 +547,10 @@ int fat_alloc_clusters(struct inode *inode, int *cluster, int nr_cluster) if (sbi->free_clusters != -1) sbi->free_clusters--; - cluster[idx_clus] = entry; + if (return_all) + cluster[idx_clus] = entry; + else if (!idx_clus) + *cluster = entry; idx_clus++; if (nr_bhs + fatent.nr_bhs > MAX_BUF_PER_PAGE) { @@ -596,6 +600,16 @@ int fat_alloc_clusters(struct inode *inode, int *cluster, int nr_cluster) return err; } +int fat_alloc_clusters(struct inode *inode, int *cluster, int nr_cluster) +{ + return __fat_alloc_clusters(inode, cluster, nr_cluster, true); +} + +int fat_alloc_chain(struct inode *inode, int *cluster, int nr_cluster) +{ + return __fat_alloc_clusters(inode, cluster, nr_cluster, false); +} + int fat_free_clusters(struct inode *inode, int cluster) { struct super_block *sb = inode->i_sb; diff --git a/fs/fat/file.c b/fs/fat/file.c index 6c475c53334c..fc77d20e8fe7 100644 --- a/fs/fat/file.c +++ b/fs/fat/file.c @@ -292,7 +292,7 @@ static long fat_fallocate(struct file *file, int mode, /* Start the allocation.We are not zeroing out the clusters */ while (nr_cluster-- > 0) { - err = fat_add_cluster(inode); + err = fat_add_clusters(inode, 1); if (err) goto error; } diff --git a/fs/fat/inode.c b/fs/fat/inode.c index 0b0bbe777842..d85c8fbdcca4 100644 --- a/fs/fat/inode.c +++ b/fs/fat/inode.c @@ -102,16 +102,16 @@ static struct fat_floppy_defaults { }, }; -int fat_add_cluster(struct inode *inode) +int fat_add_clusters(struct inode *inode, int nr_cluster) { int err, cluster; - err = fat_alloc_clusters(inode, &cluster, 1); + err = fat_alloc_chain(inode, &cluster, nr_cluster); if (err) return err; /* FIXME: this cluster should be added after data of this * cluster is writed */ - err = fat_chain_add(inode, cluster, 1); + err = fat_chain_add(inode, cluster, nr_cluster); if (err) fat_free_clusters(inode, cluster); return err; @@ -153,7 +153,7 @@ static inline int __fat_get_block(struct inode *inode, sector_t iblock, */ if (!offset && !(iblock < last_block)) { /* TODO: multiple cluster allocation would be desirable. */ - err = fat_add_cluster(inode); + err = fat_add_clusters(inode, 1); if (err) return err; }