From patchwork Mon Aug 15 11:45:12 2022 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Qu Wenruo X-Patchwork-Id: 12943468 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by smtp.lore.kernel.org (Postfix) with ESMTP id 2179BC00140 for ; Mon, 15 Aug 2022 11:45:52 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S241433AbiHOLpu (ORCPT ); Mon, 15 Aug 2022 07:45:50 -0400 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:60084 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S240848AbiHOLpq (ORCPT ); Mon, 15 Aug 2022 07:45:46 -0400 Received: from smtp-out2.suse.de (smtp-out2.suse.de [IPv6:2001:67c:2178:6::1d]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id 299C29FFF for ; Mon, 15 Aug 2022 04:45:45 -0700 (PDT) Received: from imap2.suse-dmz.suse.de (imap2.suse-dmz.suse.de [192.168.254.74]) (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits) key-exchange X25519 server-signature ECDSA (P-521) server-digest SHA512) (No client certificate requested) by smtp-out2.suse.de (Postfix) with ESMTPS id BCE8C20853; Mon, 15 Aug 2022 11:45:43 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=suse.com; s=susede1; t=1660563943; h=from:from:reply-to:date:date:message-id:message-id:to:to:cc:cc: mime-version:mime-version: content-transfer-encoding:content-transfer-encoding: in-reply-to:in-reply-to:references:references; bh=gsHg5/alQcTRp96b1M8LR+g9AnV9yvQ2Ftt9iKDE7lc=; b=Q+Wjd9H0Wn2F990m9nkAbWLFL3I4r0pf1aqPd8Wtl/UprmrfGrj9xkZLjhQveYSwzOTu7k wV934u1ghQVOYmR53YQyqn13yAkcL2e37/L0gH7sr+2wc7getjV80H/o0Ly/TtKSwLvRYA fEregu7/T3r++4PU+fiwIve+YED/OjY= Received: from imap2.suse-dmz.suse.de (imap2.suse-dmz.suse.de [192.168.254.74]) (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits) key-exchange X25519 server-signature ECDSA (P-521) server-digest SHA512) (No client certificate requested) by imap2.suse-dmz.suse.de (Postfix) with ESMTPS id 4FB2613A93; Mon, 15 Aug 2022 11:45:40 +0000 (UTC) Received: from dovecot-director2.suse.de ([192.168.254.65]) by imap2.suse-dmz.suse.de with ESMTPSA id KCleBeQx+mLsGAAAMHmgww (envelope-from ); Mon, 15 Aug 2022 11:45:40 +0000 From: Qu Wenruo To: u-boot@lists.denx.de Cc: marek.behun@nic.cz, linux-btrfs@vger.kernel.org, jnhuang95@gmail.com, linux-erofs@lists.ozlabs.org, trini@konsulko.com, joaomarcos.costa@bootlin.com, thomas.petazzoni@bootlin.com, miquel.raynal@bootlin.com Subject: [PATCH v3 1/8] fs: fat: unexport file_fat_read_at() Date: Mon, 15 Aug 2022 19:45:12 +0800 Message-Id: <45a6f44305500b3f7f3d5488ae8bfa9463ba8b31.1660563403.git.wqu@suse.com> X-Mailer: git-send-email 2.37.1 In-Reply-To: References: MIME-Version: 1.0 Precedence: bulk List-ID: X-Mailing-List: linux-btrfs@vger.kernel.org That function is only utilized inside fat driver, unexport it. Signed-off-by: Qu Wenruo --- fs/fat/fat.c | 4 ++-- include/fat.h | 2 -- 2 files changed, 2 insertions(+), 4 deletions(-) diff --git a/fs/fat/fat.c b/fs/fat/fat.c index df9ea2c028fc..dcceccbcee0a 100644 --- a/fs/fat/fat.c +++ b/fs/fat/fat.c @@ -1243,8 +1243,8 @@ out_free_itr: return ret; } -int file_fat_read_at(const char *filename, loff_t pos, void *buffer, - loff_t maxsize, loff_t *actread) +static int file_fat_read_at(const char *filename, loff_t pos, void *buffer, + loff_t maxsize, loff_t *actread) { fsdata fsdata; fat_itr *itr; diff --git a/include/fat.h b/include/fat.h index bd8e450b33a3..a9756fb4cd1b 100644 --- a/include/fat.h +++ b/include/fat.h @@ -200,8 +200,6 @@ static inline u32 sect_to_clust(fsdata *fsdata, int sect) int file_fat_detectfs(void); int fat_exists(const char *filename); int fat_size(const char *filename, loff_t *size); -int file_fat_read_at(const char *filename, loff_t pos, void *buffer, - loff_t maxsize, loff_t *actread); int file_fat_read(const char *filename, void *buffer, int maxsize); int fat_set_blk_dev(struct blk_desc *rbdd, struct disk_partition *info); int fat_register_device(struct blk_desc *dev_desc, int part_no); From patchwork Mon Aug 15 11:45:13 2022 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Qu Wenruo X-Patchwork-Id: 12943469 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by smtp.lore.kernel.org (Postfix) with ESMTP id E8FA9C25B0E for ; Mon, 15 Aug 2022 11:45:52 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S230061AbiHOLpv (ORCPT ); Mon, 15 Aug 2022 07:45:51 -0400 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:60144 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S241432AbiHOLps (ORCPT ); Mon, 15 Aug 2022 07:45:48 -0400 Received: from smtp-out2.suse.de (smtp-out2.suse.de [195.135.220.29]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id 08F75B4BB for ; Mon, 15 Aug 2022 04:45:48 -0700 (PDT) Received: from imap2.suse-dmz.suse.de (imap2.suse-dmz.suse.de [192.168.254.74]) (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits) key-exchange X25519 server-signature ECDSA (P-521) server-digest SHA512) (No client certificate requested) by smtp-out2.suse.de (Postfix) with ESMTPS id B808D20866; Mon, 15 Aug 2022 11:45:46 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=suse.com; s=susede1; t=1660563946; h=from:from:reply-to:date:date:message-id:message-id:to:to:cc:cc: mime-version:mime-version: content-transfer-encoding:content-transfer-encoding: in-reply-to:in-reply-to:references:references; bh=eTUxYj1OZDkY14aB7vIzWLz6w9dpyMmDNCfmBP+tQss=; b=vYKQQAcOZvfBzzTVRPp2uMoKJ2+Oq7ldkICJXN1nBPStK/RnQ+wBkKzfSCizuTbNj+xH8O a2jgwsZ2XGjjGZVrYQMKO6db8zDlTmBQ4IgZCQM0XtUHGZxEWKLMwRi5VIZGK5EAwTr403 gPYHmnvtYWEicOiRynkrXXzk1dq/aC4= Received: from imap2.suse-dmz.suse.de (imap2.suse-dmz.suse.de [192.168.254.74]) (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits) key-exchange X25519 server-signature ECDSA (P-521) server-digest SHA512) (No client certificate requested) by imap2.suse-dmz.suse.de (Postfix) with ESMTPS id 35DCE13A93; Mon, 15 Aug 2022 11:45:43 +0000 (UTC) Received: from dovecot-director2.suse.de ([192.168.254.65]) by imap2.suse-dmz.suse.de with ESMTPSA id uGLIOucx+mLsGAAAMHmgww (envelope-from ); Mon, 15 Aug 2022 11:45:43 +0000 From: Qu Wenruo To: u-boot@lists.denx.de Cc: marek.behun@nic.cz, linux-btrfs@vger.kernel.org, jnhuang95@gmail.com, linux-erofs@lists.ozlabs.org, trini@konsulko.com, joaomarcos.costa@bootlin.com, thomas.petazzoni@bootlin.com, miquel.raynal@bootlin.com Subject: [PATCH v3 2/8] fs: btrfs: fix a bug which no data get read if the length is not 0 Date: Mon, 15 Aug 2022 19:45:13 +0800 Message-Id: X-Mailer: git-send-email 2.37.1 In-Reply-To: References: MIME-Version: 1.0 Precedence: bulk List-ID: X-Mailing-List: linux-btrfs@vger.kernel.org [BUG] When testing with unaligned read, if a specific length is passed in, btrfs driver will read out nothing: => load host 0 $kernel_addr_r 5k_file 0x1000 0 0 bytes read in 0 ms But if no length is passed in, it works fine, even if we pass a non-zero length: => load host 0 $kernel_addr_r 5k_file 0 0x1000 1024 bytes read in 0 ms [CAUSE] In btrfs_read() if we have a larger size than our file, we will try to truncate it using the file size. However the real file size is not initialized if @len is not zero, thus we always truncate our length to 0, and cause the problem. [FIX] Fix it by just always do the file size check. In fact btrfs_size() always follow soft link, thus it will return the real file size correctly. Signed-off-by: Qu Wenruo --- fs/btrfs/btrfs.c | 17 +++++++++-------- 1 file changed, 9 insertions(+), 8 deletions(-) diff --git a/fs/btrfs/btrfs.c b/fs/btrfs/btrfs.c index 4cdbbbe3d066..309cd595d37d 100644 --- a/fs/btrfs/btrfs.c +++ b/fs/btrfs/btrfs.c @@ -246,16 +246,17 @@ int btrfs_read(const char *file, void *buf, loff_t offset, loff_t len, return -EINVAL; } - if (!len) { - ret = btrfs_size(file, &real_size); - if (ret < 0) { - error("Failed to get inode size: %s", file); - return ret; - } - len = real_size; + ret = btrfs_size(file, &real_size); + if (ret < 0) { + error("Failed to get inode size: %s", file); + return ret; } - if (len > real_size - offset) + /* + * If the length is 0 (meaning read the whole file) or the range is + * beyond file size, truncate it to the end of the file. + */ + if (!len || len > real_size - offset) len = real_size - offset; ret = btrfs_file_read(root, ino, offset, len, buf); From patchwork Mon Aug 15 11:45:14 2022 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Qu Wenruo X-Patchwork-Id: 12943470 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by smtp.lore.kernel.org (Postfix) with ESMTP id D7EB1C00140 for ; Mon, 15 Aug 2022 11:45:54 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S231621AbiHOLpx (ORCPT ); Mon, 15 Aug 2022 07:45:53 -0400 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:60236 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S231219AbiHOLpx (ORCPT ); Mon, 15 Aug 2022 07:45:53 -0400 Received: from smtp-out2.suse.de (smtp-out2.suse.de [IPv6:2001:67c:2178:6::1d]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id 017FDBC24 for ; Mon, 15 Aug 2022 04:45:52 -0700 (PDT) Received: from imap2.suse-dmz.suse.de (imap2.suse-dmz.suse.de [192.168.254.74]) (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits) key-exchange X25519 server-signature ECDSA (P-521) server-digest SHA512) (No client certificate requested) by smtp-out2.suse.de (Postfix) with ESMTPS id A29DE20873; Mon, 15 Aug 2022 11:45:50 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=suse.com; s=susede1; t=1660563950; h=from:from:reply-to:date:date:message-id:message-id:to:to:cc:cc: mime-version:mime-version: content-transfer-encoding:content-transfer-encoding: in-reply-to:in-reply-to:references:references; bh=pa2DMiG9S3CyUHkRL/8ty/NybH2uIbDVUCnFXp2wS5k=; b=OMHmcLzHk8eHsj7CLbIT3DU+0rn2jV7sBKfJxM25yxL83zVXcG+nLP7Jqpu3XyXUemrtiW giNcn/ySd+dshC4gAcWNd43zG7vFdVab6yeXrNvcrIXphjK9weVLU5rDkgy3/DSA9YvBM0 XlbPXY6OFzz5WhrcTWeJgOCSEReqmZM= Received: from imap2.suse-dmz.suse.de (imap2.suse-dmz.suse.de [192.168.254.74]) (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits) key-exchange X25519 server-signature ECDSA (P-521) server-digest SHA512) (No client certificate requested) by imap2.suse-dmz.suse.de (Postfix) with ESMTPS id 30D7713A93; Mon, 15 Aug 2022 11:45:46 +0000 (UTC) Received: from dovecot-director2.suse.de ([192.168.254.65]) by imap2.suse-dmz.suse.de with ESMTPSA id UOeYOeox+mLsGAAAMHmgww (envelope-from ); Mon, 15 Aug 2022 11:45:46 +0000 From: Qu Wenruo To: u-boot@lists.denx.de Cc: marek.behun@nic.cz, linux-btrfs@vger.kernel.org, jnhuang95@gmail.com, linux-erofs@lists.ozlabs.org, trini@konsulko.com, joaomarcos.costa@bootlin.com, thomas.petazzoni@bootlin.com, miquel.raynal@bootlin.com Subject: [PATCH v3 3/8] fs: btrfs: fix a crash if specified range is beyond file size Date: Mon, 15 Aug 2022 19:45:14 +0800 Message-Id: X-Mailer: git-send-email 2.37.1 In-Reply-To: References: MIME-Version: 1.0 Precedence: bulk List-ID: X-Mailing-List: linux-btrfs@vger.kernel.org [BUG] When try to read a range beyond file size, btrfs driver will cause crash/segfault: => load host 0 $kernel_addr_r 5k_file 0 0x2000 SEGFAULT [CAUSE] In btrfs_read(), if @len is 0, we will truncated it to file end, but if file end is beyond our file size, this truncation will underflow @len, making it -3K in this case. And later that @len is used to memzero the output buffer, resulting above crash. [FIX] Just error out if @offset is already beyond our file size. Now it will fail properly with correct error message: => load host 0 $kernel_addr_r 5m_origin 0 0x2000 BTRFS: Read range beyond file size, offset 8192 file size 5120 Failed to load '5m_origin' Signed-off-by: Qu Wenruo --- fs/btrfs/btrfs.c | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/fs/btrfs/btrfs.c b/fs/btrfs/btrfs.c index 309cd595d37d..74a992fa012d 100644 --- a/fs/btrfs/btrfs.c +++ b/fs/btrfs/btrfs.c @@ -252,6 +252,12 @@ int btrfs_read(const char *file, void *buf, loff_t offset, loff_t len, return ret; } + if (offset >= real_size) { + error("Read range beyond file size, offset %llu file size %llu", + offset, real_size); + return -EINVAL; + } + /* * If the length is 0 (meaning read the whole file) or the range is * beyond file size, truncate it to the end of the file. From patchwork Mon Aug 15 11:45:15 2022 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Qu Wenruo X-Patchwork-Id: 12943471 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by smtp.lore.kernel.org (Postfix) with ESMTP id 6DD91C00140 for ; Mon, 15 Aug 2022 11:45:58 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S231754AbiHOLp5 (ORCPT ); Mon, 15 Aug 2022 07:45:57 -0400 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:60300 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S231246AbiHOLp4 (ORCPT ); Mon, 15 Aug 2022 07:45:56 -0400 Received: from smtp-out1.suse.de (smtp-out1.suse.de [IPv6:2001:67c:2178:6::1c]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id 10490BC24 for ; Mon, 15 Aug 2022 04:45:54 -0700 (PDT) Received: from imap2.suse-dmz.suse.de (imap2.suse-dmz.suse.de [192.168.254.74]) (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits) key-exchange X25519 server-signature ECDSA (P-521) server-digest SHA512) (No client certificate requested) by smtp-out1.suse.de (Postfix) with ESMTPS id A99F2352B4; Mon, 15 Aug 2022 11:45:53 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=suse.com; s=susede1; t=1660563953; h=from:from:reply-to:date:date:message-id:message-id:to:to:cc:cc: mime-version:mime-version: content-transfer-encoding:content-transfer-encoding: in-reply-to:in-reply-to:references:references; bh=CtsbuhFwz7WFmf8gcu+PGCBqvgCXA/IgHM6zeZu4TYE=; b=VrJ2MaG7knqSJ/YPZSP9XFlumQo31Gs4bMFO1er5qkIZfQR42iPA1Qfe2sdscIHwkX29mE ilM3rDQMm4Q9/tW+gHDLvBEOsGkYucIpdrort6PKEDIxR+Mi6P2m2nJ/RVQ0hBKvhvhqCL DmofbFNMXvyyTUvWFcU2mmecR3g4WGs= Received: from imap2.suse-dmz.suse.de (imap2.suse-dmz.suse.de [192.168.254.74]) (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits) key-exchange X25519 server-signature ECDSA (P-521) server-digest SHA512) (No client certificate requested) by imap2.suse-dmz.suse.de (Postfix) with ESMTPS id 192F813A93; Mon, 15 Aug 2022 11:45:50 +0000 (UTC) Received: from dovecot-director2.suse.de ([192.168.254.65]) by imap2.suse-dmz.suse.de with ESMTPSA id KFk2NO4x+mLsGAAAMHmgww (envelope-from ); Mon, 15 Aug 2022 11:45:50 +0000 From: Qu Wenruo To: u-boot@lists.denx.de Cc: marek.behun@nic.cz, linux-btrfs@vger.kernel.org, jnhuang95@gmail.com, linux-erofs@lists.ozlabs.org, trini@konsulko.com, joaomarcos.costa@bootlin.com, thomas.petazzoni@bootlin.com, miquel.raynal@bootlin.com Subject: [PATCH v3 4/8] fs: btrfs: move the unaligned read code to _fs_read() for btrfs Date: Mon, 15 Aug 2022 19:45:15 +0800 Message-Id: <8b83e5e0f1d2bd7c02714de4cd26dc24327604c6.1660563403.git.wqu@suse.com> X-Mailer: git-send-email 2.37.1 In-Reply-To: References: MIME-Version: 1.0 Precedence: bulk List-ID: X-Mailing-List: linux-btrfs@vger.kernel.org Unlike FUSE or kernel, U-boot filesystem code makes the underly fs code to handle the unaligned read (aka, read range is not aligned to fs block size). This makes underlying fs code harder to implement, as they have to handle unaligned read all by themselves. This patch will change the behavior, starting from btrfs, by moving the unaligned read code into _fs_read(). The idea is pretty simple, if we have an unaligned read request, we handle it in the following steps: 1. Grab the blocksize of the fs 2. Read the leading unaligned range We will read the block that @offset is in, and copy the requested part into buf. The the block we read covers the whole range, we just call it a day. 3. Read the remaining part The tailing part may be unaligned, but all fses handles the tailing part much easier than the leading unaligned part. As they just need to do a min(extent_size, start + len - cur) to calculate the real read size. In fact, for most file reading, the file size is not aligned and we need to handle the tailing part anyway. There is a btrfs specific cleanup involved: - In btrfs_file_read(), merge the tailing unaligned read into the main loop. Just reuse the existing read length calculation is enough. - Remove read_and_truncate_page() call Since there is no explicit leading/tailing unaligned read anymore. This has been tested with a proper randomly populated btrfs file, then tried in sandbox mode with different aligned and unaligned range and compare the output with md5sum. Cc: Marek Behun Cc: linux-btrfs@vger.kernel.org Signed-off-by: Qu Wenruo --- fs/btrfs/btrfs.c | 10 ++++ fs/btrfs/inode.c | 89 +++----------------------------- fs/fs.c | 130 ++++++++++++++++++++++++++++++++++++++++++++--- include/btrfs.h | 1 + 4 files changed, 141 insertions(+), 89 deletions(-) diff --git a/fs/btrfs/btrfs.c b/fs/btrfs/btrfs.c index 74a992fa012d..ac0e972d0249 100644 --- a/fs/btrfs/btrfs.c +++ b/fs/btrfs/btrfs.c @@ -234,6 +234,10 @@ int btrfs_read(const char *file, void *buf, loff_t offset, loff_t len, int ret; ASSERT(fs_info); + + /* Higher layer has ensures it never pass unaligned offset in. */ + ASSERT(IS_ALIGNED(offset, fs_info->sectorsize)); + ret = btrfs_lookup_path(fs_info->fs_root, BTRFS_FIRST_FREE_OBJECTID, file, &root, &ino, &type, 40); if (ret < 0) { @@ -275,6 +279,12 @@ int btrfs_read(const char *file, void *buf, loff_t offset, loff_t len, return 0; } +int btrfs_get_blocksize(const char *filename) +{ + ASSERT(current_fs_info); + return current_fs_info->sectorsize; +} + void btrfs_close(void) { if (current_fs_info) { diff --git a/fs/btrfs/inode.c b/fs/btrfs/inode.c index 40025662f250..f12be46f6262 100644 --- a/fs/btrfs/inode.c +++ b/fs/btrfs/inode.c @@ -617,44 +617,6 @@ check_next: return 1; } -static int read_and_truncate_page(struct btrfs_path *path, - struct btrfs_file_extent_item *fi, - int start, int len, char *dest) -{ - struct extent_buffer *leaf = path->nodes[0]; - struct btrfs_fs_info *fs_info = leaf->fs_info; - u64 aligned_start = round_down(start, fs_info->sectorsize); - u8 extent_type; - char *buf; - int page_off = start - aligned_start; - int page_len = fs_info->sectorsize - page_off; - int ret; - - ASSERT(start + len <= aligned_start + fs_info->sectorsize); - buf = malloc_cache_aligned(fs_info->sectorsize); - if (!buf) - return -ENOMEM; - - extent_type = btrfs_file_extent_type(leaf, fi); - if (extent_type == BTRFS_FILE_EXTENT_INLINE) { - ret = btrfs_read_extent_inline(path, fi, buf); - memcpy(dest, buf + page_off, min(page_len, ret)); - free(buf); - return len; - } - - ret = btrfs_read_extent_reg(path, fi, - round_down(start, fs_info->sectorsize), - fs_info->sectorsize, buf); - if (ret < 0) { - free(buf); - return ret; - } - memcpy(dest, buf + page_off, page_len); - free(buf); - return len; -} - int btrfs_file_read(struct btrfs_root *root, u64 ino, u64 file_offset, u64 len, char *dest) { @@ -663,7 +625,6 @@ int btrfs_file_read(struct btrfs_root *root, u64 ino, u64 file_offset, u64 len, struct btrfs_path path; struct btrfs_key key; u64 aligned_start = round_down(file_offset, fs_info->sectorsize); - u64 aligned_end = round_down(file_offset + len, fs_info->sectorsize); u64 next_offset; u64 cur = aligned_start; int ret = 0; @@ -673,34 +634,14 @@ int btrfs_file_read(struct btrfs_root *root, u64 ino, u64 file_offset, u64 len, /* Set the whole dest all zero, so we won't need to bother holes */ memset(dest, 0, len); - /* Read out the leading unaligned part */ - if (aligned_start != file_offset) { - ret = lookup_data_extent(root, &path, ino, aligned_start, - &next_offset); - if (ret < 0) - goto out; - if (ret == 0) { - /* Read the unaligned part out*/ - fi = btrfs_item_ptr(path.nodes[0], path.slots[0], - struct btrfs_file_extent_item); - ret = read_and_truncate_page(&path, fi, file_offset, - round_up(file_offset, fs_info->sectorsize) - - file_offset, dest); - if (ret < 0) - goto out; - cur += fs_info->sectorsize; - } else { - /* The whole file is a hole */ - if (!next_offset) { - memset(dest, 0, len); - return len; - } - cur = next_offset; - } - } + /* + * Ensured by higher layer, which should have already handled the + * first unaligned sector. + */ + ASSERT(aligned_start == file_offset); /* Read the aligned part */ - while (cur < aligned_end) { + while (cur < file_offset + len) { u64 extent_num_bytes; u8 type; @@ -743,27 +684,13 @@ int btrfs_file_read(struct btrfs_root *root, u64 ino, u64 file_offset, u64 len, extent_num_bytes = btrfs_file_extent_num_bytes(path.nodes[0], fi); ret = btrfs_read_extent_reg(&path, fi, cur, - min(extent_num_bytes, aligned_end - cur), + min(extent_num_bytes, file_offset + len - cur), dest + cur - file_offset); if (ret < 0) goto out; - cur += min(extent_num_bytes, aligned_end - cur); + cur += min(extent_num_bytes, file_offset + len - cur); } - /* Read the tailing unaligned part*/ - if (file_offset + len != aligned_end) { - btrfs_release_path(&path); - ret = lookup_data_extent(root, &path, ino, aligned_end, - &next_offset); - /* <0 is error, >0 means no extent */ - if (ret) - goto out; - fi = btrfs_item_ptr(path.nodes[0], path.slots[0], - struct btrfs_file_extent_item); - ret = read_and_truncate_page(&path, fi, aligned_end, - file_offset + len - aligned_end, - dest + aligned_end - file_offset); - } out: btrfs_release_path(&path); if (ret < 0) diff --git a/fs/fs.c b/fs/fs.c index 8324b4a22f20..6d43d616de4b 100644 --- a/fs/fs.c +++ b/fs/fs.c @@ -29,6 +29,7 @@ #include #include #include +#include DECLARE_GLOBAL_DATA_PTR; @@ -140,6 +141,11 @@ static inline int fs_mkdir_unsupported(const char *dirname) return -1; } +static inline int fs_get_blocksize_unsupported(const char *filename) +{ + return -1; +} + struct fstype_info { int fstype; char *name; @@ -159,6 +165,14 @@ struct fstype_info { int (*size)(const char *filename, loff_t *size); int (*read)(const char *filename, void *buf, loff_t offset, loff_t len, loff_t *actread); + /* + * Report the minimal data blocksize the fs supprts. + * + * This is used to handle unaligned read offset. + * If not supported, read() will handle the unaligned offset all by + * itself. + */ + int (*get_blocksize)(const char *filename); int (*write)(const char *filename, void *buf, loff_t offset, loff_t len, loff_t *actwrite); void (*close)(void); @@ -194,6 +208,7 @@ static struct fstype_info fstypes[] = { .exists = fat_exists, .size = fat_size, .read = fat_read_file, + .get_blocksize = fs_get_blocksize_unsupported, #if CONFIG_IS_ENABLED(FAT_WRITE) .write = file_fat_write, .unlink = fat_unlink, @@ -222,6 +237,7 @@ static struct fstype_info fstypes[] = { .exists = ext4fs_exists, .size = ext4fs_size, .read = ext4_read_file, + .get_blocksize = fs_get_blocksize_unsupported, #ifdef CONFIG_CMD_EXT4_WRITE .write = ext4_write_file, .ln = ext4fs_create_link, @@ -246,6 +262,11 @@ static struct fstype_info fstypes[] = { .exists = sandbox_fs_exists, .size = sandbox_fs_size, .read = fs_read_sandbox, + /* + * Sandbox doesn't need to bother blocksize, as its + * os_read() can handle unaligned range without any problem. + */ + .get_blocksize = fs_get_blocksize_unsupported, .write = fs_write_sandbox, .uuid = fs_uuid_unsupported, .opendir = fs_opendir_unsupported, @@ -265,6 +286,12 @@ static struct fstype_info fstypes[] = { .exists = fs_exists_unsupported, .size = smh_fs_size, .read = smh_fs_read, + /* + * Semihost doesn't need to bother blocksize, as it is using + * read() system calls, and can handle unaligned range without + * any problem. + */ + .get_blocksize = fs_get_blocksize_unsupported, .write = smh_fs_write, .uuid = fs_uuid_unsupported, .opendir = fs_opendir_unsupported, @@ -285,6 +312,7 @@ static struct fstype_info fstypes[] = { .exists = ubifs_exists, .size = ubifs_size, .read = ubifs_read, + .get_blocksize = fs_get_blocksize_unsupported, .write = fs_write_unsupported, .uuid = fs_uuid_unsupported, .opendir = fs_opendir_unsupported, @@ -306,6 +334,7 @@ static struct fstype_info fstypes[] = { .exists = btrfs_exists, .size = btrfs_size, .read = btrfs_read, + .get_blocksize = btrfs_get_blocksize, .write = fs_write_unsupported, .uuid = btrfs_uuid, .opendir = fs_opendir_unsupported, @@ -325,6 +354,7 @@ static struct fstype_info fstypes[] = { .readdir = sqfs_readdir, .ls = fs_ls_generic, .read = sqfs_read, + .get_blocksize = fs_get_blocksize_unsupported, .size = sqfs_size, .close = sqfs_close, .closedir = sqfs_closedir, @@ -346,6 +376,7 @@ static struct fstype_info fstypes[] = { .readdir = erofs_readdir, .ls = fs_ls_generic, .read = erofs_read, + .get_blocksize = fs_get_blocksize_unsupported, .size = erofs_size, .close = erofs_close, .closedir = erofs_closedir, @@ -367,6 +398,7 @@ static struct fstype_info fstypes[] = { .exists = fs_exists_unsupported, .size = fs_size_unsupported, .read = fs_read_unsupported, + .get_blocksize = fs_get_blocksize_unsupported, .write = fs_write_unsupported, .uuid = fs_uuid_unsupported, .opendir = fs_opendir_unsupported, @@ -580,7 +612,11 @@ static int _fs_read(const char *filename, ulong addr, loff_t offset, loff_t len, { struct fstype_info *info = fs_get_info(fs_type); void *buf; + int blocksize; int ret; + loff_t cur = offset; + loff_t bytes_read = 0; + loff_t total_read = 0; #ifdef CONFIG_LMB if (do_lmb_check) { @@ -590,19 +626,97 @@ static int _fs_read(const char *filename, ulong addr, loff_t offset, loff_t len, } #endif + blocksize = info->get_blocksize(filename); /* - * We don't actually know how many bytes are being read, since len==0 - * means read the whole file. + * The fs doesn't report its blocksize, let its read() to handle + * the unaligned read. + */ + if (blocksize < 0) { + buf = map_sysmem(addr, len); + ret = info->read(filename, buf, offset, len, &total_read); + + /* If we requested a specific number of bytes, check we got it */ + if (ret == 0 && len && total_read != len) + log_debug("** %s shorter than offset + len **\n", filename); + goto out; + } + + if (unlikely(blocksize == 0)) { + log_err("invalid blocksize 0 found\n"); + return -EINVAL; + } + + /* + * @len can be 0, meaning read the whole file. + * And we can not rely on info->size(), as some fses doesn't resolve + * softlinks to their final destinations. */ buf = map_sysmem(addr, len); - ret = info->read(filename, buf, offset, len, actread); - unmap_sysmem(buf); - /* If we requested a specific number of bytes, check we got it */ - if (ret == 0 && len && *actread != len) - log_debug("** %s shorter than offset + len **\n", filename); - fs_close(); + /* Unaligned read offset, handle the unaligned read here. */ + if (!IS_ALIGNED(offset, blocksize)) { + void *block_buf; + const int offset_in_block = offset & (blocksize - 1); + int copy_len; + + block_buf = malloc_cache_aligned(blocksize); + if (!block_buf) { + log_err("** Unable to alloc memory for one block **\n"); + return -ENOMEM; + } + memset(block_buf, 0, blocksize); + + cur = round_down(offset, blocksize); + ret = info->read(filename, block_buf, cur, blocksize, + &bytes_read); + if (ret < 0) { + log_err("** Failed to read %s at offset %llu, %d **\n", + filename, cur, ret); + free(block_buf); + goto out; + } + if (bytes_read <= offset_in_block) { + log_err("** Offset %llu is beyond file size of %s **\n", + offset, filename); + free(block_buf); + ret = -EIO; + goto out; + } + + copy_len = min_t(int, blocksize, bytes_read) - offset_in_block; + memcpy(buf, block_buf + offset_in_block, copy_len); + free(block_buf); + total_read += copy_len; + + /* + * A short read on the block, or we have already covered the + * whole read range, just call it a day. + */ + if (bytes_read < blocksize || + (len && offset + len <= cur + blocksize)) + goto out; + + cur += blocksize; + if (len) + len -= copy_len; + } + + ret = info->read(filename, buf + total_read, cur, len, &bytes_read); + if (ret < 0) { + log_err("** failed to read %s off %llu len %llu, %d **\n", + filename, cur, len, ret); + goto out; + } + if (len && bytes_read < len) + log_debug("** %s short read, off %llu len %llu actual read %llu **\n", + filename, cur, len, bytes_read); + total_read += bytes_read; +out: + unmap_sysmem(buf); + fs_close(); + if (!ret) + *actread = total_read; return ret; } diff --git a/include/btrfs.h b/include/btrfs.h index 2d73add18e09..a2d709273b53 100644 --- a/include/btrfs.h +++ b/include/btrfs.h @@ -17,6 +17,7 @@ int btrfs_ls(const char *); int btrfs_exists(const char *); int btrfs_size(const char *, loff_t *); int btrfs_read(const char *, void *, loff_t, loff_t, loff_t *); +int btrfs_get_blocksize(const char *); void btrfs_close(void); int btrfs_uuid(char *); void btrfs_list_subvols(void); From patchwork Mon Aug 15 11:45:16 2022 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Qu Wenruo X-Patchwork-Id: 12943472 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by smtp.lore.kernel.org (Postfix) with ESMTP id 2C052C00140 for ; Mon, 15 Aug 2022 11:46:02 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S231246AbiHOLqB (ORCPT ); Mon, 15 Aug 2022 07:46:01 -0400 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:60362 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S231808AbiHOLqA (ORCPT ); Mon, 15 Aug 2022 07:46:00 -0400 Received: from smtp-out1.suse.de (smtp-out1.suse.de [IPv6:2001:67c:2178:6::1c]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id E7147BC9F for ; Mon, 15 Aug 2022 04:45:58 -0700 (PDT) Received: from imap2.suse-dmz.suse.de (imap2.suse-dmz.suse.de [192.168.254.74]) (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits) key-exchange X25519 server-signature ECDSA (P-521) server-digest SHA512) (No client certificate requested) by smtp-out1.suse.de (Postfix) with ESMTPS id A271B352B5; Mon, 15 Aug 2022 11:45:57 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=suse.com; s=susede1; t=1660563957; h=from:from:reply-to:date:date:message-id:message-id:to:to:cc:cc: mime-version:mime-version: content-transfer-encoding:content-transfer-encoding: in-reply-to:in-reply-to:references:references; bh=RT0BTzg0LT7QlYZlw1Y7agdMFP6If8NjMFPJKBgrbL0=; b=pGLOtxArcP6RkIZ/kjlil87/9fkHYCNmIZzVKgDt0LJqpMQEuGll+0PUPgMuR0wPPZBQeu 1vDKdvR4/thlvv79Pg75Q3trZ7zzvArf4AfCBqECQjfNxZxIMhMpBCOn4CVWGeP0SB/3Ft 55Rz2rylJd1XYep8/ai9Ma3abHw0Vrg= Received: from imap2.suse-dmz.suse.de (imap2.suse-dmz.suse.de [192.168.254.74]) (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits) key-exchange X25519 server-signature ECDSA (P-521) server-digest SHA512) (No client certificate requested) by imap2.suse-dmz.suse.de (Postfix) with ESMTPS id 277D713A93; Mon, 15 Aug 2022 11:45:53 +0000 (UTC) Received: from dovecot-director2.suse.de ([192.168.254.65]) by imap2.suse-dmz.suse.de with ESMTPSA id 8OSnN/Ex+mLsGAAAMHmgww (envelope-from ); Mon, 15 Aug 2022 11:45:53 +0000 From: Qu Wenruo To: u-boot@lists.denx.de Cc: marek.behun@nic.cz, linux-btrfs@vger.kernel.org, jnhuang95@gmail.com, linux-erofs@lists.ozlabs.org, trini@konsulko.com, joaomarcos.costa@bootlin.com, thomas.petazzoni@bootlin.com, miquel.raynal@bootlin.com Subject: [PATCH v3 5/8] fs: ext4: rely on _fs_read() to handle leading unaligned block read Date: Mon, 15 Aug 2022 19:45:16 +0800 Message-Id: <08bd4c42bd1f7a96b17d193cdf7c6d4e68aa265c.1660563403.git.wqu@suse.com> X-Mailer: git-send-email 2.37.1 In-Reply-To: References: MIME-Version: 1.0 Precedence: bulk List-ID: X-Mailing-List: linux-btrfs@vger.kernel.org Just add ext4_get_blocksize() and a new assert() in ext4fs_read_file(). Signed-off-by: Qu Wenruo --- Several cleanup candicate: 1. ext_fs->blksz is never populated, thus it's always 0 We can not easily grab blocksize just like btrfs in this case. Thus we have to go the same calculation in ext4fs_read_file(). 2. can not easily cleanup @skipfirst in ext4fs_read_file() It seems to screw up with soft link read. --- fs/ext4/ext4fs.c | 22 ++++++++++++++++++++++ fs/fs.c | 2 +- include/ext4fs.h | 1 + 3 files changed, 24 insertions(+), 1 deletion(-) diff --git a/fs/ext4/ext4fs.c b/fs/ext4/ext4fs.c index 4c89152ce4ad..b0568e77a895 100644 --- a/fs/ext4/ext4fs.c +++ b/fs/ext4/ext4fs.c @@ -69,6 +69,8 @@ int ext4fs_read_file(struct ext2fs_node *node, loff_t pos, short status; struct ext_block_cache cache; + assert(IS_ALIGNED(pos, blocksize)); + ext_cache_init(&cache); /* Adjust len so it we can't read past the end of the file. */ @@ -259,6 +261,26 @@ int ext4_read_file(const char *filename, void *buf, loff_t offset, loff_t len, return ext4fs_read(buf, offset, len, len_read); } +int ext4_get_blocksize(const char *filename) +{ + struct ext_filesystem *fs; + int log2blksz; + int log2_fs_blocksize; + loff_t file_len; + int ret; + + ret = ext4fs_open(filename, &file_len); + if (ret < 0) { + printf("** File not found %s **\n", filename); + return -1; + } + fs = get_fs(); + log2blksz = fs->dev_desc->log2blksz; + log2_fs_blocksize = LOG2_BLOCK_SIZE(ext4fs_file->data) - log2blksz; + + return (1 << (log2_fs_blocksize + log2blksz)); +} + int ext4fs_uuid(char *uuid_str) { if (ext4fs_root == NULL) diff --git a/fs/fs.c b/fs/fs.c index 6d43d616de4b..b26cc8e2e840 100644 --- a/fs/fs.c +++ b/fs/fs.c @@ -237,7 +237,7 @@ static struct fstype_info fstypes[] = { .exists = ext4fs_exists, .size = ext4fs_size, .read = ext4_read_file, - .get_blocksize = fs_get_blocksize_unsupported, + .get_blocksize = ext4_get_blocksize, #ifdef CONFIG_CMD_EXT4_WRITE .write = ext4_write_file, .ln = ext4fs_create_link, diff --git a/include/ext4fs.h b/include/ext4fs.h index cb5d9cc0a5c0..0f4cf32dcc2a 100644 --- a/include/ext4fs.h +++ b/include/ext4fs.h @@ -161,6 +161,7 @@ int ext4fs_probe(struct blk_desc *fs_dev_desc, struct disk_partition *fs_partition); int ext4_read_file(const char *filename, void *buf, loff_t offset, loff_t len, loff_t *actread); +int ext4_get_blocksize(const char *filename); int ext4_read_superblock(char *buffer); int ext4fs_uuid(char *uuid_str); void ext_cache_init(struct ext_block_cache *cache); From patchwork Mon Aug 15 11:45:17 2022 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Qu Wenruo X-Patchwork-Id: 12943473 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by smtp.lore.kernel.org (Postfix) with ESMTP id 14C73C25B0E for ; Mon, 15 Aug 2022 11:46:06 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S232081AbiHOLqE (ORCPT ); Mon, 15 Aug 2022 07:46:04 -0400 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:60408 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S231808AbiHOLqD (ORCPT ); Mon, 15 Aug 2022 07:46:03 -0400 Received: from smtp-out1.suse.de (smtp-out1.suse.de [195.135.220.28]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id 2E05ABC9F for ; Mon, 15 Aug 2022 04:46:03 -0700 (PDT) Received: from imap2.suse-dmz.suse.de (imap2.suse-dmz.suse.de [192.168.254.74]) (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits) key-exchange X25519 server-signature ECDSA (P-521) server-digest SHA512) (No client certificate requested) by smtp-out1.suse.de (Postfix) with ESMTPS id C947A352B4; Mon, 15 Aug 2022 11:46:01 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=suse.com; s=susede1; t=1660563961; h=from:from:reply-to:date:date:message-id:message-id:to:to:cc:cc: mime-version:mime-version: content-transfer-encoding:content-transfer-encoding: in-reply-to:in-reply-to:references:references; bh=MCKxMgXFwdkGpSDQPhoMw3j6fGGECVOIJmuZZk37QjQ=; b=f3m+j49SiLQhfXNly4L66OiUh0+/I+le6WnS/uOwwVgWdNp4zAetQ/XuJnsaI261HyG+HD /FxhLlv28F8qtaorfyvbcqkD8/wZ+RGqAug2A1Cu9664FBc0UVJR2XURgI3JLssLo7vzng 0eBuXqF/LpVpURsCpDMYFTUgjDwNo+Q= Received: from imap2.suse-dmz.suse.de (imap2.suse-dmz.suse.de [192.168.254.74]) (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits) key-exchange X25519 server-signature ECDSA (P-521) server-digest SHA512) (No client certificate requested) by imap2.suse-dmz.suse.de (Postfix) with ESMTPS id 90B4413A93; Mon, 15 Aug 2022 11:45:57 +0000 (UTC) Received: from dovecot-director2.suse.de ([192.168.254.65]) by imap2.suse-dmz.suse.de with ESMTPSA id ILHqNPUx+mLsGAAAMHmgww (envelope-from ); Mon, 15 Aug 2022 11:45:57 +0000 From: Qu Wenruo To: u-boot@lists.denx.de Cc: marek.behun@nic.cz, linux-btrfs@vger.kernel.org, jnhuang95@gmail.com, linux-erofs@lists.ozlabs.org, trini@konsulko.com, joaomarcos.costa@bootlin.com, thomas.petazzoni@bootlin.com, miquel.raynal@bootlin.com Subject: [PATCH v3 6/8] fs: fat: rely on higher layer to get block aligned read range Date: Mon, 15 Aug 2022 19:45:17 +0800 Message-Id: X-Mailer: git-send-email 2.37.1 In-Reply-To: References: MIME-Version: 1.0 Precedence: bulk List-ID: X-Mailing-List: linux-btrfs@vger.kernel.org Just implement fat_get_blocksize() for fat, so that fat_read_file() always get a block aligned read range. Unfortunately I'm not experienced enough to cleanup the fat code, thus further cleanup is appreciated. Cc: Tom Rini Signed-off-by: Qu Wenruo --- fs/fat/fat.c | 13 +++++++++++++ fs/fs.c | 2 +- include/fat.h | 1 + 3 files changed, 15 insertions(+), 1 deletion(-) diff --git a/fs/fat/fat.c b/fs/fat/fat.c index dcceccbcee0a..e13035e8e6d1 100644 --- a/fs/fat/fat.c +++ b/fs/fat/fat.c @@ -1299,6 +1299,19 @@ int fat_read_file(const char *filename, void *buf, loff_t offset, loff_t len, return ret; } +int fat_get_blocksize(const char *filename) +{ + fsdata fsdata = {0}; + int ret; + + ret = get_fs_info(&fsdata); + if (ret) + return ret; + + free(fsdata.fatbuf); + return fsdata.sect_size; +} + typedef struct { struct fs_dir_stream parent; struct fs_dirent dirent; diff --git a/fs/fs.c b/fs/fs.c index b26cc8e2e840..ea4325cd0b00 100644 --- a/fs/fs.c +++ b/fs/fs.c @@ -208,7 +208,7 @@ static struct fstype_info fstypes[] = { .exists = fat_exists, .size = fat_size, .read = fat_read_file, - .get_blocksize = fs_get_blocksize_unsupported, + .get_blocksize = fat_get_blocksize, #if CONFIG_IS_ENABLED(FAT_WRITE) .write = file_fat_write, .unlink = fat_unlink, diff --git a/include/fat.h b/include/fat.h index a9756fb4cd1b..c03a2bebecef 100644 --- a/include/fat.h +++ b/include/fat.h @@ -201,6 +201,7 @@ int file_fat_detectfs(void); int fat_exists(const char *filename); int fat_size(const char *filename, loff_t *size); int file_fat_read(const char *filename, void *buffer, int maxsize); +int fat_get_blocksize(const char *filename); int fat_set_blk_dev(struct blk_desc *rbdd, struct disk_partition *info); int fat_register_device(struct blk_desc *dev_desc, int part_no); From patchwork Mon Aug 15 11:45:18 2022 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Qu Wenruo X-Patchwork-Id: 12943474 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by smtp.lore.kernel.org (Postfix) with ESMTP id 23416C25B0E for ; Mon, 15 Aug 2022 11:46:10 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S232016AbiHOLqI (ORCPT ); Mon, 15 Aug 2022 07:46:08 -0400 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:60448 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S229752AbiHOLqH (ORCPT ); Mon, 15 Aug 2022 07:46:07 -0400 Received: from smtp-out1.suse.de (smtp-out1.suse.de [195.135.220.28]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id C92B9BC28 for ; Mon, 15 Aug 2022 04:46:06 -0700 (PDT) Received: from imap2.suse-dmz.suse.de (imap2.suse-dmz.suse.de [192.168.254.74]) (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits) key-exchange X25519 server-signature ECDSA (P-521) server-digest SHA512) (No client certificate requested) by smtp-out1.suse.de (Postfix) with ESMTPS id 85F9B352B4; Mon, 15 Aug 2022 11:46:05 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=suse.com; s=susede1; t=1660563965; h=from:from:reply-to:date:date:message-id:message-id:to:to:cc:cc: mime-version:mime-version: content-transfer-encoding:content-transfer-encoding: in-reply-to:in-reply-to:references:references; bh=PGSn9v/Vb0Fgf7jHEoYdiN2Gzn+Oveqc6/QJerTYZBg=; b=W08dxO9UBy8bkGKUTXlxaJkz+qQLIOoQLWEJJfZlegEAvtI9Tc4BZN6yW2ubfWgpAxfzMm nrTmhGLgfRXVHDHxMxRWObd8sw8DQkVFNo7nYIwQIyXeJ/BC28UnvRTJ1teRp0i6x1C4a2 Pqj1ng/R173KPCGnNQzREqnoK/S31MY= Received: from imap2.suse-dmz.suse.de (imap2.suse-dmz.suse.de [192.168.254.74]) (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits) key-exchange X25519 server-signature ECDSA (P-521) server-digest SHA512) (No client certificate requested) by imap2.suse-dmz.suse.de (Postfix) with ESMTPS id 4B5AB13B10; Mon, 15 Aug 2022 11:46:02 +0000 (UTC) Received: from dovecot-director2.suse.de ([192.168.254.65]) by imap2.suse-dmz.suse.de with ESMTPSA id mPNhA/ox+mLsGAAAMHmgww (envelope-from ); Mon, 15 Aug 2022 11:46:02 +0000 From: Qu Wenruo To: u-boot@lists.denx.de Cc: marek.behun@nic.cz, linux-btrfs@vger.kernel.org, jnhuang95@gmail.com, linux-erofs@lists.ozlabs.org, trini@konsulko.com, joaomarcos.costa@bootlin.com, thomas.petazzoni@bootlin.com, miquel.raynal@bootlin.com Subject: [PATCH v3 7/8] fs: ubifs: rely on higher layer to do unaligned read Date: Mon, 15 Aug 2022 19:45:18 +0800 Message-Id: X-Mailer: git-send-email 2.37.1 In-Reply-To: References: MIME-Version: 1.0 Precedence: bulk List-ID: X-Mailing-List: linux-btrfs@vger.kernel.org Currently ubifs doesn't support unaligned read offset, thanks to the recent _fs_read() work to handle unaligned read, we only need to implement ubifs_get_blocksize() to take advantage of it. Now ubifs can do unaligned read without any problem. Signed-off-by: Qu Wenruo --- Unfortunately I can not test ubifs, as enabling UBI would cause compile failure due to missing of header. --- fs/fs.c | 2 +- fs/ubifs/ubifs.c | 13 ++++++++----- include/ubifs_uboot.h | 1 + 3 files changed, 10 insertions(+), 6 deletions(-) diff --git a/fs/fs.c b/fs/fs.c index ea4325cd0b00..43c7128bcfc5 100644 --- a/fs/fs.c +++ b/fs/fs.c @@ -312,7 +312,7 @@ static struct fstype_info fstypes[] = { .exists = ubifs_exists, .size = ubifs_size, .read = ubifs_read, - .get_blocksize = fs_get_blocksize_unsupported, + .get_blocksize = ubifs_get_blocksize, .write = fs_write_unsupported, .uuid = fs_uuid_unsupported, .opendir = fs_opendir_unsupported, diff --git a/fs/ubifs/ubifs.c b/fs/ubifs/ubifs.c index d3026e310168..a8ab556dd376 100644 --- a/fs/ubifs/ubifs.c +++ b/fs/ubifs/ubifs.c @@ -846,11 +846,9 @@ int ubifs_read(const char *filename, void *buf, loff_t offset, *actread = 0; - if (offset & (PAGE_SIZE - 1)) { - printf("ubifs: Error offset must be a multiple of %d\n", - PAGE_SIZE); - return -1; - } + /* Higher layer should ensure it always pass page aligned range. */ + assert(IS_ALIGNED(offset, PAGE_SIZE)); + assert(IS_ALIGNED(size, PAGE_SIZE)); c->ubi = ubi_open_volume(c->vi.ubi_num, c->vi.vol_id, UBI_READONLY); /* ubifs_findfile will resolve symlinks, so we know that we get @@ -920,6 +918,11 @@ out: return err; } +int ubifs_get_blocksize(const char *filename) +{ + return PAGE_SIZE; +} + void ubifs_close(void) { } diff --git a/include/ubifs_uboot.h b/include/ubifs_uboot.h index b025779d59ff..bcd21715314a 100644 --- a/include/ubifs_uboot.h +++ b/include/ubifs_uboot.h @@ -29,6 +29,7 @@ int ubifs_exists(const char *filename); int ubifs_size(const char *filename, loff_t *size); int ubifs_read(const char *filename, void *buf, loff_t offset, loff_t size, loff_t *actread); +int ubifs_get_blocksize(const char *filename); void ubifs_close(void); #endif /* __UBIFS_UBOOT_H__ */ From patchwork Mon Aug 15 11:45:19 2022 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Qu Wenruo X-Patchwork-Id: 12943475 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by smtp.lore.kernel.org (Postfix) with ESMTP id C9E57C25B06 for ; Mon, 15 Aug 2022 11:46:12 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S233573AbiHOLqL (ORCPT ); Mon, 15 Aug 2022 07:46:11 -0400 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:60484 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S232094AbiHOLqL (ORCPT ); Mon, 15 Aug 2022 07:46:11 -0400 Received: from smtp-out2.suse.de (smtp-out2.suse.de [195.135.220.29]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id 1957EBC28 for ; Mon, 15 Aug 2022 04:46:10 -0700 (PDT) Received: from imap2.suse-dmz.suse.de (imap2.suse-dmz.suse.de [192.168.254.74]) (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits) key-exchange X25519 server-signature ECDSA (P-521) server-digest SHA512) (No client certificate requested) by smtp-out2.suse.de (Postfix) with ESMTPS id C6C881FE69; Mon, 15 Aug 2022 11:46:08 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=suse.com; s=susede1; t=1660563968; h=from:from:reply-to:date:date:message-id:message-id:to:to:cc:cc: mime-version:mime-version: content-transfer-encoding:content-transfer-encoding: in-reply-to:in-reply-to:references:references; bh=nmei75UQLrXMG2L7/xFI+FjzoA3oEelPp+lH7jJuaIs=; b=RXdEnIvMc1W7juWH+dQBLJza+h04qayfi59RzDYwBuc1a5htaxzLCM16rW9wTTDGBTy5Xw sBN6ZC2yhv78D0XJ7+Ms0CExP0xEmO+YpW5t26NVAF/PL433WXoJm0wYDEkVNXra6/DNZ8 MlCDCCw9L4Fwjj2Vhj0kb6+frqvR4so= Received: from imap2.suse-dmz.suse.de (imap2.suse-dmz.suse.de [192.168.254.74]) (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits) key-exchange X25519 server-signature ECDSA (P-521) server-digest SHA512) (No client certificate requested) by imap2.suse-dmz.suse.de (Postfix) with ESMTPS id 089D313A93; Mon, 15 Aug 2022 11:46:05 +0000 (UTC) Received: from dovecot-director2.suse.de ([192.168.254.65]) by imap2.suse-dmz.suse.de with ESMTPSA id sCGlLv0x+mLsGAAAMHmgww (envelope-from ); Mon, 15 Aug 2022 11:46:05 +0000 From: Qu Wenruo To: u-boot@lists.denx.de Cc: marek.behun@nic.cz, linux-btrfs@vger.kernel.org, jnhuang95@gmail.com, linux-erofs@lists.ozlabs.org, trini@konsulko.com, joaomarcos.costa@bootlin.com, thomas.petazzoni@bootlin.com, miquel.raynal@bootlin.com Subject: [PATCH v3 8/8] fs: erofs: add unaligned read range handling Date: Mon, 15 Aug 2022 19:45:19 +0800 Message-Id: X-Mailer: git-send-email 2.37.1 In-Reply-To: References: MIME-Version: 1.0 Precedence: bulk List-ID: X-Mailing-List: linux-btrfs@vger.kernel.org I'm not an expert on erofs, but my quick glance didn't expose any special handling on unaligned range, thus I think the U-boot erofs driver doesn't really support unaligned read range. This patch will add erofs_get_blocksize() so erofs can benefit from the generic unaligned read support. Cc: Huang Jianan Cc: linux-erofs@lists.ozlabs.org Signed-off-by: Qu Wenruo --- fs/erofs/internal.h | 1 + fs/erofs/super.c | 6 ++++++ fs/fs.c | 2 +- include/erofs.h | 1 + 4 files changed, 9 insertions(+), 1 deletion(-) diff --git a/fs/erofs/internal.h b/fs/erofs/internal.h index 4af7c91560cc..d368a6481bf1 100644 --- a/fs/erofs/internal.h +++ b/fs/erofs/internal.h @@ -83,6 +83,7 @@ struct erofs_sb_info { u16 available_compr_algs; u16 lz4_max_distance; u32 checksum; + u32 blocksize; u16 extra_devices; union { u16 devt_slotoff; /* used for mkfs */ diff --git a/fs/erofs/super.c b/fs/erofs/super.c index 8277d9b53fb3..82625da59001 100644 --- a/fs/erofs/super.c +++ b/fs/erofs/super.c @@ -99,7 +99,13 @@ int erofs_read_superblock(void) sbi.build_time = le64_to_cpu(dsb->build_time); sbi.build_time_nsec = le32_to_cpu(dsb->build_time_nsec); + sbi.blocksize = 1 << blkszbits; memcpy(&sbi.uuid, dsb->uuid, sizeof(dsb->uuid)); return erofs_init_devices(&sbi, dsb); } + +int erofs_get_blocksize(const char *filename) +{ + return sbi.blocksize; +} diff --git a/fs/fs.c b/fs/fs.c index 43c7128bcfc5..2ac43c05fcd8 100644 --- a/fs/fs.c +++ b/fs/fs.c @@ -376,7 +376,7 @@ static struct fstype_info fstypes[] = { .readdir = erofs_readdir, .ls = fs_ls_generic, .read = erofs_read, - .get_blocksize = fs_get_blocksize_unsupported, + .get_blocksize = erofs_get_blocksize, .size = erofs_size, .close = erofs_close, .closedir = erofs_closedir, diff --git a/include/erofs.h b/include/erofs.h index 1fbe82bf72cb..18bd6807c538 100644 --- a/include/erofs.h +++ b/include/erofs.h @@ -10,6 +10,7 @@ int erofs_probe(struct blk_desc *fs_dev_desc, struct disk_partition *fs_partition); int erofs_read(const char *filename, void *buf, loff_t offset, loff_t len, loff_t *actread); +int erofs_get_blocksize(const char *filename); int erofs_size(const char *filename, loff_t *size); int erofs_exists(const char *filename); void erofs_close(void);