From patchwork Tue Apr 21 18:34:44 2026 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Simon Glass X-Patchwork-Id: 2229 Return-Path: X-Original-To: u-boot-concept@u-boot.org Delivered-To: u-boot-concept@u-boot.org DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=u-boot.org; s=default; t=1776796552; bh=PaUvXkFIciP/qVsK8sQOvV8z0lBYbiyfebrojDEPO/0=; h=From:To:Date:In-Reply-To:References:CC:Subject:List-Id: List-Archive:List-Help:List-Owner:List-Post:List-Subscribe: List-Unsubscribe:From; b=jaau7iTLkcd7v5ThmxSgXYgvimc5pw6i64FCrq8dNHLb11A/U9qkGD6sR62tZYh1B N6QZPoLrC2ObGtA0H1+wBBWX3zMvvf9aOPv2hk7c+R+lGN69PvxVulwBHZCUSLR8OJ 65jIUh2p/8txPwrSprxp272VHB6zrc2awuCzs7Y0= Received: from localhost (localhost [127.0.0.1]) by mail.u-boot.org (Postfix) with ESMTP id 08A386A601 for ; Tue, 21 Apr 2026 12:35:52 -0600 (MDT) X-Virus-Scanned: Debian amavis at Received: from mail.u-boot.org ([127.0.0.1]) by localhost (mail.u-boot.org [127.0.0.1]) (amavis, port 10024) with ESMTP id zpQuGnJil7TA for ; Tue, 21 Apr 2026 12:35:51 -0600 (MDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=u-boot.org; s=default; t=1776796551; bh=PaUvXkFIciP/qVsK8sQOvV8z0lBYbiyfebrojDEPO/0=; h=From:To:Date:In-Reply-To:References:CC:Subject:List-Id: List-Archive:List-Help:List-Owner:List-Post:List-Subscribe: List-Unsubscribe:From; b=hRU8OjUy8BeMI0uXrjtM42RReWbNX3XbyIU/7xchfE6kgEjK/ySXzTTgjx8Vmy4Gp rzsCBGYhuD+rnp8ZWfzhwW0M7KbHHv2hoqb8BTDV6GVyM/xiVbeftaPRGWIBt8Gjn8 AEe6XYUADvkStDyr9nHqGzJwC3+nUEz8RarzpaMo= Received: from mail.u-boot.org (localhost [127.0.0.1]) by mail.u-boot.org (Postfix) with ESMTP id E97116A603 for ; Tue, 21 Apr 2026 12:35:51 -0600 (MDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=u-boot.org; s=default; t=1776796549; bh=8Cn1cePR6h5fN0q+tjnlr+TfQ/wPhtOZqNE/5E4tZgs=; h=From:To:Cc:Subject:Date:In-Reply-To:References:From; b=UjN1XuLEmv13a2GCDnQkt1tN1qBjxYsTaWxNPtO1SQNtSf0vWPc31wKHqs9NsuwW4 FqSpR1VlaAOgAV547IddQTGUvSnJW+Ekx6Zznf4qjULFNMd6VmR2MSKrHOpDV01/63 gw1OEk0PfsPY3o8YeEAShpAFPl63uk1sDdnJKFXE= Received: from localhost (localhost [127.0.0.1]) by mail.u-boot.org (Postfix) with ESMTP id B9C876A601; Tue, 21 Apr 2026 12:35:49 -0600 (MDT) X-Virus-Scanned: Debian amavis at Received: from mail.u-boot.org ([127.0.0.1]) by localhost (mail.u-boot.org [127.0.0.1]) (amavis, port 10026) with ESMTP id pDXBZBOmnm6k; Tue, 21 Apr 2026 12:35:49 -0600 (MDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=u-boot.org; s=default; t=1776796549; bh=q3yoBPYwmwNTZ1R7baEns8oQPS96Kqkz5Zncq97/ycU=; h=From:To:Cc:Subject:Date:In-Reply-To:References:From; b=Ix8il2neuXg3nGzqxalO9Xb652mpMWCBFRcn9I25+L5q5AfJLRi58WFmkys954fa+ mQBCsgWleVPKGYWuSzdjuDxLhlAtA/9TAt9Y6x4MFaT1/00aMB+jmJZaKtCXOmpz7+ e+JuXPodEMxTvbtZT1OhSc7tBZmeLbiSTAbhW804= Received: from u-boot.org (unknown [174.51.25.52]) by mail.u-boot.org (Postfix) with ESMTPSA id 07FCD6A528; Tue, 21 Apr 2026 12:35:48 -0600 (MDT) From: Simon Glass To: U-Boot Concept Date: Tue, 21 Apr 2026 12:34:44 -0600 Message-ID: <20260421183511.2044469-4-sjg@u-boot.org> X-Mailer: git-send-email 2.43.0 In-Reply-To: <20260421183511.2044469-1-sjg@u-boot.org> References: <20260421183511.2044469-1-sjg@u-boot.org> MIME-Version: 1.0 Message-ID-Hash: O57UPHE4KRMUSQPTDIKLGOHOLIVHDXEL X-Message-ID-Hash: O57UPHE4KRMUSQPTDIKLGOHOLIVHDXEL X-MailFrom: sjg@u-boot.org X-Mailman-Rule-Misses: dmarc-mitigation; no-senders; approved; loop; banned-address; emergency; member-moderation; nonmember-moderation; administrivia; implicit-dest; max-recipients; max-size; news-moderation; no-subject; digests; suspicious-header CC: Simon Glass X-Mailman-Version: 3.3.10 Precedence: list Subject: [Concept] [PATCH 03/16] fs: Add sb_bread_uncached() for streaming reads List-Id: Discussion and patches related to U-Boot Concept Archived-At: List-Archive: List-Help: List-Owner: List-Post: List-Subscribe: List-Unsubscribe: From: Simon Glass The existing sb_bread() path populates a global buffer-head cache in sb_getblk() and brelse() does not evict cached entries. That is the right trade-off for ext4l, where journal and metadata blocks are re-read from a small working set, but it is a disaster for filesystems that stream large files: every block read is retained, each allocation carries a buffer_head, a folio and a data buffer, and the malloc heap fills up long before the read completes. Add sb_bread_uncached() which allocates a fresh buffer_head, reads the block, and returns it without touching the cache. Callers release the buffer with brelse() exactly as before; since buffer_cached() is not set, brelse() now frees the buffer immediately. Signed-off-by: Simon Glass --- fs/linux_fs.c | 26 ++++++++++++++++++++++++++ include/linux/buffer_head.h | 14 ++++++++++++++ 2 files changed, 40 insertions(+) diff --git a/fs/linux_fs.c b/fs/linux_fs.c index db2b3b3942a..8f36b96a74e 100644 --- a/fs/linux_fs.c +++ b/fs/linux_fs.c @@ -472,6 +472,32 @@ struct buffer_head *sb_bread(struct super_block *sb, sector_t block) return bh; } +struct buffer_head *sb_bread_uncached(struct super_block *sb, sector_t block) +{ + struct buffer_head *bh; + int ret; + + if (!sb) + return NULL; + + bh = alloc_buffer_head_with_data(sb->s_blocksize); + if (!bh) + return NULL; + + bh->b_blocknr = block; + bh->b_bdev = sb->s_bdev; + + ret = linux_fs_read_block(sb, block, sb->s_blocksize, bh->b_data); + if (ret) { + free_buffer_head(bh); + return NULL; + } + + set_buffer_uptodate(bh); + + return bh; +} + /** * bdev_getblk() - Get buffer via block_device * @bdev: Block device diff --git a/include/linux/buffer_head.h b/include/linux/buffer_head.h index e844402500d..aad6dec3542 100644 --- a/include/linux/buffer_head.h +++ b/include/linux/buffer_head.h @@ -178,6 +178,20 @@ static inline void put_bh(struct buffer_head *bh) void brelse(struct buffer_head *bh); void __brelse(struct buffer_head *bh); +/** + * sb_bread_uncached() - Read a block without inserting it in the buffer cache + * @sb: Super block + * @block: Block number + * + * Same as sb_bread() but skips the buffer-head cache. Useful for streaming + * reads of large file contents where caching every block would exhaust the + * malloc heap before the read completes. Caller must release with brelse(), + * which frees the buffer immediately since it is not cached. + * + * Return: Buffer head with valid data, or NULL on error + */ +struct buffer_head *sb_bread_uncached(struct super_block *sb, sector_t block); + /* * Buffer operation stubs - U-Boot is single-threaded */