[<prev] [next>] [<thread-prev] [thread-next>] [day] [month] [year] [list]
Message-ID: <20260107153332.64727-14-john@groves.net>
Date: Wed, 7 Jan 2026 09:33:22 -0600
From: John Groves <John@...ves.net>
To: John Groves <John@...ves.net>,
Miklos Szeredi <miklos@...redi.hu>,
Dan Williams <dan.j.williams@...el.com>,
Bernd Schubert <bschubert@....com>,
Alison Schofield <alison.schofield@...el.com>
Cc: John Groves <jgroves@...ron.com>,
Jonathan Corbet <corbet@....net>,
Vishal Verma <vishal.l.verma@...el.com>,
Dave Jiang <dave.jiang@...el.com>,
Matthew Wilcox <willy@...radead.org>,
Jan Kara <jack@...e.cz>,
Alexander Viro <viro@...iv.linux.org.uk>,
David Hildenbrand <david@...nel.org>,
Christian Brauner <brauner@...nel.org>,
"Darrick J . Wong" <djwong@...nel.org>,
Randy Dunlap <rdunlap@...radead.org>,
Jeff Layton <jlayton@...nel.org>,
Amir Goldstein <amir73il@...il.com>,
Jonathan Cameron <Jonathan.Cameron@...wei.com>,
Stefan Hajnoczi <shajnocz@...hat.com>,
Joanne Koong <joannelkoong@...il.com>,
Josef Bacik <josef@...icpanda.com>,
Bagas Sanjaya <bagasdotme@...il.com>,
Chen Linxuan <chenlinxuan@...ontech.com>,
James Morse <james.morse@....com>,
Fuad Tabba <tabba@...gle.com>,
Sean Christopherson <seanjc@...gle.com>,
Shivank Garg <shivankg@....com>,
Ackerley Tng <ackerleytng@...gle.com>,
Gregory Price <gourry@...rry.net>,
Aravind Ramesh <arramesh@...ron.com>,
Ajay Joshi <ajayjoshi@...ron.com>,
venkataravis@...ron.com,
linux-doc@...r.kernel.org,
linux-kernel@...r.kernel.org,
nvdimm@...ts.linux.dev,
linux-cxl@...r.kernel.org,
linux-fsdevel@...r.kernel.org,
John Groves <john@...ves.net>
Subject: [PATCH V3 13/21] famfs_fuse: Famfs mount opt: -o shadow=<shadowpath>
The shadow path is a (usually in tmpfs) file system area used by the
famfs user space to communicate with the famfs fuse server. There is a
minor dilemma that the user space tools must be able to resolve from a
mount point path to a shadow path. Passing in the 'shadow=<path>'
argument at mount time causes the shadow path to be exposed via
/proc/mounts, Solving this dilemma. The shadow path is not otherwise
used in the kernel.
Signed-off-by: John Groves <john@...ves.net>
---
fs/fuse/fuse_i.h | 25 ++++++++++++++++++++++++-
fs/fuse/inode.c | 28 +++++++++++++++++++++++++++-
2 files changed, 51 insertions(+), 2 deletions(-)
diff --git a/fs/fuse/fuse_i.h b/fs/fuse/fuse_i.h
index ec2446099010..84d0ee2a501d 100644
--- a/fs/fuse/fuse_i.h
+++ b/fs/fuse/fuse_i.h
@@ -620,9 +620,11 @@ struct fuse_fs_context {
unsigned int blksize;
const char *subtype;
- /* DAX device, may be NULL */
+ /* DAX device for virtiofs, may be NULL */
struct dax_device *dax_dev;
+ const char *shadow; /* famfs - null if not famfs */
+
/* fuse_dev pointer to fill in, should contain NULL on entry */
void **fudptr;
};
@@ -998,6 +1000,18 @@ struct fuse_conn {
/* Request timeout (in jiffies). 0 = no timeout */
unsigned int req_timeout;
} timeout;
+
+ /*
+ * This is a workaround until fuse uses iomap for reads.
+ * For fuseblk servers, this represents the blocksize passed in at
+ * mount time and for regular fuse servers, this is equivalent to
+ * inode->i_blkbits.
+ */
+ u8 blkbits;
+
+#if IS_ENABLED(CONFIG_FUSE_FAMFS_DAX)
+ char *shadow;
+#endif
};
/*
@@ -1631,4 +1645,13 @@ extern void fuse_sysctl_unregister(void);
#define fuse_sysctl_unregister() do { } while (0)
#endif /* CONFIG_SYSCTL */
+/* famfs.c */
+
+static inline void famfs_teardown(struct fuse_conn *fc)
+{
+#if IS_ENABLED(CONFIG_FUSE_FAMFS_DAX)
+ kfree(fc->shadow);
+#endif
+}
+
#endif /* _FS_FUSE_I_H */
diff --git a/fs/fuse/inode.c b/fs/fuse/inode.c
index acabf92a11f8..2e0844aabbae 100644
--- a/fs/fuse/inode.c
+++ b/fs/fuse/inode.c
@@ -783,6 +783,9 @@ enum {
OPT_ALLOW_OTHER,
OPT_MAX_READ,
OPT_BLKSIZE,
+#if IS_ENABLED(CONFIG_FUSE_FAMFS_DAX)
+ OPT_SHADOW,
+#endif
OPT_ERR
};
@@ -797,6 +800,9 @@ static const struct fs_parameter_spec fuse_fs_parameters[] = {
fsparam_u32 ("max_read", OPT_MAX_READ),
fsparam_u32 ("blksize", OPT_BLKSIZE),
fsparam_string ("subtype", OPT_SUBTYPE),
+#if IS_ENABLED(CONFIG_FUSE_FAMFS_DAX)
+ fsparam_string("shadow", OPT_SHADOW),
+#endif
{}
};
@@ -892,6 +898,15 @@ static int fuse_parse_param(struct fs_context *fsc, struct fs_parameter *param)
ctx->blksize = result.uint_32;
break;
+#if IS_ENABLED(CONFIG_FUSE_FAMFS_DAX)
+ case OPT_SHADOW:
+ if (ctx->shadow)
+ return invalfc(fsc, "Multiple shadows specified");
+ ctx->shadow = param->string;
+ param->string = NULL;
+ break;
+#endif
+
default:
return -EINVAL;
}
@@ -905,6 +920,7 @@ static void fuse_free_fsc(struct fs_context *fsc)
if (ctx) {
kfree(ctx->subtype);
+ kfree(ctx->shadow);
kfree(ctx);
}
}
@@ -936,7 +952,10 @@ static int fuse_show_options(struct seq_file *m, struct dentry *root)
else if (fc->dax_mode == FUSE_DAX_INODE_USER)
seq_puts(m, ",dax=inode");
#endif
-
+#if IS_ENABLED(CONFIG_FUSE_FAMFS_DAX)
+ if (fc->shadow)
+ seq_printf(m, ",shadow=%s", fc->shadow);
+#endif
return 0;
}
@@ -1041,6 +1060,8 @@ void fuse_conn_put(struct fuse_conn *fc)
WARN_ON(atomic_read(&bucket->count) != 1);
kfree(bucket);
}
+ famfs_teardown(fc);
+
if (IS_ENABLED(CONFIG_FUSE_PASSTHROUGH))
fuse_backing_files_free(fc);
call_rcu(&fc->rcu, delayed_release);
@@ -1916,6 +1937,11 @@ int fuse_fill_super_common(struct super_block *sb, struct fuse_fs_context *ctx)
*ctx->fudptr = fud;
wake_up_all(&fuse_dev_waitq);
}
+
+#if IS_ENABLED(CONFIG_FUSE_FAMFS_DAX)
+ fc->shadow = kstrdup(ctx->shadow, GFP_KERNEL);
+#endif
+
mutex_unlock(&fuse_mutex);
return 0;
--
2.49.0
Powered by blists - more mailing lists