51
#define FUSE_MAX_READ_BYTES (MIN(BDRV_REQUEST_MAX_BYTES, 1 * 1024 * 1024))
52
#define FUSE_MAX_WRITE_BYTES (64 * 1024)
53
54
-/*
55
- * fuse_init_in structure before 7.36. We don't need the flags2 field added
56
- * there, so we can work with the smaller older structure to stay compatible
57
- * with older kernels.
58
- */
59
-struct fuse_init_in_compat {
60
- uint32_t major;
61
- uint32_t minor;
62
- uint32_t max_readahead;
63
- uint32_t flags;
64
-};
65
-
54
typedef struct FuseRequestInHeader {
55
struct fuse_in_header common;
56
/* All supported requests */
57
union {
70
- struct fuse_init_in_compat init;
58
+ /*
59
+ * When using_old_fuse_init_in() is true, then the smaller older struct
60
+ * is used by the kernel. The flags2 member and other new members must
61
+ * be treated as absent then.
62
+ */
63
+ struct fuse_init_in init;
64
struct fuse_open_in open;
65
struct fuse_setattr_in setattr;
66
struct fuse_read_in read;
622
return new_fd;
623
}
624
625
+/**
626
+ * Check whether the smaller older fuse_init_in structure from before protocol
627
+ * version 7.36 is used. The flags2 member and other new members must be treated
628
+ * as absent then.
629
+ */
630
+static bool using_old_fuse_init_in(const struct fuse_init_in *in)
631
+{
632
+ return in->major < 7 || (in->major == 7 && in->minor < 36);
633
+}
634
+
635
/**
636
* Try to read a single request from the FUSE FD.
637
* Takes a FuseQueue pointer in `opaque`.
696
goto no_request;
697
}
698
699
+ /*
700
+ * If the request is of type FUSE_INIT, need to check the version to
701
+ * actually determine the length of the fuse_init_in structure used by the
702
+ * kernel. In protocol version 7.36, the structure was extended.
703
+ */
704
+ if (in_hdr->common.opcode == FUSE_INIT) {
705
+ /* Length of the fuse_init_in structure before 7.36. */
706
+ size_t old_init_hdr_len = 16;
707
+
708
+ /*
709
+ * Expect at least the size of the smaller older structure to ensure the
710
+ * version can be checked.
711
+ */
712
+ if (unlikely(ret < sizeof(in_hdr->common) + old_init_hdr_len)) {
713
+ error_report("FUSE_INIT request truncated, read only %zi bytes",
714
+ ret);
715
+ fuse_write_err(fuse_fd, &in_hdr->common, -EINVAL);
716
+ goto no_request;
717
+ }
718
+
719
+ if (using_old_fuse_init_in(&in_hdr->init)) {
720
+ op_hdr_len = old_init_hdr_len;
721
+ }
722
+ }
723
+
724
if (unlikely(ret < sizeof(in_hdr->common) + op_hdr_len)) {
725
error_report("FUSE request truncated, expected %zu bytes, read %zi "
726
"bytes",
854
*/
855
static ssize_t coroutine_fn GRAPH_RDLOCK
856
fuse_co_init(FuseExport *exp, struct fuse_init_out *out,
829
- const struct fuse_init_in_compat *in)
857
+ const struct fuse_init_in *in)
858
{
859
const uint32_t supported_flags = FUSE_ASYNC_READ | FUSE_ASYNC_DIO;
860