[U-Boot] [PATCH v1] fs: fat: dynamically allocate memory for temporary buffer

From: Stefan Agner stefan.agner@toradex.com
Drop the statically allocated get_contents_vfatname_block and dynamically allocate a buffer only if required. This saves 64KiB of memory.
Signed-off-by: Stefan Agner stefan.agner@toradex.com ---
fs/fat/fat.c | 20 ++++++++++++++------ 1 file changed, 14 insertions(+), 6 deletions(-)
diff --git a/fs/fat/fat.c b/fs/fat/fat.c index 4bc3030ab8..06bcd02835 100644 --- a/fs/fat/fat.c +++ b/fs/fat/fat.c @@ -305,9 +305,6 @@ get_cluster(fsdata *mydata, __u32 clustnum, __u8 *buffer, unsigned long size) * into 'buffer'. * Update the number of bytes read in *gotsize or return -1 on fatal errors. */ -__u8 get_contents_vfatname_block[MAX_CLUSTSIZE] - __aligned(ARCH_DMA_MINALIGN); - static int get_contents(fsdata *mydata, dir_entry *dentptr, loff_t pos, __u8 *buffer, loff_t maxsize, loff_t *gotsize) { @@ -318,7 +315,7 @@ static int get_contents(fsdata *mydata, dir_entry *dentptr, loff_t pos, loff_t actsize;
*gotsize = 0; - debug("Filesize: %llu bytes\n", filesize); + debug("Filesize: %llu bytes, starting at pos %llu\n", filesize, pos);
if (pos >= filesize) { debug("Read position past EOF: %llu\n", pos); @@ -350,15 +347,26 @@ static int get_contents(fsdata *mydata, dir_entry *dentptr, loff_t pos,
/* align to beginning of next cluster if any */ if (pos) { + __u8 *tmp_buffer; + + tmp_buffer = malloc_cache_aligned(MAX_CLUSTSIZE); + if (tmp_buffer == NULL) { + debug("Error: allocating buffer\n"); + return -1; + } + actsize = min(filesize, (loff_t)bytesperclust); - if (get_cluster(mydata, curclust, get_contents_vfatname_block, + if (get_cluster(mydata, curclust, tmp_buffer, (int)actsize) != 0) { printf("Error reading cluster\n"); + free(tmp_buffer); return -1; } filesize -= actsize; actsize -= pos; - memcpy(buffer, get_contents_vfatname_block + pos, actsize); + memcpy(tmp_buffer, buffer + pos, actsize); + free(tmp_buffer); + *gotsize += actsize; if (!filesize) return 0;

On Thu, 6 Dec 2018 14:58:52 +0100 Stefan Agner stefan@agner.ch wrote:
From: Stefan Agner stefan.agner@toradex.com
Drop the statically allocated get_contents_vfatname_block and dynamically allocate a buffer only if required. This saves 64KiB of memory.
Signed-off-by: Stefan Agner stefan.agner@toradex.com
fs/fat/fat.c | 20 ++++++++++++++------ 1 file changed, 14 insertions(+), 6 deletions(-)
diff --git a/fs/fat/fat.c b/fs/fat/fat.c index 4bc3030ab8..06bcd02835 100644 --- a/fs/fat/fat.c +++ b/fs/fat/fat.c @@ -305,9 +305,6 @@ get_cluster(fsdata *mydata, __u32 clustnum, __u8 *buffer, unsigned long size)
- into 'buffer'.
- Update the number of bytes read in *gotsize or return -1 on fatal
errors. */ -__u8 get_contents_vfatname_block[MAX_CLUSTSIZE]
- __aligned(ARCH_DMA_MINALIGN);
static int get_contents(fsdata *mydata, dir_entry *dentptr, loff_t pos, __u8 *buffer, loff_t maxsize, loff_t *gotsize) { @@ -318,7 +315,7 @@ static int get_contents(fsdata *mydata, dir_entry *dentptr, loff_t pos, loff_t actsize;
*gotsize = 0;
- debug("Filesize: %llu bytes\n", filesize);
- debug("Filesize: %llu bytes, starting at pos %llu\n",
filesize, pos); if (pos >= filesize) { debug("Read position past EOF: %llu\n", pos); @@ -350,15 +347,26 @@ static int get_contents(fsdata *mydata, dir_entry *dentptr, loff_t pos, /* align to beginning of next cluster if any */ if (pos) {
__u8 *tmp_buffer;
tmp_buffer = malloc_cache_aligned(MAX_CLUSTSIZE);
if (tmp_buffer == NULL) {
debug("Error: allocating buffer\n");
return -1;
}
- actsize = min(filesize, (loff_t)bytesperclust);
if (get_cluster(mydata, curclust,
get_contents_vfatname_block,
if (get_cluster(mydata, curclust, tmp_buffer, (int)actsize) != 0) { printf("Error reading cluster\n");
} filesize -= actsize; actsize -= pos;free(tmp_buffer); return -1;
memcpy(buffer, get_contents_vfatname_block + pos,
actsize);
memcpy(tmp_buffer, buffer + pos, actsize);
free(tmp_buffer);
- *gotsize += actsize; if (!filesize) return 0;
Reviewed-by: Lukasz Majewski lukma@denx.de
Best regards,
Lukasz Majewski
--
DENX Software Engineering GmbH, Managing Director: Wolfgang Denk HRB 165235 Munich, Office: Kirchenstr.5, D-82194 Groebenzell, Germany Phone: (+49)-8142-66989-59 Fax: (+49)-8142-66989-80 Email: lukma@denx.de

On Thu, Dec 06, 2018 at 02:58:52PM +0100, Stefan Agner wrote:
From: Stefan Agner stefan.agner@toradex.com
Drop the statically allocated get_contents_vfatname_block and dynamically allocate a buffer only if required. This saves 64KiB of memory.
Signed-off-by: Stefan Agner stefan.agner@toradex.com
Is there a particular issue you're running into here, or just that what we're doing is just generally not a great idea? I ask since I need to poke git history to make sure that the thing at the back of my mind about us needing to do this for some annoying boot case is intentional. Thanks!

On 06.12.2018 16:13, Tom Rini wrote:
On Thu, Dec 06, 2018 at 02:58:52PM +0100, Stefan Agner wrote:
From: Stefan Agner stefan.agner@toradex.com
Drop the statically allocated get_contents_vfatname_block and dynamically allocate a buffer only if required. This saves 64KiB of memory.
Signed-off-by: Stefan Agner stefan.agner@toradex.com
Is there a particular issue you're running into here, or just that what we're doing is just generally not a great idea? I ask since I need to poke git history to make sure that the thing at the back of my mind about us needing to do this for some annoying boot case is intentional.
I was in the process checking large global variables since I had issues on a target with limited SRAM (used pre-relocation). I only after writing this patch I realized that the space for the .bss section is not required pre-relocation, so the patch did not help in my particular case.
That said, in git history I saw that get_contents_vfatname_block has been used more broadly in earlier FAT implementations. Now it is only used to handle a corner case: when loading from a file with an offset... I guess the .bss section is cleared, so we probably safe 64KiB of zeroing out... I feel it is still worth doing the change, but I don't have a really strong feeling.
-- Stefan

On Thu, Dec 06, 2018 at 04:45:08PM +0100, Stefan Agner wrote:
On 06.12.2018 16:13, Tom Rini wrote:
On Thu, Dec 06, 2018 at 02:58:52PM +0100, Stefan Agner wrote:
From: Stefan Agner stefan.agner@toradex.com
Drop the statically allocated get_contents_vfatname_block and dynamically allocate a buffer only if required. This saves 64KiB of memory.
Signed-off-by: Stefan Agner stefan.agner@toradex.com
Is there a particular issue you're running into here, or just that what we're doing is just generally not a great idea? I ask since I need to poke git history to make sure that the thing at the back of my mind about us needing to do this for some annoying boot case is intentional.
I was in the process checking large global variables since I had issues on a target with limited SRAM (used pre-relocation). I only after writing this patch I realized that the space for the .bss section is not required pre-relocation, so the patch did not help in my particular case.
That said, in git history I saw that get_contents_vfatname_block has been used more broadly in earlier FAT implementations. Now it is only used to handle a corner case: when loading from a file with an offset... I guess the .bss section is cleared, so we probably safe 64KiB of zeroing out... I feel it is still worth doing the change, but I don't have a really strong feeling.
Thanks for checking. Yes, this is probably a good thing to do overall and whatever historical reason we needed it like this isn't applicable now if we're doing offset loading only in this case which isn't an SPL thing anyhow.

On 06.12.2018 14:58, Stefan Agner wrote:
From: Stefan Agner stefan.agner@toradex.com
Drop the statically allocated get_contents_vfatname_block and dynamically allocate a buffer only if required. This saves 64KiB of memory.
Signed-off-by: Stefan Agner stefan.agner@toradex.com
fs/fat/fat.c | 20 ++++++++++++++------ 1 file changed, 14 insertions(+), 6 deletions(-)
diff --git a/fs/fat/fat.c b/fs/fat/fat.c index 4bc3030ab8..06bcd02835 100644 --- a/fs/fat/fat.c +++ b/fs/fat/fat.c @@ -305,9 +305,6 @@ get_cluster(fsdata *mydata, __u32 clustnum, __u8 *buffer, unsigned long size)
- into 'buffer'.
- Update the number of bytes read in *gotsize or return -1 on fatal errors.
*/ -__u8 get_contents_vfatname_block[MAX_CLUSTSIZE]
- __aligned(ARCH_DMA_MINALIGN);
static int get_contents(fsdata *mydata, dir_entry *dentptr, loff_t pos, __u8 *buffer, loff_t maxsize, loff_t *gotsize) { @@ -318,7 +315,7 @@ static int get_contents(fsdata *mydata, dir_entry *dentptr, loff_t pos, loff_t actsize;
*gotsize = 0;
- debug("Filesize: %llu bytes\n", filesize);
debug("Filesize: %llu bytes, starting at pos %llu\n", filesize, pos);
if (pos >= filesize) { debug("Read position past EOF: %llu\n", pos);
@@ -350,15 +347,26 @@ static int get_contents(fsdata *mydata, dir_entry *dentptr, loff_t pos,
/* align to beginning of next cluster if any */ if (pos) {
__u8 *tmp_buffer;
tmp_buffer = malloc_cache_aligned(MAX_CLUSTSIZE);
if (tmp_buffer == NULL) {
debug("Error: allocating buffer\n");
return -1;
}
- actsize = min(filesize, (loff_t)bytesperclust);
if (get_cluster(mydata, curclust, get_contents_vfatname_block,
if (get_cluster(mydata, curclust, tmp_buffer, (int)actsize) != 0) { printf("Error reading cluster\n");
} filesize -= actsize; actsize -= pos;free(tmp_buffer); return -1;
memcpy(buffer, get_contents_vfatname_block + pos, actsize);
memcpy(tmp_buffer, buffer + pos, actsize);
I somehow managed to mix up copy direction here. Will send a v2.
-- Stefan
free(tmp_buffer);
- *gotsize += actsize; if (!filesize) return 0;
participants (3)
-
Lukasz Majewski
-
Stefan Agner
-
Tom Rini