diff options
Diffstat (limited to 'xlators/mount/fuse/src/fuse-bridge.h')
| -rw-r--r-- | xlators/mount/fuse/src/fuse-bridge.h | 337 |
1 files changed, 290 insertions, 47 deletions
diff --git a/xlators/mount/fuse/src/fuse-bridge.h b/xlators/mount/fuse/src/fuse-bridge.h index f20e47272..34794b6ea 100644 --- a/xlators/mount/fuse/src/fuse-bridge.h +++ b/xlators/mount/fuse/src/fuse-bridge.h @@ -1,22 +1,12 @@ /* - Copyright (c) 2006-2010 Gluster, Inc. <http://www.gluster.com> + Copyright (c) 2006-2012 Red Hat, Inc. <http://www.redhat.com> This file is part of GlusterFS. - GlusterFS is free software; you can redistribute it and/or modify - it under the terms of the GNU Affero General Public License as published - by the Free Software Foundation; either version 3 of the License, - or (at your option) any later version. - - GlusterFS is distributed in the hope that it will be useful, but - WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - Affero General Public License for more details. - - You should have received a copy of the GNU Affero General Public License - along with this program. If not, see - <http://www.gnu.org/licenses/>. + This file is licensed to you under your choice of the GNU Lesser + General Public License, version 3 or any later version (LGPLv3 or + later), or the GNU General Public License, version 2 (GPLv2), in all + cases as published by the Free Software Foundation. */ - #ifndef _GF_FUSE_BRIDGE_H_ #define _GF_FUSE_BRIDGE_H_ @@ -54,12 +44,11 @@ #include "list.h" #include "dict.h" +#include "syncop.h" +#include "gidcache.h" -/* TODO: when supporting posix acl, remove this definition */ -#define DISABLE_POSIX_ACL - -#ifdef GF_LINUX_HOST_OS -#define FUSE_OP_HIGH (FUSE_POLL + 1) +#if defined(GF_LINUX_HOST_OS) || defined(__NetBSD__) +#define FUSE_OP_HIGH (FUSE_READDIRPLUS + 1) #endif #ifdef GF_DARWIN_HOST_OS #define FUSE_OP_HIGH (FUSE_DESTROY + 1) @@ -87,11 +76,12 @@ struct fuse_private { size_t *msg0_len_p; double entry_timeout; + double negative_timeout; double attribute_timeout; pthread_cond_t sync_cond; pthread_mutex_t sync_mutex; - char child_up; + char event_recvd; char init_recvd; @@ -107,17 +97,58 @@ struct fuse_private { pid_t client_pid; gf_boolean_t client_pid_set; + unsigned uid_map_root; + gf_boolean_t acl; + gf_boolean_t selinux; + gf_boolean_t read_only; + int32_t fopen_keep_cache; + int32_t gid_cache_timeout; + gf_boolean_t enable_ino32; + fdtable_t *fdtable; + gid_cache_t gid_cache; + char *fuse_mountopts; + + /* For fuse-reverse-validation */ + int revchan_in; + int revchan_out; + gf_boolean_t reverse_fuse_thread_started; + + /* For communicating with separate mount thread. */ + int status_pipe[2]; + + /* for fuse queue length and congestion threshold */ + int background_qlen; + int congestion_threshold; + + /* for using fuse-kernel readdirp*/ + gf_boolean_t use_readdirp; }; typedef struct fuse_private fuse_private_t; +struct fuse_graph_switch_args { + xlator_t *this; + xlator_t *old_subvol; + xlator_t *new_subvol; +}; +typedef struct fuse_graph_switch_args fuse_graph_switch_args_t; + +#define INVAL_BUF_SIZE (sizeof (struct fuse_out_header) + \ + max (sizeof (struct fuse_notify_inval_inode_out), \ + sizeof (struct fuse_notify_inval_entry_out) + \ + NAME_MAX + 1)) + +#define FUSE_EVENT_HISTORY_SIZE 1024 + #define _FH_TO_FD(fh) ((fd_t *)(uintptr_t)(fh)) #define FH_TO_FD(fh) ((_FH_TO_FD (fh))?(fd_ref (_FH_TO_FD (fh))):((fd_t *) 0)) #define FUSE_FOP(state, ret, op_num, fop, args ...) \ do { \ - call_frame_t *frame = NULL; \ - xlator_t *xl = NULL; \ + call_frame_t *frame = NULL; \ + xlator_t *xl = NULL; \ + int32_t op_ret = 0, op_errno = 0; \ + fuse_resolve_t *resolve = NULL; \ \ frame = get_call_frame_for_req (state); \ if (!frame) { \ @@ -127,7 +158,7 @@ typedef struct fuse_private fuse_private_t; * better than trying to go on with a NULL \ * frame ... \ */ \ - gf_log ("glusterfs-fuse", \ + gf_log_callingfn ("glusterfs-fuse", \ GF_LOG_ERROR, \ "FUSE message" \ " unique %"PRIu64" opcode %d:" \ @@ -135,29 +166,86 @@ typedef struct fuse_private fuse_private_t; state->finh->unique, \ state->finh->opcode); \ free_fuse_state (state); \ - return; \ + /* ideally, need to 'return', but let the */ \ + /* calling function take care of it */ \ + break; \ } \ \ frame->root->state = state; \ frame->root->op = op_num; \ frame->op = op_num; \ \ - xl = fuse_state_subvol (state); \ + if ( state->resolve_now ) { \ + resolve = state->resolve_now; \ + } else { \ + resolve = &(state->resolve); \ + } \ + \ + xl = state->active_subvol; \ if (!xl) { \ - gf_log ("glusterfs-fuse", GF_LOG_ERROR, \ - "xl is NULL"); \ - send_fuse_err (state->this, state->finh, ENOENT); \ + gf_log_callingfn ("glusterfs-fuse", GF_LOG_ERROR, \ + "xl is NULL"); \ + op_errno = ENOENT; \ + op_ret = -1; \ + } else if (resolve->op_ret < 0) { \ + op_errno = resolve->op_errno; \ + op_ret = -1; \ + if (op_num == GF_FOP_LOOKUP) { \ + gf_log ("glusterfs-fuse", \ + (op_errno == ENOENT ? GF_LOG_TRACE \ + : GF_LOG_WARNING), \ + "%"PRIu64": %s() %s => -1 (%s)", \ + frame->root->unique, \ + gf_fop_list[frame->root->op], \ + resolve->resolve_loc.path, \ + strerror (op_errno)); \ + } else { \ + gf_log ("glusterfs-fuse", \ + GF_LOG_WARNING, \ + "%"PRIu64": %s() inode " \ + "migration of %s failed (%s)", \ + frame->root->unique, \ + gf_fop_list[frame->root->op], \ + resolve->resolve_loc.path, \ + strerror (op_errno)); \ + } \ + } else if (state->resolve2.op_ret < 0) { \ + op_errno = state->resolve2.op_errno; \ + op_ret = -1; \ + gf_log ("glusterfs-fuse", \ + GF_LOG_WARNING, \ + "%"PRIu64": %s() inode " \ + "migration of %s failed (%s)", \ + frame->root->unique, \ + gf_fop_list[frame->root->op], \ + state->resolve2.resolve_loc.path, \ + strerror (op_errno)); \ + } \ + \ + if (op_ret < 0) { \ + send_fuse_err (state->this, state->finh, op_errno); \ free_fuse_state (state); \ STACK_DESTROY (frame->root); \ } else { \ + if (state->this->history) \ + gf_log_eh ("%"PRIu64", %s, path: (%s), gfid: " \ + "(%s)", frame->root->unique, \ + gf_fop_list[frame->root->op], \ + state->loc.path, \ + (state->fd == NULL)? \ + uuid_utoa (state->loc.gfid): \ + uuid_utoa (state->fd->inode->gfid));\ STACK_WIND (frame, ret, xl, xl->fops->fop, args); \ } \ + \ } while (0) #define FUSE_FOP_COOKIE(state, xl, ret, cky, op_num, fop, args ...) \ do { \ - call_frame_t *frame = NULL; \ + call_frame_t *frame = NULL; \ + xlator_t *xl = NULL; \ + int32_t op_ret = 0, op_errno = 0; \ \ frame = get_call_frame_for_req (state); \ if (!frame) { \ @@ -175,7 +263,62 @@ typedef struct fuse_private fuse_private_t; frame->root->state = state; \ frame->root->op = op_num; \ frame->op = op_num; \ - STACK_WIND_COOKIE (frame, ret, cky, xl, xl->fops->fop, args); \ + \ + xl = state->active_subvol; \ + if (!xl) { \ + gf_log_callingfn ("glusterfs-fuse", GF_LOG_ERROR, \ + "xl is NULL"); \ + op_errno = ENOENT; \ + op_ret = -1; \ + } else if (state->resolve.op_ret < 0) { \ + op_errno = state->resolve.op_errno; \ + op_ret = -1; \ + if (op_num == GF_FOP_LOOKUP) { \ + gf_log ("glusterfs-fuse", \ + (op_errno == ENOENT ? GF_LOG_TRACE \ + : GF_LOG_WARNING), \ + "%"PRIu64": %s() %s => -1 (%s)", \ + frame->root->unique, \ + gf_fop_list[frame->root->op], \ + state->resolve.resolve_loc.path, \ + strerror (op_errno)); \ + } else { \ + gf_log ("glusterfs-fuse", \ + GF_LOG_WARNING, \ + "%"PRIu64": %s() inode " \ + "migration of %s failed (%s)", \ + frame->root->unique, \ + gf_fop_list[frame->root->op], \ + state->resolve.resolve_loc.path, \ + strerror (op_errno)); \ + } \ + } else if (state->resolve2.op_ret < 0) { \ + op_errno = state->resolve2.op_errno; \ + op_ret = -1; \ + gf_log ("glusterfs-fuse", \ + GF_LOG_WARNING, \ + "%"PRIu64": %s() inode " \ + "migration of %s failed (%s)", \ + frame->root->unique, \ + gf_fop_list[frame->root->op], \ + state->resolve2.resolve_loc.path, \ + strerror (op_errno)); \ + } \ + \ + if (op_ret < 0) { \ + send_fuse_err (state->this, state->finh, op_errno); \ + free_fuse_state (state); \ + STACK_DESTROY (frame->root); \ + } else { \ + if (xl->history) \ + gf_log_eh ("%"PRIu64", %s, path: (%s), gfid: " \ + "(%s)", frame->root->unique, \ + gf_fop_list[frame->root->op], \ + state->loc.path, \ + uuid_utoa (state->loc.gfid)); \ + STACK_WIND_COOKIE (frame, ret, cky, xl, xl->fops->fop, \ + args); \ + } \ } while (0) #define GF_SELECT_LOG_LEVEL(_errno) \ @@ -199,6 +342,90 @@ typedef struct fuse_private fuse_private_t; } \ } while (0) +#define FUSE_ENTRY_CREATE(this, priv, finh, state, fci, op) \ + do { \ + if (priv->proto_minor >= 12) \ + state->mode &= ~fci->umask; \ + if (priv->proto_minor >= 12 && priv->acl) { \ + state->xdata = dict_new (); \ + if (!state->xdata) { \ + gf_log ("glusterfs-fuse", \ + GF_LOG_WARNING, \ + "%s failed to allocate " \ + "a param dictionary", op); \ + send_fuse_err (this, finh, ENOMEM); \ + free_fuse_state (state); \ + return; \ + } \ + state->umask = fci->umask; \ + \ +/* TODO: remove this after 3.4.0 release. keeping it for the \ + sake of backward compatibility with old (3.3.[01]) \ + releases till then. */ \ + ret = dict_set_int16 (state->xdata, "umask", \ + fci->umask); \ + if (ret < 0) { \ + gf_log ("glusterfs-fuse", \ + GF_LOG_WARNING, \ + "%s Failed adding umask"\ + " to request", op); \ + dict_destroy (state->xdata); \ + send_fuse_err (this, finh, ENOMEM); \ + free_fuse_state (state); \ + return; \ + } \ + ret = dict_set_int16 (state->xdata, "mode", \ + fci->mode); \ + if (ret < 0) { \ + gf_log ("glusterfs-fuse", \ + GF_LOG_WARNING, \ + "%s Failed adding mode " \ + "to request", op); \ + dict_destroy (state->xdata); \ + send_fuse_err (this, finh, ENOMEM); \ + free_fuse_state (state); \ + return; \ + } \ + } \ + } while (0) + +#define fuse_log_eh_fop(this, state, frame, op_ret, op_errno) \ + do { \ + if (this->history) { \ + if (state->fd) \ + gf_log_eh ("op_ret: %d, op_errno: %d, " \ + "%"PRIu64", %s () => %p, gfid: %s", \ + op_ret, op_errno, \ + frame->root->unique, \ + gf_fop_list[frame->root->op], \ + state->fd, \ + uuid_utoa (state->fd->inode->gfid)); \ + else \ + gf_log_eh ("op_ret: %d, op_errno: %d, " \ + "%"PRIu64", %s () => %s, gfid: %s", \ + op_ret, op_errno, \ + frame->root->unique, \ + gf_fop_list[frame->root->op], \ + state->loc.path, \ + uuid_utoa (state->loc.gfid)); \ + } \ + } while(0) + +#define fuse_log_eh(this, args...) \ + do { \ + if (this->history) \ + gf_log_eh(args); \ + } while (0) + +static inline xlator_t * +fuse_active_subvol (xlator_t *fuse) +{ + fuse_private_t *priv = NULL; + + priv = fuse->private; + + return priv->active_subvol; +} typedef enum { @@ -209,35 +436,27 @@ typedef enum { RESOLVE_EXACT } fuse_resolve_type_t; -struct fuse_resolve_comp { - char *basename; - ino_t ino; - uint64_t gen; - inode_t *inode; -}; typedef struct { fuse_resolve_type_t type; - ino_t ino; - uint64_t gen; - ino_t par; fd_t *fd; char *path; char *bname; u_char gfid[16]; + inode_t *hint; u_char pargfid[16]; + inode_t *parhint; char *resolved; int op_ret; int op_errno; - loc_t deep_loc; - struct fuse_resolve_comp *components; - int comp_count; + loc_t resolve_loc; } fuse_resolve_t; typedef struct { void *pool; xlator_t *this; + xlator_t *active_subvol; inode_table_t *itable; loc_t loc; loc_t loc2; @@ -247,7 +466,8 @@ typedef struct { size_t size; unsigned long nlookup; fd_t *fd; - dict_t *dict; + dict_t *xattr; + dict_t *xdata; char *name; char is_revalidate; gf_boolean_t truncate_needed; @@ -268,13 +488,22 @@ typedef struct { int mask; dev_t rdev; mode_t mode; + mode_t umask; struct iatt attr; struct gf_flock lk_lock; struct iovec vector; uuid_t gfid; + uint32_t io_flags; + int32_t fd_no; } fuse_state_t; +typedef struct { + uint32_t open_flags; + char migration_failed; + fd_t *activefd; +} fuse_fd_ctx_t; + typedef void (*fuse_resume_fn_t) (fuse_state_t *state); GF_MUST_CHECK int32_t @@ -283,12 +512,26 @@ fuse_loc_fill (loc_t *loc, fuse_state_t *state, ino_t ino, call_frame_t *get_call_frame_for_req (fuse_state_t *state); fuse_state_t *get_fuse_state (xlator_t *this, fuse_in_header_t *finh); void free_fuse_state (fuse_state_t *state); -void gf_fuse_stat2attr (struct iatt *st, struct fuse_attr *fa); +void gf_fuse_stat2attr (struct iatt *st, struct fuse_attr *fa, + gf_boolean_t enable_ino32); +void gf_fuse_fill_dirent (gf_dirent_t *entry, struct fuse_dirent *fde, + gf_boolean_t enable_ino32); uint64_t inode_to_fuse_nodeid (inode_t *inode); -xlator_t *fuse_state_subvol (fuse_state_t *state); xlator_t *fuse_active_subvol (xlator_t *fuse); inode_t *fuse_ino_to_inode (uint64_t ino, xlator_t *fuse); -int fuse_resolve_and_resume (fuse_state_t *state, fuse_resume_fn_t fn); int send_fuse_err (xlator_t *this, fuse_in_header_t *finh, int error); int fuse_gfid_set (fuse_state_t *state); +int fuse_flip_xattr_ns (struct fuse_private *priv, char *okey, char **nkey); +fuse_fd_ctx_t * __fuse_fd_ctx_check_n_create (xlator_t *this, fd_t *fd); +fuse_fd_ctx_t * fuse_fd_ctx_check_n_create (xlator_t *this, fd_t *fd); + +int fuse_resolve_and_resume (fuse_state_t *state, fuse_resume_fn_t fn); +int fuse_resolve_inode_init (fuse_state_t *state, fuse_resolve_t *resolve, + ino_t ino); +int fuse_resolve_entry_init (fuse_state_t *state, fuse_resolve_t *resolve, + ino_t par, char *name); +int fuse_resolve_fd_init (fuse_state_t *state, fuse_resolve_t *resolve, + fd_t *fd); +int fuse_ignore_xattr_set (fuse_private_t *priv, char *key); +int dump_history_fuse (circular_buffer_t *cb, void *data); #endif /* _GF_FUSE_BRIDGE_H_ */ |
