"Fossies" - the Fresh Open Source Software Archive

Member "glusterfs-8.2/xlators/cluster/dht/src/nufa.c" (16 Sep 2020, 18284 Bytes) of package /linux/misc/glusterfs-8.2.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 "nufa.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 "dht-common.h"
   12 
   13 /* TODO: all 'TODO's in dht.c holds good */
   14 
   15 extern struct volume_options dht_options[];
   16 
   17 int
   18 nufa_local_lookup_cbk(call_frame_t *frame, void *cookie, xlator_t *this,
   19                       int op_ret, int op_errno, inode_t *inode,
   20                       struct iatt *stbuf, dict_t *xattr,
   21                       struct iatt *postparent)
   22 {
   23     xlator_t *subvol = NULL;
   24     char is_linkfile = 0;
   25     char is_dir = 0;
   26     dht_conf_t *conf = NULL;
   27     dht_local_t *local = NULL;
   28     loc_t *loc = NULL;
   29     int i = 0;
   30     xlator_t *prev = NULL;
   31     int call_cnt = 0;
   32     int ret = 0;
   33 
   34     conf = this->private;
   35 
   36     prev = cookie;
   37     local = frame->local;
   38     loc = &local->loc;
   39 
   40     if (ENTRY_MISSING(op_ret, op_errno)) {
   41         if (conf->search_unhashed) {
   42             local->op_errno = ENOENT;
   43             dht_lookup_everywhere(frame, this, loc);
   44             return 0;
   45         }
   46     }
   47 
   48     if (op_ret == -1)
   49         goto out;
   50 
   51     is_linkfile = check_is_linkfile(inode, stbuf, xattr, conf->link_xattr_name);
   52     is_dir = check_is_dir(inode, stbuf, xattr);
   53 
   54     if (!is_dir && !is_linkfile) {
   55         /* non-directory and not a linkfile */
   56         ret = dht_layout_preset(this, prev, inode);
   57         if (ret < 0) {
   58             gf_msg_debug(this->name, 0,
   59                          "could not set pre-set layout for subvol"
   60                          " %s",
   61                          prev->name);
   62             op_ret = -1;
   63             op_errno = EINVAL;
   64             goto err;
   65         }
   66 
   67         goto out;
   68     }
   69 
   70     if (is_dir) {
   71         call_cnt = conf->subvolume_cnt;
   72         local->call_cnt = call_cnt;
   73 
   74         local->inode = inode_ref(inode);
   75         local->xattr = dict_ref(xattr);
   76 
   77         local->op_ret = 0;
   78         local->op_errno = 0;
   79 
   80         local->layout = dht_layout_new(this, conf->subvolume_cnt);
   81         if (!local->layout) {
   82             op_ret = -1;
   83             op_errno = ENOMEM;
   84             goto err;
   85         }
   86 
   87         for (i = 0; i < call_cnt; i++) {
   88             STACK_WIND_COOKIE(frame, dht_lookup_dir_cbk, conf->subvolumes[i],
   89                               conf->subvolumes[i],
   90                               conf->subvolumes[i]->fops->lookup, &local->loc,
   91                               local->xattr_req);
   92         }
   93     }
   94 
   95     if (is_linkfile) {
   96         subvol = dht_linkfile_subvol(this, inode, stbuf, xattr);
   97 
   98         if (!subvol) {
   99             gf_msg_debug(this->name, 0,
  100                          "linkfile has no link subvolume. path=%s", loc->path);
  101             dht_lookup_everywhere(frame, this, loc);
  102             return 0;
  103         }
  104 
  105         STACK_WIND_COOKIE(frame, dht_lookup_linkfile_cbk, subvol, subvol,
  106                           subvol->fops->lookup, &local->loc, local->xattr_req);
  107     }
  108 
  109     return 0;
  110 
  111 out:
  112     if (!local->hashed_subvol) {
  113         gf_msg_debug(this->name, 0, "no subvolume in layout for path=%s",
  114                      local->loc.path);
  115         local->op_errno = ENOENT;
  116         dht_lookup_everywhere(frame, this, loc);
  117         return 0;
  118     }
  119 
  120     STACK_WIND_COOKIE(frame, dht_lookup_cbk, local->hashed_subvol,
  121                       local->hashed_subvol, local->hashed_subvol->fops->lookup,
  122                       &local->loc, local->xattr_req);
  123 
  124     return 0;
  125 
  126 err:
  127     DHT_STACK_UNWIND(lookup, frame, op_ret, op_errno, inode, stbuf, xattr,
  128                      postparent);
  129     return 0;
  130 }
  131 
  132 int
  133 nufa_lookup(call_frame_t *frame, xlator_t *this, loc_t *loc, dict_t *xattr_req)
  134 {
  135     xlator_t *hashed_subvol = NULL;
  136     xlator_t *subvol = NULL;
  137     dht_local_t *local = NULL;
  138     dht_conf_t *conf = NULL;
  139     int ret = -1;
  140     int op_errno = -1;
  141     dht_layout_t *layout = NULL;
  142     int i = 0;
  143     int call_cnt = 0;
  144 
  145     VALIDATE_OR_GOTO(frame, err);
  146     VALIDATE_OR_GOTO(this, err);
  147     VALIDATE_OR_GOTO(loc, err);
  148     VALIDATE_OR_GOTO(loc->inode, err);
  149     VALIDATE_OR_GOTO(loc->path, err);
  150 
  151     conf = this->private;
  152 
  153     local = dht_local_init(frame, loc, NULL, GF_FOP_LOOKUP);
  154     if (!local) {
  155         op_errno = ENOMEM;
  156         goto err;
  157     }
  158 
  159     if (xattr_req) {
  160         local->xattr_req = dict_ref(xattr_req);
  161     } else {
  162         local->xattr_req = dict_new();
  163     }
  164 
  165     hashed_subvol = dht_subvol_get_hashed(this, &local->loc);
  166 
  167     local->hashed_subvol = hashed_subvol;
  168 
  169     if (is_revalidate(loc)) {
  170         layout = local->layout;
  171         if (!layout) {
  172             gf_msg_debug(this->name, 0,
  173                          "revalidate lookup without cache. "
  174                          "path=%s",
  175                          loc->path);
  176             op_errno = EINVAL;
  177             goto err;
  178         }
  179 
  180         if (layout->gen && (layout->gen < conf->gen)) {
  181             gf_msg_debug(this->name, 0, "incomplete layout failure for path=%s",
  182                          loc->path);
  183             dht_layout_unref(this, local->layout);
  184             goto do_fresh_lookup;
  185         }
  186 
  187         local->inode = inode_ref(loc->inode);
  188 
  189         local->call_cnt = layout->cnt;
  190         call_cnt = local->call_cnt;
  191 
  192         /* NOTE: we don't require 'trusted.glusterfs.dht.linkto' attribute,
  193          *       revalidates directly go to the cached-subvolume.
  194          */
  195         ret = dict_set_uint32(local->xattr_req, conf->xattr_name, 4 * 4);
  196         if (ret < 0) {
  197             gf_msg(this->name, GF_LOG_ERROR, 0, DHT_MSG_DICT_SET_FAILED,
  198                    "Failed to set dict value.");
  199             op_errno = -1;
  200             goto err;
  201         }
  202 
  203         for (i = 0; i < layout->cnt; i++) {
  204             subvol = layout->list[i].xlator;
  205 
  206             STACK_WIND_COOKIE(frame, dht_revalidate_cbk, subvol, subvol,
  207                               subvol->fops->lookup, loc, local->xattr_req);
  208 
  209             if (!--call_cnt)
  210                 break;
  211         }
  212     } else {
  213     do_fresh_lookup:
  214         ret = dict_set_uint32(local->xattr_req, conf->xattr_name, 4 * 4);
  215         if (ret < 0) {
  216             gf_msg(this->name, GF_LOG_ERROR, 0, DHT_MSG_DICT_SET_FAILED,
  217                    "Failed to set dict value.");
  218             op_errno = -1;
  219             goto err;
  220         }
  221 
  222         ret = dict_set_uint32(local->xattr_req, conf->link_xattr_name, 256);
  223         if (ret < 0) {
  224             gf_msg(this->name, GF_LOG_ERROR, 0, DHT_MSG_DICT_SET_FAILED,
  225                    "Failed to set dict value.");
  226             op_errno = -1;
  227             goto err;
  228         }
  229 
  230         /* Send it to only local volume */
  231         STACK_WIND_COOKIE(
  232             frame, nufa_local_lookup_cbk, ((xlator_t *)conf->private),
  233             ((xlator_t *)conf->private),
  234             ((xlator_t *)conf->private)->fops->lookup, loc, local->xattr_req);
  235     }
  236 
  237     return 0;
  238 
  239 err:
  240     op_errno = (op_errno == -1) ? errno : op_errno;
  241     DHT_STACK_UNWIND(lookup, frame, -1, op_errno, NULL, NULL, NULL, NULL);
  242     return 0;
  243 }
  244 
  245 int
  246 nufa_create_linkfile_create_cbk(call_frame_t *frame, void *cookie,
  247                                 xlator_t *this, int op_ret, int op_errno,
  248                                 inode_t *inode, struct iatt *stbuf,
  249                                 struct iatt *preparent, struct iatt *postparent,
  250                                 dict_t *xdata)
  251 {
  252     dht_local_t *local = NULL;
  253 
  254     local = frame->local;
  255 
  256     if (op_ret == -1)
  257         goto err;
  258 
  259     STACK_WIND_COOKIE(frame, dht_create_cbk, local->cached_subvol,
  260                       local->cached_subvol, local->cached_subvol->fops->create,
  261                       &local->loc, local->flags, local->mode, local->umask,
  262                       local->fd, local->params);
  263 
  264     return 0;
  265 
  266 err:
  267     DHT_STACK_UNWIND(create, frame, -1, op_errno, NULL, NULL, NULL, NULL, NULL,
  268                      NULL);
  269     return 0;
  270 }
  271 
  272 int
  273 nufa_create(call_frame_t *frame, xlator_t *this, loc_t *loc, int32_t flags,
  274             mode_t mode, mode_t umask, fd_t *fd, dict_t *params)
  275 {
  276     dht_local_t *local = NULL;
  277     dht_conf_t *conf = NULL;
  278     xlator_t *subvol = NULL;
  279     xlator_t *avail_subvol = NULL;
  280     int op_errno = -1;
  281 
  282     VALIDATE_OR_GOTO(frame, err);
  283     VALIDATE_OR_GOTO(this, err);
  284     VALIDATE_OR_GOTO(loc, err);
  285 
  286     conf = this->private;
  287 
  288     dht_get_du_info(frame, this, loc);
  289 
  290     local = dht_local_init(frame, loc, fd, GF_FOP_CREATE);
  291     if (!local) {
  292         op_errno = ENOMEM;
  293         goto err;
  294     }
  295 
  296     subvol = dht_subvol_get_hashed(this, loc);
  297     if (!subvol) {
  298         gf_msg_debug(this->name, 0, "no subvolume in layout for path=%s",
  299                      loc->path);
  300         op_errno = ENOENT;
  301         goto err;
  302     }
  303 
  304     avail_subvol = conf->private;
  305     if (dht_is_subvol_filled(this, (xlator_t *)conf->private)) {
  306         avail_subvol = dht_free_disk_available_subvol(
  307             this, (xlator_t *)conf->private, local);
  308     }
  309 
  310     if (subvol != avail_subvol) {
  311         /* create a link file instead of actual file */
  312         local->params = dict_ref(params);
  313         local->mode = mode;
  314         local->flags = flags;
  315         local->umask = umask;
  316         local->cached_subvol = avail_subvol;
  317         dht_linkfile_create(frame, nufa_create_linkfile_create_cbk, this,
  318                             avail_subvol, subvol, loc);
  319         return 0;
  320     }
  321 
  322     gf_msg_trace(this->name, 0, "creating %s on %s", loc->path, subvol->name);
  323 
  324     STACK_WIND_COOKIE(frame, dht_create_cbk, subvol, subvol,
  325                       subvol->fops->create, loc, flags, mode, umask, fd,
  326                       params);
  327 
  328     return 0;
  329 
  330 err:
  331     op_errno = (op_errno == -1) ? errno : op_errno;
  332     DHT_STACK_UNWIND(create, frame, -1, op_errno, NULL, NULL, NULL, NULL, NULL,
  333                      NULL);
  334 
  335     return 0;
  336 }
  337 
  338 int
  339 nufa_mknod_linkfile_cbk(call_frame_t *frame, void *cookie, xlator_t *this,
  340                         int op_ret, int op_errno, inode_t *inode,
  341                         struct iatt *stbuf, struct iatt *preparent,
  342                         struct iatt *postparent, dict_t *xdata)
  343 {
  344     dht_local_t *local = NULL;
  345 
  346     local = frame->local;
  347     if (!local || !local->cached_subvol) {
  348         op_errno = EINVAL;
  349         op_ret = -1;
  350         goto err;
  351     }
  352 
  353     if (op_ret >= 0) {
  354         STACK_WIND_COOKIE(
  355             frame, dht_newfile_cbk, (void *)local->cached_subvol,
  356             local->cached_subvol, local->cached_subvol->fops->mknod,
  357             &local->loc, local->mode, local->rdev, local->umask, local->params);
  358 
  359         return 0;
  360     }
  361 err:
  362     WIPE(postparent);
  363     WIPE(preparent);
  364 
  365     DHT_STACK_UNWIND(link, frame, op_ret, op_errno, inode, stbuf, preparent,
  366                      postparent, xdata);
  367     return 0;
  368 }
  369 
  370 int
  371 nufa_mknod(call_frame_t *frame, xlator_t *this, loc_t *loc, mode_t mode,
  372            dev_t rdev, mode_t umask, dict_t *params)
  373 {
  374     dht_local_t *local = NULL;
  375     dht_conf_t *conf = NULL;
  376     xlator_t *subvol = NULL;
  377     xlator_t *avail_subvol = NULL;
  378     int op_errno = -1;
  379 
  380     VALIDATE_OR_GOTO(frame, err);
  381     VALIDATE_OR_GOTO(this, err);
  382     VALIDATE_OR_GOTO(loc, err);
  383 
  384     conf = this->private;
  385 
  386     dht_get_du_info(frame, this, loc);
  387 
  388     local = dht_local_init(frame, loc, NULL, GF_FOP_MKNOD);
  389     if (!local) {
  390         op_errno = ENOMEM;
  391         goto err;
  392     }
  393 
  394     subvol = dht_subvol_get_hashed(this, loc);
  395     if (!subvol) {
  396         gf_msg_debug(this->name, 0, "no subvolume in layout for path=%s",
  397                      loc->path);
  398         op_errno = ENOENT;
  399         goto err;
  400     }
  401 
  402     /* Consider the disksize in consideration */
  403     avail_subvol = conf->private;
  404     if (dht_is_subvol_filled(this, (xlator_t *)conf->private)) {
  405         avail_subvol = dht_free_disk_available_subvol(
  406             this, (xlator_t *)conf->private, local);
  407     }
  408 
  409     if (avail_subvol != subvol) {
  410         /* Create linkfile first */
  411 
  412         local->params = dict_ref(params);
  413         local->mode = mode;
  414         local->umask = umask;
  415         local->rdev = rdev;
  416         local->cached_subvol = avail_subvol;
  417 
  418         dht_linkfile_create(frame, nufa_mknod_linkfile_cbk, this, avail_subvol,
  419                             subvol, loc);
  420         return 0;
  421     }
  422 
  423     gf_msg_trace(this->name, 0, "creating %s on %s", loc->path, subvol->name);
  424 
  425     STACK_WIND_COOKIE(frame, dht_newfile_cbk, (void *)subvol, subvol,
  426                       subvol->fops->mknod, loc, mode, rdev, umask, params);
  427 
  428     return 0;
  429 
  430 err:
  431     op_errno = (op_errno == -1) ? errno : op_errno;
  432     DHT_STACK_UNWIND(mknod, frame, -1, op_errno, NULL, NULL, NULL, NULL, NULL);
  433 
  434     return 0;
  435 }
  436 
  437 gf_boolean_t
  438 same_first_part(char *str1, char term1, char *str2, char term2)
  439 {
  440     gf_boolean_t ended1;
  441     gf_boolean_t ended2;
  442 
  443     for (;;) {
  444         ended1 = ((*str1 == '\0') || (*str1 == term1));
  445         ended2 = ((*str2 == '\0') || (*str2 == term2));
  446         if (ended1 && ended2) {
  447             return _gf_true;
  448         }
  449         if (ended1 || ended2 || (*str1 != *str2)) {
  450             return _gf_false;
  451         }
  452         ++str1;
  453         ++str2;
  454     }
  455 }
  456 
  457 typedef struct nufa_args {
  458     xlator_t *this;
  459     char *volname;
  460     gf_boolean_t addr_match;
  461 } nufa_args_t;
  462 
  463 static void
  464 nufa_find_local_brick(xlator_t *xl, void *data)
  465 {
  466     nufa_args_t *args = data;
  467     xlator_t *this = args->this;
  468     char *local_volname = args->volname;
  469     gf_boolean_t addr_match = args->addr_match;
  470     char *brick_host = NULL;
  471     dht_conf_t *conf = this->private;
  472     int ret = -1;
  473 
  474     /*This means a local subvol was already found. We pick the first brick
  475      * that is local*/
  476     if (conf->private)
  477         return;
  478 
  479     if (strcmp(xl->name, local_volname) == 0) {
  480         conf->private = xl;
  481         gf_msg(this->name, GF_LOG_INFO, 0, DHT_MSG_SUBVOL_INFO,
  482                "Using specified subvol %s", local_volname);
  483         return;
  484     }
  485 
  486     if (!addr_match)
  487         return;
  488 
  489     ret = dict_get_str(xl->options, "remote-host", &brick_host);
  490     if ((ret == 0) && (gf_is_same_address(local_volname, brick_host) ||
  491                        gf_is_local_addr(brick_host))) {
  492         conf->private = xl;
  493         gf_msg(this->name, GF_LOG_INFO, 0, DHT_MSG_SUBVOL_INFO,
  494                "Using the first local "
  495                "subvol %s",
  496                xl->name);
  497         return;
  498     }
  499 }
  500 
  501 static void
  502 nufa_to_dht(xlator_t *this)
  503 {
  504     GF_ASSERT(this);
  505     GF_ASSERT(this->fops);
  506 
  507     this->fops->lookup = dht_lookup;
  508     this->fops->create = dht_create;
  509     this->fops->mknod = dht_mknod;
  510 }
  511 
  512 int
  513 nufa_find_local_subvol(xlator_t *this, void (*fn)(xlator_t *each, void *data),
  514                        void *data)
  515 {
  516     int ret = -1;
  517     dht_conf_t *conf = this->private;
  518     xlator_list_t *trav = NULL;
  519     xlator_t *parent = NULL;
  520     xlator_t *candidate = NULL;
  521 
  522     xlator_foreach_depth_first(this, fn, data);
  523     if (!conf->private) {
  524         gf_msg(this->name, GF_LOG_ERROR, 0, DHT_MSG_BRICK_ERROR,
  525                "Couldn't find a local "
  526                "brick");
  527         return -1;
  528     }
  529 
  530     candidate = conf->private;
  531     trav = candidate->parents;
  532     while (trav) {
  533         parent = trav->xlator;
  534         if (strcmp(parent->type, "cluster/nufa") == 0) {
  535             gf_msg(this->name, GF_LOG_INFO, 0, DHT_MSG_SUBVOL_INFO,
  536                    "Found local subvol, "
  537                    "%s",
  538                    candidate->name);
  539             ret = 0;
  540             conf->private = candidate;
  541             break;
  542         }
  543 
  544         candidate = parent;
  545         trav = parent->parents;
  546     }
  547 
  548     return ret;
  549 }
  550 
  551 int
  552 nufa_init(xlator_t *this)
  553 {
  554     data_t *data = NULL;
  555     char *local_volname = NULL;
  556     int ret = -1;
  557     char my_hostname[256];
  558     gf_boolean_t addr_match = _gf_false;
  559     nufa_args_t args = {
  560         0,
  561     };
  562 
  563     ret = dht_init(this);
  564     if (ret) {
  565         return ret;
  566     }
  567 
  568     if ((data = dict_get(this->options, "local-volume-name"))) {
  569         local_volname = data->data;
  570 
  571     } else {
  572         addr_match = _gf_true;
  573         local_volname = "localhost";
  574         ret = gethostname(my_hostname, 256);
  575         if (ret == 0)
  576             local_volname = my_hostname;
  577 
  578         else
  579             gf_msg(this->name, GF_LOG_WARNING, errno,
  580                    DHT_MSG_GET_HOSTNAME_FAILED, "could not find hostname");
  581     }
  582 
  583     args.this = this;
  584     args.volname = local_volname;
  585     args.addr_match = addr_match;
  586     ret = nufa_find_local_subvol(this, nufa_find_local_brick, &args);
  587     if (ret) {
  588         gf_msg(this->name, GF_LOG_INFO, 0, DHT_MSG_SUBVOL_INFO,
  589                "Unable to find local subvolume, switching "
  590                "to dht mode");
  591         nufa_to_dht(this);
  592     }
  593     return 0;
  594 }
  595 
  596 dht_methods_t dht_methods = {
  597     .migration_get_dst_subvol = dht_migration_get_dst_subvol,
  598     .migration_needed = dht_migration_needed,
  599     .layout_search = dht_layout_search,
  600 };
  601 
  602 struct xlator_fops fops = {
  603     .lookup = nufa_lookup,
  604     .create = nufa_create,
  605     .mknod = nufa_mknod,
  606 
  607     .stat = dht_stat,
  608     .fstat = dht_fstat,
  609     .truncate = dht_truncate,
  610     .ftruncate = dht_ftruncate,
  611     .access = dht_access,
  612     .readlink = dht_readlink,
  613     .setxattr = dht_setxattr,
  614     .getxattr = dht_getxattr,
  615     .removexattr = dht_removexattr,
  616     .open = dht_open,
  617     .readv = dht_readv,
  618     .writev = dht_writev,
  619     .flush = dht_flush,
  620     .fsync = dht_fsync,
  621     .statfs = dht_statfs,
  622     .lk = dht_lk,
  623     .opendir = dht_opendir,
  624     .readdir = dht_readdir,
  625     .readdirp = dht_readdirp,
  626     .fsyncdir = dht_fsyncdir,
  627     .symlink = dht_symlink,
  628     .unlink = dht_unlink,
  629     .link = dht_link,
  630     .mkdir = dht_mkdir,
  631     .rmdir = dht_rmdir,
  632     .rename = dht_rename,
  633     .inodelk = dht_inodelk,
  634     .finodelk = dht_finodelk,
  635     .entrylk = dht_entrylk,
  636     .fentrylk = dht_fentrylk,
  637     .xattrop = dht_xattrop,
  638     .fxattrop = dht_fxattrop,
  639     .setattr = dht_setattr,
  640 };
  641 
  642 struct xlator_cbks cbks = {.forget = dht_forget};
  643 extern int32_t
  644 mem_acct_init(xlator_t *this);
  645 
  646 xlator_api_t xlator_api = {
  647     .init = nufa_init,
  648     .fini = dht_fini,
  649     .notify = dht_notify,
  650     .reconfigure = dht_reconfigure,
  651     .mem_acct_init = mem_acct_init,
  652     .op_version = {1}, /* Present from the initial version */
  653     .fops = &fops,
  654     .cbks = &cbks,
  655     .options = dht_options,
  656     .identifier = "nufa",
  657     .category = GF_TECH_PREVIEW,
  658 };