Re: [PATCH V12 09/12] famfs: Register secondary daxdevs by path (FAMFSIOC_DAXDEV_OPEN)

John Groves <[email protected]>
Newsgroups dev.linux.lists.nvdimm,dev.linux.lists.fuse-devel,org.kernel.vger.linux-cxl,org.kernel.vger.linux-doc,org.kernel.vger.linux-fsdevel,org.kernel.vger.linux-kernel
Message-ID <[email protected]>
On 26/08/05 10:29PM, Darrick J. Wong wrote:
> On Mon, Aug 03, 2026 at 02:29:47AM +0000, John Groves wrote:
> > From: John Groves <[email protected]>
> > 
> > Famfs file maps (fmaps) may reference multiple daxdevs. Before passing
> > an fmap that references a new daxdev, the daxdev is pushed into the
> > kernel via FAMFSIOC_DAXDEV_OPEN). This adds daxdevs to daxdev_table for
> > index-based resolution from famfs extents to daxdevs.
> > 
> > Signed-off-by: John Groves <[email protected]>
> > ---
> >  fs/famfs/famfs_file.c            | 74 ++++++++++++++++++++++++++++++++
> >  include/uapi/linux/famfs_ioctl.h | 24 +++++++++++
> >  2 files changed, 98 insertions(+)
> > 
> > diff --git a/fs/famfs/famfs_file.c b/fs/famfs/famfs_file.c
> > index e7f271ce6d03..e11a55ecf8d7 100644
> > --- a/fs/famfs/famfs_file.c
> > +++ b/fs/famfs/famfs_file.c
> > @@ -287,6 +287,76 @@ famfs_file_init_dax(struct file *file, void __user *arg)
> >  	return rc;
> >  }
> >  
> > +/**
> > + * famfs_daxdev_open() - FAMFSIOC_DAXDEV_OPEN ioctl handler
> > + * @file: any file in the famfs mount (the table is per-superblock)
> > + * @arg:  ptr to struct famfs_ioc_daxdev in user space
> > + *
> > + * Register a devdax device (identified by path) into the mount's daxdev table
> > + * at the caller-specified index, so files whose extents reference that index
> > + * can be mapped. The path is resolved by lookup_daxdev() - the same helper the
> > + * mount uses for the primary daxdev - so every slot is resolved identically.
> > + * Registering exposes raw device memory, so it requires CAP_SYS_RAWIO.
> > + */
> > +static int
> > +famfs_daxdev_open(struct file *file, void __user *arg)
> > +{
> > +	struct super_block *sb = file_inode(file)->i_sb;
> > +	struct famfs_fs_info *fsi = sb->s_fs_info;
> > +	struct famfs_ioc_daxdev dd;
> > +	dev_t devno;
> > +	char *path;
> > +	int rc;
> > +
> > +	if (!capable(CAP_SYS_RAWIO))
> > +		return -EPERM;
> > +
> > +	if (copy_from_user(&dd, arg, sizeof(dd)))
> > +		return -EFAULT;
> > +
> > +	/* @flags is reserved; reject non-zero so it stays available */
> > +	if (dd.flags)
> > +		return -EINVAL;
> > +
> > +	/*
> > +	 * If this daxdev index is already populated there is nothing to do.
> > +	 * The index is cluster-invariant, so a valid slot already names this
> > +	 * device; skip the path resolution entirely. install_daxdev() rechecks
> > +	 * ->valid under the write lock, so this is purely an optimization.
> > +	 */
> > +	scoped_guard(rwsem_read, &fsi->devlist_sem) {
> > +		if (dd.daxdev_index >= fsi->dax_devlist->nslots)
> > +			return -EINVAL;
> > +		if (fsi->dax_devlist->devlist[dd.daxdev_index].valid)
> > +			return 0;
> > +	}
> > +
> > +	if (dd.daxdev_path_len == 0 || dd.daxdev_path_len >= PATH_MAX)
> > +		return -EINVAL;
> > +
> > +	/* +1 so the terminating NUL is included within the bound */
> > +	path = strndup_user((const char __user *)(uintptr_t)dd.daxdev_path,
> > +			    dd.daxdev_path_len + 1);
> > +	if (IS_ERR(path))
> > +		return PTR_ERR(path);
> > +
> > +	rc = lookup_daxdev(path, &devno);
> > +	if (rc)
> > +		goto out;
> > +
> > +	/*
> > +	 * The daxdev table is allocated at mount time (for the slot-0 primary),
> > +	 * so it is always present here; no need to allocate it.
> > +	 */
> > +	rc = famfs_install_daxdev(fsi, sb, dd.daxdev_index, devno, path);
> > +	if (rc)
> > +		pr_debug("%s: failed to install daxdev index %llu (%s)\n",
> > +		       __func__, dd.daxdev_index, path);
> > +out:
> > +	kfree(path);
> > +	return rc;
> > +}
> > +
> >  /**
> >   * famfs_file_ioctl() - Top-level famfs file ioctl handler
> >   * @file: the file
> > @@ -308,6 +378,10 @@ famfs_file_ioctl(struct file *file, unsigned int cmd, unsigned long arg)
> >  		rc = 0;
> >  		break;
> >  
> > +	case FAMFSIOC_DAXDEV_OPEN:
> > +		rc = famfs_daxdev_open(file, (void __user *)arg);
> > +		break;
> > +
> >  	case FAMFSIOC_MAP_CREATE:
> >  		rc = famfs_file_init_dax(file, (void __user *)arg);
> >  		break;
> > diff --git a/include/uapi/linux/famfs_ioctl.h b/include/uapi/linux/famfs_ioctl.h
> > index b4eb373c1ade..751d8b033c2e 100644
> > --- a/include/uapi/linux/famfs_ioctl.h
> > +++ b/include/uapi/linux/famfs_ioctl.h
> > @@ -77,6 +77,29 @@ struct famfs_ioc_fmap_header {
> >  	__u64 reserved1;
> >  };
> >  
> > +/**
> > + * struct famfs_ioc_daxdev - register an additional backing daxdev by path
> > + * @daxdev_index:    the (cluster-invariant) index this daxdev occupies in
> > + *                   extent dev_index fields. Index 0 is the mount-time primary.
> > + * @daxdev_path:     userspace pointer to the devdax device path (e.g.
> > + *                   "/dev/dax0.0"); resolved in the kernel the same way the
> > + *                   mount primary is.
> > + * @daxdev_path_len: length of the path string, not counting the NUL.
> > + * @flags:           reserved; must be zero.
> > + *
> > + * Standalone famfs registers every daxdev by path: the mount primary comes in
> > + * as the mount device name, and slots 1..n come in here. (This deliberately
> > + * differs from fuse's fd-based FUSE_DEV_IOC_DAXDEV_OPEN; each side is uniform
> > + * within itself.) Passing the path by pointer keeps the struct fixed-size, so
> > + * longer paths never require an ABI change.
> > + */
> > +struct famfs_ioc_daxdev {
> > +	__u64 daxdev_index;
> > +	__u64 daxdev_path;
> > +	__u32 daxdev_path_len;
> 
> Can't we just pass an open fd to a dax device and have it use that
> rather than doing its own path operations?
> 
> --D

Could do, but then there would be two ways to "open" a daxdev, since the primary
is passed by path via the mount command or call.

If anybody thinks that's superior enough to do it 2 different ways, let me know.
Otherwise I'll leave it.

Thanks!
John

<snip>
lmpx.com only provides a reader for public news (NNTP) servers. It is not affiliated with the servers or forums shown here and is not responsible for the content of articles, which is written by their respective authors.