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>
diff --git a/fs/fat/fat_write.c b/fs/fat/fat_write.c
index 0746d73..941f878 100644
--- a/fs/fat/fat_write.c
+++ b/fs/fat/fat_write.c
@@ -738,17 +738,32 @@
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 @@
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;