@@ -635,8 +635,8 @@ struct btrfs_ioctl_send_args {
__u64 reserved[4]; /* in */
} __attribute__((packed));
/*
- * Size of structure depends on pointer width, was not caught. Kernel handles
- * pointer width differences transparently
+ * Size of structure depends on pointer width, was not caught in the early
+ * days. Kernel handles pointer width differences transparently.
*/
BUILD_ASSERT(sizeof(__u64 *) == 8
? sizeof(struct btrfs_ioctl_send_args) == 72
@@ -644,6 +644,28 @@ BUILD_ASSERT(sizeof(__u64 *) == 8
? sizeof(struct btrfs_ioctl_send_args) == 68
: 0));
+/*
+ * Different pointer width leads to structure size change. Kernel should accept
+ * both ioctl values (derived from the structures) for backward compatibility.
+ * Size of this structure is same on 32bit and 64bit though.
+ *
+ * NOTE: do not use in your code, this is for testing only
+ */
+struct btrfs_ioctl_send_args_64 {
+ __s64 send_fd; /* in */
+ __u64 clone_sources_count; /* in */
+ union {
+ __u64 __user *clone_sources; /* in */
+ __u64 __clone_sources_alignment;
+ };
+ __u64 parent_root; /* in */
+ __u64 flags; /* in */
+ __u64 reserved[4]; /* in */
+} __attribute__((packed));
+BUILD_ASSERT(sizeof(struct btrfs_ioctl_send_args_64) == 72);
+
+#define BTRFS_IOC_SEND_64_COMPAT_DEFINED 1
+
/* Error codes as returned by the kernel */
enum btrfs_err_code {
notused,
@@ -761,6 +783,11 @@ static inline char *btrfs_err_str(enum btrfs_err_code err_code)
struct btrfs_ioctl_received_subvol_args_32)
#endif
+#ifdef BTRFS_IOC_SEND_64_COMPAT_DEFINED
+#define BTRFS_IOC_SEND_64 _IOW(BTRFS_IOCTL_MAGIC, 38, \
+ struct btrfs_ioctl_send_args_64)
+#endif
+
#define BTRFS_IOC_SEND _IOW(BTRFS_IOCTL_MAGIC, 38, struct btrfs_ioctl_send_args)
#define BTRFS_IOC_DEVICES_READY _IOR(BTRFS_IOCTL_MAGIC, 39, \
struct btrfs_ioctl_vol_args)
The ioctl value of SEND will be different on 32bit userspace and 64bit kernel due to different pointer type width, that unfortunatelly made it into the structure definition. To maintain backward compatibility, we must do it in the 64bit->32bit way, because we don't have the kernel side workardound like SET_RECEIVED_SUBVOL has. Changing value of SEND would then break existing users of the raw ioctl. The compatibility structure and ioctl should not be used, exists for documentation, and testing. Signed-off-by: David Sterba <dsterba@suse.com> --- ioctl.h | 31 +++++++++++++++++++++++++++++-- 1 file changed, 29 insertions(+), 2 deletions(-)