"Fossies" - the Fresh Open Source Software Archive

Member "glusterfs-6.9/xlators/cluster/afr/src/afr-dir-read.c" (23 Apr 2020, 9482 Bytes) of package /linux/misc/glusterfs-6.9.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 "afr-dir-read.c" see the Fossies "Dox" file reference documentation.

    1 /*
    2   Copyright (c) 2008-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 
   11 #include <libgen.h>
   12 #include <unistd.h>
   13 #include <fnmatch.h>
   14 #include <sys/time.h>
   15 #include <stdlib.h>
   16 #include <signal.h>
   17 #include <string.h>
   18 
   19 #include <glusterfs/glusterfs.h>
   20 #include <glusterfs/dict.h>
   21 #include <glusterfs/xlator.h>
   22 #include <glusterfs/hashfn.h>
   23 #include <glusterfs/logging.h>
   24 #include <glusterfs/list.h>
   25 #include <glusterfs/call-stub.h>
   26 #include <glusterfs/defaults.h>
   27 #include <glusterfs/common-utils.h>
   28 #include <glusterfs/compat-errno.h>
   29 #include <glusterfs/compat.h>
   30 #include <glusterfs/checksum.h>
   31 
   32 #include "afr.h"
   33 #include "afr-transaction.h"
   34 
   35 int32_t
   36 afr_opendir_cbk(call_frame_t *frame, void *cookie, xlator_t *this,
   37                 int32_t op_ret, int32_t op_errno, fd_t *fd, dict_t *xdata)
   38 {
   39     afr_local_t *local = NULL;
   40     int call_count = -1;
   41     int32_t child_index = 0;
   42     afr_fd_ctx_t *fd_ctx = NULL;
   43 
   44     local = frame->local;
   45     fd_ctx = local->fd_ctx;
   46     child_index = (long)cookie;
   47 
   48     LOCK(&frame->lock);
   49     {
   50         if (op_ret == -1) {
   51             local->op_errno = op_errno;
   52             fd_ctx->opened_on[child_index] = AFR_FD_NOT_OPENED;
   53         } else {
   54             local->op_ret = op_ret;
   55             fd_ctx->opened_on[child_index] = AFR_FD_OPENED;
   56             if (!local->xdata_rsp && xdata)
   57                 local->xdata_rsp = dict_ref(xdata);
   58         }
   59     }
   60     UNLOCK(&frame->lock);
   61 
   62     call_count = afr_frame_return(frame);
   63 
   64     if (call_count == 0)
   65         AFR_STACK_UNWIND(opendir, frame, local->op_ret, local->op_errno,
   66                          local->fd, NULL);
   67     return 0;
   68 }
   69 
   70 int
   71 afr_opendir(call_frame_t *frame, xlator_t *this, loc_t *loc, fd_t *fd)
   72 {
   73     afr_private_t *priv = NULL;
   74     afr_local_t *local = NULL;
   75     int i = 0;
   76     int call_count = -1;
   77     int32_t op_errno = ENOMEM;
   78     afr_fd_ctx_t *fd_ctx = NULL;
   79 
   80     priv = this->private;
   81 
   82     local = AFR_FRAME_INIT(frame, op_errno);
   83     if (!local)
   84         goto out;
   85 
   86     local->op = GF_FOP_OPENDIR;
   87     if (!afr_is_consistent_io_possible(local, priv, &op_errno))
   88         goto out;
   89 
   90     fd_ctx = afr_fd_ctx_get(fd, this);
   91     if (!fd_ctx)
   92         goto out;
   93 
   94     loc_copy(&local->loc, loc);
   95 
   96     local->fd = fd_ref(fd);
   97     local->fd_ctx = fd_ctx;
   98 
   99     call_count = local->call_count;
  100 
  101     for (i = 0; i < priv->child_count; i++) {
  102         if (local->child_up[i]) {
  103             STACK_WIND_COOKIE(frame, afr_opendir_cbk, (void *)(long)i,
  104                               priv->children[i],
  105                               priv->children[i]->fops->opendir, loc, fd, NULL);
  106 
  107             if (!--call_count)
  108                 break;
  109         }
  110     }
  111 
  112     return 0;
  113 out:
  114     AFR_STACK_UNWIND(opendir, frame, -1, op_errno, fd, NULL);
  115     return 0;
  116 }
  117 
  118 static int
  119 afr_validate_read_subvol(inode_t *inode, xlator_t *this, int par_read_subvol)
  120 {
  121     int gen = 0;
  122     int entry_read_subvol = 0;
  123     unsigned char *data_readable = NULL;
  124     unsigned char *metadata_readable = NULL;
  125     afr_private_t *priv = NULL;
  126 
  127     priv = this->private;
  128     data_readable = alloca0(priv->child_count);
  129     metadata_readable = alloca0(priv->child_count);
  130 
  131     afr_inode_read_subvol_get(inode, this, data_readable, metadata_readable,
  132                               &gen);
  133 
  134     if (gen != priv->event_generation || !data_readable[par_read_subvol] ||
  135         !metadata_readable[par_read_subvol])
  136         return -1;
  137 
  138     /* Once the control reaches the following statement, it means that the
  139      * parent's read subvol is perfectly readable. So calling
  140      * either afr_data_subvol_get() or afr_metadata_subvol_get() would
  141      * yield the same result. Hence, choosing afr_data_subvol_get() below.
  142      */
  143 
  144     if (!priv->consistent_metadata)
  145         return 0;
  146 
  147     /* For an inode fetched through readdirp which is yet to be linked,
  148      * inode ctx would not be initialised (yet). So this function returns
  149      * -1 above due to gen being 0, which is why it is OK to pass NULL for
  150      *  read_subvol_args here.
  151      */
  152     entry_read_subvol = afr_data_subvol_get(inode, this, NULL, NULL, NULL,
  153                                             NULL);
  154     if (entry_read_subvol != par_read_subvol)
  155         return -1;
  156 
  157     return 0;
  158 }
  159 
  160 static void
  161 afr_readdir_transform_entries(gf_dirent_t *subvol_entries, int subvol,
  162                               gf_dirent_t *entries, fd_t *fd)
  163 {
  164     int ret = -1;
  165     gf_dirent_t *entry = NULL;
  166     gf_dirent_t *tmp = NULL;
  167     xlator_t *this = NULL;
  168     afr_private_t *priv = NULL;
  169     gf_boolean_t need_heal = _gf_false;
  170     gf_boolean_t validate_subvol = _gf_false;
  171 
  172     this = THIS;
  173     priv = this->private;
  174 
  175     need_heal = afr_get_need_heal(this);
  176     validate_subvol = need_heal | priv->consistent_metadata;
  177 
  178     list_for_each_entry_safe(entry, tmp, &subvol_entries->list, list)
  179     {
  180         if (__is_root_gfid(fd->inode->gfid) &&
  181             !strcmp(entry->d_name, GF_REPLICATE_TRASH_DIR)) {
  182             continue;
  183         }
  184 
  185         list_del_init(&entry->list);
  186         list_add_tail(&entry->list, &entries->list);
  187 
  188         if (!validate_subvol)
  189             continue;
  190 
  191         if (entry->inode) {
  192             ret = afr_validate_read_subvol(entry->inode, this, subvol);
  193             if (ret == -1) {
  194                 inode_unref(entry->inode);
  195                 entry->inode = NULL;
  196                 continue;
  197             }
  198         }
  199     }
  200 }
  201 
  202 int32_t
  203 afr_readdir_cbk(call_frame_t *frame, void *cookie, xlator_t *this,
  204                 int32_t op_ret, int32_t op_errno, gf_dirent_t *subvol_entries,
  205                 dict_t *xdata)
  206 {
  207     afr_local_t *local = NULL;
  208     gf_dirent_t entries;
  209 
  210     INIT_LIST_HEAD(&entries.list);
  211 
  212     local = frame->local;
  213 
  214     if (op_ret < 0 && !local->cont.readdir.offset) {
  215         /* failover only if this was first readdir, detected
  216            by offset == 0 */
  217         local->op_ret = op_ret;
  218         local->op_errno = op_errno;
  219 
  220         afr_read_txn_continue(frame, this, (long)cookie);
  221         return 0;
  222     }
  223 
  224     if (op_ret >= 0)
  225         afr_readdir_transform_entries(subvol_entries, (long)cookie, &entries,
  226                                       local->fd);
  227 
  228     AFR_STACK_UNWIND(readdir, frame, op_ret, op_errno, &entries, xdata);
  229 
  230     gf_dirent_free(&entries);
  231 
  232     return 0;
  233 }
  234 
  235 int
  236 afr_readdir_wind(call_frame_t *frame, xlator_t *this, int subvol)
  237 {
  238     afr_local_t *local = NULL;
  239     afr_private_t *priv = NULL;
  240     afr_fd_ctx_t *fd_ctx = NULL;
  241 
  242     priv = this->private;
  243     local = frame->local;
  244     fd_ctx = afr_fd_ctx_get(local->fd, this);
  245     if (!fd_ctx) {
  246         local->op_errno = EINVAL;
  247         local->op_ret = -1;
  248     }
  249 
  250     if (subvol == -1 || !fd_ctx) {
  251         AFR_STACK_UNWIND(readdir, frame, local->op_ret, local->op_errno, 0, 0);
  252         return 0;
  253     }
  254 
  255     fd_ctx->readdir_subvol = subvol;
  256 
  257     if (local->op == GF_FOP_READDIR)
  258         STACK_WIND_COOKIE(frame, afr_readdir_cbk, (void *)(long)subvol,
  259                           priv->children[subvol],
  260                           priv->children[subvol]->fops->readdir, local->fd,
  261                           local->cont.readdir.size, local->cont.readdir.offset,
  262                           local->xdata_req);
  263     else
  264         STACK_WIND_COOKIE(frame, afr_readdir_cbk, (void *)(long)subvol,
  265                           priv->children[subvol],
  266                           priv->children[subvol]->fops->readdirp, local->fd,
  267                           local->cont.readdir.size, local->cont.readdir.offset,
  268                           local->xdata_req);
  269     return 0;
  270 }
  271 
  272 int
  273 afr_do_readdir(call_frame_t *frame, xlator_t *this, fd_t *fd, size_t size,
  274                off_t offset, int whichop, dict_t *dict)
  275 {
  276     afr_local_t *local = NULL;
  277     int32_t op_errno = 0;
  278     int subvol = -1;
  279     afr_fd_ctx_t *fd_ctx = NULL;
  280 
  281     local = AFR_FRAME_INIT(frame, op_errno);
  282     if (!local)
  283         goto out;
  284 
  285     fd_ctx = afr_fd_ctx_get(fd, this);
  286     if (!fd_ctx) {
  287         op_errno = EINVAL;
  288         goto out;
  289     }
  290 
  291     local->op = whichop;
  292     local->fd = fd_ref(fd);
  293     local->cont.readdir.size = size;
  294     local->cont.readdir.offset = offset;
  295     local->xdata_req = (dict) ? dict_ref(dict) : NULL;
  296 
  297     subvol = fd_ctx->readdir_subvol;
  298 
  299     if (offset == 0 || subvol == -1) {
  300         /* First readdir has option of failing over and selecting
  301            an appropriate read subvolume */
  302         afr_read_txn(frame, this, fd->inode, afr_readdir_wind,
  303                      AFR_DATA_TRANSACTION);
  304     } else {
  305         /* But continued readdirs MUST stick to the same subvolume
  306            without an option to failover */
  307         afr_readdir_wind(frame, this, subvol);
  308     }
  309 
  310     return 0;
  311 out:
  312     AFR_STACK_UNWIND(readdir, frame, -1, op_errno, NULL, NULL);
  313     return 0;
  314 }
  315 
  316 int32_t
  317 afr_readdir(call_frame_t *frame, xlator_t *this, fd_t *fd, size_t size,
  318             off_t offset, dict_t *xdata)
  319 {
  320     afr_do_readdir(frame, this, fd, size, offset, GF_FOP_READDIR, xdata);
  321 
  322     return 0;
  323 }
  324 
  325 int32_t
  326 afr_readdirp(call_frame_t *frame, xlator_t *this, fd_t *fd, size_t size,
  327              off_t offset, dict_t *dict)
  328 {
  329     afr_do_readdir(frame, this, fd, size, offset, GF_FOP_READDIRP, dict);
  330 
  331     return 0;
  332 }
  333 
  334 int32_t
  335 afr_releasedir(xlator_t *this, fd_t *fd)
  336 {
  337     afr_cleanup_fd_ctx(this, fd);
  338 
  339     return 0;
  340 }