summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMatheus Alves de Almeida <matheus.aalmeida@inf.ufrgs.br>2026-10-12 14:11:05 -0300
committerAndrew Morton <akpm@linux-foundation.org>2026-10-20 22:29:55 -0700
commitd2febfdc2b7f77d409f19af8d289a0cf7ff63dbc (patch)
treee05e272b4d99d9664f26cc3b28f6d1909cd4b338
parent930256458a8a53b89466a3f90c82dbe554efeced (diff)
downloadlinux-d2febfdc2b7f77d409f19af8d289a0cf7ff63dbc.tar.gz
linux-d2febfdc2b7f77d409f19af8d289a0cf7ff63dbc.zip
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 <matheus.aalmeida@inf.ufrgs.br> Signed-off-by: Andrew Morton <akpm@linux-foundation.org> Acked-by: OGAWA Hirofumi <hirofumi@mail.parknet.co.jp>
-rw-r--r--fs/fat/fat.h3
-rw-r--r--fs/fat/fatent.c18
-rw-r--r--fs/fat/file.c2
-rw-r--r--fs/fat/inode.c8
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 @@ out:
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;
}