From patchwork Tue Sep 4 07:49:35 2018 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: AKASHI Takahiro X-Patchwork-Id: 965810 X-Patchwork-Delegate: trini@ti.com Return-Path: X-Original-To: incoming@patchwork.ozlabs.org Delivered-To: patchwork-incoming@bilbo.ozlabs.org Authentication-Results: ozlabs.org; spf=none (mailfrom) smtp.mailfrom=lists.denx.de (client-ip=81.169.180.215; helo=lists.denx.de; envelope-from=u-boot-bounces@lists.denx.de; receiver=) Authentication-Results: ozlabs.org; dmarc=fail (p=none dis=none) header.from=linaro.org Authentication-Results: ozlabs.org; dkim=fail reason="signature verification failed" (1024-bit key; unprotected) header.d=linaro.org header.i=@linaro.org header.b="FvLj5MVT"; dkim-atps=neutral Received: from lists.denx.de (dione.denx.de [81.169.180.215]) by ozlabs.org (Postfix) with ESMTP id 424K3s25g4z9sfR for ; Tue, 4 Sep 2018 17:59:21 +1000 (AEST) Received: by lists.denx.de (Postfix, from userid 105) id DF18BC21F63; Tue, 4 Sep 2018 07:55:02 +0000 (UTC) X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on lists.denx.de X-Spam-Level: X-Spam-Status: No, score=-0.0 required=5.0 tests=RCVD_IN_MSPIKE_H3, RCVD_IN_MSPIKE_WL, T_DKIM_INVALID autolearn=unavailable autolearn_force=no version=3.4.0 Received: from lists.denx.de (localhost [IPv6:::1]) by lists.denx.de (Postfix) with ESMTP id A870EC21E44; Tue, 4 Sep 2018 07:53:35 +0000 (UTC) Received: by lists.denx.de (Postfix, from userid 105) id D2BD0C21EF1; Tue, 4 Sep 2018 07:51:39 +0000 (UTC) Received: from mail-pf1-f195.google.com (mail-pf1-f195.google.com [209.85.210.195]) by lists.denx.de (Postfix) with ESMTPS id E40A5C21E4E for ; Tue, 4 Sep 2018 07:51:38 +0000 (UTC) Received: by mail-pf1-f195.google.com with SMTP id d4-v6so1296234pfn.0 for ; Tue, 04 Sep 2018 00:51:38 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=linaro.org; s=google; h=from:to:cc:subject:date:message-id:in-reply-to:references; bh=62Cnji+Q6WSq+AxhlzBta2yfmUXHF/pflqMhI73rUqo=; b=FvLj5MVTNcRe8u74OPhasL5Au/DAEBJaE7tPmakRsSl+V3aLAcL6Ffqd24h4q2uXdx iHQvYoQscH0iZgsDPb3fzkfsuraVlmk/LiDxboB6X8M03IjcikoVqCyMHfNAzr3CLbA1 4FNABAnu+1NeRPVEyAXd/kk3kNjAzkFkJWQZ4= X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20161025; h=x-gm-message-state:from:to:cc:subject:date:message-id:in-reply-to :references; bh=62Cnji+Q6WSq+AxhlzBta2yfmUXHF/pflqMhI73rUqo=; b=LelS6WLSX0ktTyB+ZV50NZUAd8Do+p83cMV1fek2n09cHqOEBWwdKq66A71l9ugCj9 t1DfhCAkMLzQtfyR0UE+JNepyEL9UMroZV7EJyO4kkQOCDrvidqBm0ULmANBZnu+XAjI /IggbDer1g8r8PX0FP6aNfzrtJPTGg8/mMryDaJcdCQq1EY5MVYUY6ICBtEfkUbZPJoc UxzEOqr9MumukgX6ycZJCMoVBN9iQjJsGNXXdqRFYZsiR+PB03fIQFk/IpHpqpFLbWlY hjeWqlLDQb+ywhxO0q1Ve/RNye/cGWCPkIBjd8Oai/eL/SAp2GeV+oxv7zlb3+VPhK4e Yy0A== X-Gm-Message-State: APzg51DeRJlstKdERwK4JHBZDonKrqUXGYx2WTFU4E1pQXMaMwNNxI87 VWUmr0JMkH0UtvSGakaTQgx+nA== X-Google-Smtp-Source: ANB0VdZG0oKHSZrGRwnaoQS5dNzNOVNL3Jh1RVYqKz6JRXrvlAv5bUMVutuO7cGy76Iz6A1ghlvKOA== X-Received: by 2002:a62:4255:: with SMTP id p82-v6mr33672781pfa.238.1536047497448; Tue, 04 Sep 2018 00:51:37 -0700 (PDT) Received: from linaro.org ([121.95.100.191]) by smtp.googlemail.com with ESMTPSA id d66-v6sm37287260pfd.121.2018.09.04.00.51.36 (version=TLS1_2 cipher=ECDHE-RSA-AES128-GCM-SHA256 bits=128/128); Tue, 04 Sep 2018 00:51:36 -0700 (PDT) From: AKASHI Takahiro To: trini@konsulko.com Date: Tue, 4 Sep 2018 16:49:35 +0900 Message-Id: <20180904074948.18146-11-takahiro.akashi@linaro.org> X-Mailer: git-send-email 2.18.0 In-Reply-To: <20180904074948.18146-1-takahiro.akashi@linaro.org> References: <20180904074948.18146-1-takahiro.akashi@linaro.org> Cc: xypron.glpk@gmx.de, agraf@suse.de, u-boot@lists.denx.de Subject: [U-Boot] [PATCH v2 10/23] fs: fat: refactor write interface for a file offset X-BeenThere: u-boot@lists.denx.de X-Mailman-Version: 2.1.18 Precedence: list List-Id: U-Boot discussion List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , MIME-Version: 1.0 Errors-To: u-boot-bounces@lists.denx.de Sender: "U-Boot" The current write implementation is quite simple: remove existing clusters and then allocating new ones and filling them with data. This, inevitably, enforces always writing from the beginning of a file. As the first step to lift this restriction, fat_file_write() and set_contents() are modified to accept an additional parameter, file offset and further re-factored so that, in the next patch, all the necessary code will be put into set_contents(). Signed-off-by: AKASHI Takahiro --- fs/fat/fat_write.c | 179 ++++++++++++++++----------------------------- 1 file changed, 65 insertions(+), 114 deletions(-) diff --git a/fs/fat/fat_write.c b/fs/fat/fat_write.c index cc55c94f1b72..5db7830ad43c 100644 --- a/fs/fat/fat_write.c +++ b/fs/fat/fat_write.c @@ -528,6 +528,42 @@ static int clear_fatent(fsdata *mydata, __u32 entry) return 0; } +/* + * Set start cluster in directory entry + */ +static void set_start_cluster(const fsdata *mydata, dir_entry *dentptr, + __u32 start_cluster) +{ + if (mydata->fatsize == 32) + dentptr->starthi = + cpu_to_le16((start_cluster & 0xffff0000) >> 16); + dentptr->start = cpu_to_le16(start_cluster & 0xffff); +} + +/* + * Check whether adding a file makes the file system to + * exceed the size of the block device + * Return -1 when overflow occurs, otherwise return 0 + */ +static int check_overflow(fsdata *mydata, __u32 clustnum, loff_t size) +{ + __u32 startsect, sect_num, offset; + + if (clustnum > 0) + startsect = clust_to_sect(mydata, clustnum); + else + startsect = mydata->rootdir_sect; + + sect_num = div_u64_rem(size, mydata->sect_size, &offset); + + if (offset != 0) + sect_num++; + + if (startsect + sect_num > total_sector) + return -1; + return 0; +} + /* * Write at most 'maxsize' bytes from 'buffer' into * the file associated with 'dentptr' @@ -535,29 +571,36 @@ static int clear_fatent(fsdata *mydata, __u32 entry) * or return -1 on fatal errors. */ static int -set_contents(fsdata *mydata, dir_entry *dentptr, __u8 *buffer, - loff_t maxsize, loff_t *gotsize) +set_contents(fsdata *mydata, dir_entry *dentptr, loff_t pos, __u8 *buffer, + loff_t maxsize, loff_t *gotsize) { - loff_t filesize = FAT2CPU32(dentptr->size); + loff_t filesize; unsigned int bytesperclust = mydata->clust_size * mydata->sect_size; __u32 curclust = START(dentptr); __u32 endclust = 0, newclust = 0; loff_t actsize; *gotsize = 0; - debug("Filesize: %llu bytes\n", filesize); - - if (maxsize > 0 && filesize > maxsize) - filesize = maxsize; + filesize = maxsize; debug("%llu bytes\n", filesize); - if (!curclust) { - if (filesize) { - debug("error: nonempty clusterless file!\n"); + if (curclust) { + /* + * release already-allocated clusters anyway + */ + if (clear_fatent(mydata, curclust)) { + printf("Error: clearing FAT entries\n"); return -1; } - return 0; + } + + curclust = find_empty_cluster(mydata); + set_start_cluster(mydata, dentptr, curclust); + + if (check_overflow(mydata, curclust, filesize)) { + printf("Error: no space left: %llu\n", filesize); + return -1; } actsize = bytesperclust; @@ -568,6 +611,7 @@ set_contents(fsdata *mydata, dir_entry *dentptr, __u8 *buffer, newclust = determine_fatent(mydata, endclust); if ((newclust - 1) != endclust) + /* write to */ goto getit; if (CHECK_CLUST(newclust, mydata->fatsize)) { @@ -614,18 +658,8 @@ getit: actsize = bytesperclust; curclust = endclust = newclust; } while (1); -} -/* - * Set start cluster in directory entry - */ -static void set_start_cluster(const fsdata *mydata, dir_entry *dentptr, - __u32 start_cluster) -{ - if (mydata->fatsize == 32) - dentptr->starthi = - cpu_to_le16((start_cluster & 0xffff0000) >> 16); - dentptr->start = cpu_to_le16(start_cluster & 0xffff); + return 0; } /* @@ -642,31 +676,6 @@ static void fill_dentry(fsdata *mydata, dir_entry *dentptr, set_name(dentptr, filename); } -/* - * Check whether adding a file makes the file system to - * exceed the size of the block device - * Return -1 when overflow occurs, otherwise return 0 - */ -static int check_overflow(fsdata *mydata, __u32 clustnum, loff_t size) -{ - __u32 startsect, sect_num, offset; - - if (clustnum > 0) { - startsect = clust_to_sect(mydata, clustnum); - } else { - startsect = mydata->rootdir_sect; - } - - sect_num = div_u64_rem(size, mydata->sect_size, &offset); - - if (offset != 0) - sect_num++; - - if (startsect + sect_num > total_sector) - return -1; - return 0; -} - /* * Find a directory entry based on filename or start cluster number * If the directory entry is not found, @@ -784,11 +793,10 @@ static int normalize_longname(char *l_filename, const char *filename) return 0; } -static int do_fat_write(const char *filename, void *buffer, loff_t size, - loff_t *actwrite) +int file_fat_write_at(const char *filename, loff_t pos, void *buffer, + loff_t size, loff_t *actwrite) { dir_entry *retdent; - __u32 start_cluster; fsdata datablock = { .fatbuf = NULL, }; fsdata *mydata = &datablock; fat_itr *itr = NULL; @@ -796,6 +804,8 @@ static int do_fat_write(const char *filename, void *buffer, loff_t size, char *filename_copy, *parent, *basename; char l_filename[VFAT_MAXLEN_BYTES]; + debug("writing %s\n", filename); + filename_copy = strdup(filename); if (!filename_copy) return -ENOMEM; @@ -839,47 +849,8 @@ static int do_fat_write(const char *filename, void *buffer, loff_t size, goto exit; } - /* Update file size and start_cluster in a directory entry */ - retdent->size = cpu_to_le32(size); - start_cluster = START(retdent); - - if (start_cluster) { - if (size) { - ret = check_overflow(mydata, start_cluster, - size); - if (ret) { - printf("Error: %llu overflow\n", size); - ret = -ENOSPC; - goto exit; - } - } - - ret = clear_fatent(mydata, start_cluster); - if (ret) { - printf("Error: clearing FAT entries\n"); - ret = -EIO; - goto exit; - } - - if (!size) - set_start_cluster(mydata, retdent, 0); - } else if (size) { - ret = start_cluster = find_empty_cluster(mydata); - if (ret < 0) { - printf("Error: finding empty cluster\n"); - ret = -ENOSPC; - goto exit; - } - - ret = check_overflow(mydata, start_cluster, size); - if (ret) { - printf("Error: %llu overflow\n", size); - ret = -ENOSPC; - goto exit; - } - - set_start_cluster(mydata, retdent, start_cluster); - } + /* Update file size in a directory entry */ + retdent->size = cpu_to_le32(pos + size); } else { /* Create a new file */ @@ -907,32 +878,13 @@ static int do_fat_write(const char *filename, void *buffer, loff_t size, goto exit; } - if (size) { - ret = start_cluster = find_empty_cluster(mydata); - if (ret < 0) { - printf("Error: finding empty cluster\n"); - ret = -ENOSPC; - goto exit; - } - - ret = check_overflow(mydata, start_cluster, size); - if (ret) { - printf("Error: %llu overflow\n", size); - ret = -ENOSPC; - goto exit; - } - } else { - start_cluster = 0; - } - /* Set attribute as archieve for regular file */ - fill_dentry(itr->fsdata, itr->dent, filename, - start_cluster, size, 0x20); + fill_dentry(itr->fsdata, itr->dent, filename, 0, size, 0x20); retdent = itr->dent; } - ret = set_contents(mydata, retdent, buffer, size, actwrite); + ret = set_contents(mydata, retdent, pos, buffer, size, actwrite); if (ret < 0) { printf("Error: writing contents\n"); ret = -EIO; @@ -971,6 +923,5 @@ int file_fat_write(const char *filename, void *buffer, loff_t offset, return -EINVAL; } - printf("writing %s\n", filename); - return do_fat_write(filename, buffer, maxsize, actwrite); + return file_fat_write_at(filename, offset, buffer, maxsize, actwrite); }