From ab5df475c5c7e9e0f3268fe94a6280e71d34c1db Mon Sep 17 00:00:00 2001 From: Csaba Henk Date: Tue, 14 Jul 2009 17:10:38 -0700 Subject: upgrade FUSE protocol to 7.12 and add support for older versions of the protocol --- xlators/mount/fuse/src/fuse-bridge.c | 65 +++++++++++++++++++++++++--------- xlators/mount/fuse/src/fuse_kernel.h | 68 ++++++++++++++++++++++++++++++++++-- 2 files changed, 115 insertions(+), 18 deletions(-) diff --git a/xlators/mount/fuse/src/fuse-bridge.c b/xlators/mount/fuse/src/fuse-bridge.c index 2700d6ed05d..8e1b26258c6 100644 --- a/xlators/mount/fuse/src/fuse-bridge.c +++ b/xlators/mount/fuse/src/fuse-bridge.c @@ -59,7 +59,7 @@ #define ZR_DIRECT_IO_OPT "direct-io-mode" #define ZR_STRICT_VOLFILE_CHECK "strict-volfile-check" -#define FUSE_711_OP_HIGH (FUSE_POLL + 1) +#define FUSE_712_OP_HIGH (FUSE_POLL + 1) #define OFFSET_MAX 0x7fffffffffffffffLL #define GLUSTERFS_XATTR_LEN_MAX 65536 @@ -69,6 +69,7 @@ typedef void (fuse_handler_t) (xlator_t *this, fuse_in_header_t *finh, struct fuse_private { int fd; + uint32_t proto_minor; char *volfile; size_t volfile_size; char *mount_point; @@ -525,7 +526,10 @@ fuse_entry_cbk (call_frame_t *frame, void *cookie, xlator_t *this, feo.attr_valid_nsec = calc_timeout_nsec (priv->attribute_timeout); - send_fuse_obj (this, finh, &feo); + priv->proto_minor >= 9 ? + send_fuse_obj (this, finh, &feo) : + send_fuse_data (this, finh, &feo, + FUSE_COMPAT_ENTRY_OUT_SIZE); } else { /* Refurbish the entry_out as attr_out. Too hacky?... */ fao = (struct fuse_attr_out *) @@ -537,7 +541,10 @@ fuse_entry_cbk (call_frame_t *frame, void *cookie, xlator_t *this, fao->attr_valid_nsec = calc_timeout_nsec (priv->attribute_timeout); - send_fuse_obj (this, finh, fao); + priv->proto_minor >= 9 ? + send_fuse_obj (this, finh, fao) : + send_fuse_data (this, finh, fao, + FUSE_COMPAT_ATTR_OUT_SIZE); } } else { gf_log ("glusterfs-fuse", @@ -1194,8 +1201,13 @@ fuse_mknod (xlator_t *this, fuse_in_header_t *finh, void *msg) struct fuse_mknod_in *fmi = msg; char *name = (char *)(fmi + 1); - fuse_state_t *state = NULL; - int32_t ret = -1; + fuse_state_t *state = NULL; + fuse_private_t *priv = NULL; + int32_t ret = -1; + + priv = this->private; + if (priv->proto_minor < 12) + name = (char *)msg + FUSE_COMPAT_MKNOD_IN_SIZE; GET_STATE (this, finh, state); ret = fuse_loc_fill (&state->loc, state, 0, finh->nodeid, name); @@ -1542,7 +1554,9 @@ fuse_create_cbk (call_frame_t *frame, void *cookie, xlator_t *this, fouh.error = 0; iov_out[0].iov_base = &fouh; iov_out[1].iov_base = &feo; - iov_out[1].iov_len = sizeof (feo); + iov_out[1].iov_len = priv->proto_minor >= 9 ? + sizeof (feo) : + FUSE_COMPAT_ENTRY_OUT_SIZE; iov_out[2].iov_base = &foo; iov_out[2].iov_len = sizeof (foo); if (send_fuse_iov (this, finh, iov_out, 3) == ENOENT) { @@ -1571,15 +1585,20 @@ out: static void fuse_create (xlator_t *this, fuse_in_header_t *finh, void *msg) { - struct fuse_open_in *foi = msg; - char *name = (char *)(foi + 1); + struct fuse_create_in *fci = msg; + char *name = (char *)(fci + 1); + fuse_private_t *priv = NULL; fuse_state_t *state = NULL; fd_t *fd = NULL; int32_t ret = -1; + priv = this->private; + if (priv->proto_minor < 12) + name = (char *)((struct fuse_open_in *)msg + 1); + GET_STATE (this, finh, state); - state->flags = foi->flags; + state->flags = fci->flags; ret = fuse_loc_fill (&state->loc, state, 0, finh->nodeid, name); if (ret < 0) { @@ -1602,7 +1621,7 @@ fuse_create (xlator_t *this, fuse_in_header_t *finh, void *msg) state->loc.path); FUSE_FOP (state, fuse_create_cbk, GF_FOP_CREATE, - create, &state->loc, state->flags, foi->mode, fd); + create, &state->loc, state->flags, fci->mode, fd); return; } @@ -1757,12 +1776,17 @@ fuse_write (xlator_t *this, fuse_in_header_t *finh, void *msg) struct fuse_write_in *fwi = msg; char *buf = (char *)(fwi + 1); + fuse_private_t *priv = NULL; fuse_state_t *state = NULL; struct iovec vector; fd_t *fd = NULL; struct iobref *iobref = NULL; struct iobuf *iobuf = NULL; + priv = this->private; + if (priv->proto_minor < 9) + buf = (char *)msg + FUSE_COMPAT_WRITE_IN_SIZE; + GET_STATE (this, finh, state); state->size = fwi->size; state->off = fwi->offset; @@ -2034,9 +2058,11 @@ fuse_statfs_cbk (call_frame_t *frame, void *cookie, xlator_t *this, { fuse_state_t *state = NULL; fuse_in_header_t *finh = NULL; + fuse_private_t *priv = NULL; struct fuse_statfs_out fso = {{0, }, }; state = frame->root->state; + priv = this->private; finh = state->finh; /* Filesystems (like ZFS on solaris) reports @@ -2075,8 +2101,9 @@ fuse_statfs_cbk (call_frame_t *frame, void *cookie, xlator_t *this, fso.st.ffree = buf->f_ffree; fso.st.namelen = buf->f_namemax; - send_fuse_obj (this, finh, &fso); - + priv->proto_minor >= 4 ? + send_fuse_obj (this, finh, &fso) : + send_fuse_data (this, finh, &fso, FUSE_COMPAT_STATFS_SIZE); } else { gf_log ("glusterfs-fuse", GF_LOG_WARNING, "%"PRIu64": ERR => -1 (%s)", frame->root->unique, @@ -2634,8 +2661,7 @@ fuse_init (xlator_t *this, fuse_in_header_t *finh, void *msg) goto out; } - if (fini->major != FUSE_KERNEL_VERSION || - fini->minor < 9) { + if (fini->major != FUSE_KERNEL_VERSION) { gf_log ("glusterfs-fuse", GF_LOG_ERROR, "unsupported FUSE protocol version %d.%d", fini->major, fini->minor); @@ -2643,6 +2669,7 @@ fuse_init (xlator_t *this, fuse_in_header_t *finh, void *msg) close (priv->fd); goto out; } + priv->proto_minor = fini->minor; fino.major = FUSE_KERNEL_VERSION; fino.minor = FUSE_KERNEL_MINOR_VERSION; @@ -2684,7 +2711,7 @@ fuse_discard (xlator_t *this, fuse_in_header_t *finh, void *msg) FREE (finh); } -static fuse_handler_t *fuse_ops[FUSE_711_OP_HIGH]; +static fuse_handler_t *fuse_ops[FUSE_712_OP_HIGH]; int fuse_root_lookup_cbk (call_frame_t *frame, void *cookie, xlator_t *this, @@ -3048,6 +3075,12 @@ init (xlator_t *this_xl) } ret = mount (fsname, priv->mount_point, "fuse.glusterfs", 0, mount_param); + if (ret == -1 && errno == ENODEV) + /* fs subtype support was added by 79c0b2df aka + v2.6.21-3159-g79c0b2d. Probably we have an + older kernel ... */ + ret = mount (fsname, priv->mount_point, "fuse", 0, + mount_param); if (ret == -1) { gf_log ("glusterfs-fuse", GF_LOG_ERROR, "mount failed (%s)", strerror (errno)); @@ -3061,7 +3094,7 @@ init (xlator_t *this_xl) priv->first_call = 2; - for (i = 0; i < FUSE_711_OP_HIGH; i++) + for (i = 0; i < FUSE_712_OP_HIGH; i++) fuse_ops[i] = fuse_enosys; fuse_ops[FUSE_INIT] = fuse_init; fuse_ops[FUSE_DESTROY] = fuse_discard; diff --git a/xlators/mount/fuse/src/fuse_kernel.h b/xlators/mount/fuse/src/fuse_kernel.h index df558e394ff..dac35d8b9b1 100644 --- a/xlators/mount/fuse/src/fuse_kernel.h +++ b/xlators/mount/fuse/src/fuse_kernel.h @@ -51,6 +51,11 @@ * - add IOCTL message * - add unsolicited notification support * - add POLL message and NOTIFY_POLL notification + * + * 7.12 + * - add umask flag to input argument of open, mknod and mkdir + * - add notification messages for invalidation of inodes and + * directory entries */ #ifndef _LINUX_FUSE_H @@ -58,6 +63,7 @@ #include #define __u64 uint64_t +#define __s64 int64_t #define __u32 uint32_t #define __s32 int32_t @@ -65,7 +71,7 @@ #define FUSE_KERNEL_VERSION 7 /** Minor version number of this interface */ -#define FUSE_KERNEL_MINOR_VERSION 11 +#define FUSE_KERNEL_MINOR_VERSION 12 /** The node ID of the root inode */ #define FUSE_ROOT_ID 1 @@ -141,6 +147,7 @@ struct fuse_file_lock { * INIT request/reply flags * * FUSE_EXPORT_SUPPORT: filesystem handles lookups of "." and ".." + * FUSE_DONT_MASK: don't apply umask to file mode on create operations */ #define FUSE_ASYNC_READ (1 << 0) #define FUSE_POSIX_LOCKS (1 << 1) @@ -148,6 +155,14 @@ struct fuse_file_lock { #define FUSE_ATOMIC_O_TRUNC (1 << 3) #define FUSE_EXPORT_SUPPORT (1 << 4) #define FUSE_BIG_WRITES (1 << 5) +#define FUSE_DONT_MASK (1 << 6) + +/** + * CUSE INIT request/reply flags + * + * CUSE_UNRESTRICTED_IOCTL: use unrestricted ioctl + */ +#define CUSE_UNRESTRICTED_IOCTL (1 << 0) /** * Release flags @@ -239,10 +254,15 @@ enum fuse_opcode { FUSE_DESTROY = 38, FUSE_IOCTL = 39, FUSE_POLL = 40, + + /* CUSE specific operations */ + CUSE_INIT = 4096, }; enum fuse_notify_code { FUSE_NOTIFY_POLL = 1, + FUSE_NOTIFY_INVAL_INODE = 2, + FUSE_NOTIFY_INVAL_ENTRY = 3, FUSE_NOTIFY_CODE_MAX, }; @@ -281,14 +301,18 @@ struct fuse_attr_out { struct fuse_attr attr; }; +#define FUSE_COMPAT_MKNOD_IN_SIZE 8 + struct fuse_mknod_in { __u32 mode; __u32 rdev; + __u32 umask; + __u32 padding; }; struct fuse_mkdir_in { __u32 mode; - __u32 padding; + __u32 umask; }; struct fuse_rename_in { @@ -319,8 +343,15 @@ struct fuse_setattr_in { }; struct fuse_open_in { + __u32 flags; + __u32 unused; +}; + +struct fuse_create_in { __u32 flags; __u32 mode; + __u32 umask; + __u32 padding; }; struct fuse_open_out { @@ -430,6 +461,27 @@ struct fuse_init_out { __u32 max_write; }; +#define CUSE_INIT_INFO_MAX 4096 + +struct cuse_init_in { + __u32 major; + __u32 minor; + __u32 unused; + __u32 flags; +}; + +struct cuse_init_out { + __u32 major; + __u32 minor; + __u32 unused; + __u32 flags; + __u32 max_read; + __u32 max_write; + __u32 dev_major; /* chardev major */ + __u32 dev_minor; /* chardev minor */ + __u32 spare[10]; +}; + struct fuse_interrupt_in { __u64 unique; }; @@ -506,4 +558,16 @@ struct fuse_dirent { #define FUSE_DIRENT_SIZE(d) \ FUSE_DIRENT_ALIGN(FUSE_NAME_OFFSET + (d)->namelen) +struct fuse_notify_inval_inode_out { + __u64 ino; + __s64 off; + __s64 len; +}; + +struct fuse_notify_inval_entry_out { + __u64 parent; + __u32 namelen; + __u32 padding; +}; + #endif /* _LINUX_FUSE_H */ -- cgit