Jeffle Xu
2021-Aug-17 02:23 UTC
[virtiofsd PATCH v4 3/4] virtiofsd: support per-file DAX negotiation in FUSE_INIT
In FUSE_INIT negotiating phase, server/client should advertise if it
supports per-file DAX.
Once advertising support for per-file DAX feature, virtiofsd should
support storing FS_DAX_FL flag persistently passed by
FS_IOC_SETFLAGS/FS_IOC_FSSETXATTR ioctl, and set FUSE_ATTR_DAX in
FUSE_LOOKUP accordingly if the file is capable of per-file DAX.
Currently only ext4/xfs since linux kernel v5.8 support storing
FS_DAX_FL flag persistently, and thus advertise support for per-file
DAX feature only when the backend fs type is ext4 and xfs.
Signed-off-by: Jeffle Xu <jefflexu at linux.alibaba.com>
---
tools/virtiofsd/fuse_common.h | 5 +++++
tools/virtiofsd/fuse_lowlevel.c | 6 ++++++
tools/virtiofsd/passthrough_ll.c | 29 +++++++++++++++++++++++++++++
3 files changed, 40 insertions(+)
diff --git a/tools/virtiofsd/fuse_common.h b/tools/virtiofsd/fuse_common.h
index 8a75729be9..ee6fc64c23 100644
--- a/tools/virtiofsd/fuse_common.h
+++ b/tools/virtiofsd/fuse_common.h
@@ -372,6 +372,11 @@ struct fuse_file_info {
*/
#define FUSE_CAP_HANDLE_KILLPRIV_V2 (1 << 28)
+/**
+ * Indicates support for per-file DAX.
+ */
+#define FUSE_CAP_PERFILE_DAX (1 << 29)
+
/**
* Ioctl flags
*
diff --git a/tools/virtiofsd/fuse_lowlevel.c b/tools/virtiofsd/fuse_lowlevel.c
index 50fc5c8d5a..04a4f17423 100644
--- a/tools/virtiofsd/fuse_lowlevel.c
+++ b/tools/virtiofsd/fuse_lowlevel.c
@@ -2065,6 +2065,9 @@ static void do_init(fuse_req_t req, fuse_ino_t nodeid,
if (arg->flags & FUSE_HANDLE_KILLPRIV_V2) {
se->conn.capable |= FUSE_CAP_HANDLE_KILLPRIV_V2;
}
+ if (arg->flags & FUSE_PERFILE_DAX) {
+ se->conn.capable |= FUSE_CAP_PERFILE_DAX;
+ }
#ifdef HAVE_SPLICE
#ifdef HAVE_VMSPLICE
se->conn.capable |= FUSE_CAP_SPLICE_WRITE | FUSE_CAP_SPLICE_MOVE;
@@ -2180,6 +2183,9 @@ static void do_init(fuse_req_t req, fuse_ino_t nodeid,
if (se->conn.want & FUSE_CAP_POSIX_ACL) {
outarg.flags |= FUSE_POSIX_ACL;
}
+ if (se->op.ioctl && (se->conn.want &
FUSE_CAP_PERFILE_DAX)) {
+ outarg.flags |= FUSE_PERFILE_DAX;
+ }
outarg.max_readahead = se->conn.max_readahead;
outarg.max_write = se->conn.max_write;
if (se->conn.max_background >= (1 << 16)) {
diff --git a/tools/virtiofsd/passthrough_ll.c b/tools/virtiofsd/passthrough_ll.c
index e170b17adb..5b6228210f 100644
--- a/tools/virtiofsd/passthrough_ll.c
+++ b/tools/virtiofsd/passthrough_ll.c
@@ -53,8 +53,10 @@
#include <sys/syscall.h>
#include <sys/wait.h>
#include <sys/xattr.h>
+#include <sys/vfs.h>
#include <syslog.h>
#include <linux/fs.h>
+#include <linux/magic.h>
#include "qemu/cutils.h"
#include "passthrough_helpers.h"
@@ -136,6 +138,13 @@ enum {
SANDBOX_CHROOT,
};
+/* capability of storing DAX flag persistently */
+enum {
+ DAX_CAP_NONE, /* not supported */
+ DAX_CAP_FLAGS, /* stored in flags (FS_IOC_GETFLAGS/FS_IOC_SETFLAGS) */
+ DAX_CAP_XATTR, /* stored in xflags (FS_IOC_FSGETXATTR/FS_IOC_FSSETXATTR) */
+};
+
typedef struct xattr_map_entry {
char *key;
char *prepend;
@@ -161,6 +170,7 @@ struct lo_data {
int readdirplus_clear;
int allow_direct_io;
int announce_submounts;
+ int perfile_dax_cap; /* capability of backend fs */
bool use_statx;
struct lo_inode root;
GHashTable *inodes; /* protected by lo->mutex */
@@ -703,6 +713,10 @@ static void lo_init(void *userdata, struct fuse_conn_info
*conn)
conn->want &= ~FUSE_CAP_HANDLE_KILLPRIV_V2;
lo->killpriv_v2 = 0;
}
+
+ if (conn->capable & FUSE_CAP_PERFILE_DAX &&
lo->perfile_dax_cap ) {
+ conn->want |= FUSE_CAP_PERFILE_DAX;
+ }
}
static void lo_getattr(fuse_req_t req, fuse_ino_t ino,
@@ -3800,6 +3814,7 @@ static void setup_root(struct lo_data *lo, struct lo_inode
*root)
int fd, res;
struct stat stat;
uint64_t mnt_id;
+ struct statfs statfs;
fd = open("/", O_PATH);
if (fd == -1) {
@@ -3826,6 +3841,20 @@ static void setup_root(struct lo_data *lo, struct
lo_inode *root)
root->posix_locks = g_hash_table_new_full(
g_direct_hash, g_direct_equal, NULL, posix_locks_value_destroy);
}
+
+ /*
+ * Currently only ext4/xfs since linux kernel v5.8 support storing
+ * FS_DAX_FL flag persistently. Ext4 accesses this flag through
+ * FS_IOC_G[S]ETFLAGS ioctl, while xfs accesses this flag through
+ * FS_IOC_FSG[S]ETXATTR ioctl.
+ */
+ res = fstatfs(fd, &statfs);
+ if (!res) {
+ if (statfs.f_type == EXT4_SUPER_MAGIC)
+ lo->perfile_dax_cap = DAX_CAP_FLAGS;
+ else if (statfs.f_type == XFS_SUPER_MAGIC)
+ lo->perfile_dax_cap = DAX_CAP_XATTR;
+ }
}
static guint lo_key_hash(gconstpointer key)
--
2.27.0
Dr. David Alan Gilbert
2021-Aug-17 17:15 UTC
[Virtio-fs] [virtiofsd PATCH v4 3/4] virtiofsd: support per-file DAX negotiation in FUSE_INIT
* Jeffle Xu (jefflexu at linux.alibaba.com) wrote:> In FUSE_INIT negotiating phase, server/client should advertise if it > supports per-file DAX. > > Once advertising support for per-file DAX feature, virtiofsd should > support storing FS_DAX_FL flag persistently passed by > FS_IOC_SETFLAGS/FS_IOC_FSSETXATTR ioctl, and set FUSE_ATTR_DAX in > FUSE_LOOKUP accordingly if the file is capable of per-file DAX. > > Currently only ext4/xfs since linux kernel v5.8 support storing > FS_DAX_FL flag persistently, and thus advertise support for per-file > DAX feature only when the backend fs type is ext4 and xfs.I'm a little worried about the meaning of the flags we're storing and the fact we're storing them in the normal host DAX flags. Doesn't this mean that we're using a single host flag to mean: a) It can be mapped as DAX on the host if it was a real DAX device b) We can map it as DAX inside the guest with virtiofs? what happens when we're using usernamespaces for the guest? Dave> Signed-off-by: Jeffle Xu <jefflexu at linux.alibaba.com> > --- > tools/virtiofsd/fuse_common.h | 5 +++++ > tools/virtiofsd/fuse_lowlevel.c | 6 ++++++ > tools/virtiofsd/passthrough_ll.c | 29 +++++++++++++++++++++++++++++ > 3 files changed, 40 insertions(+) > > diff --git a/tools/virtiofsd/fuse_common.h b/tools/virtiofsd/fuse_common.h > index 8a75729be9..ee6fc64c23 100644 > --- a/tools/virtiofsd/fuse_common.h > +++ b/tools/virtiofsd/fuse_common.h > @@ -372,6 +372,11 @@ struct fuse_file_info { > */ > #define FUSE_CAP_HANDLE_KILLPRIV_V2 (1 << 28) > > +/** > + * Indicates support for per-file DAX. > + */ > +#define FUSE_CAP_PERFILE_DAX (1 << 29) > + > /** > * Ioctl flags > * > diff --git a/tools/virtiofsd/fuse_lowlevel.c b/tools/virtiofsd/fuse_lowlevel.c > index 50fc5c8d5a..04a4f17423 100644 > --- a/tools/virtiofsd/fuse_lowlevel.c > +++ b/tools/virtiofsd/fuse_lowlevel.c > @@ -2065,6 +2065,9 @@ static void do_init(fuse_req_t req, fuse_ino_t nodeid, > if (arg->flags & FUSE_HANDLE_KILLPRIV_V2) { > se->conn.capable |= FUSE_CAP_HANDLE_KILLPRIV_V2; > } > + if (arg->flags & FUSE_PERFILE_DAX) { > + se->conn.capable |= FUSE_CAP_PERFILE_DAX; > + } > #ifdef HAVE_SPLICE > #ifdef HAVE_VMSPLICE > se->conn.capable |= FUSE_CAP_SPLICE_WRITE | FUSE_CAP_SPLICE_MOVE; > @@ -2180,6 +2183,9 @@ static void do_init(fuse_req_t req, fuse_ino_t nodeid, > if (se->conn.want & FUSE_CAP_POSIX_ACL) { > outarg.flags |= FUSE_POSIX_ACL; > } > + if (se->op.ioctl && (se->conn.want & FUSE_CAP_PERFILE_DAX)) { > + outarg.flags |= FUSE_PERFILE_DAX; > + } > outarg.max_readahead = se->conn.max_readahead; > outarg.max_write = se->conn.max_write; > if (se->conn.max_background >= (1 << 16)) { > diff --git a/tools/virtiofsd/passthrough_ll.c b/tools/virtiofsd/passthrough_ll.c > index e170b17adb..5b6228210f 100644 > --- a/tools/virtiofsd/passthrough_ll.c > +++ b/tools/virtiofsd/passthrough_ll.c > @@ -53,8 +53,10 @@ > #include <sys/syscall.h> > #include <sys/wait.h> > #include <sys/xattr.h> > +#include <sys/vfs.h> > #include <syslog.h> > #include <linux/fs.h> > +#include <linux/magic.h> > > #include "qemu/cutils.h" > #include "passthrough_helpers.h" > @@ -136,6 +138,13 @@ enum { > SANDBOX_CHROOT, > }; > > +/* capability of storing DAX flag persistently */ > +enum { > + DAX_CAP_NONE, /* not supported */ > + DAX_CAP_FLAGS, /* stored in flags (FS_IOC_GETFLAGS/FS_IOC_SETFLAGS) */ > + DAX_CAP_XATTR, /* stored in xflags (FS_IOC_FSGETXATTR/FS_IOC_FSSETXATTR) */ > +}; > + > typedef struct xattr_map_entry { > char *key; > char *prepend; > @@ -161,6 +170,7 @@ struct lo_data { > int readdirplus_clear; > int allow_direct_io; > int announce_submounts; > + int perfile_dax_cap; /* capability of backend fs */ > bool use_statx; > struct lo_inode root; > GHashTable *inodes; /* protected by lo->mutex */ > @@ -703,6 +713,10 @@ static void lo_init(void *userdata, struct fuse_conn_info *conn) > conn->want &= ~FUSE_CAP_HANDLE_KILLPRIV_V2; > lo->killpriv_v2 = 0; > } > + > + if (conn->capable & FUSE_CAP_PERFILE_DAX && lo->perfile_dax_cap ) { > + conn->want |= FUSE_CAP_PERFILE_DAX; > + } > } > > static void lo_getattr(fuse_req_t req, fuse_ino_t ino, > @@ -3800,6 +3814,7 @@ static void setup_root(struct lo_data *lo, struct lo_inode *root) > int fd, res; > struct stat stat; > uint64_t mnt_id; > + struct statfs statfs; > > fd = open("/", O_PATH); > if (fd == -1) { > @@ -3826,6 +3841,20 @@ static void setup_root(struct lo_data *lo, struct lo_inode *root) > root->posix_locks = g_hash_table_new_full( > g_direct_hash, g_direct_equal, NULL, posix_locks_value_destroy); > } > + > + /* > + * Currently only ext4/xfs since linux kernel v5.8 support storing > + * FS_DAX_FL flag persistently. Ext4 accesses this flag through > + * FS_IOC_G[S]ETFLAGS ioctl, while xfs accesses this flag through > + * FS_IOC_FSG[S]ETXATTR ioctl. > + */ > + res = fstatfs(fd, &statfs); > + if (!res) { > + if (statfs.f_type == EXT4_SUPER_MAGIC) > + lo->perfile_dax_cap = DAX_CAP_FLAGS; > + else if (statfs.f_type == XFS_SUPER_MAGIC) > + lo->perfile_dax_cap = DAX_CAP_XATTR; > + } > } > > static guint lo_key_hash(gconstpointer key) > -- > 2.27.0 > > _______________________________________________ > Virtio-fs mailing list > Virtio-fs at redhat.com > https://listman.redhat.com/mailman/listinfo/virtio-fs >-- Dr. David Alan Gilbert / dgilbert at redhat.com / Manchester, UK