From patchwork Fri Jul 20 02:57:14 2018 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: AKASHI Takahiro X-Patchwork-Id: 946696 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="Or+ibdTw"; dkim-atps=neutral Received: from lists.denx.de (dione.denx.de [81.169.180.215]) by ozlabs.org (Postfix) with ESMTP id 41Wwcd3pN2z9s4V for ; Fri, 20 Jul 2018 13:00:49 +1000 (AEST) Received: by lists.denx.de (Postfix, from userid 105) id 42CEBC21E2B; Fri, 20 Jul 2018 02:59:03 +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 2C616C21E0D; Fri, 20 Jul 2018 02:59:01 +0000 (UTC) Received: by lists.denx.de (Postfix, from userid 105) id 540D6C21D9A; Fri, 20 Jul 2018 02:57:46 +0000 (UTC) Received: from mail-pg1-f193.google.com (mail-pg1-f193.google.com [209.85.215.193]) by lists.denx.de (Postfix) with ESMTPS id 24A4AC21D8E for ; Fri, 20 Jul 2018 02:57:45 +0000 (UTC) Received: by mail-pg1-f193.google.com with SMTP id g2-v6so5510211pgs.6 for ; Thu, 19 Jul 2018 19:57:45 -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=mZ0VFtsJ299qPD9pw0oWcdMdEsjf1I013YEVr4EGJB8=; b=Or+ibdTwHoKTLNXar7vJC8BUncOhKURQTphi31DantEw5x9vHiZkcgIy5RuyanxzQe KprubHcaRKivX5pglSqvd1z953iiD0DX3WhZj9ASP7qL7nYdAfuh7ny9Nfa7B/JTCDeM pdoUvJ3z5edCFJgkTwPYX5+2KAI9KtQmkTUTw= 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=mZ0VFtsJ299qPD9pw0oWcdMdEsjf1I013YEVr4EGJB8=; b=Ai/dxVl+k4KJ2wiYzoXq/rbNJdKkHCPBAzMwMtjwl2DdB3GZmI9jRj84PKz4FEt3Ry 6AYAFJse7r9v91+9VHR0w8M1EkkdRT+siFnJj2lsS0ffjmeM2jtuQvTMywR9qK/WPcUS uNyx28DJr73SdAVTKpXWuNt2DILMMVow0dd7IzLRiMKbz9Rgc1M69kUixge4XHLAkbIB 9Dj4eVhu6av1dlagbDsFgDfdcheOkpA7BC2Riwd3qPmKnUwR5D9mOEy4yQOE3HN+Khxq HaOSwTdE5lxSEj8piv46GiGln6YK3rGmDsKI87/qXONze8907Xp0vlEA3jIamWY2HTss TvPg== X-Gm-Message-State: AOUpUlH7Qpn9C1oHFMKg43E/km7+4oLvJGSq9Ac4KdvKliPxAsR9rT8W 5JEq5HsVvgObtsdbaqzGtKAS2w== X-Google-Smtp-Source: AAOMgpeJWCOMGRO9cK7AP+h++UdCLI0yAV3gPKbyYaB9TZLoJBafKJ7uYPX2aqwpG2d0jyg70e16rg== X-Received: by 2002:a63:6441:: with SMTP id y62-v6mr299743pgb.240.1532055463735; Thu, 19 Jul 2018 19:57:43 -0700 (PDT) Received: from linaro.org ([121.95.100.191]) by smtp.googlemail.com with ESMTPSA id v22-v6sm810236pfi.60.2018.07.19.19.57.42 (version=TLS1_2 cipher=ECDHE-RSA-AES128-GCM-SHA256 bits=128/128); Thu, 19 Jul 2018 19:57:43 -0700 (PDT) From: AKASHI Takahiro To: trini@konsulko.com Date: Fri, 20 Jul 2018 11:57:14 +0900 Message-Id: <20180720025723.6736-9-takahiro.akashi@linaro.org> X-Mailer: git-send-email 2.17.0 In-Reply-To: <20180720025723.6736-1-takahiro.akashi@linaro.org> References: <20180720025723.6736-1-takahiro.akashi@linaro.org> Cc: u-boot@lists.denx.de, xypron.glpk@gmx.de, agraf@suse.de Subject: [U-Boot] [PATCH 08/17] 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 | 178 +++++++++++++++++---------------------------- 1 file changed, 65 insertions(+), 113 deletions(-) diff --git a/fs/fat/fat_write.c b/fs/fat/fat_write.c index 96edb6674c..3a9c53e253 100644 --- a/fs/fat/fat_write.c +++ b/fs/fat/fat_write.c @@ -528,6 +528,43 @@ 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 +572,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, +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 +612,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 +659,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 +677,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 +794,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 +805,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; @@ -841,47 +852,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 */ @@ -909,32 +881,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; @@ -973,6 +926,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); }