[PATCH] libmisc/untar: Use a larger block size to read and write files

Chris Johns chrisj at rtems.org
Fri Apr 1 03:16:45 UTC 2022


On 1/4/2022 11:14 am, Joel Sherrill wrote:
> This looks ok. Does it impact any array declaration that I missed? I'm just
> worrying about changes in stack consumption.

Not that I could see. A buffer allocated on the heap is now bigger to hold the
larger data block and that has been adjusted.

I have an application where the JFFS slowed down from 4.11 to 6 and the only
difference I could see was 6 had a lot more, I would say 50%, small blocks being
written to the flash device over 4.11. This change makes using untar on JFFS
much more efficient.

Chris

> 
> On Thu, Mar 31, 2022, 6:26 PM <chrisj at rtems.org <mailto:chrisj at rtems.org>> wrote:
> 
>     From: Chris Johns <chrisj at rtems.org <mailto:chrisj at rtems.org>>
> 
>     - A larger block size lets files systems work better. On JFFS
>       a 512 byte compressed block means lots of small flash updates
> 
>     Closes #4635
>     ---
>      cpukit/libmisc/untar/untar.c | 53 ++++++++++++++++++++++--------------
>      1 file changed, 33 insertions(+), 20 deletions(-)
> 
>     diff --git a/cpukit/libmisc/untar/untar.c b/cpukit/libmisc/untar/untar.c
>     index 7bc1fff02a..fff737db68 100644
>     --- a/cpukit/libmisc/untar/untar.c
>     +++ b/cpukit/libmisc/untar/untar.c
>     @@ -84,6 +84,14 @@
> 
>      #define MAX_NAME_FIELD_SIZE      99
> 
>     +#define TAR_BLOCK_SIZE           512
>     +#define TAR_BLOCK_SIZE_MASK      (TAR_BLOCK_SIZE - 1)
>     +
>     +/*
>     + * Number of blocks read or written
>     + */
>     +#define TAR_WORK_BLOCKS          16
>     +
>      static int _rtems_tar_header_checksum(const char *bufr);
> 
>      /*
>     @@ -240,7 +248,8 @@ Untar_ProcessHeader(
>        } else if (ctx->linkflag == REGTYPE) {
>          rtems_printf(ctx->printer, "untar: file: %s (s:%lu,m:%04lo)\n",
>                       ctx->file_path, ctx->file_size, ctx->mode);
>     -    ctx->nblocks = (((ctx->file_size) + 511) & ~511) / 512;
>     +    ctx->nblocks =
>     +      (((ctx->file_size) + TAR_BLOCK_SIZE_MASK) & ~TAR_BLOCK_SIZE_MASK) /
>     TAR_BLOCK_SIZE;
>        } else if (ctx->linkflag == DIRTYPE) {
>          rtems_printf(ctx->printer, "untar: dir: %s\n", ctx->file_path);
>          r = mkdir(ctx->file_path, ctx->mode);
>     @@ -311,14 +320,14 @@ Untar_FromMemory_Print(
> 
>        ptr = 0;
>        while (true) {
>     -    if (ptr + 512 > size) {
>     +    if (ptr + TAR_BLOCK_SIZE > size) {
>            retval = UNTAR_SUCCESSFUL;
>            break;
>          }
> 
>          /* Read the header */
>          bufr = &tar_ptr[ptr];
>     -    ptr += 512;
>     +    ptr += TAR_BLOCK_SIZE;
> 
>          retval = Untar_ProcessHeader(&ctx, bufr);
> 
>     @@ -329,27 +338,26 @@ Untar_FromMemory_Print(
>            if ((fd = open(ctx.file_path,
>                           O_TRUNC | O_CREAT | O_WRONLY, ctx.mode)) == -1) {
>              Print_Error(printer, "open", ctx.file_path);
>     -        ptr += 512 * ctx.nblocks;
>     +        ptr += TAR_BLOCK_SIZE * ctx.nblocks;
>            } else {
>     -        unsigned long sizeToGo = ctx.file_size;
>     -        ssize_t       len;
>     -        ssize_t       i;
>     -        ssize_t       n;
>     -
>              /*
>               * Read out the data.  There are nblocks of data where nblocks is the
>               * file_size rounded to the nearest 512-byte boundary.
>               */
>     -        for (i = 0; i < ctx.nblocks; i++) {
>     -          len = ((sizeToGo < 512L) ? (sizeToGo) : (512L));
>     -          n = write(fd, &tar_ptr[ptr], len);
>     +        ssize_t file_size = ctx.file_size;
>     +        size_t blocks = ctx.nblocks;
>     +        while (blocks > 0) {
>     +          size_t blks = blocks > TAR_WORK_BLOCKS ? TAR_WORK_BLOCKS : blocks;
>     +          ssize_t len = MIN(blks * TAR_BLOCK_SIZE, file_size);
>     +          ssize_t n = write(fd, &tar_ptr[ptr], len);
>                if (n != len) {
>                  Print_Error(printer, "write", ctx.file_path);
>                  retval  = UNTAR_FAIL;
>                  break;
>                }
>     -          ptr += 512;
>     -          sizeToGo -= n;
>     +          ptr += blks * TAR_BLOCK_SIZE;
>     +          file_size -= n;
>     +          blocks -= blks;
>              }
>              close(fd);
>            }
>     @@ -419,7 +427,6 @@ Untar_FromFile_Print(
>        char                *bufr;
>        ssize_t              n;
>        int                  retval;
>     -  unsigned long        i;
>        char                 buf[UNTAR_FILE_NAME_SIZE];
>        Untar_HeaderContext  ctx;
> 
>     @@ -429,7 +436,7 @@ Untar_FromFile_Print(
>          return UNTAR_FAIL;
>        }
> 
>     -  bufr = (char *)malloc(512);
>     +  bufr = (char *)malloc(TAR_WORK_BLOCKS * TAR_BLOCK_SIZE);
>        if (bufr == NULL) {
>          close(fd);
>          return(UNTAR_FAIL);
>     @@ -442,7 +449,7 @@ Untar_FromFile_Print(
>        while (1) {
>          /* Read the header */
>          /* If the header read fails, we just consider it the end of the tarfile. */
>     -    if ((n = read(fd, bufr, 512)) != 512) {
>     +    if ((n = read(fd, bufr, TAR_BLOCK_SIZE)) != TAR_BLOCK_SIZE) {
>            break;
>          }
> 
>     @@ -464,10 +471,16 @@ Untar_FromFile_Print(
>              retval = UNTAR_FAIL;
>              break;
>            } else {
>     -        for (i = 0; i < ctx.nblocks; i++) {
>     -          n = read(fd, bufr, 512);
>     -          n = MIN(n, ctx.file_size - (i * 512UL));
>     +        ssize_t file_size = ctx.file_size;
>     +        size_t blocks = ctx.nblocks;
>     +        while (blocks > 0) {
>     +          size_t blks = blocks > TAR_WORK_BLOCKS ? TAR_WORK_BLOCKS : blocks;
>     +          size_t bytes = blks * TAR_BLOCK_SIZE;
>     +          n = read(fd, bufr, bytes);
>     +          n = MIN(n, file_size);
>                (void) write(out_fd, bufr, n);
>     +          file_size -= n;
>     +          blocks -= blks;
>              }
>              close(out_fd);
>            }
>     -- 
>     2.24.1
> 
>     _______________________________________________
>     devel mailing list
>     devel at rtems.org <mailto:devel at rtems.org>
>     http://lists.rtems.org/mailman/listinfo/devel
>     <http://lists.rtems.org/mailman/listinfo/devel>
> 


More information about the devel mailing list