summaryrefslogtreecommitdiffstats
path: root/fs
diff options
context:
space:
mode:
authorHeinrich Schuchardt <xypron.glpk@gmx.de>2020-11-26 19:06:55 +0100
committerHeinrich Schuchardt <xypron.glpk@gmx.de>2020-12-10 09:14:59 +0100
commit569b0e1938a5c78b6f4152704ef8c8a4e04fcb09 (patch)
tree97e1e30fb85d07a08165ccd76c2786c40af8690e /fs
parent7557c8485517aa9d2602abb0010c10ab64feee72 (diff)
downloadu-boot-569b0e1938a5c78b6f4152704ef8c8a4e04fcb09.tar.gz
u-boot-569b0e1938a5c78b6f4152704ef8c8a4e04fcb09.tar.xz
u-boot-569b0e1938a5c78b6f4152704ef8c8a4e04fcb09.zip
fs: fat: flush new directory cluster
When handling long file names directory entries may be split over multiple clusters. We must make sure that new clusters are zero filled on disk. When allocating a new cluster for a directory flush it. The flushing should be executed before updating the FAT. This way if flushing fails, we still have a valid directory structure. Signed-off-by: Heinrich Schuchardt <xypron.glpk@gmx.de>
Diffstat (limited to 'fs')
-rw-r--r--fs/fat/fat_write.c28
1 files changed, 19 insertions, 9 deletions
diff --git a/fs/fat/fat_write.c b/fs/fat/fat_write.c
index 0746d73f8d..941f8789ab 100644
--- a/fs/fat/fat_write.c
+++ b/fs/fat/fat_write.c
@@ -738,17 +738,32 @@ static int find_empty_cluster(fsdata *mydata)
return entry;
}
-/*
- * Allocate a cluster for additional directory entries
+/**
+ * new_dir_table() - allocate a cluster for additional directory entries
+ *
+ * @itr: directory iterator
+ * Return: 0 on success, -EIO otherwise
*/
static int new_dir_table(fat_itr *itr)
{
fsdata *mydata = itr->fsdata;
int dir_newclust = 0;
+ int dir_oldclust = itr->clust;
unsigned int bytesperclust = mydata->clust_size * mydata->sect_size;
dir_newclust = find_empty_cluster(mydata);
- set_fatent_value(mydata, itr->clust, dir_newclust);
+
+ /*
+ * Flush before updating FAT to ensure valid directory structure
+ * in case of failure.
+ */
+ itr->clust = dir_newclust;
+ itr->next_clust = dir_newclust;
+ memset(itr->block, 0x00, bytesperclust);
+ if (flush_dir(itr))
+ return -EIO;
+
+ set_fatent_value(mydata, dir_oldclust, dir_newclust);
if (mydata->fatsize == 32)
set_fatent_value(mydata, dir_newclust, 0xffffff8);
else if (mydata->fatsize == 16)
@@ -756,13 +771,8 @@ static int new_dir_table(fat_itr *itr)
else if (mydata->fatsize == 12)
set_fatent_value(mydata, dir_newclust, 0xff8);
- itr->clust = dir_newclust;
- itr->next_clust = dir_newclust;
-
if (flush_dirty_fat_buffer(mydata) < 0)
- return -1;
-
- memset(itr->block, 0x00, bytesperclust);
+ return -EIO;
itr->dent = (dir_entry *)itr->block;
itr->last_cluster = 1;