diff options
Diffstat (limited to 'libglusterfs/src/gf-dirent.c')
| -rw-r--r-- | libglusterfs/src/gf-dirent.c | 315 |
1 files changed, 262 insertions, 53 deletions
diff --git a/libglusterfs/src/gf-dirent.c b/libglusterfs/src/gf-dirent.c index bb028c9671d..a809efc97ef 100644 --- a/libglusterfs/src/gf-dirent.c +++ b/libglusterfs/src/gf-dirent.c @@ -8,63 +8,232 @@ cases as published by the Free Software Foundation. */ - -#ifndef _CONFIG_H -#define _CONFIG_H -#include "config.h" -#endif - - #include <stdio.h> #include <string.h> #include <stdint.h> -#include "compat.h" -#include "xlator.h" +#include "glusterfs/compat.h" +#include "glusterfs/syncop.h" + +#define ONE 1ULL +#define PRESENT_D_OFF_BITS 63 +#define BACKEND_D_OFF_BITS 63 +#define TOP_BIT (ONE << (PRESENT_D_OFF_BITS - 1)) +#define MASK (~0ULL) +#define SHIFT_BITS (max(0, (BACKEND_D_OFF_BITS - PRESENT_D_OFF_BITS + 1))) +#define PRESENT_MASK (MASK >> (64 - PRESENT_D_OFF_BITS)) + +static uint64_t +bits_for(uint64_t num) +{ + uint64_t bits = 0, ctrl = 1; + + while (ctrl < num) { + ctrl *= 2; + bits++; + } + + return bits; +} + +int +gf_deitransform(xlator_t *this, uint64_t offset) +{ + int cnt = 0; + int max = 0; + int max_bits = 0; + uint64_t off_mask = 0; + uint64_t host_mask = 0; + + max = glusterfs_get_leaf_count(this->graph); + + if (max == 1) { + cnt = 0; + goto out; + } + + if (offset & TOP_BIT) { + /* HUGE d_off */ + max_bits = bits_for(max); + off_mask = (MASK << max_bits); + host_mask = ~(off_mask); + + cnt = offset & host_mask; + } else { + /* small d_off */ + cnt = offset % max; + } +out: + return cnt; +} + +uint64_t +gf_dirent_orig_offset(xlator_t *this, uint64_t offset) +{ + int max = 0; + int max_bits = 0; + uint64_t off_mask = 0; + uint64_t orig_offset; + + max = glusterfs_get_leaf_count(this->graph); + + if (max == 1) { + orig_offset = offset; + goto out; + } + + if (offset & TOP_BIT) { + /* HUGE d_off */ + max_bits = bits_for(max); + off_mask = (MASK << max_bits); + orig_offset = ((offset & ~TOP_BIT) & off_mask) << SHIFT_BITS; + } else { + /* small d_off */ + orig_offset = offset / max; + } +out: + return orig_offset; +} + +int +gf_itransform(xlator_t *this, uint64_t x, uint64_t *y_p, int client_id) +{ + int max = 0; + uint64_t y = 0; + uint64_t hi_mask = 0; + uint64_t off_mask = 0; + int max_bits = 0; + + if (x == ((uint64_t)-1)) { + y = (uint64_t)-1; + goto out; + } + + if (!x) { + y = 0; + goto out; + } + + max = glusterfs_get_leaf_count(this->graph); + + if (max == 1) { + y = x; + goto out; + } + + max_bits = bits_for(max); + + hi_mask = ~(PRESENT_MASK >> (max_bits + 1)); + + if (x & hi_mask) { + /* HUGE d_off */ + off_mask = MASK << max_bits; + y = TOP_BIT | ((x >> SHIFT_BITS) & off_mask) | client_id; + } else { + /* small d_off */ + y = ((x * max) + client_id); + } + +out: + if (y_p) + *y_p = y; + + return 0; +} gf_dirent_t * -gf_dirent_for_name (const char *name) +gf_dirent_for_name(const char *name) { - gf_dirent_t *gf_dirent = NULL; + gf_dirent_t *gf_dirent = NULL; - /* TODO: use mem-pool */ - gf_dirent = GF_CALLOC (gf_dirent_size (name), 1, - gf_common_mt_gf_dirent_t); - if (!gf_dirent) - return NULL; + /* TODO: use mem-pool */ + gf_dirent = GF_CALLOC(gf_dirent_size(name), 1, gf_common_mt_gf_dirent_t); + if (!gf_dirent) + return NULL; - INIT_LIST_HEAD (&gf_dirent->list); - strcpy (gf_dirent->d_name, name); + INIT_LIST_HEAD(&gf_dirent->list); + strcpy(gf_dirent->d_name, name); - gf_dirent->d_off = 0; - gf_dirent->d_ino = -1; - gf_dirent->d_type = 0; - gf_dirent->d_len = strlen (name); + gf_dirent->d_off = 0; + gf_dirent->d_ino = -1; + gf_dirent->d_type = 0; + gf_dirent->d_len = strlen(name); - return gf_dirent; + return gf_dirent; } +void +gf_dirent_entry_free(gf_dirent_t *entry) +{ + if (!entry) + return; + + if (entry->dict) + dict_unref(entry->dict); + if (entry->inode) + inode_unref(entry->inode); + + list_del_init(&entry->list); + GF_FREE(entry); +} void -gf_dirent_free (gf_dirent_t *entries) +gf_dirent_free(gf_dirent_t *entries) { - gf_dirent_t *entry = NULL; - gf_dirent_t *tmp = NULL; + gf_dirent_t *entry = NULL; + gf_dirent_t *tmp = NULL; + + if (!entries) + return; + + if (list_empty(&entries->list)) + return; + + list_for_each_entry_safe(entry, tmp, &entries->list, list) + { + gf_dirent_entry_free(entry); + } +} + +gf_dirent_t * +entry_copy(gf_dirent_t *source) +{ + gf_dirent_t *sink = NULL; + + sink = gf_dirent_for_name(source->d_name); + if (!sink) + return NULL; - if (!entries) - return; + sink->d_off = source->d_off; + sink->d_ino = source->d_ino; + sink->d_type = source->d_type; + sink->d_stat = source->d_stat; + sink->d_len = source->d_len; - if (list_empty (&entries->list)) - return; + if (source->inode) + sink->inode = inode_ref(source->inode); - list_for_each_entry_safe (entry, tmp, &entries->list, list) { - if (entry->dict) - dict_unref (entry->dict); - if (entry->inode) - inode_unref (entry->inode); + if (source->dict) + sink->dict = dict_ref(source->dict); + return sink; +} + +void +gf_link_inode_from_dirent(xlator_t *this, inode_t *parent, gf_dirent_t *entry) +{ + inode_t *link_inode = NULL; + inode_t *tmp = NULL; - list_del (&entry->list); - GF_FREE (entry); - } + if (!entry->inode) + return; + link_inode = inode_link(entry->inode, parent, entry->d_name, + &entry->d_stat); + if (!link_inode) + return; + + inode_lookup(link_inode); + tmp = entry->inode; + entry->inode = link_inode; + inode_unref(tmp); } /* TODO: Currently, with this function, we will be breaking the @@ -73,20 +242,60 @@ gf_dirent_free (gf_dirent_t *entries) Need more thoughts before finalizing this function */ int -gf_link_inodes_from_dirent (xlator_t *this, inode_t *parent, - gf_dirent_t *entries) +gf_link_inodes_from_dirent(xlator_t *this, inode_t *parent, + gf_dirent_t *entries) +{ + gf_dirent_t *entry = NULL; + + list_for_each_entry(entry, &entries->list, list) + { + gf_link_inode_from_dirent(this, parent, entry); + } + + return 0; +} + +int +gf_fill_iatt_for_dirent(gf_dirent_t *entry, inode_t *parent, xlator_t *subvol) { - gf_dirent_t *entry = NULL; - inode_t *link_inode = NULL; - - list_for_each_entry (entry, &entries->list, list) { - if (entry->inode) { - link_inode = inode_link (entry->inode, parent, - entry->d_name, &entry->d_stat); - inode_lookup (link_inode); - inode_unref (link_inode); - } - } - - return 0; + loc_t loc = { + 0, + }; + int ret = -1; + char *path = NULL; + struct iatt iatt = { + 0, + }; + + loc.inode = inode_grep(parent->table, parent, entry->d_name); + if (!loc.inode) { + loc.inode = inode_new(parent->table); + gf_uuid_copy(loc.inode->gfid, entry->d_stat.ia_gfid); + } + + gf_uuid_copy(loc.pargfid, parent->gfid); + loc.name = entry->d_name; + loc.parent = inode_ref(parent); + ret = inode_path(loc.parent, entry->d_name, &path); + loc.path = path; + if (ret < 0) + goto out; + + ret = syncop_lookup(subvol, &loc, &iatt, NULL, NULL, NULL); + if (ret) + goto out; + + entry->d_stat = iatt; + entry->inode = inode_ref(loc.inode); + /* We don't need to link inode here, because as part of readdirp_cbk + * we will link all dirents. + * + * Since we did a proper lookup, we don't need to set need_lookup + * flag. + */ + + ret = 0; +out: + loc_wipe(&loc); + return ret; } |
