From nobody Mon Sep 28 04:07:36 2026 Received: from mail-pj1-f44.google.com (mail-pj1-f44.google.com [209.85.216.44]) (using TLSv1.2 with cipher ECDHE-RSA-AES128-GCM-SHA256 (128/128 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id B19B739A4DC for ; Wed, 26 Aug 2026 21:42:03 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=209.85.216.44 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1787780525; cv=none; b=amd+Y+eCqlSYrV0QZVh7KIDcaePj6Ut6Cagx2FElv+rpOX+MjpoNybSxpB/pJWV7uJ4sJQ3VHiNzrdCR7Le0hvxLHK5eaiz+IptQ6eebpdVI0J98NQeAFGx7smIYGF2i/jH8fw4SQNy4jaI0ZSCoag74JLVoaIGrPAiS2ilBnDQ= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1787780525; c=relaxed/simple; bh=z2bpPA0zFqHTTfq+pC+oO6AhfjTtFERuFYEXNXt0CCc=; h=From:To:Cc:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version; b=txpJ3wDYaVGkAUuzyirnz3ax9Op3ItH2iC9j5lmLa2RONQGPHNMAhQfUVfFAEY1l9Rke1C0ANSZjKXZRDUk5ZVfJNINHKAQsRvhibSUxd8Sph9FbVELtVE23PjpQxwmcAOWTW8Kyu9TdgeRzxxRP5QPM6xoZV+sIdrT9iFfuZiI= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=gmail.com; spf=pass smtp.mailfrom=gmail.com; dkim=pass (2048-bit key) header.d=gmail.com header.i=@gmail.com header.b=Y+Qh0Tvs; arc=none smtp.client-ip=209.85.216.44 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=gmail.com Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=gmail.com Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=gmail.com header.i=@gmail.com header.b="Y+Qh0Tvs" Received: by mail-pj1-f44.google.com with SMTP id 98e67ed59e1d1-38e347638adso1836872a91.0 for ; Wed, 26 Aug 2026 14:42:03 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20251104; t=1787780523; x=1788385323; darn=vger.kernel.org; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:from:to:cc:subject:date :message-id:reply-to:content-type; bh=mHqs09P+vXI3i5WkDlwO+qGDsL/5qc/GgQNXxBzNt2o=; b=Y+Qh0Tvs9a+ktbE7hTYClLf/Mni4+irvkl05dkZBEfz1suzCBdMqyPMcRkdFBQMfkI rQNKpIs7fFidScWj/wW9zfezC+VGdQ5b20hIFBSHy2BiM3ZR0wXidLxgkKV+SGH/NXXD du8EJmXqF8qrPnvE4sekASP5urEkFywqhAbzVSg6w4tThKecYYgVpNtzApWtI5iqPfDI Sv11ysTr7nlV9S1mBC2RDIFQMULED76omDbcopsomZWd2bwMXEDyeBmD6vJruNun1isY f8X1QWWdXLSDwgYR9PtyAk7NT7L3/Uy6PkDFI/ty2gwTA/U934ftL4ZJ0KlZdqt182Ig +TJw== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20251104; t=1787780523; x=1788385323; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:x-gm-gg:x-gm-message-state:from :to:cc:subject:date:message-id:reply-to:content-type; bh=mHqs09P+vXI3i5WkDlwO+qGDsL/5qc/GgQNXxBzNt2o=; b=kRcgWAwM/vCL8wmMceTPtNdofuWQbZcfpzyu0UCg8eTkXpWxX4zjfEGWqPLrJ4/FpB xWl84en2rb4mfg/oVaKAOLrCSN/0hHzSb8FkAY9LmxQ9Innx5w3ITC9MWIpTONc3aQlH OIyzNn8k5PYfELU5bu92+zcqDgyJ7J6xka9jgkY9mOw0+7rV2BPX/6OCxkxXBfVbP3PM mWx6oXDGmX2PJcgSE/DPhytq3RbhiymdFvWpScDQcDjbsUCpckZhPAXYNi9dMKl/tHpK tE82I82tyq+QRJxUxpMof6cr6KY5CnNguekJ8qoni1keBih+u1qhFIJaHaMjbJOtTn42 tgKA== X-Gm-Message-State: AFuF++l/Z/hmtF1f3pnROz5EiXmly7LXXAEHku7ZsCmW+1WLhLGK+LBM 6TUTahj69BVpinvFUTeCdlmYHQzSS6Z6T33c89JJjCMdLQ8AwDBnBMf6 X-Gm-Gg: AR+sD13TZFYE5bTisby5IjN5rW58GYAncJvaIOq+O490+xz+dLUWQFF5ptXJVUMhLIv 04LvMo4649SvDZkcgkpQIll0ay0VImR1pwr8jHN0qdfomGNVk2A3YUo+EWAAamlGvEcg2sA6Tq1 jjhpGtLc+qVP9XAJQhSZ+KoUxBdAcXuE3ZGgUKZphiHrex6v/oGBYB81jzx58OPUU/TlIBEdHkT LZ9/WaiqD9bMydrra51jPviSXlcs6honMoNsMJOcsEXJV+BDQ6zKnn0cV6evHhydqC6fTZdwBKM /ifyL8FQoBoIWI8VjD34Hz867hbmp7+lD2vJraWknLs9A6uCEzCihnq4+l6IuAZ2cNWzZrAlIBO m6ODFb2NCfx+Ch+6Sy0L69+iVKwbHKfrc7FoVPXEqFccoPzjLzsTLL6SMoXzxS3sYr62tfc/WNQ kKCu56VDx90suSO7/TyO9IxNB0jQHqDeVTsEgt X-Received: by 2002:a17:90b:4e8f:b0:38e:2517:5d1f with SMTP id 98e67ed59e1d1-3966d4032e5mr22602354a91.9.1787780522963; Wed, 26 Aug 2026 14:42:02 -0700 (PDT) Received: from nineveh.sos.local ([131.191.24.68]) by smtp.gmail.com with ESMTPSA id 98e67ed59e1d1-396689f1419sm5628673a91.9.2026.08.26.14.42.02 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Wed, 26 Aug 2026 14:42:02 -0700 (PDT) From: Jeremy Bingham To: linux-fsdevel@vger.kernel.org Cc: linux-kernel@vger.kernel.org, brauner@kernel.org, jkoolstra@xs4all.nl, jack@suse.cz, djwong@kernel.org, viro@zeniv.linux.org.uk, hch@infradead.org, Jeremy Bingham Subject: [PATCH v4 1/3] iomap: add iomap_symlink_write Date: Wed, 26 Aug 2026 14:41:55 -0700 Message-ID: <348ed49a8aa85c6c23c21034c8598401e9938e3d.1787770110.git.jbingham@gmail.com> X-Mailer: git-send-email 2.47.3 In-Reply-To: References: Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Transfer-Encoding: quoted-printable Content-Type: text/plain; charset="utf-8" Add a new iomap_symlink_write function as an iomap based equivalent to page_symlink found in fs/namei.c. Part of being that equivalency is behaving similarly to page_symlink. This function now expects the same len as page_symlink, where len is the length of the null terminated target string. The target is still written out without the trailing null. Suggested-by: Darrick J. Wong Suggested-by: Christoph Hellwig Signed-off-by: Jeremy Bingham Reviewed-by: Christoph Hellwig --- fs/iomap/buffered-io.c | 34 ++++++++++++++++++++++++++++++++++ include/linux/iomap.h | 3 +++ 2 files changed, 37 insertions(+) diff --git a/fs/iomap/buffered-io.c b/fs/iomap/buffered-io.c index 0a5ebfda90f1..5e8ac3fad671 100644 --- a/fs/iomap/buffered-io.c +++ b/fs/iomap/buffered-io.c @@ -2100,3 +2100,37 @@ iomap_writepages(struct iomap_writepage_ctx *wpc) return error; } EXPORT_SYMBOL_GPL(iomap_writepages); + +int iomap_symlink_write(struct inode *inode, const char *target, int len, + const struct iomap_ops *ops, + const struct iomap_write_ops *write_ops, void *private) +{ + struct kvec vec =3D { + .iov_base =3D (void *)target, + .iov_len =3D len - 1, + }; + struct iomap_iter iter =3D { + .inode =3D inode, + .pos =3D 0, + .len =3D len - 1, + .flags =3D IOMAP_WRITE, + .private =3D private, + }; + struct iov_iter iov; + int ret; + + iov_iter_kvec(&iov, ITER_SOURCE, &vec, 1, len - 1); + + while ((ret =3D iomap_iter(&iter, ops)) > 0) + iter.status =3D iomap_write_iter(&iter, &iov, write_ops); + + if (ret < 0) + return ret; + + if (unlikely(iter.pos =3D=3D 0)) + return -EIO; + + mark_inode_dirty(inode); + return 0; +} +EXPORT_SYMBOL_GPL(iomap_symlink_write); diff --git a/include/linux/iomap.h b/include/linux/iomap.h index 8c754eb974fb..ab27a3a5b8d2 100644 --- a/include/linux/iomap.h +++ b/include/linux/iomap.h @@ -471,6 +471,9 @@ loff_t iomap_seek_data(struct inode *inode, loff_t offs= et, const struct iomap_ops *ops); sector_t iomap_bmap(struct address_space *mapping, sector_t bno, const struct iomap_ops *ops); +int iomap_symlink_write(struct inode *inode, const char *target, int len, + const struct iomap_ops *ops, + const struct iomap_write_ops *write_ops, void *private); =20 /* * Flags for iomap_ioend->io_flags. --=20 2.47.3 From nobody Mon Sep 28 04:07:36 2026 Received: from mail-pj1-f41.google.com (mail-pj1-f41.google.com [209.85.216.41]) (using TLSv1.2 with cipher ECDHE-RSA-AES128-GCM-SHA256 (128/128 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id B394C488DBA for ; Wed, 26 Aug 2026 21:42:04 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=209.85.216.41 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1787780526; cv=none; b=k78NTRzFh0y3fVMJInrOXoN4AP7AmIwWXl/EoveJPMYkFIX9tXPp02XXSu7c8K2/e6RUQZ70xaKlak8ysw3elwez2vl5RwRBbvru7rqHEPd7uUHkufVm9oYrAsoWd7XlqzklBvQdVu01mWc1TzVkadwWAlE6sfUGgI+xnxCIV8Y= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1787780526; c=relaxed/simple; bh=ov0ZxImQEsYJcJvX8xdhNnzUus7UhmOk1kD3vKbinrE=; h=From:To:Cc:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version; b=J0B6jbHJmIrwlZB/1ALOBuA1gEK08KvoCsIi0X8MWtNH/tNqvuaGpF4+dyZWI982rRxAuLuix/ppeiKjK+8ViQEWEYpOC6ejmt+2OQVQFQAezarjaTAk7lCOrALDg6n4U0KOS8lXAPb4jVe1Vx8EuafTkz4uF1K6FzWpnRpqZuI= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=gmail.com; spf=pass smtp.mailfrom=gmail.com; dkim=pass (2048-bit key) header.d=gmail.com header.i=@gmail.com header.b=eElqbU+y; arc=none smtp.client-ip=209.85.216.41 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=gmail.com Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=gmail.com Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=gmail.com header.i=@gmail.com header.b="eElqbU+y" Received: by mail-pj1-f41.google.com with SMTP id 98e67ed59e1d1-3964dfb5a69so1420398a91.1 for ; Wed, 26 Aug 2026 14:42:04 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20251104; t=1787780524; x=1788385324; darn=vger.kernel.org; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:from:to:cc:subject:date :message-id:reply-to:content-type; bh=Kv3c9GC/khtykDvIth2imKR6x9vvbRKSQGnD75nijyQ=; b=eElqbU+yJC6UGX0OMP80ODLsjdxq25NdFB8V5krsRrqGHnuI2MvagBsVxfx0lPcoKC KDwin3e4OPP9H31wuvKRnhAGXa+ORRAySRTlMwW9OoyW/9U4LI8OMluyHYxjf5uPj3Lj 8W3osyi+JgbVpaGupBnxGatYc79fxgKA1r9TxT7zDjZSS7hN20ASygjEcXu0BlQR6lpx MhOX9YSl5fEnm7MsFQtC/WNoPM6BSP3qlnPwqhamr7lf9fd8IX2soCneFzKLZN7Y1MSB D5tvwdfz4Zbxt8X7Clwyc1T1mya8QKb4pBhzXcKttxhuVGouQ20VyYgHXKgRUednuUfS QSVQ== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20251104; t=1787780524; x=1788385324; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:x-gm-gg:x-gm-message-state:from :to:cc:subject:date:message-id:reply-to:content-type; bh=Kv3c9GC/khtykDvIth2imKR6x9vvbRKSQGnD75nijyQ=; b=B+FuCHUM3F4SwZpBcgGRtYCiHAoechjio0//iZLtQ1KXVTcsWomiwoem8jzpBpt3ug 1sd5xJLgE1+T48dubSxDY1mPBVQkTWVd4x4/uJwckxORDNZ3UPFGxvakvyy4vEPH6x+q adsO8mR+I5JMo9hc6BlsVvDKt/8mYeRFj6pnk1uVV4DeRKUHrZlNlZuQ3dZrsoxPis+x grXaLbRXPygzE2aXhCZx6QeKZyTPoDkN1Z2D407mvTdzyElSSWSmgvWpRC5soQgrkqRM TUgjI4SK0bajj/jtTua4zhhVtapyM8bP8GGsloN+f5EDld1HIFycKEMQYaJHYbVydZel Cwew== X-Gm-Message-State: AFuF++mK50T9YOAy+BtyAq1dR9mKIBcBINF5rn76L0RDSzHDGy2CPrMh iVgJnzLyBD/Of0MbAd5u3G1q9agNu7piV2IBDw8QpJDV/6T/huhum+OL X-Gm-Gg: AR+sD13g95qxHTPb3BbU/F05zAwYS3FiOkiBBs6pKakwjEHt65FYMeUYVKySHczoWOu eJGIOBzQJ6oHgRXq6cAJDZGyAK4Qk2VxvLZ4lMefSF1b6Vn1DdJ2dAW/lqmfc0c56Iedh7TS1O6 TSj9tfTwY8IhmGdXfK3XOib/Ni2pxwa0XVuRts4QIuqxd/nHmZrer/esI9toUJSvO50UFgvy1Q7 vkeR5w7Y0/8qvZIxHe1+muhskZQ0b95+pHMde4wacdbwBnLuDB4e/AnJUVy2g+pN2JYjqVbpn+M oIEF4CxwRKXTOMYsafn7TQy8ed3W5EvDEw3vqnHDLBGiFyjJL+b3YDKbSmScqxPNjkVQ1SEtxJz J6k6clPpfrVyA/iWi/U3BJanK7J+xv5khOkoF/iAwpQn373cnst8swMgzfbRYiIfbSsg1LgjG5D tMhI33XCpl1s9koKrFzoTOOFOjB7scbEnYo4c= X-Received: by 2002:a17:90b:3d4f:b0:396:635a:9b12 with SMTP id 98e67ed59e1d1-3966d48beb5mr20657270a91.12.1787780523937; Wed, 26 Aug 2026 14:42:03 -0700 (PDT) Received: from nineveh.sos.local ([131.191.24.68]) by smtp.gmail.com with ESMTPSA id 98e67ed59e1d1-396689f1419sm5628673a91.9.2026.08.26.14.42.03 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Wed, 26 Aug 2026 14:42:03 -0700 (PDT) From: Jeremy Bingham To: linux-fsdevel@vger.kernel.org Cc: linux-kernel@vger.kernel.org, brauner@kernel.org, jkoolstra@xs4all.nl, jack@suse.cz, djwong@kernel.org, viro@zeniv.linux.org.uk, hch@infradead.org, Jeremy Bingham Subject: [PATCH v4 2/3] minix: add iomap functions and definitions Date: Wed, 26 Aug 2026 14:41:56 -0700 Message-ID: X-Mailer: git-send-email 2.47.3 In-Reply-To: References: Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Transfer-Encoding: quoted-printable Content-Type: text/plain; charset="utf-8" Adds a new file, iomap.c, to fs/minix. This provides minix_iomap_begin, which is the iomap-based version of get_block in itree_common.c. It also provides minix_iomap_end, which is a no-op function required by the iomap_ops struct. The minix_iomap_begin function also uses helper functions to undo the nest of gotos inherited from get_block. This patch also wires iomap.c into itree_v1.c and itree_v2.c, similarly to how itree_common.c is included in those files, and exports version specific versions of minix_iomap_begin and iomap_ops. Also updates 'unsigned' to 'unsigned int' a few places that got picked up by checkpatch.pl. Suggested-by: Darrick J. Wong Signed-off-by: Jeremy Bingham --- fs/minix/iomap.c | 122 ++++++++++++++++++++++++++++++++++++++++++++ fs/minix/itree_v1.c | 25 ++++++++- fs/minix/itree_v2.c | 17 +++++- fs/minix/minix.h | 21 +++++++- 4 files changed, 181 insertions(+), 4 deletions(-) create mode 100644 fs/minix/iomap.c diff --git a/fs/minix/iomap.c b/fs/minix/iomap.c new file mode 100644 index 000000000000..90e016aaa01e --- /dev/null +++ b/fs/minix/iomap.c @@ -0,0 +1,122 @@ +// SPDX-License-Identifier: GPL-2.0-only +/* + * iomap functions for minix. + */ + +static inline void minix_chain_cleanup(Indirect *chain, Indirect *partial) +{ + while (partial > chain) { + brelse(partial->bh); + partial--; + } +} + +static inline void minix_iomap_set_mapped(struct iomap *iomap, sector_t ph= ys, + unsigned int blkbits, sector_t iblock) +{ + iomap->type =3D IOMAP_MAPPED; + iomap->addr =3D (u64)phys << blkbits; + iomap->length =3D 1 << blkbits; + iomap->offset =3D (u64)iblock << blkbits; +} + +static inline void minix_iomap_set_hole(struct iomap *iomap, + unsigned int blkbits, sector_t iblock) +{ + iomap->type =3D IOMAP_HOLE; + iomap->addr =3D IOMAP_NULL_ADDR; + iomap->length =3D 1 << blkbits; + iomap->offset =3D (u64)iblock << blkbits; +} + +/* + * minix_iomap_begin - map a file range to disk blocks. It acts as a repla= cement + * for get_block in itree_common.c, at least in the important ways, and is + * adapted from it, but it uses iomap instead of buffer_head. + */ +static int minix_iomap_begin(struct inode *inode, loff_t offset, loff_t le= ngth, + unsigned int flags, struct iomap *iomap, struct iomap *srcmap) +{ + struct super_block *sb =3D inode->i_sb; + unsigned int blkbits =3D sb->s_blocksize_bits; + sector_t iblock =3D offset >> blkbits; + int create =3D flags & IOMAP_WRITE; + + int offsets[DEPTH]; + Indirect chain[DEPTH]; + Indirect *partial; + int depth =3D block_to_path(inode, iblock, offsets); + int left; + int err =3D -EIO; + + sector_t phys; + + /* block is beyond max file size */ + if (depth =3D=3D 0) + return -EINVAL; + + iomap->bdev =3D inode->i_sb->s_bdev; + +reread: + partial =3D get_branch(inode, depth, offsets, chain, &err); + + /* Simplest case - block found, no allocation needed */ + if (!partial) { + iomap->flags =3D 0; + phys =3D block_to_cpu(chain[depth - 1].key); + partial =3D chain+depth-1; + minix_iomap_set_mapped(iomap, phys, blkbits, iblock); + minix_chain_cleanup(chain, partial); + return err; + } + + /* Next simple case - plain lookup or failed read of indirect block */ + if (!create || err =3D=3D -EIO) { + minix_iomap_set_hole(iomap, blkbits, iblock); + minix_chain_cleanup(chain, partial); + return err; + } + + /* + * This is held over from the original get_block logic, where it + * acted as a guard in case truncate() deleted blocks from under that + * function. There should not be a race with iomap operations, but + * we're retaining the defensive coding here to be extra safe just in + * case. + */ + if (err =3D=3D -EAGAIN) { + minix_chain_cleanup(chain, partial); + goto reread; + } + + left =3D (chain + depth) - partial; + err =3D alloc_branch(inode, left, offsets + (partial - chain), partial); + if (err) { + minix_chain_cleanup(chain, partial); + return err; + } + + if (splice_branch(inode, chain, partial, left) < 0) { + minix_chain_cleanup(chain, partial); + goto reread; + } + + /* Successful allocation, mapping it. */ + iomap->flags =3D IOMAP_F_NEW; + phys =3D block_to_cpu(chain[depth - 1].key); + minix_iomap_set_mapped(iomap, phys, blkbits, iblock); + minix_chain_cleanup(chain, partial); + + return err; +} + +/* + * minix_iomap_end ends up being a nop; since minix doesn't have any exten= ts or + * transactions to worry about, there isn't anything to update here. The o= n-disk + * indirect blocks get dirtied in minix_iomap_begin. + */ +static int minix_iomap_end(struct inode *inode, loff_t offset, loff_t leng= th, + ssize_t written, unsigned int flags, struct iomap *iomap) +{ + return 0; +} diff --git a/fs/minix/itree_v1.c b/fs/minix/itree_v1.c index 1fed906042aa..58c29f4443d3 100644 --- a/fs/minix/itree_v1.c +++ b/fs/minix/itree_v1.c @@ -49,6 +49,18 @@ static int block_to_path(struct inode * inode, long bloc= k, int offsets[DEPTH]) } =20 #include "itree_common.c" +/* NOTA BENE: + * + * This is icky to me, but at the same time having it be a standalone C fi= le + * that's compiled to object form and linked separately like it is in xiaf= s is + * much nastier in minix because of the different versions of the minix fs= that + * have some very, very different aspects, like the size of block_t. I don= 't + * like it, but since minix already has this pattern where a common itree = file + * is included in the itree_v1 and itree_v2(and v3) files, I'm including i= omap.c + * in these files as well. It does at least avoid exporting some currently + * static functions that aren't needed anywhere but itree_common.c and iom= ap.c. + */ +#include "iomap.c" =20 int V1_minix_get_block(struct inode * inode, long block, struct buffer_head *bh_result, int create) @@ -61,7 +73,18 @@ void V1_minix_truncate(struct inode * inode) truncate(inode); } =20 -unsigned V1_minix_blocks(loff_t size, struct super_block *sb) +unsigned int V1_minix_blocks(loff_t size, struct super_block *sb) { return nblocks(size, sb); } + +int V1_minix_iomap_begin(struct inode *inode, loff_t offset, loff_t length, + unsigned int flags, struct iomap *iomap, struct iomap *srcmap) +{ + return minix_iomap_begin(inode, offset, length, flags, iomap, srcmap); +} + +const struct iomap_ops V1_minix_iomap_ops =3D { + .iomap_begin =3D V1_minix_iomap_begin, + .iomap_end =3D minix_iomap_end, +}; diff --git a/fs/minix/itree_v2.c b/fs/minix/itree_v2.c index 9d00f31a2d9d..fc7a5ae8fa1c 100644 --- a/fs/minix/itree_v2.c +++ b/fs/minix/itree_v2.c @@ -57,6 +57,10 @@ static int block_to_path(struct inode * inode, long bloc= k, int offsets[DEPTH]) } =20 #include "itree_common.c" +/* See the note in itree_v1 in a comment that starts "NOTA BENE" for an + * explanation for why iomap.c is included here. + */ +#include "iomap.c" =20 int V2_minix_get_block(struct inode * inode, long block, struct buffer_head *bh_result, int create) @@ -69,7 +73,18 @@ void V2_minix_truncate(struct inode * inode) truncate(inode); } =20 -unsigned V2_minix_blocks(loff_t size, struct super_block *sb) +unsigned int V2_minix_blocks(loff_t size, struct super_block *sb) { return nblocks(size, sb); } + +int V2_minix_iomap_begin(struct inode *inode, loff_t offset, loff_t length, + unsigned int flags, struct iomap *iomap, struct iomap *srcmap) +{ + return minix_iomap_begin(inode, offset, length, flags, iomap, srcmap); +} + +const struct iomap_ops V2_minix_iomap_ops =3D { + .iomap_begin =3D V2_minix_iomap_begin, + .iomap_end =3D minix_iomap_end, +}; diff --git a/fs/minix/minix.h b/fs/minix/minix.h index 78722ce22e1e..f1141d36e3d5 100644 --- a/fs/minix/minix.h +++ b/fs/minix/minix.h @@ -5,6 +5,7 @@ #include #include #include +#include =20 #define INODE_VERSION(inode) minix_sb(inode->i_sb)->s_version #define MINIX_V1 0x0001 /* original minix fs */ @@ -76,13 +77,23 @@ int minix_make_empty(struct inode*, struct inode*); int minix_empty_dir(struct inode*); int minix_set_link(struct minix_dir_entry *de, struct folio *folio, struct inode *inode); + struct minix_dir_entry *minix_dotdot(struct inode*, struct folio **); ino_t minix_inode_by_name(struct dentry*); =20 +int V1_minix_iomap_begin(struct inode *inode, loff_t offset, + loff_t length, unsigned int flags, struct iomap *iomap, + struct iomap *srcmap); +int V2_minix_iomap_begin(struct inode *inode, loff_t offset, + loff_t length, unsigned int flags, struct iomap *iomap, + struct iomap *srcmap); + extern const struct inode_operations minix_file_inode_operations; extern const struct inode_operations minix_dir_inode_operations; extern const struct file_operations minix_file_operations; extern const struct file_operations minix_dir_operations; +extern const struct iomap_ops V1_minix_iomap_ops; +extern const struct iomap_ops V2_minix_iomap_ops; =20 static inline struct minix_sb_info *minix_sb(struct super_block *sb) { @@ -94,11 +105,17 @@ static inline struct minix_inode_info *minix_i(struct = inode *inode) return container_of(inode, struct minix_inode_info, vfs_inode); } =20 -static inline unsigned minix_blocks_needed(unsigned bits, unsigned blocksi= ze) +static inline unsigned int minix_blocks_needed(unsigned int bits, unsigned= int blocksize) { return DIV_ROUND_UP_POW2(bits, blocksize * 8); } =20 +static inline const struct iomap_ops *minix_iomap_ops_ver(struct inode *in= ode) +{ + return (INODE_VERSION(inode) =3D=3D MINIX_V1) ? + &V1_minix_iomap_ops : &V2_minix_iomap_ops; +} + #if defined(CONFIG_MINIX_FS_NATIVE_ENDIAN) && \ defined(CONFIG_MINIX_FS_BIG_ENDIAN_16BIT_INDEXED) =20 @@ -128,7 +145,7 @@ static inline unsigned minix_blocks_needed(unsigned bit= s, unsigned blocksize) * big-endian 16bit indexed bitmaps */ =20 -static inline int minix_find_first_zero_bit(const void *vaddr, unsigned si= ze) +static inline int minix_find_first_zero_bit(const void *vaddr, unsigned in= t size) { const unsigned short *p =3D vaddr, *addr =3D vaddr; unsigned short num; --=20 2.47.3 From nobody Mon Sep 28 04:07:36 2026 Received: from mail-pg1-f181.google.com (mail-pg1-f181.google.com [209.85.215.181]) (using TLSv1.2 with cipher ECDHE-RSA-AES128-GCM-SHA256 (128/128 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id D041B48A8B6 for ; Wed, 26 Aug 2026 21:42:05 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=209.85.215.181 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1787780527; cv=none; b=cnrTnDxrbtxzFyijGv4T4O/jC99ln2AnDotrfpdR2pWTd9NMrE0jmlR1pdcDUmlQfZFraTZXqJtyFyQA+kBBQyltXdcu/JF9CBADuNfsEOMbi0U/i/4Ui7YkPXaudKNqDbCHQ0VdrHddJapKST3guoBE2ZAXx0R8q7WSA5K1qvU= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1787780527; c=relaxed/simple; bh=ZBTCYxg/g/1YoU4wXmnf1kFuJEma80I5r1HtT2UZx1E=; h=From:To:Cc:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version; b=g9j+ZFCPo1jlK8nZg6fjNfk1dXzrDksXXiEIXxBfbMlFWK7fhl+8mNBCeKWx4oXW4BaK731erJ1PYZ06Qsc+xkoZw2SGOfGtNZWp7iK/saBJPEUzh+roPC7mUsdedR2yTFggpGck3zu5zcABOXcDmr7XzuqpGiV1a3bhClXQxPc= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=gmail.com; spf=pass smtp.mailfrom=gmail.com; dkim=pass (2048-bit key) header.d=gmail.com header.i=@gmail.com header.b=dWRYp3/r; arc=none smtp.client-ip=209.85.215.181 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=gmail.com Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=gmail.com Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=gmail.com header.i=@gmail.com header.b="dWRYp3/r" Received: by mail-pg1-f181.google.com with SMTP id 41be03b00d2f7-cc149372c14so1141604a12.1 for ; Wed, 26 Aug 2026 14:42:05 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20251104; t=1787780525; x=1788385325; darn=vger.kernel.org; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:from:to:cc:subject:date :message-id:reply-to:content-type; bh=Gg73ZkRLNpj1F3eKZcoeBv1OHmS+aB70wYPXjLHVKFg=; b=dWRYp3/rCgHPGIAN4VpVLLXFkrIGOt7D9rswWAEMkSQ33wx7FrgDOW7cvXffPCLAt+ nusN3wva+FS/Odln2skapHEUEX5h/zVBeJrq6VzBUD1MXO4cVDQN5h/OsguM0MEIn30h gZNK8oTgsyaB15wrGhB/JgSgQCMZMqf29xt3rqzwtmqoWeia/SiOF66H72InGuVhaW9u Yn+r/r8EQ7G9QLeyiRml+nSgxLK6r/JvqmEPjVEaGU48luUdIzUuypYTb85PR80MEoIh dkAjYPJuV4tzw166rdycVvy+Fp11+nOmSs1ToDA/OIg2DBmBkpsxej9buPMP9kx3fi+I +Nwg== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20251104; t=1787780525; x=1788385325; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:x-gm-gg:x-gm-message-state:from :to:cc:subject:date:message-id:reply-to:content-type; bh=Gg73ZkRLNpj1F3eKZcoeBv1OHmS+aB70wYPXjLHVKFg=; b=bTuxFa8SGMifhJqgN9gbS2clb+7/Brjy/19qlzPLTF/1ayNhNuj72JoRddfETAosHC A1EiBuHdQLOJG8Ld0uht01an+K46Dtk5yka761OVC2T3KW0G0pDptzoNs3XPdfR7rJ2w 2PryrEh3p8aaWeT08WURBC57ziKHnWDQbhsITwjrBK+W1o1VKxNLiB4oL29k6OWfRIUl 0k9tlFh+OAGn2wGjQPelmidsppzneT4k4oVwvI5DGxbCvF3/f/oBh2SVfGLC4+jZIjfX Kn45+wGo8XQaqD/3G5Xo1kBm+b/1eclz8Md1Dcn4vl2qMJbGOuRYyDstN1XrWknszVRK QcmA== X-Gm-Message-State: AFuF++ly2OcVILsvOBb1UWkq8+77vUQLfiybsRG+zhDoFquKhwR3bfgx rsdJsgAjTyrTGI28YWaUKEroD4qICuixDBEGpD4aypl+TazxgBSR3Xo8 X-Gm-Gg: AR+sD139PKnSP0qfYbaKqFZpJPbT8kNAfoPeFtTbrzOzaSHh5uMId0jHkN1z6KwIwQQ WnfIlAQ072TLQha0zImXhB8oHeAeJvnP6QdbuUVoC10LLsBe8LyMTfWzeRhxBtPu7nC+/BG9ukN 1Jaany5XRFSjNC3z2SZHvEaoMvj1FbanfdiC7s7v20HZmv3WW13uguwBQdFnldK/9yKQvQS7Jdk H6XG/H0Ufr2pGT//kNIXyL+W71QvZdieYu8PkbUB0yTTLc2a1uvGaGww/166lA8rF73Fq9VGSGh sn6JnBH4rc08E/0qivi8zwa7KvySEVaPmapEbW95d/Zo7VEgLSEFzKEgh2GL+GdJS4XPMBDoBU4 oKg2pN323ZjOdeqnrueAClxgKw/f0OExJ5ovFOz+eJOMuvIfEfMPRqP0lIr3lY/DW8FA9YZ2u5e yaMqNu3mzcM0CgqGDBvFM3NtrWCuhuEixllnQ= X-Received: by 2002:a17:90b:3a05:b0:37f:fd1f:d30f with SMTP id 98e67ed59e1d1-3966d44312fmr21131048a91.12.1787780525021; Wed, 26 Aug 2026 14:42:05 -0700 (PDT) Received: from nineveh.sos.local ([131.191.24.68]) by smtp.gmail.com with ESMTPSA id 98e67ed59e1d1-396689f1419sm5628673a91.9.2026.08.26.14.42.04 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Wed, 26 Aug 2026 14:42:04 -0700 (PDT) From: Jeremy Bingham To: linux-fsdevel@vger.kernel.org Cc: linux-kernel@vger.kernel.org, brauner@kernel.org, jkoolstra@xs4all.nl, jack@suse.cz, djwong@kernel.org, viro@zeniv.linux.org.uk, hch@infradead.org, Jeremy Bingham Subject: [PATCH v4 3/3] minix: finish wiring in iomap functions Date: Wed, 26 Aug 2026 14:41:57 -0700 Message-ID: <668bd5f317e3bf8eaee0254ca79e595395b6e332.1787770110.git.jbingham@gmail.com> X-Mailer: git-send-email 2.47.3 In-Reply-To: References: Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Transfer-Encoding: quoted-printable Content-Type: text/plain; charset="utf-8" Wire in the new iomap functionality in one pass. Per Christoph Hellwig's feedback, there are no longer direct I/O operations. Without that, only write_iter in minix_file_operations needs a custom function. That and exporting minix_setattr for minix_symlink_inode_operations are the only changes in file.c. There are two main additions in inode.c. First, minix_writeback_range and minix_writeback_ops are newly added. Secondly, the old minix_writepages and minix_read_folio functions were renamed to minix_block_writepages and minix_block_read_folio respectively while new functions with those names were created that use iomap. Because directory operations need to stay using buffer heads, a new set of address space operations just for directory operations was created while other file types use the new iomap based address space operations. The minix_symlink_inode_operations also have setattr set to minix_setattr now. Support for bmap has been dropped entirely, per Darrick J. Wong's suggestion. In itree_common.c, truncate() is updated to use different functions depending on whether the inode being truncated is a directory or not. This is because of the changes above where directory operations still use buffer heads and have their own address operations. This patch also updates minix_symlink to use the new iomap_symlink_write function, which brings symlinks under iomap and removes the need to bypass it with a private custom function. This was suggested by Darrick J. Wong in an earlier version of this patch series. Suggested-by: Darrick J. Wong Suggested-by: Christoph Hellwig Signed-off-by: Jeremy Bingham --- fs/minix/file.c | 30 ++++++++++++++- fs/minix/inode.c | 85 +++++++++++++++++++++++++++++++++++------ fs/minix/itree_common.c | 10 ++++- fs/minix/minix.h | 2 + fs/minix/namei.c | 7 +++- 5 files changed, 118 insertions(+), 16 deletions(-) diff --git a/fs/minix/file.c b/fs/minix/file.c index 02aabbdb5dea..6765f571bd3f 100644 --- a/fs/minix/file.c +++ b/fs/minix/file.c @@ -10,6 +10,32 @@ #include #include "minix.h" =20 +static ssize_t minix_file_write_iter(struct kiocb *iocb, struct iov_iter *= from) +{ + struct inode *inode =3D iocb->ki_filp->f_mapping->host; + ssize_t ret; + const struct iomap_ops *ops =3D minix_iomap_ops_ver(inode); + + inode_lock(inode); + ret =3D generic_write_checks(iocb, from); + if (ret <=3D 0) + goto unlock; + + ret =3D file_modified(iocb->ki_filp); + if (ret) + goto unlock; + + ret =3D iomap_file_buffered_write(iocb, from, ops, + NULL, NULL); + + if (ret > 0) + ret =3D generic_write_sync(iocb, ret); + +unlock: + inode_unlock(inode); + return ret; +} + /* * We have mostly NULLs here: the current defaults are OK for * the minix filesystem. @@ -17,13 +43,13 @@ const struct file_operations minix_file_operations =3D { .llseek =3D generic_file_llseek, .read_iter =3D generic_file_read_iter, - .write_iter =3D generic_file_write_iter, + .write_iter =3D minix_file_write_iter, .mmap_prepare =3D generic_file_mmap_prepare, .fsync =3D simple_fsync, .splice_read =3D filemap_splice_read, }; =20 -static int minix_setattr(struct mnt_idmap *idmap, +int minix_setattr(struct mnt_idmap *idmap, struct dentry *dentry, struct iattr *attr) { struct inode *inode =3D d_inode(dentry); diff --git a/fs/minix/inode.c b/fs/minix/inode.c index daf83e4ff25c..2bf5ea92360a 100644 --- a/fs/minix/inode.c +++ b/fs/minix/inode.c @@ -439,6 +439,31 @@ static int minix_statfs(struct dentry *dentry, struct = kstatfs *buf) return 0; } =20 +static ssize_t minix_writeback_range(struct iomap_writepage_ctx *wpc, + struct folio *folio, u64 pos, unsigned int len, u64 end_pos) +{ + int error; + + if (pos < wpc->iomap.offset || + pos >=3D wpc->iomap.offset + wpc->iomap.length) { + if (INODE_VERSION(wpc->inode) =3D=3D MINIX_V1) + error =3D V1_minix_iomap_begin(wpc->inode, pos, len, IOMAP_WRITE, + &wpc->iomap, NULL); + else + error =3D V2_minix_iomap_begin(wpc->inode, pos, len, IOMAP_WRITE, + &wpc->iomap, NULL); + if (error) + return error; + } + + return iomap_add_to_ioend(wpc, folio, pos, end_pos, len); +} + +static const struct iomap_writeback_ops minix_writeback_ops =3D { + .writeback_range =3D minix_writeback_range, + .writeback_submit =3D iomap_ioend_writeback_submit, +}; + static int minix_get_block(struct inode *inode, sector_t block, struct buffer_head *bh_result, int create) { @@ -448,17 +473,45 @@ static int minix_get_block(struct inode *inode, secto= r_t block, return V2_minix_get_block(inode, block, bh_result, create); } =20 -static int minix_writepages(struct address_space *mapping, +/* The old minix_writepages, preserved for directory operations. */ +static int minix_block_writepages(struct address_space *mapping, struct writeback_control *wbc) { return mpage_writepages(mapping, wbc, minix_get_block); } =20 +static int minix_writepages(struct address_space *mapping, + struct writeback_control *wbc) +{ + struct iomap_writepage_ctx wpc =3D { + .inode =3D mapping->host, + .wbc =3D wbc, + .ops =3D &minix_writeback_ops, + }; + return iomap_writepages(&wpc); +} + static int minix_read_folio(struct file *file, struct folio *folio) +{ + const struct iomap_ops *ops =3D minix_iomap_ops_ver(folio->mapping->host); + + iomap_bio_read_folio(folio, ops); + return 0; +} + +/* The old minix_read_folio, preserved for directory operations. */ +static int minix_block_read_folio(struct file *file, struct folio *folio) { return block_read_full_folio(folio, minix_get_block); } =20 +static void minix_readahead(struct readahead_control *rac) +{ + const struct iomap_ops *ops =3D minix_iomap_ops_ver(rac->mapping->host); + + iomap_bio_readahead(rac, ops); +} + int minix_prepare_chunk(struct folio *folio, loff_t pos, unsigned len) { return __block_write_begin(folio, pos, len, minix_get_block); @@ -488,26 +541,35 @@ static int minix_write_begin(const struct kiocb *iocb, return ret; } =20 -static sector_t minix_bmap(struct address_space *mapping, sector_t block) -{ - return generic_block_bmap(mapping,block,minix_get_block); -} - static const struct address_space_operations minix_aops =3D { - .dirty_folio =3D block_dirty_folio, - .invalidate_folio =3D block_invalidate_folio, + .dirty_folio =3D iomap_dirty_folio, + .invalidate_folio =3D iomap_invalidate_folio, .read_folio =3D minix_read_folio, + .readahead =3D minix_readahead, .writepages =3D minix_writepages, + .migrate_folio =3D filemap_migrate_folio, + .is_partially_uptodate =3D iomap_is_partially_uptodate, + .release_folio =3D iomap_release_folio, + .error_remove_folio =3D generic_error_remove_folio, +}; + +/* A special aops for directories that keeps using the buffer head chunks,= at + * least for the time being. + */ +static const struct address_space_operations minix_dir_aops =3D { + .dirty_folio =3D block_dirty_folio, + .invalidate_folio =3D block_invalidate_folio, + .read_folio =3D minix_block_read_folio, .write_begin =3D minix_write_begin, .write_end =3D generic_write_end, .migrate_folio =3D buffer_migrate_folio, - .bmap =3D minix_bmap, - .direct_IO =3D noop_direct_IO + .writepages =3D minix_block_writepages, }; =20 static const struct inode_operations minix_symlink_inode_operations =3D { .get_link =3D page_get_link, .getattr =3D minix_getattr, + .setattr =3D minix_setattr, }; =20 void minix_set_inode(struct inode *inode, dev_t rdev) @@ -519,7 +581,7 @@ void minix_set_inode(struct inode *inode, dev_t rdev) } else if (S_ISDIR(inode->i_mode)) { inode->i_op =3D &minix_dir_inode_operations; inode->i_fop =3D &minix_dir_operations; - inode->i_mapping->a_ops =3D &minix_aops; + inode->i_mapping->a_ops =3D &minix_dir_aops; } else if (S_ISLNK(inode->i_mode)) { inode->i_op =3D &minix_symlink_inode_operations; inode_nohighmem(inode); @@ -786,4 +848,3 @@ module_init(init_minix_fs) module_exit(exit_minix_fs) MODULE_DESCRIPTION("Minix file system"); MODULE_LICENSE("GPL"); - diff --git a/fs/minix/itree_common.c b/fs/minix/itree_common.c index c3cd2c75af9c..d73ab1caacfe 100644 --- a/fs/minix/itree_common.c +++ b/fs/minix/itree_common.c @@ -311,7 +311,15 @@ static inline void truncate (struct inode * inode) long iblock; =20 iblock =3D (inode->i_size + sb->s_blocksize -1) >> sb->s_blocksize_bits; - block_truncate_page(inode->i_mapping, inode->i_size, get_block); + + /* Depending on whether the inode being truncated is a directory or not, + * we need to either call iomap_truncate_page or block_truncate_page. + */ + if (S_ISDIR(inode->i_mode)) + block_truncate_page(inode->i_mapping, inode->i_size, get_block); + else + iomap_truncate_page(inode, inode->i_size, NULL, + minix_iomap_ops_ver(inode), NULL, NULL); =20 n =3D block_to_path(inode, iblock, offsets); if (!n) diff --git a/fs/minix/minix.h b/fs/minix/minix.h index f1141d36e3d5..9035604c68ca 100644 --- a/fs/minix/minix.h +++ b/fs/minix/minix.h @@ -58,6 +58,8 @@ void minix_free_block(struct inode *inode, unsigned long = block); unsigned long minix_count_free_blocks(struct super_block *sb); int minix_getattr(struct mnt_idmap *, const struct path *, struct kstat *, u32, unsigned int); +int minix_setattr(struct mnt_idmap *idmap, struct dentry *dentry, + struct iattr *attr); int minix_prepare_chunk(struct folio *folio, loff_t pos, unsigned len); struct mapping_metadata_bhs *minix_get_metadata_bhs(struct inode *inode); =20 diff --git a/fs/minix/namei.c b/fs/minix/namei.c index 5525ba367ed7..52e115013abf 100644 --- a/fs/minix/namei.c +++ b/fs/minix/namei.c @@ -6,6 +6,7 @@ */ =20 #include "minix.h" +#include =20 static int add_nondir(struct dentry *dentry, struct inode *inode) { @@ -84,12 +85,16 @@ static int minix_symlink(struct mnt_idmap *idmap, struc= t inode *dir, return PTR_ERR(inode); =20 minix_set_inode(inode, 0); - err =3D page_symlink(inode, symname, i); + err =3D iomap_symlink_write(inode, symname, i, minix_iomap_ops_ver(inode)= , NULL, NULL); + if (unlikely(err)) { inode_dec_link_count(inode); iput(inode); return err; } + + i_size_write(inode, i - 1); + return add_nondir(dentry, inode); } =20 --=20 2.47.3