From patchwork Tue Jul 12 22:33:12 2022 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Heinrich Schuchardt X-Patchwork-Id: 1655692 Return-Path: X-Original-To: incoming@patchwork.ozlabs.org Delivered-To: patchwork-incoming@bilbo.ozlabs.org Authentication-Results: bilbo.ozlabs.org; dkim=pass (1024-bit key; secure) header.d=gmx.net header.i=@gmx.net header.a=rsa-sha256 header.s=badeba3b8450 header.b=DzPX2JWZ; dkim-atps=neutral Authentication-Results: ozlabs.org; spf=pass (sender SPF authorized) smtp.mailfrom=lists.denx.de (client-ip=2a01:238:438b:c500:173d:9f52:ddab:ee01; helo=phobos.denx.de; envelope-from=u-boot-bounces@lists.denx.de; receiver=) Received: from phobos.denx.de (phobos.denx.de [IPv6:2a01:238:438b:c500:173d:9f52:ddab:ee01]) (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits) key-exchange X25519 server-signature RSA-PSS (2048 bits)) (No client certificate requested) by bilbo.ozlabs.org (Postfix) with ESMTPS id 4LjFsb1JQkz9ryY for ; Wed, 13 Jul 2022 08:33:55 +1000 (AEST) Received: from h2850616.stratoserver.net (localhost [IPv6:::1]) by phobos.denx.de (Postfix) with ESMTP id 03B06841F5; Wed, 13 Jul 2022 00:33:35 +0200 (CEST) Authentication-Results: phobos.denx.de; dmarc=fail (p=none dis=none) header.from=gmx.de Authentication-Results: phobos.denx.de; spf=pass smtp.mailfrom=u-boot-bounces@lists.denx.de Authentication-Results: phobos.denx.de; dkim=pass (1024-bit key; secure) header.d=gmx.net header.i=@gmx.net header.b="DzPX2JWZ"; dkim-atps=neutral Received: by phobos.denx.de (Postfix, from userid 109) id AB923841EB; Wed, 13 Jul 2022 00:33:27 +0200 (CEST) X-Spam-Checker-Version: SpamAssassin 3.4.2 (2018-09-13) on phobos.denx.de X-Spam-Level: X-Spam-Status: No, score=-1.9 required=5.0 tests=BAYES_00,DKIM_SIGNED, DKIM_VALID,FREEMAIL_FROM,RCVD_IN_MSPIKE_H2,SPF_HELO_NONE,SPF_PASS, T_SCC_BODY_TEXT_LINE autolearn=ham autolearn_force=no version=3.4.2 Received: from mout.gmx.net (mout.gmx.net [212.227.17.22]) (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits)) (No client certificate requested) by phobos.denx.de (Postfix) with ESMTPS id 3D51B84160 for ; Wed, 13 Jul 2022 00:33:22 +0200 (CEST) Authentication-Results: phobos.denx.de; dmarc=pass (p=none dis=none) header.from=gmx.de Authentication-Results: phobos.denx.de; spf=pass smtp.mailfrom=xypron.glpk@gmx.de DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=gmx.net; s=badeba3b8450; t=1657665200; bh=rph8rLpfBTkAJ0UocRGqJGB1zXbiktxhaYfa+QwhsqE=; h=X-UI-Sender-Class:From:To:Cc:Subject:Date:In-Reply-To:References; b=DzPX2JWZJIAbaaZ9xKmrc6PeEKHa4Xx321ueIAfmRYPMLJ9i5KmRferF/2t6e1BW5 yE1pbsO9wNvfP3pO5/2uYB9t0+CrIVdTWff6tt6VcN0tmfMnxzAzpMheorI2aJbPcy 1+WdGBrFu66kZtHredbM0cGhocx2hEJF9KCL4l0Q= X-UI-Sender-Class: 01bb95c1-4bf8-414a-932a-4f6e2808ef9c Received: from rpi3.fritz.box ([62.143.94.109]) by mail.gmx.net (mrgmx105 [212.227.17.174]) with ESMTPSA (Nemesis) id 1Ma24y-1o5lkC1FPo-00VvJH; Wed, 13 Jul 2022 00:33:20 +0200 From: Heinrich Schuchardt To: Tom Rini Cc: AKASHI Takahiro , u-boot@lists.denx.de, Heinrich Schuchardt Subject: [PATCH 1/3] fs: fat: finding an empty FAT cluster Date: Tue, 12 Jul 2022 22:33:12 +0000 Message-Id: <20220712223314.20530-2-xypron.glpk@gmx.de> X-Mailer: git-send-email 2.30.2 In-Reply-To: <20220712223314.20530-1-xypron.glpk@gmx.de> References: <20220712223314.20530-1-xypron.glpk@gmx.de> MIME-Version: 1.0 X-Provags-ID: V03:K1:ouWnyKRHHjVrb/CajFRfNJV5/kSqXikk+fDYWQjlemUZ/MyfEto 5XSrdcL76rsZXppWlfvBCW4Zx6xbHZ9gOoozDwGoIf+wCT3ZTQ8tE93YaSaeBRtb3VsBYyh GmxSpLU9NAe9KXH5C9AY1LSFFkMjA4nZbkXaZpl/uqYq//6jfJ/HNWPvpPzzPF48CadMnKg EOh3fplgNQAs21C/S6fEw== X-UI-Out-Filterresults: notjunk:1;V03:K0:c6N5oIuITgg=:JzVt2dTIl7jEkitq/7D2RY mdCI+4lnJkoNMrwiDJFL19vyZfweWbis0Z0U0pW5ol70Y2Ioa7uSPzObznEKM1TYdpjCfSMdO /I/v2xRpOLOGOp4eG2gxvsCkq3MWo0GdcJdA4rEsyboDfPxAZ3bAopCtRep5Sri+qFBRFXSqB sy3YqzuU8Ze71CvKklFGLGand7Xz2WrL4jpH6cAccU65Fi38i4f75jBe5pV82iW158trJw7tb cWyjrw8zGSB6osuezZPVwtIVB7fXPlv3qFwDkK8a8Ix8JWuVCuKU46id4I364dchqB9azugpc 3Zf8tmGORpHnNIqhOTjP9glkigM9nflOUoaLaOLd/lnWgLq1KYH/oFoKfNfj/99oyX7w/m+ZO X8IihD5+p2WbHgzGpsIQOn0kFoES1Mf6JQxCF4sAB13+Gect9nYgjOJXF6cO4hitN/Y3zFBzq NCwgNtjIoBe0wga0DvCVEN3GnlWb/S5hbT4IO8WMa7at7EhRyPwJ2GAvtUdsaFwv88MwpJGxV JUxPn/j9V+vrIIkCgLyCyQvp7JxmML7ooV0OAN2uG81DEeAaoO5hiIJGYM7LPpHaB/ZhCP3d8 IN3oLT0igFkTXsnCw4OX8PpFKZlvFW7iVBeSxaeLc08L+LZyx/EkbShBR49QJNVZRvV+789uE TRmGJQ2l3uXQHNoHkOEaR6QSx6wO6xTOEJyZs3AAN5eT5rI2ghj8BJM6i7ouPJwjR4Ffz/wFb D1bMa0w5tkjj/ZRb/1jdM0Dr7YS75bQLi/tIpvKGu5RkiP+EOODidtt6pqqgnJVDHyRiBhF3r Y0w6IYAI7EuNE3ojIIqJvFpZPs6UwniaLcFO75XqXZBDv6EDEeEqexothfROg4nFyBE5i8KX3 wnPNIPWruFNY/HXlL+9wWxX9hQ83w5e7ilk9XGttAolnp2tEto59ftJZNbqmEfXEXabZiA5oc A1K9janvgNLYj6KoT9OF8oBg/cVsxAXVjvYs0Bj4XLbq3G0WLOXSbvocuALQPeH6wt0mOxDzC mWcv/a+P2DqlMxw2d5ykfgeRwMONcIUQ5SIcPA8T26iaei91jphov1uND0YKXzd0nE8vtGAMK xby03cPWHk/7BFBXufkE/VB2xQKzt1Id65n8rou1/LqiDy4VCtgEG90SQ== X-BeenThere: u-boot@lists.denx.de X-Mailman-Version: 2.1.39 Precedence: list List-Id: U-Boot discussion List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: u-boot-bounces@lists.denx.de Sender: "U-Boot" X-Virus-Scanned: clamav-milter 0.103.6 at phobos.denx.de X-Virus-Status: Clean Currently we have two functions with redundant coding to find an empty cluster: * find_empty_cluster() seeks from the beginning of the FAT table * determine_fatent() seeks after a given entry Both do not detect the end of the FAT table correctly and return an invalid cluster number if no empty entry if found. find_empty_cluster() is replaced by an invocation of determine_fatent(). determine_fatent() is changed to seek in a second round from the beginning of the FAT table and to return an error code if no free entry is found. With this patch we will always find an empty cluster if it exists. Further patches are needed to handle the disk full error gracefully. Signed-off-by: Heinrich Schuchardt --- fs/fat/fat_write.c | 56 ++++++++++++++++++++++++---------------------- 1 file changed, 29 insertions(+), 27 deletions(-) -- 2.30.2 diff --git a/fs/fat/fat_write.c b/fs/fat/fat_write.c index 8ff2f6def0..a137e14f41 100644 --- a/fs/fat/fat_write.c +++ b/fs/fat/fat_write.c @@ -536,22 +536,41 @@ static int set_fatent_value(fsdata *mydata, __u32 entry, __u32 entry_value) return 0; } -/* - * Determine the next free cluster after 'entry' in a FAT (12/16/32) table - * and link it to 'entry'. EOC marker is not set on returned entry. +/** + * determine_fatent() - get next free FAT cluster + * + * The parameter @entry indicates the current cluster. To reduce fragementation + * the function first searches for a free cluster after the current cluster. + * If none is found, the search is repeated from the beginning of the FAT table. + * + * If @entry is set, the new FAT entry is appended to the given one. + * If @entry is zero, only the number of the first free cluster is returned. + * + * @entry: current entry + * Return: next free cluster or negative error */ -static __u32 determine_fatent(fsdata *mydata, __u32 entry) +static int determine_fatent(fsdata *mydata, __u32 entry) { - __u32 next_fat, next_entry = entry + 1; + __u32 next_fat, next_entry = entry; + int second_round = 0; while (1) { + ++next_entry; + if (CHECK_CLUST(next_entry, mydata->fatsize)) { + if (!second_round) { + second_round = 1; + next_entry = 3; + } else { + return -ENOSPC; + } + } next_fat = get_fatent(mydata, next_entry); - if (next_fat == 0) { + if (!next_fat) { /* found free entry, link to entry */ - set_fatent_value(mydata, entry, next_entry); + if (entry) + set_fatent_value(mydata, entry, next_entry); break; } - next_entry++; } debug("FAT%d: entry: %08x, entry_value: %04x\n", mydata->fatsize, entry, next_entry); @@ -794,23 +813,6 @@ get_set_cluster(fsdata *mydata, __u32 clustnum, loff_t pos, __u8 *buffer, return 0; } -/* - * Find the first empty cluster - */ -static int find_empty_cluster(fsdata *mydata) -{ - __u32 fat_val, entry = 3; - - while (1) { - fat_val = get_fatent(mydata, entry); - if (fat_val == 0) - break; - entry++; - } - - return entry; -} - /** * new_dir_table() - allocate a cluster for additional directory entries * @@ -824,7 +826,7 @@ static int new_dir_table(fat_itr *itr) int dir_oldclust = itr->clust; unsigned int bytesperclust = mydata->clust_size * mydata->sect_size; - dir_newclust = find_empty_cluster(mydata); + dir_newclust = determine_fatent(mydata, 0); /* * Flush before updating FAT to ensure valid directory structure @@ -1066,7 +1068,7 @@ set_clusters: /* Assure that curclust is valid */ if (!curclust) { - curclust = find_empty_cluster(mydata); + curclust = determine_fatent(mydata, 0); set_start_cluster(mydata, dentptr, curclust); } else { newclust = get_fatent(mydata, curclust);