"Fossies" - the Fresh Open Source Software Archive

Member "glusterfs-7.6/xlators/mount/fuse/src/fuse-bridge.h" (18 May 2020, 21850 Bytes) of package /linux/misc/glusterfs-7.6.tar.gz:


As a special service "Fossies" has tried to format the requested source page into HTML format using (guessed) C and C++ source code syntax highlighting (style: standard) with prefixed line numbers and code folding option. Alternatively you can here view or download the uninterpreted source code file. For more information about "fuse-bridge.h" see the Fossies "Dox" file reference documentation and the latest Fossies "Diffs" side-by-side code changes report: 7.5_vs_7.6.

    1 /*
    2    Copyright (c) 2006-2012 Red Hat, Inc. <http://www.redhat.com>
    3    This file is part of GlusterFS.
    4 
    5    This file is licensed to you under your choice of the GNU Lesser
    6    General Public License, version 3 or any later version (LGPLv3 or
    7    later), or the GNU General Public License, version 2 (GPLv2), in all
    8    cases as published by the Free Software Foundation.
    9 */
   10 #ifndef _GF_FUSE_BRIDGE_H_
   11 #define _GF_FUSE_BRIDGE_H_
   12 
   13 #include <stdint.h>
   14 #include <signal.h>
   15 #include <pthread.h>
   16 #include <stddef.h>
   17 #include <dirent.h>
   18 #include <sys/mount.h>
   19 #include <sys/time.h>
   20 #include <fnmatch.h>
   21 
   22 #include <glusterfs/glusterfs.h>
   23 #include <glusterfs/logging.h>
   24 #include <glusterfs/xlator.h>
   25 #include <glusterfs/defaults.h>
   26 #include <glusterfs/common-utils.h>
   27 #include <glusterfs/statedump.h>
   28 
   29 #ifdef GF_DARWIN_HOST_OS
   30 #include "fuse_kernel_macfuse.h"
   31 #else
   32 #include "fuse_kernel.h"
   33 #endif
   34 #include "fuse-misc.h"
   35 #include "fuse-mount.h"
   36 #include "fuse-mem-types.h"
   37 
   38 #include <glusterfs/list.h>
   39 #include <glusterfs/dict.h>
   40 #include <glusterfs/syncop.h>
   41 #include <glusterfs/gidcache.h>
   42 
   43 #if defined(GF_LINUX_HOST_OS) || defined(__FreeBSD__) || defined(__NetBSD__)
   44 
   45 /*
   46  * TODO:
   47  * So, with the addition of copy_file_range support, it might
   48  * require a bump up of fuse kernel minor version (like it was
   49  * done when support for lseek fop was added. But, as of now,
   50  * the copy_file_range support has just landed in upstream
   51  * kernel fuse module. So, until, there is a release of that
   52  * fuse as part of a kernel, the FUSE_KERNEL_MINOR_VERSION
   53  * from fuse_kernel.h in the contrib might not be changed.
   54  * If so, then the highest op available should be based on
   55  * the current minor version (which is 24). So, selectively
   56  * determine. When, the minor version is changed to 28 in
   57  * fuse_kernel.h from contrib (because in upstream linux
   58  * kernel source tree, the kernel minor version which
   59  * contains support for copy_file_range is 28), then remove
   60  * the reference to FUSE_LSEEK below and just determine
   61  * FUSE_OP_HIGH based on copy_file_range.
   62  */
   63 #if FUSE_KERNEL_MINOR_VERSION >= 28
   64 #define FUSE_OP_HIGH (FUSE_COPY_FILE_RANGE + 1)
   65 #else
   66 #define FUSE_OP_HIGH (FUSE_LSEEK + 1)
   67 #endif
   68 
   69 #endif
   70 #ifdef GF_DARWIN_HOST_OS
   71 #define FUSE_OP_HIGH (FUSE_DESTROY + 1)
   72 #endif
   73 #define GLUSTERFS_XATTR_LEN_MAX 65536
   74 
   75 #define MAX_FUSE_PROC_DELAY 1
   76 
   77 typedef struct fuse_in_header fuse_in_header_t;
   78 typedef void(fuse_handler_t)(xlator_t *this, fuse_in_header_t *finh, void *msg,
   79                              struct iobuf *iobuf);
   80 
   81 struct fuse_private {
   82     int fd;
   83     uint32_t proto_minor;
   84     char *volfile;
   85     size_t volfile_size;
   86     char *mount_point;
   87     struct iobuf *iobuf;
   88 
   89     pthread_t *fuse_thread;
   90     uint32_t reader_thread_count;
   91     char fuse_thread_started;
   92 
   93     uint32_t direct_io_mode;
   94     size_t *msg0_len_p;
   95 
   96     double entry_timeout;
   97     double negative_timeout;
   98     double attribute_timeout;
   99 
  100     pthread_cond_t sync_cond;
  101     pthread_mutex_t sync_mutex;
  102     char event_recvd;
  103 
  104     char init_recvd;
  105 
  106     gf_boolean_t strict_volfile_check;
  107 
  108     fuse_handler_t **fuse_ops;
  109     fuse_handler_t **fuse_ops0;
  110     pthread_mutex_t fuse_dump_mutex;
  111     int fuse_dump_fd;
  112 
  113     glusterfs_graph_t *next_graph;
  114     xlator_t *active_subvol;
  115 
  116     pid_t client_pid;
  117     gf_boolean_t client_pid_set;
  118     unsigned uid_map_root;
  119     gf_boolean_t acl;
  120     gf_boolean_t selinux;
  121     gf_boolean_t read_only;
  122     int32_t fopen_keep_cache;
  123     int32_t gid_cache_timeout;
  124     gf_boolean_t enable_ino32;
  125     /* This is the mount option for disabling the root-squash for the
  126        mount irrespective of whether the root-squash option for the
  127        volume is set or not. But this option is honoured only for
  128        thr trusted clients. For non trusted clients this value does
  129        not have any affect and the volume option for root-squash is
  130        honoured.
  131     */
  132     gf_boolean_t no_root_squash;
  133     fdtable_t *fdtable;
  134     gid_cache_t gid_cache;
  135     char *fuse_mountopts;
  136 
  137     /* For fuse-reverse-validation */
  138     struct list_head invalidate_list;
  139     pthread_cond_t invalidate_cond;
  140     pthread_mutex_t invalidate_mutex;
  141     gf_boolean_t reverse_fuse_thread_started;
  142 
  143     /* For communicating with separate mount thread. */
  144     int status_pipe[2];
  145 
  146     /* for fuse queue length and congestion threshold */
  147     int background_qlen;
  148     int congestion_threshold;
  149 
  150     /* for using fuse-kernel readdirp*/
  151     gf_boolean_t use_readdirp;
  152 
  153     /* fini started, helps prevent multiple epoll worker threads
  154      * firing up the fini routine */
  155     gf_boolean_t fini_invoked;
  156 
  157     /* resolve gid with getgrouplist() instead of /proc/%d/status */
  158     gf_boolean_t resolve_gids;
  159 
  160     /* Enable or disable capability support */
  161     gf_boolean_t capability;
  162 
  163     /* Enable or disable event history */
  164     gf_boolean_t event_history;
  165 
  166     /* whether to run the unmount daemon */
  167     gf_boolean_t auto_unmount;
  168 
  169     /* Load the thin volfile, and connect to gfproxyd*/
  170     gf_boolean_t thin_client;
  171     gf_boolean_t mount_finished;
  172     gf_boolean_t handle_graph_switch;
  173     pthread_cond_t migrate_cond;
  174 
  175     /* Writeback cache support */
  176     gf_boolean_t kernel_writeback_cache;
  177     int attr_times_granularity;
  178 
  179     /* Delayed fuse response */
  180     struct list_head timed_list;
  181     pthread_cond_t timed_cond;
  182     pthread_mutex_t timed_mutex;
  183     gf_boolean_t timed_response_fuse_thread_started;
  184 
  185     /* Interrupt subscription */
  186     struct list_head interrupt_list;
  187     pthread_mutex_t interrupt_mutex;
  188 
  189     gf_boolean_t flush_handle_interrupt;
  190     gf_boolean_t fuse_auto_inval;
  191 
  192     /* LRU Limit, if not set, default is 128k for now */
  193     uint32_t lru_limit;
  194 };
  195 typedef struct fuse_private fuse_private_t;
  196 
  197 typedef uint64_t errnomask_t[2];
  198 #define MASK_ERRNO(mask, n) ((mask)[(n) >> 6] |= ((uint64_t)1 << ((n)&63)))
  199 #define GET_ERRNO_MASK(mask, n) ((mask)[(n) >> 6] & ((uint64_t)1 << ((n)&63)))
  200 #define ERRNOMASK_MAX (64 * (sizeof(errnomask_t) / sizeof(uint64_t)))
  201 
  202 #define INVAL_BUF_SIZE                                                         \
  203     (sizeof(struct fuse_out_header) +                                          \
  204      max(sizeof(struct fuse_notify_inval_inode_out),                           \
  205          sizeof(struct fuse_notify_inval_entry_out) + NAME_MAX + 1))
  206 
  207 struct fuse_invalidate_node {
  208     errnomask_t errnomask;
  209     struct list_head next;
  210     char inval_buf[INVAL_BUF_SIZE];
  211 };
  212 typedef struct fuse_invalidate_node fuse_invalidate_node_t;
  213 
  214 struct fuse_timed_message {
  215     struct fuse_out_header fuse_out_header;
  216     void *fuse_message_body;
  217     struct timespec scheduled_ts;
  218     errnomask_t errnomask;
  219     struct list_head next;
  220 };
  221 typedef struct fuse_timed_message fuse_timed_message_t;
  222 
  223 enum fuse_interrupt_state {
  224     INTERRUPT_NONE,
  225     INTERRUPT_SQUELCHED,
  226     INTERRUPT_HANDLED,
  227 };
  228 typedef enum fuse_interrupt_state fuse_interrupt_state_t;
  229 struct fuse_interrupt_record;
  230 typedef struct fuse_interrupt_record fuse_interrupt_record_t;
  231 typedef void (*fuse_interrupt_handler_t)(xlator_t *this,
  232                                          fuse_interrupt_record_t *);
  233 struct fuse_interrupt_record {
  234     fuse_in_header_t fuse_in_header;
  235     void *data;
  236     gf_boolean_t hit;
  237     fuse_interrupt_state_t interrupt_state;
  238     fuse_interrupt_handler_t interrupt_handler;
  239     pthread_cond_t handler_cond;
  240     pthread_mutex_t handler_mutex;
  241     struct list_head next;
  242 };
  243 
  244 struct fuse_graph_switch_args {
  245     xlator_t *this;
  246     xlator_t *old_subvol;
  247     xlator_t *new_subvol;
  248 };
  249 typedef struct fuse_graph_switch_args fuse_graph_switch_args_t;
  250 
  251 #define FUSE_EVENT_HISTORY_SIZE 1024
  252 
  253 #define _FH_TO_FD(fh) ((fd_t *)(uintptr_t)(fh))
  254 
  255 #define FH_TO_FD(fh) ((_FH_TO_FD(fh)) ? (fd_ref(_FH_TO_FD(fh))) : ((fd_t *)0))
  256 
  257 /* Use the same logic as the Linux NFS-client */
  258 #define GF_FUSE_SQUASH_INO(ino) (((uint32_t)ino) ^ (ino >> 32))
  259 
  260 #define FUSE_FOP(state, ret, op_num, fop, args...)                             \
  261     do {                                                                       \
  262         xlator_t *xl = NULL;                                                   \
  263         call_frame_t *frame = NULL;                                            \
  264                                                                                \
  265         xl = state->active_subvol;                                             \
  266         if (!xl) {                                                             \
  267             gf_log_callingfn(state->this->name, GF_LOG_ERROR,                  \
  268                              "No active subvolume");                           \
  269             send_fuse_err(state->this, state->finh, ENOENT);                   \
  270             free_fuse_state(state);                                            \
  271             break;                                                             \
  272         }                                                                      \
  273                                                                                \
  274         frame = get_call_frame_for_req(state);                                 \
  275         if (!frame) {                                                          \
  276             /* This is not completely clean, as some                           \
  277              * earlier allocations might remain unfreed                        \
  278              * if we return at this point, but still                           \
  279              * better than trying to go on with a NULL                         \
  280              * frame ...                                                       \
  281              */                                                                \
  282             send_fuse_err(state->this, state->finh, ENOMEM);                   \
  283             free_fuse_state(state);                                            \
  284             /* ideally, need to 'return', but let the */                       \
  285             /* calling function take care of it */                             \
  286             break;                                                             \
  287         }                                                                      \
  288                                                                                \
  289         frame->root->state = state;                                            \
  290         frame->root->op = op_num;                                              \
  291         frame->op = op_num;                                                    \
  292                                                                                \
  293         if (state->this->history)                                              \
  294             gf_log_eh("%" PRIu64                                               \
  295                       ", %s, path: (%s), gfid: "                               \
  296                       "(%s)",                                                  \
  297                       frame->root->unique, gf_fop_list[frame->root->op],       \
  298                       state->loc.path,                                         \
  299                       (state->fd == NULL)                                      \
  300                           ? uuid_utoa(state->loc.gfid)                         \
  301                           : uuid_utoa(state->fd->inode->gfid));                \
  302         STACK_WIND(frame, ret, xl, xl->fops->fop, args);                       \
  303     } while (0)
  304 
  305 #define GF_SELECT_LOG_LEVEL(_errno)                                            \
  306         (((_errno == ENOENT) || (_errno == ESTALE))?    \
  307          GF_LOG_DEBUG)
  308 
  309 #define GET_STATE(this, finh, state)                                           \
  310     do {                                                                       \
  311         state = get_fuse_state(this, finh);                                    \
  312         if (!state) {                                                          \
  313             gf_log("glusterfs-fuse", GF_LOG_ERROR,                             \
  314                    "FUSE message unique %" PRIu64                              \
  315                    " opcode %d:"                                               \
  316                    " state allocation failed",                                 \
  317                    finh->unique, finh->opcode);                                \
  318                                                                                \
  319             send_fuse_err(this, finh, ENOMEM);                                 \
  320             GF_FREE(finh);                                                     \
  321                                                                                \
  322             return;                                                            \
  323         }                                                                      \
  324     } while (0)
  325 
  326 #define FUSE_ENTRY_CREATE(this, priv, finh, state, fci, op)                    \
  327     do {                                                                       \
  328         if (priv->proto_minor >= 12)                                           \
  329             state->mode &= ~fci->umask;                                        \
  330         if (priv->proto_minor >= 12 && priv->acl) {                            \
  331             state->xdata = dict_new();                                         \
  332             if (!state->xdata) {                                               \
  333                 gf_log("glusterfs-fuse", GF_LOG_WARNING,                       \
  334                        "%s failed to allocate "                                \
  335                        "a param dictionary",                                   \
  336                        op);                                                    \
  337                 send_fuse_err(this, finh, ENOMEM);                             \
  338                 free_fuse_state(state);                                        \
  339                 return;                                                        \
  340             }                                                                  \
  341             state->umask = fci->umask;                                         \
  342                                                                                \
  343             /* TODO: remove this after 3.4.0 release. keeping it for the       \
  344                sake of backward compatibility with old (3.3.[01])              \
  345                releases till then. */                                          \
  346             ret = dict_set_int16(state->xdata, "umask", fci->umask);           \
  347             if (ret < 0) {                                                     \
  348                 gf_log("glusterfs-fuse", GF_LOG_WARNING,                       \
  349                        "%s Failed adding umask"                                \
  350                        " to request",                                          \
  351                        op);                                                    \
  352                 send_fuse_err(this, finh, ENOMEM);                             \
  353                 free_fuse_state(state);                                        \
  354                 return;                                                        \
  355             }                                                                  \
  356             ret = dict_set_int16(state->xdata, "mode", fci->mode);             \
  357             if (ret < 0) {                                                     \
  358                 gf_log("glusterfs-fuse", GF_LOG_WARNING,                       \
  359                        "%s Failed adding mode "                                \
  360                        "to request",                                           \
  361                        op);                                                    \
  362                 send_fuse_err(this, finh, ENOMEM);                             \
  363                 free_fuse_state(state);                                        \
  364                 return;                                                        \
  365             }                                                                  \
  366         }                                                                      \
  367     } while (0)
  368 
  369 #define fuse_log_eh_fop(this, state, frame, op_ret, op_errno)                  \
  370     do {                                                                       \
  371         fuse_private_t *priv = this->private;                                  \
  372         if (this->history && priv->event_history) {                            \
  373             if (state->fd)                                                     \
  374                 gf_log_eh(                                                     \
  375                     "op_ret: %d, op_errno: %d, "                               \
  376                     "%" PRIu64 ", %s () => %p, gfid: %s",                      \
  377                     op_ret, op_errno, frame->root->unique,                     \
  378                     gf_fop_list[frame->root->op], state->fd,                   \
  379                     uuid_utoa(state->fd->inode->gfid));                        \
  380             else                                                               \
  381                 gf_log_eh(                                                     \
  382                     "op_ret: %d, op_errno: %d, "                               \
  383                     "%" PRIu64 ", %s () => %s, gfid: %s",                      \
  384                     op_ret, op_errno, frame->root->unique,                     \
  385                     gf_fop_list[frame->root->op], state->loc.path,             \
  386                     uuid_utoa(state->loc.gfid));                               \
  387         }                                                                      \
  388     } while (0)
  389 
  390 #define fuse_log_eh(this, args...)                                             \
  391     do {                                                                       \
  392         fuse_private_t *priv = this->private;                                  \
  393         if (this->history && priv->event_history)                              \
  394             gf_log_eh(args);                                                   \
  395     } while (0)
  396 
  397 static inline xlator_t *
  398 fuse_active_subvol(xlator_t *fuse)
  399 {
  400     fuse_private_t *priv = NULL;
  401 
  402     priv = fuse->private;
  403 
  404     return priv->active_subvol;
  405 }
  406 
  407 typedef enum {
  408     RESOLVE_MUST = 1,
  409     RESOLVE_NOT,
  410     RESOLVE_MAY,
  411     RESOLVE_DONTCARE,
  412     RESOLVE_EXACT
  413 } fuse_resolve_type_t;
  414 
  415 typedef struct {
  416     fuse_resolve_type_t type;
  417     fd_t *fd;
  418     char *path;
  419     char *bname;
  420     u_char gfid[16];
  421     inode_t *hint;
  422     u_char pargfid[16];
  423     inode_t *parhint;
  424     int op_ret;
  425     int op_errno;
  426     loc_t resolve_loc;
  427 } fuse_resolve_t;
  428 
  429 typedef struct {
  430     void *pool;
  431     xlator_t *this;
  432     xlator_t *active_subvol;
  433     inode_table_t *itable;
  434     loc_t loc;
  435     loc_t loc2;
  436     fuse_in_header_t *finh;
  437     int32_t flags;
  438 
  439     off_t off;
  440     /*
  441      * The man page of copy_file_range tells that the offset
  442      * arguments are of type loff_t *. Here in fuse state, the values of
  443      * those offsets are saved instead of pointers as the kernel sends
  444      * the values of the offsets from those pointers instead of pointers.
  445      * But the type loff_t is linux specific and is actually a typedef of
  446      * off64_t. Hence using off64_t
  447      */
  448     off64_t off_in;  /* for copy_file_range source fd */
  449     off64_t off_out; /* for copy_file_range destination fd */
  450     size_t size;
  451     unsigned long nlookup;
  452     fd_t *fd;
  453     fd_t *fd_dst; /* for copy_file_range destination */
  454     dict_t *xattr;
  455     dict_t *xdata;
  456     char *name;
  457     char is_revalidate;
  458     gf_boolean_t truncate_needed;
  459     gf_lock_t lock;
  460     uint64_t lk_owner;
  461 
  462     /* used within resolve_and_resume */
  463     /* */
  464     fuse_resolve_t resolve;
  465     fuse_resolve_t resolve2;
  466 
  467     loc_t *loc_now;
  468     fuse_resolve_t *resolve_now;
  469 
  470     void *resume_fn;
  471 
  472     int valid;
  473     int mask;
  474     dev_t rdev;
  475     mode_t mode;
  476     mode_t umask;
  477     struct iatt attr;
  478     struct gf_flock lk_lock;
  479     struct iovec vector;
  480 
  481     uuid_t gfid;
  482     uint32_t io_flags;
  483     int32_t fd_no;
  484 
  485     gf_seek_what_t whence;
  486     struct iobuf *iobuf;
  487 } fuse_state_t;
  488 
  489 typedef struct {
  490     uint32_t open_flags;
  491     char migration_failed;
  492     fd_t *activefd;
  493 } fuse_fd_ctx_t;
  494 
  495 typedef void (*fuse_resume_fn_t)(fuse_state_t *state);
  496 
  497 GF_MUST_CHECK int32_t
  498 fuse_loc_fill(loc_t *loc, fuse_state_t *state, ino_t ino, ino_t par,
  499               const char *name);
  500 call_frame_t *
  501 get_call_frame_for_req(fuse_state_t *state);
  502 fuse_state_t *
  503 get_fuse_state(xlator_t *this, fuse_in_header_t *finh);
  504 void
  505 free_fuse_state(fuse_state_t *state);
  506 void
  507 gf_fuse_stat2attr(struct iatt *st, struct fuse_attr *fa,
  508                   gf_boolean_t enable_ino32);
  509 void
  510 gf_fuse_fill_dirent(gf_dirent_t *entry, struct fuse_dirent *fde,
  511                     gf_boolean_t enable_ino32);
  512 uint64_t
  513 inode_to_fuse_nodeid(inode_t *inode);
  514 xlator_t *
  515 fuse_active_subvol(xlator_t *fuse);
  516 inode_t *
  517 fuse_ino_to_inode(uint64_t ino, xlator_t *fuse);
  518 int
  519 send_fuse_err(xlator_t *this, fuse_in_header_t *finh, int error);
  520 int
  521 fuse_gfid_set(fuse_state_t *state);
  522 int
  523 fuse_flip_xattr_ns(struct fuse_private *priv, char *okey, char **nkey);
  524 fuse_fd_ctx_t *
  525 __fuse_fd_ctx_check_n_create(xlator_t *this, fd_t *fd);
  526 fuse_fd_ctx_t *
  527 fuse_fd_ctx_check_n_create(xlator_t *this, fd_t *fd);
  528 
  529 int
  530 fuse_resolve_and_resume(fuse_state_t *state, fuse_resume_fn_t fn);
  531 int
  532 fuse_resolve_inode_init(fuse_state_t *state, fuse_resolve_t *resolve,
  533                         ino_t ino);
  534 int
  535 fuse_resolve_entry_init(fuse_state_t *state, fuse_resolve_t *resolve, ino_t par,
  536                         char *name);
  537 int
  538 fuse_resolve_fd_init(fuse_state_t *state, fuse_resolve_t *resolve, fd_t *fd);
  539 int
  540 fuse_ignore_xattr_set(fuse_private_t *priv, char *key);
  541 void
  542 fuse_fop_resume(fuse_state_t *state);
  543 int
  544 dump_history_fuse(circular_buffer_t *cb, void *data);
  545 int
  546 fuse_check_selinux_cap_xattr(fuse_private_t *priv, char *name);
  547 #endif /* _GF_FUSE_BRIDGE_H_ */