
On 5/13/19 7:49 AM, AKASHI Takahiro wrote:
With the commit below, fat now correctly handles a file read under a non-cluster-aligned root directory of fat12/16. Write operation should be fixed in the same manner.
Fixes: commit 9b18358dc05d ("fs: fat: fix reading non-cluster-aligned root directory") Signed-off-by: AKASHI Takahiro takahiro.akashi@linaro.org Cc: Anssi Hannula anssi.hannula@bitwise.fi
Thanks a lot for addressing this.
fs/fat/fat.c | 15 ++++----- fs/fat/fat_write.c | 78 +++++++++++++++++++++++++++++++--------------- 2 files changed, 61 insertions(+), 32 deletions(-)
diff --git a/fs/fat/fat.c b/fs/fat/fat.c index c5997c21735f..fccaa385d187 100644 --- a/fs/fat/fat.c +++ b/fs/fat/fat.c @@ -619,13 +619,14 @@ static int get_fs_info(fsdata *mydata) return -1; }
- debug("FAT%d, fat_sect: %d, fatlength: %d\n",
mydata->fatsize, mydata->fat_sect, mydata->fatlength);
- debug("Rootdir begins at cluster: %d, sector: %d, offset: %x\n"
"Data begins at: %d\n",
mydata->root_cluster,
mydata->rootdir_sect,
mydata->rootdir_sect * mydata->sect_size, mydata->data_begin);
- debug("FAT%d, fat_sect: %d, fatlength: %d, num: %d\n",
mydata->fatsize, mydata->fat_sect, mydata->fatlength,
mydata->fats);
- debug("Rootdir begins at cluster: %d, sector: %d, size: %x\n"
"Data begins at: %d\n",
mydata->root_cluster,
mydata->rootdir_sect,
mydata->rootdir_size * mydata->sect_size, mydata->data_begin);
This seems to be an unrelated change. It should be either in a separate patch or the commit message should explain why it is related.
Tested-by: Heinrich Schuchardt xypron.glpk@gmx.de
debug("Sector size: %d, cluster size: %d\n", mydata->sect_size, mydata->clust_size);
diff --git a/fs/fat/fat_write.c b/fs/fat/fat_write.c index 852f874e5817..3bc0dd637521 100644 --- a/fs/fat/fat_write.c +++ b/fs/fat/fat_write.c @@ -388,29 +388,23 @@ static __u32 determine_fatent(fsdata *mydata, __u32 entry) }
/**
- set_cluster() - write data to cluster
- set_sectors() - write data to sectors
- Write 'size' bytes from 'buffer' into the specified cluster.
- Write 'size' bytes from 'buffer' into the specified sector.
- @mydata: data to be written
- @clustnum: cluster to be written to
*/ static int
- @startsect: sector to be written to
- @buffer: data to be written
- @size: bytes to be written (but not more than the size of a cluster)
- Return: 0 on success, -1 otherwise
-set_cluster(fsdata *mydata, u32 clustnum, u8 *buffer, u32 size) +set_sectors(fsdata *mydata, u32 startsect, u8 *buffer, u32 size) {
- u32 idx = 0;
- u32 startsect;
- u32 nsects = 0; int ret;
- if (clustnum > 0)
startsect = clust_to_sect(mydata, clustnum);
- else
startsect = mydata->rootdir_sect;
- debug("clustnum: %d, startsect: %d\n", clustnum, startsect);
debug("startsect: %d\n", startsect);
if ((unsigned long)buffer & (ARCH_DMA_MINALIGN - 1)) { ALLOC_CACHE_ALIGN_BUFFER(__u8, tmpbuf, mydata->sect_size);
@@ -429,17 +423,16 @@ set_cluster(fsdata *mydata, u32 clustnum, u8 *buffer, u32 size) size -= mydata->sect_size; } } else if (size >= mydata->sect_size) {
idx = size / mydata->sect_size;
ret = disk_write(startsect, idx, buffer);
if (ret != idx) {
nsects = size / mydata->sect_size;
ret = disk_write(startsect, nsects, buffer);
}if (ret != nsects) { debug("Error writing data (got %d)\n", ret); return -1;
startsect += idx;
idx *= mydata->sect_size;
buffer += idx;
size -= idx;
startsect += nsects;
buffer += nsects * mydata->sect_size;
size -= nsects * mydata->sect_size;
}
if (size) {
@@ -457,6 +450,44 @@ set_cluster(fsdata *mydata, u32 clustnum, u8 *buffer, u32 size) return 0; }
+/**
- set_cluster() - write data to cluster
- Write 'size' bytes from 'buffer' into the specified cluster.
- @mydata: data to be written
- @clustnum: cluster to be written to
- @buffer: data to be written
- @size: bytes to be written (but not more than the size of a cluster)
- Return: 0 on success, -1 otherwise
- */
+static int +set_cluster(fsdata *mydata, u32 clustnum, u8 *buffer, u32 size) +{
- return set_sectors(mydata, clust_to_sect(mydata, clustnum),
buffer, size);
+}
+static int +flush_dir(fat_itr *itr) +{
- fsdata *mydata = itr->fsdata;
- u32 startsect, sect_offset, nsects;
- if (!itr->is_root || mydata->fatsize == 32)
return set_cluster(mydata, itr->clust, itr->block,
mydata->clust_size * mydata->sect_size);
- sect_offset = itr->clust * mydata->clust_size;
- startsect = mydata->rootdir_sect + sect_offset;
- /* do not write past the end of rootdir */
- nsects = min_t(u32, mydata->clust_size,
mydata->rootdir_size - sect_offset);
- return set_sectors(mydata, startsect, itr->block,
nsects * mydata->sect_size);
+}
static __u8 tmpbuf_cluster[MAX_CLUSTSIZE] __aligned(ARCH_DMA_MINALIGN);
/*
@@ -1171,8 +1202,7 @@ int file_fat_write_at(const char *filename, loff_t pos, void *buffer, }
/* Write directory table to device */
- ret = set_cluster(mydata, itr->clust, itr->block,
mydata->clust_size * mydata->sect_size);
- ret = flush_dir(itr); if (ret) { printf("Error: writing directory entry\n"); ret = -EIO;
@@ -1249,8 +1279,7 @@ static int delete_dentry(fat_itr *itr) memset(dentptr, 0, sizeof(*dentptr)); dentptr->name[0] = 0xe5;
- if (set_cluster(mydata, itr->clust, itr->block,
mydata->clust_size * mydata->sect_size) != 0) {
- if (flush_dir(itr)) { printf("error: writing directory entry\n"); return -EIO; }
@@ -1452,8 +1481,7 @@ int fat_mkdir(const char *new_dirname) }
/* Write directory table to device */
- ret = set_cluster(mydata, itr->clust, itr->block,
mydata->clust_size * mydata->sect_size);
- ret = flush_dir(itr); if (ret) printf("Error: writing directory entry\n");