From: Jonathan Cameron <jonathan.cameron@huawei.com>
To: John Groves <John@Groves.net>
Cc: Miklos Szeredi <miklos@szeredi.hu>,
Dan Williams <dan.j.williams@intel.com>,
Bernd Schubert <bschubert@ddn.com>,
"Alison Schofield" <alison.schofield@intel.com>,
John Groves <jgroves@micron.com>,
Jonathan Corbet <corbet@lwn.net>,
Vishal Verma <vishal.l.verma@intel.com>,
Dave Jiang <dave.jiang@intel.com>,
Matthew Wilcox <willy@infradead.org>, Jan Kara <jack@suse.cz>,
Alexander Viro <viro@zeniv.linux.org.uk>,
"David Hildenbrand" <david@kernel.org>,
Christian Brauner <brauner@kernel.org>,
"Darrick J . Wong" <djwong@kernel.org>,
Randy Dunlap <rdunlap@infradead.org>,
Jeff Layton <jlayton@kernel.org>,
Amir Goldstein <amir73il@gmail.com>,
Stefan Hajnoczi <shajnocz@redhat.com>,
Joanne Koong <joannelkoong@gmail.com>,
Josef Bacik <josef@toxicpanda.com>,
Bagas Sanjaya <bagasdotme@gmail.com>,
Chen Linxuan <chenlinxuan@uniontech.com>,
"James Morse" <james.morse@arm.com>,
Fuad Tabba <tabba@google.com>,
"Sean Christopherson" <seanjc@google.com>,
Shivank Garg <shivankg@amd.com>,
Ackerley Tng <ackerleytng@google.com>,
Gregory Price <gourry@gourry.net>,
Aravind Ramesh <arramesh@micron.com>,
Ajay Joshi <ajayjoshi@micron.com>, <venkataravis@micron.com>,
<linux-doc@vger.kernel.org>, <linux-kernel@vger.kernel.org>,
<nvdimm@lists.linux.dev>, <linux-cxl@vger.kernel.org>,
<linux-fsdevel@vger.kernel.org>
Subject: Re: [PATCH V3 15/21] famfs_fuse: Create files with famfs fmaps
Date: Thu, 8 Jan 2026 13:14:00 +0000 [thread overview]
Message-ID: <20260108131400.000017f5@huawei.com> (raw)
In-Reply-To: <20260107153332.64727-16-john@groves.net>
On Wed, 7 Jan 2026 09:33:24 -0600
John Groves <John@Groves.net> wrote:
> On completion of GET_FMAP message/response, setup the full famfs
> metadata such that it's possible to handle read/write/mmap directly to
> dax. Note that the devdax_iomap plumbing is not in yet...
>
> * Add famfs_kfmap.h: in-memory structures for resolving famfs file maps
> (fmaps) to dax.
> * famfs.c: allocate, initialize and free fmaps
> * inode.c: only allow famfs mode if the fuse server has CAP_SYS_RAWIO
> * Update MAINTAINERS for the new files.
>
> Signed-off-by: John Groves <john@groves.net>
> diff --git a/fs/fuse/famfs.c b/fs/fuse/famfs.c
> index 0f7e3f00e1e7..2aabd1d589fd 100644
> --- a/fs/fuse/famfs.c
> +++ b/fs/fuse/famfs.c
> @@ -17,9 +17,355 @@
> #include <linux/namei.h>
> #include <linux/string.h>
>
> +#include "famfs_kfmap.h"
> #include "fuse_i.h"
>
>
> +/***************************************************************************/
Who doesn't like stars? Why have them here?
> +
> +void
> +__famfs_meta_free(void *famfs_meta)
Maybe a local convention, but if not one line.
Same for other cases.
> +{
> + struct famfs_file_meta *fmap = famfs_meta;
> +
> + if (!fmap)
> + return;
> +
> + if (fmap) {
Well that's never going to fail given 2 lines above.
> + switch (fmap->fm_extent_type) {
> + case SIMPLE_DAX_EXTENT:
> + kfree(fmap->se);
> + break;
> + case INTERLEAVED_EXTENT:
> + if (fmap->ie)
> + kfree(fmap->ie->ie_strips);
> +
> + kfree(fmap->ie);
> + break;
> + default:
> + pr_err("%s: invalid fmap type\n", __func__);
> + break;
> + }
> + }
> + kfree(fmap);
> +}
> +/**
> + * famfs_fuse_meta_alloc() - Allocate famfs file metadata
> + * @metap: Pointer to an mcache_map_meta pointer
> + * @ext_count: The number of extents needed
run kernel-doc over the file as that's not the parameters...
> + *
> + * Returns: 0=success
> + * -errno=failure
> + */
> +static int
> +famfs_fuse_meta_alloc(
> + void *fmap_buf,
> + size_t fmap_buf_size,
> + struct famfs_file_meta **metap)
> +{
> + struct famfs_file_meta *meta = NULL;
> + struct fuse_famfs_fmap_header *fmh;
> + size_t extent_total = 0;
> + size_t next_offset = 0;
> + int errs = 0;
> + int i, j;
> + int rc;
> +
> + fmh = (struct fuse_famfs_fmap_header *)fmap_buf;
void * so cast not needed and hence just assign it at the
declaration.
> +
> + /* Move past fmh in fmap_buf */
> + next_offset += sizeof(*fmh);
> + if (next_offset > fmap_buf_size) {
> + pr_err("%s:%d: fmap_buf underflow offset/size %ld/%ld\n",
> + __func__, __LINE__, next_offset, fmap_buf_size);
> + return -EINVAL;
> + }
> +
> + if (fmh->nextents < 1) {
> + pr_err("%s: nextents %d < 1\n", __func__, fmh->nextents);
> + return -EINVAL;
> + }
> +
> + if (fmh->nextents > FUSE_FAMFS_MAX_EXTENTS) {
> + pr_err("%s: nextents %d > max (%d) 1\n",
> + __func__, fmh->nextents, FUSE_FAMFS_MAX_EXTENTS);
> + return -E2BIG;
> + }
> +
> + meta = kzalloc(sizeof(*meta), GFP_KERNEL);
Maybe sprinkle some __free magic on this then you can return in
all the goto error_out places which to me makes this more readable.
> + if (!meta)
> + return -ENOMEM;
> +
> + meta->error = false;
> + meta->file_type = fmh->file_type;
> + meta->file_size = fmh->file_size;
> + meta->fm_extent_type = fmh->ext_type;
> +
> + switch (fmh->ext_type) {
> + case FUSE_FAMFS_EXT_SIMPLE: {
> + struct fuse_famfs_simple_ext *se_in;
> +
> + se_in = (struct fuse_famfs_simple_ext *)(fmap_buf + next_offset);
void * so no need for cast. Though you could keep the cast but apply it to
fmh + 1 to take advantage of that type.
> +
> + /* Move past simple extents */
> + next_offset += fmh->nextents * sizeof(*se_in);
> + if (next_offset > fmap_buf_size) {
> + pr_err("%s:%d: fmap_buf underflow offset/size %ld/%ld\n",
> + __func__, __LINE__, next_offset, fmap_buf_size);
> + rc = -EINVAL;
> + goto errout;
> + }
> +
> + meta->fm_nextents = fmh->nextents;
> +
> + meta->se = kcalloc(meta->fm_nextents, sizeof(*(meta->se)),
> + GFP_KERNEL);
> + if (!meta->se) {
> + rc = -ENOMEM;
> + goto errout;
> + }
> +
> + if ((meta->fm_nextents > FUSE_FAMFS_MAX_EXTENTS) ||
> + (meta->fm_nextents < 1)) {
> + rc = -EINVAL;
> + goto errout;
> + }
> +
> + for (i = 0; i < fmh->nextents; i++) {
> + meta->se[i].dev_index = se_in[i].se_devindex;
> + meta->se[i].ext_offset = se_in[i].se_offset;
> + meta->se[i].ext_len = se_in[i].se_len;
> +
> + /* Record bitmap of referenced daxdev indices */
> + meta->dev_bitmap |= (1 << meta->se[i].dev_index);
> +
> + errs += famfs_check_ext_alignment(&meta->se[i]);
> +
> + extent_total += meta->se[i].ext_len;
> + }
> + break;
> + }
> +
> + case FUSE_FAMFS_EXT_INTERLEAVE: {
> + s64 size_remainder = meta->file_size;
> + struct fuse_famfs_iext *ie_in;
> + int niext = fmh->nextents;
> +
> + meta->fm_niext = niext;
> +
> + /* Allocate interleaved extent */
> + meta->ie = kcalloc(niext, sizeof(*(meta->ie)), GFP_KERNEL);
> + if (!meta->ie) {
> + rc = -ENOMEM;
> + goto errout;
> + }
> +
> + /*
> + * Each interleaved extent has a simple extent list of strips.
> + * Outer loop is over separate interleaved extents
> + */
> + for (i = 0; i < niext; i++) {
> + u64 nstrips;
> + struct fuse_famfs_simple_ext *sie_in;
> +
> + /* ie_in = one interleaved extent in fmap_buf */
> + ie_in = (struct fuse_famfs_iext *)
> + (fmap_buf + next_offset);
void * so no cast needed.
> +
> + /* Move past one interleaved extent header in fmap_buf */
> + next_offset += sizeof(*ie_in);
> + if (next_offset > fmap_buf_size) {
> + pr_err("%s:%d: fmap_buf underflow offset/size %ld/%ld\n",
> + __func__, __LINE__, next_offset,
> + fmap_buf_size);
> + rc = -EINVAL;
> + goto errout;
> + }
> +
> + nstrips = ie_in->ie_nstrips;
> + meta->ie[i].fie_chunk_size = ie_in->ie_chunk_size;
> + meta->ie[i].fie_nstrips = ie_in->ie_nstrips;
> + meta->ie[i].fie_nbytes = ie_in->ie_nbytes;
> +
> + if (!meta->ie[i].fie_nbytes) {
> + pr_err("%s: zero-length interleave!\n",
> + __func__);
> + rc = -EINVAL;
> + goto errout;
> + }
> +
> + /* sie_in = the strip extents in fmap_buf */
> + sie_in = (struct fuse_famfs_simple_ext *)
> + (fmap_buf + next_offset);
no cast needed.
> +
> + /* Move past strip extents in fmap_buf */
> + next_offset += nstrips * sizeof(*sie_in);
> + if (next_offset > fmap_buf_size) {
> + pr_err("%s:%d: fmap_buf underflow offset/size %ld/%ld\n",
> + __func__, __LINE__, next_offset,
> + fmap_buf_size);
> + rc = -EINVAL;
> + goto errout;
> + }
> +
> + if ((nstrips > FUSE_FAMFS_MAX_STRIPS) || (nstrips < 1)) {
> + pr_err("%s: invalid nstrips=%lld (max=%d)\n",
> + __func__, nstrips,
> + FUSE_FAMFS_MAX_STRIPS);
> + errs++;
> + }
> +
> + /* Allocate strip extent array */
> + meta->ie[i].ie_strips = kcalloc(ie_in->ie_nstrips,
> + sizeof(meta->ie[i].ie_strips[0]),
> + GFP_KERNEL);
Align all lines after 1st one to same point.
...
> +
> +/**
> + * famfs_file_init_dax() - init famfs dax file metadata
> + *
> + * @fm: fuse_mount
> + * @inode: the inode
> + * @fmap_buf: fmap response message
> + * @fmap_size: Size of the fmap message
> + *
> + * Initialize famfs metadata for a file, based on the contents of the GET_FMAP
> + * response
> + *
> + * Return: 0=success
> + * -errno=failure
> + */
> +int
> +famfs_file_init_dax(
> + struct fuse_mount *fm,
> + struct inode *inode,
> + void *fmap_buf,
> + size_t fmap_size)
> +{
> + struct fuse_inode *fi = get_fuse_inode(inode);
> + struct famfs_file_meta *meta = NULL;
> + int rc = 0;
Always set before use.
> +
> + if (fi->famfs_meta) {
> + pr_notice("%s: i_no=%ld fmap_size=%ld ALREADY INITIALIZED\n",
> + __func__,
> + inode->i_ino, fmap_size);
> + return 0;
> + }
> +
> + rc = famfs_fuse_meta_alloc(fmap_buf, fmap_size, &meta);
> + if (rc)
> + goto errout;
> +
> + /* Publish the famfs metadata on fi->famfs_meta */
> + inode_lock(inode);
> + if (fi->famfs_meta) {
> + rc = -EEXIST; /* file already has famfs metadata */
> + } else {
> + if (famfs_meta_set(fi, meta) != NULL) {
> + pr_debug("%s: file already had metadata\n", __func__);
> + __famfs_meta_free(meta);
> + /* rc is 0 - the file is valid */
> + goto unlock_out;
> + }
> + i_size_write(inode, meta->file_size);
> + inode->i_flags |= S_DAX;
> + }
> + unlock_out:
> + inode_unlock(inode);
> +
> +errout:
> + if (rc)
> + __famfs_meta_free(meta);
For readability I'd split he good and bad exit paths even it unlock
needs to happen in two places.
> +
> + return rc;
> +}
> +
> diff --git a/fs/fuse/famfs_kfmap.h b/fs/fuse/famfs_kfmap.h
> new file mode 100644
> index 000000000000..058645cb10a1
> --- /dev/null
> +++ b/fs/fuse/famfs_kfmap.h
> @@ -0,0 +1,67 @@
> +/* SPDX-License-Identifier: GPL-2.0 */
> +/*
> + * famfs - dax file system for shared fabric-attached memory
> + *
> + * Copyright 2023-2025 Micron Technology, Inc.
> + */
> +#ifndef FAMFS_KFMAP_H
> +#define FAMFS_KFMAP_H
> +
> +/*
> + * The structures below are the in-memory metadata format for famfs files.
> + * Metadata retrieved via the GET_FMAP response is converted to this format
> + * for use in resolving file mapping faults.
bonus space after in
> + *
> + * The GET_FMAP response contains the same information, but in a more
> + * message-and-versioning-friendly format. Those structs can be found in the
> + * famfs section of include/uapi/linux/fuse.h (aka fuse_kernel.h in libfuse)
> + */
> +/*
> + * Each famfs dax file has this hanging from its fuse_inode->famfs_meta
> + */
> +struct famfs_file_meta {
> + bool error;
> + enum famfs_file_type file_type;
> + size_t file_size;
> + enum famfs_extent_type fm_extent_type;
> + u64 dev_bitmap; /* bitmap of referenced daxdevs by index */
> + union { /* This will make code a bit more readable */
Not sure what the comment is for. I'd drop it.
> + struct {
> + size_t fm_nextents;
> + struct famfs_meta_simple_ext *se;
> + };
> + struct {
> + size_t fm_niext;
> + struct famfs_meta_interleaved_ext *ie;
> + };
> + };
> +};
> +
> +#endif /* FAMFS_KFMAP_H */
next prev parent reply other threads:[~2026-01-08 13:14 UTC|newest]
Thread overview: 77+ messages / expand[flat|nested] mbox.gz Atom feed top
2026-01-07 15:32 [PATCH BUNDLE] famfs: Fabric-Attached Memory File System John Groves
2026-01-07 15:33 ` [PATCH V3 00/21] famfs: port into fuse John Groves
2026-01-07 15:33 ` [PATCH V3 01/21] dax: move dax_pgoff_to_phys from [drivers/dax/] device.c to bus.c John Groves
2026-01-08 10:43 ` Jonathan Cameron
2026-01-08 13:25 ` John Groves
2026-01-08 15:20 ` Jonathan Cameron
2026-01-07 15:33 ` [PATCH V3 02/21] dax: add fsdev.c driver for fs-dax on character dax John Groves
2026-01-08 11:31 ` Jonathan Cameron
2026-01-08 14:32 ` John Groves
2026-01-08 15:12 ` John Groves
2026-01-08 21:15 ` John Groves
2026-01-08 23:25 ` Gregory Price
2026-01-07 15:33 ` [PATCH V3 03/21] dax: Save the kva from memremap John Groves
2026-01-08 11:32 ` Jonathan Cameron
2026-01-08 15:15 ` John Groves
2026-01-07 15:33 ` [PATCH V3 04/21] dax: Add dax_operations for use by fs-dax on fsdev dax John Groves
2026-01-08 11:50 ` Jonathan Cameron
2026-01-08 15:59 ` John Groves
2026-01-08 16:10 ` Jonathan Cameron
2026-01-08 17:55 ` kernel test robot
2026-01-07 15:33 ` [PATCH V3 05/21] dax: Add dax_set_ops() for setting dax_operations at bind time John Groves
2026-01-08 12:06 ` Jonathan Cameron
2026-01-08 16:20 ` John Groves
2026-01-07 15:33 ` [PATCH V3 06/21] dax: Add fs_dax_get() func to prepare dax for fs-dax usage John Groves
2026-01-08 12:27 ` Jonathan Cameron
2026-01-08 16:45 ` John Groves
2026-01-07 15:33 ` [PATCH V3 07/21] dax: prevent driver unbind while filesystem holds device John Groves
2026-01-08 12:34 ` Jonathan Cameron
2026-01-08 18:08 ` John Groves
2026-01-12 18:55 ` John Groves
2026-01-07 15:33 ` [PATCH V3 08/21] dax: export dax_dev_get() John Groves
2026-01-07 15:33 ` [PATCH V3 09/21] famfs_fuse: magic.h: Add famfs magic numbers John Groves
2026-01-07 15:33 ` [PATCH V3 10/21] famfs_fuse: Kconfig John Groves
2026-01-08 12:36 ` Jonathan Cameron
2026-01-12 16:46 ` John Groves
2026-01-07 15:33 ` [PATCH V3 11/21] famfs_fuse: Update macro s/FUSE_IS_DAX/FUSE_IS_VIRTIO_DAX/ John Groves
2026-01-09 18:16 ` Joanne Koong
2026-01-09 22:15 ` [PATCH V3 11/21] famfs_fuse: Update macro s/FUSE_IS_DAX/FUSE_IS_VIRTIO_DAX John Groves
2026-01-07 15:33 ` [PATCH V3 12/21] famfs_fuse: Basic fuse kernel ABI enablement for famfs John Groves
2026-01-09 18:29 ` Joanne Koong
2026-01-09 22:58 ` John Groves
2026-01-07 15:33 ` [PATCH V3 13/21] famfs_fuse: Famfs mount opt: -o shadow=<shadowpath> John Groves
2026-01-09 19:22 ` Joanne Koong
2026-01-10 0:38 ` John Groves
2026-01-11 18:20 ` John Groves
2026-01-07 15:33 ` [PATCH V3 14/21] famfs_fuse: Plumb the GET_FMAP message/response John Groves
2026-01-08 12:49 ` Jonathan Cameron
2026-01-09 2:12 ` John Groves
2026-01-07 15:33 ` [PATCH V3 15/21] famfs_fuse: Create files with famfs fmaps John Groves
2026-01-07 21:30 ` John Groves
2026-01-08 13:14 ` Jonathan Cameron [this message]
2026-01-09 14:30 ` John Groves
2026-01-08 19:27 ` kernel test robot
2026-01-07 15:33 ` [PATCH V3 16/21] famfs_fuse: GET_DAXDEV message and daxdev_table John Groves
2026-01-08 14:45 ` Jonathan Cameron
2026-01-08 21:04 ` kernel test robot
2026-01-07 15:33 ` [PATCH V3 17/21] famfs_fuse: Plumb dax iomap and fuse read/write/mmap John Groves
2026-01-08 15:13 ` Jonathan Cameron
2026-01-09 17:44 ` John Groves
2026-01-07 15:33 ` [PATCH V3 18/21] famfs_fuse: Add holder_operations for dax notify_failure() John Groves
2026-01-08 15:17 ` Jonathan Cameron
2026-01-09 21:00 ` John Groves
2026-01-07 15:33 ` [PATCH V3 19/21] famfs_fuse: Add DAX address_space_operations with noop_dirty_folio John Groves
2026-01-07 15:33 ` [PATCH V3 20/21] famfs_fuse: Add famfs fmap metadata documentation John Groves
2026-01-07 15:33 ` [PATCH V3 21/21] famfs_fuse: Add documentation John Groves
2026-01-08 15:27 ` Jonathan Cameron
2026-01-11 18:53 ` John Groves
2026-01-07 15:34 ` [PATCH V3 0/4] libfuse: add basic famfs support to libfuse John Groves
2026-01-07 15:34 ` [PATCH V3 1/4] fuse_kernel.h: bring up to baseline 6.19 John Groves
2026-01-07 15:34 ` [PATCH V3 2/4] fuse_kernel.h: add famfs DAX fmap protocol definitions John Groves
2026-01-07 15:34 ` [PATCH V3 3/4] fuse: add API to set kernel mount options John Groves
2026-01-07 15:34 ` [PATCH V3 4/4] fuse: add famfs DAX fmap support John Groves
2026-01-08 15:31 ` Jonathan Cameron
2026-01-11 18:24 ` John Groves
2026-01-07 15:34 ` [PATCH 0/2] ndctl: Add daxctl support for the new "famfs" mode of devdax John Groves
2026-01-07 15:34 ` [PATCH 1/2] daxctl: Add support for famfs mode John Groves
2026-01-07 15:34 ` [PATCH 2/2] Add test/daxctl-famfs.sh to test famfs mode transitions: John Groves
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=20260108131400.000017f5@huawei.com \
--to=jonathan.cameron@huawei.com \
--cc=John@Groves.net \
--cc=ackerleytng@google.com \
--cc=ajayjoshi@micron.com \
--cc=alison.schofield@intel.com \
--cc=amir73il@gmail.com \
--cc=arramesh@micron.com \
--cc=bagasdotme@gmail.com \
--cc=brauner@kernel.org \
--cc=bschubert@ddn.com \
--cc=chenlinxuan@uniontech.com \
--cc=corbet@lwn.net \
--cc=dan.j.williams@intel.com \
--cc=dave.jiang@intel.com \
--cc=david@kernel.org \
--cc=djwong@kernel.org \
--cc=gourry@gourry.net \
--cc=jack@suse.cz \
--cc=james.morse@arm.com \
--cc=jgroves@micron.com \
--cc=jlayton@kernel.org \
--cc=joannelkoong@gmail.com \
--cc=josef@toxicpanda.com \
--cc=linux-cxl@vger.kernel.org \
--cc=linux-doc@vger.kernel.org \
--cc=linux-fsdevel@vger.kernel.org \
--cc=linux-kernel@vger.kernel.org \
--cc=miklos@szeredi.hu \
--cc=nvdimm@lists.linux.dev \
--cc=rdunlap@infradead.org \
--cc=seanjc@google.com \
--cc=shajnocz@redhat.com \
--cc=shivankg@amd.com \
--cc=tabba@google.com \
--cc=venkataravis@micron.com \
--cc=viro@zeniv.linux.org.uk \
--cc=vishal.l.verma@intel.com \
--cc=willy@infradead.org \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.