"Fossies" - the Fresh Open Source Software Archive

Member "glusterfs-8.2/libglusterfs/src/gf-dirent.c" (16 Sep 2020, 6394 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 "gf-dirent.c" see the Fossies "Dox" file reference documentation and the last Fossies "Diffs" side-by-side code changes report: 8.0_vs_8.1.

    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 <stdio.h>
   12 #include <string.h>
   13 #include <stdint.h>
   14 #include "glusterfs/compat.h"
   15 #include "glusterfs/syncop.h"
   16 
   17 #define ONE 1ULL
   18 #define PRESENT_D_OFF_BITS 63
   19 #define BACKEND_D_OFF_BITS 63
   20 #define TOP_BIT (ONE << (PRESENT_D_OFF_BITS - 1))
   21 #define MASK (~0ULL)
   22 #define SHIFT_BITS (max(0, (BACKEND_D_OFF_BITS - PRESENT_D_OFF_BITS + 1)))
   23 #define PRESENT_MASK (MASK >> (64 - PRESENT_D_OFF_BITS))
   24 
   25 static uint64_t
   26 bits_for(uint64_t num)
   27 {
   28     uint64_t bits = 0, ctrl = 1;
   29 
   30     while (ctrl < num) {
   31         ctrl *= 2;
   32         bits++;
   33     }
   34 
   35     return bits;
   36 }
   37 
   38 int
   39 gf_deitransform(xlator_t *this, uint64_t offset)
   40 {
   41     int cnt = 0;
   42     int max = 0;
   43     int max_bits = 0;
   44     uint64_t off_mask = 0;
   45     uint64_t host_mask = 0;
   46 
   47     max = glusterfs_get_leaf_count(this->graph);
   48 
   49     if (max == 1) {
   50         cnt = 0;
   51         goto out;
   52     }
   53 
   54     if (offset & TOP_BIT) {
   55         /* HUGE d_off */
   56         max_bits = bits_for(max);
   57         off_mask = (MASK << max_bits);
   58         host_mask = ~(off_mask);
   59 
   60         cnt = offset & host_mask;
   61     } else {
   62         /* small d_off */
   63         cnt = offset % max;
   64     }
   65 out:
   66     return cnt;
   67 }
   68 
   69 uint64_t
   70 gf_dirent_orig_offset(xlator_t *this, uint64_t offset)
   71 {
   72     int max = 0;
   73     int max_bits = 0;
   74     uint64_t off_mask = 0;
   75     uint64_t orig_offset;
   76 
   77     max = glusterfs_get_leaf_count(this->graph);
   78 
   79     if (max == 1) {
   80         orig_offset = offset;
   81         goto out;
   82     }
   83 
   84     if (offset & TOP_BIT) {
   85         /* HUGE d_off */
   86         max_bits = bits_for(max);
   87         off_mask = (MASK << max_bits);
   88         orig_offset = ((offset & ~TOP_BIT) & off_mask) << SHIFT_BITS;
   89     } else {
   90         /* small d_off */
   91         orig_offset = offset / max;
   92     }
   93 out:
   94     return orig_offset;
   95 }
   96 
   97 int
   98 gf_itransform(xlator_t *this, uint64_t x, uint64_t *y_p, int client_id)
   99 {
  100     int max = 0;
  101     uint64_t y = 0;
  102     uint64_t hi_mask = 0;
  103     uint64_t off_mask = 0;
  104     int max_bits = 0;
  105 
  106     if (x == ((uint64_t)-1)) {
  107         y = (uint64_t)-1;
  108         goto out;
  109     }
  110 
  111     if (!x) {
  112         y = 0;
  113         goto out;
  114     }
  115 
  116     max = glusterfs_get_leaf_count(this->graph);
  117 
  118     if (max == 1) {
  119         y = x;
  120         goto out;
  121     }
  122 
  123     max_bits = bits_for(max);
  124 
  125     hi_mask = ~(PRESENT_MASK >> (max_bits + 1));
  126 
  127     if (x & hi_mask) {
  128         /* HUGE d_off */
  129         off_mask = MASK << max_bits;
  130         y = TOP_BIT | ((x >> SHIFT_BITS) & off_mask) | client_id;
  131     } else {
  132         /* small d_off */
  133         y = ((x * max) + client_id);
  134     }
  135 
  136 out:
  137     if (y_p)
  138         *y_p = y;
  139 
  140     return 0;
  141 }
  142 
  143 gf_dirent_t *
  144 gf_dirent_for_name(const char *name)
  145 {
  146     gf_dirent_t *gf_dirent = NULL;
  147 
  148     /* TODO: use mem-pool */
  149     gf_dirent = GF_CALLOC(gf_dirent_size(name), 1, gf_common_mt_gf_dirent_t);
  150     if (!gf_dirent)
  151         return NULL;
  152 
  153     INIT_LIST_HEAD(&gf_dirent->list);
  154     strcpy(gf_dirent->d_name, name);
  155 
  156     gf_dirent->d_off = 0;
  157     gf_dirent->d_ino = -1;
  158     gf_dirent->d_type = 0;
  159     gf_dirent->d_len = strlen(name);
  160 
  161     return gf_dirent;
  162 }
  163 
  164 void
  165 gf_dirent_entry_free(gf_dirent_t *entry)
  166 {
  167     if (!entry)
  168         return;
  169 
  170     if (entry->dict)
  171         dict_unref(entry->dict);
  172     if (entry->inode)
  173         inode_unref(entry->inode);
  174 
  175     list_del_init(&entry->list);
  176     GF_FREE(entry);
  177 }
  178 
  179 void
  180 gf_dirent_free(gf_dirent_t *entries)
  181 {
  182     gf_dirent_t *entry = NULL;
  183     gf_dirent_t *tmp = NULL;
  184 
  185     if (!entries)
  186         return;
  187 
  188     if (list_empty(&entries->list))
  189         return;
  190 
  191     list_for_each_entry_safe(entry, tmp, &entries->list, list)
  192     {
  193         gf_dirent_entry_free(entry);
  194     }
  195 }
  196 
  197 gf_dirent_t *
  198 entry_copy(gf_dirent_t *source)
  199 {
  200     gf_dirent_t *sink = NULL;
  201 
  202     sink = gf_dirent_for_name(source->d_name);
  203     if (!sink)
  204         return NULL;
  205 
  206     sink->d_off = source->d_off;
  207     sink->d_ino = source->d_ino;
  208     sink->d_type = source->d_type;
  209     sink->d_stat = source->d_stat;
  210     sink->d_len = source->d_len;
  211 
  212     if (source->inode)
  213         sink->inode = inode_ref(source->inode);
  214 
  215     if (source->dict)
  216         sink->dict = dict_ref(source->dict);
  217     return sink;
  218 }
  219 
  220 void
  221 gf_link_inode_from_dirent(xlator_t *this, inode_t *parent, gf_dirent_t *entry)
  222 {
  223     inode_t *link_inode = NULL;
  224     inode_t *tmp = NULL;
  225 
  226     if (!entry->inode)
  227         return;
  228     link_inode = inode_link(entry->inode, parent, entry->d_name,
  229                             &entry->d_stat);
  230     if (!link_inode)
  231         return;
  232 
  233     inode_lookup(link_inode);
  234     tmp = entry->inode;
  235     entry->inode = link_inode;
  236     inode_unref(tmp);
  237 }
  238 
  239 /* TODO: Currently, with this function, we will be breaking the
  240    policy of 1-1 mapping of kernel nlookup refs with our inode_t's
  241    nlookup count.
  242    Need more thoughts before finalizing this function
  243 */
  244 int
  245 gf_link_inodes_from_dirent(xlator_t *this, inode_t *parent,
  246                            gf_dirent_t *entries)
  247 {
  248     gf_dirent_t *entry = NULL;
  249 
  250     list_for_each_entry(entry, &entries->list, list)
  251     {
  252         gf_link_inode_from_dirent(this, parent, entry);
  253     }
  254 
  255     return 0;
  256 }
  257 
  258 int
  259 gf_fill_iatt_for_dirent(gf_dirent_t *entry, inode_t *parent, xlator_t *subvol)
  260 {
  261     loc_t loc = {
  262         0,
  263     };
  264     int ret = -1;
  265     char *path = NULL;
  266     struct iatt iatt = {
  267         0,
  268     };
  269 
  270     loc.inode = inode_grep(parent->table, parent, entry->d_name);
  271     if (!loc.inode) {
  272         loc.inode = inode_new(parent->table);
  273         gf_uuid_copy(loc.inode->gfid, entry->d_stat.ia_gfid);
  274     }
  275 
  276     gf_uuid_copy(loc.pargfid, parent->gfid);
  277     loc.name = entry->d_name;
  278     loc.parent = inode_ref(parent);
  279     ret = inode_path(loc.parent, entry->d_name, &path);
  280     loc.path = path;
  281     if (ret < 0)
  282         goto out;
  283 
  284     ret = syncop_lookup(subvol, &loc, &iatt, NULL, NULL, NULL);
  285     if (ret)
  286         goto out;
  287 
  288     entry->d_stat = iatt;
  289     entry->inode = inode_ref(loc.inode);
  290     /* We don't need to link inode here, because as part of readdirp_cbk
  291      * we will link all dirents.
  292      *
  293      * Since we did a proper lookup, we don't need to set need_lookup
  294      * flag.
  295      */
  296 
  297     ret = 0;
  298 out:
  299     loc_wipe(&loc);
  300     return ret;
  301 }