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: 145861 Delivered-To: patch@linaro.org Received: by 2002:a2e:1648:0:0:0:0:0 with SMTP id 8-v6csp3368007ljw; Tue, 4 Sep 2018 00:57:39 -0700 (PDT) X-Google-Smtp-Source: ANB0Vdbk/4Z8gv6IAU9jYW+yCF4MIgeJhjcrw0NU7iffwyiwptLqm+mZ0iHK9XlrxVRfgarMfv05 X-Received: by 2002:a50:b6e3:: with SMTP id f32-v6mr35709465ede.147.1536047859440; Tue, 04 Sep 2018 00:57:39 -0700 (PDT) ARC-Seal: i=1; a=rsa-sha256; t=1536047859; cv=none; d=google.com; s=arc-20160816; b=A7JuV5JyJ42epXYtosqiW64AQUYQ/YcihzJFig+Uz6LkfN56yHc3IAKVGOhOdyCGCC hn4iJ7wCCiOZpBnvUPylf3uMkTVlLgjHWAkCwgToj3Pjt7mxiIyjPRFVTCjjVVGcGrj6 70VsrTHqaq6JENpGr/ORkmk1Yi4+AlG/MpP4SsmnF/kP7M0kzZ2SzbJkheeueZQ/+w3t HX5m1IChFgrXY4vBxMJUDeIkH9BcuhCM1AheZOgO6K+7nZW+HS1WfzNmzcLiiS1EtYHd /A2JtjEgdBOj9Pe9wwQeMVofkpTVIyf4jmYbjmA/jXfsVClwqZp31xoxR50jM46urS16 JjGg== ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=arc-20160816; h=sender:errors-to:content-transfer-encoding:mime-version :list-subscribe:list-help:list-post:list-archive:list-unsubscribe :list-id:precedence:subject:cc:references:in-reply-to:message-id :date:to:from:dkim-signature:arc-authentication-results; bh=HOxU4OhxObChd5WJPRHhyFmUwVPc241LQweBm+YKRmQ=; b=ySI8+qcfKZVKrp8/hL0WUjPyU3/BIT/qCSFLSJviHZIPm/ly3RJOtUt4E+o+/ttVXO BNMIeNOCttkV9oSR1lotfQawUtvVyuqzJaWY6ArJNO9RofQH1HGYExx7JP+wkHG1yS3a PLcfRArMIlZi8c0qBSPjWRKLsxlrQ9sUacPUh/F5AUoqko4nVMZHc4sO1+0D5/5diklj 7vVLwP9cWF3zNHUl3ZCYZowNcsvW19c4gnx7nntJ26EMYxqrY+e9OlRe0y7OV9p7R9+m RdtiTfdn/AosHv9F6SbDCVBPCWjSHL4KJaBQUshBYpC1ZgtjCqaNywI5RF6qH+R8ohLX BFkQ== ARC-Authentication-Results: i=1; mx.google.com; dkim=neutral (body hash did not verify) header.i=@linaro.org header.s=google header.b=FvLj5MVT; spf=pass (google.com: best guess record for domain of u-boot-bounces@lists.denx.de designates 81.169.180.215 as permitted sender) smtp.mailfrom=u-boot-bounces@lists.denx.de; dmarc=fail (p=NONE sp=NONE dis=NONE) header.from=linaro.org Return-Path: Received: from lists.denx.de (dione.denx.de. [81.169.180.215]) by mx.google.com with ESMTP id r9-v6si4485165edp.9.2018.09.04.00.57.39; Tue, 04 Sep 2018 00:57:39 -0700 (PDT) Received-SPF: pass (google.com: best guess record for domain of u-boot-bounces@lists.denx.de designates 81.169.180.215 as permitted sender) client-ip=81.169.180.215; Authentication-Results: mx.google.com; dkim=neutral (body hash did not verify) header.i=@linaro.org header.s=google header.b=FvLj5MVT; spf=pass (google.com: best guess record for domain of u-boot-bounces@lists.denx.de designates 81.169.180.215 as permitted sender) smtp.mailfrom=u-boot-bounces@lists.denx.de; dmarc=fail (p=NONE sp=NONE dis=NONE) header.from=linaro.org Received: by lists.denx.de (Postfix, from userid 105) id 0EE29C21F2A; Tue, 4 Sep 2018 07:55:00 +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-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); }