diff options
Diffstat (limited to 'libglusterfs/src/gf-dirent.c')
| -rw-r--r-- | libglusterfs/src/gf-dirent.c | 366 |
1 files changed, 255 insertions, 111 deletions
diff --git a/libglusterfs/src/gf-dirent.c b/libglusterfs/src/gf-dirent.c index 2023c19836f..a809efc97ef 100644 --- a/libglusterfs/src/gf-dirent.c +++ b/libglusterfs/src/gf-dirent.c @@ -1,157 +1,301 @@ /* - Copyright (c) 2008-2009 Z RESEARCH, Inc. <http://www.zresearch.com> + Copyright (c) 2008-2012 Red Hat, Inc. <http://www.redhat.com> This file is part of GlusterFS. - GlusterFS is free software; you can redistribute it and/or modify - it under the terms of the GNU General Public License as published - by the Free Software Foundation; either version 3 of the License, - or (at your option) any later version. - - GlusterFS is distributed in the hope that it will be useful, but - WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - General Public License for more details. - - You should have received a copy of the GNU General Public License - along with this program. If not, see - <http://www.gnu.org/licenses/>. + This file is licensed to you under your choice of the GNU Lesser + General Public License, version 3 or any later version (LGPLv3 or + later), or the GNU General Public License, version 2 (GPLv2), in all + 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 "byte-order.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; -struct gf_dirent_nb { - uint64_t d_ino; - uint64_t d_off; - uint32_t d_len; - uint32_t d_type; - char d_name[0]; -} __attribute__((packed)); + while (ctrl < num) { + ctrl *= 2; + bits++; + } + return bits; +} int -gf_dirent_nb_size (gf_dirent_t *entries) +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) { - return (sizeof (struct gf_dirent_nb) + strlen (entries->d_name) + 1); + 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 = CALLOC (gf_dirent_size (name), 1); - 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_free (gf_dirent_t *entries) +gf_dirent_entry_free(gf_dirent_t *entry) { - gf_dirent_t *entry = NULL; - gf_dirent_t *tmp = NULL; + if (!entry) + return; - list_for_each_entry_safe (entry, tmp, &entries->list, list) { - list_del (&entry->list); - FREE (entry); - } -} + if (entry->dict) + dict_unref(entry->dict); + if (entry->inode) + inode_unref(entry->inode); + list_del_init(&entry->list); + GF_FREE(entry); +} -int -gf_dirent_serialize (gf_dirent_t *entries, char *buf, size_t buf_size) +void +gf_dirent_free(gf_dirent_t *entries) { - struct gf_dirent_nb *entry_nb = NULL; - gf_dirent_t *entry = NULL; - int size = 0; - int entry_size = 0; - - - list_for_each_entry (entry, &entries->list, list) { - entry_size = gf_dirent_nb_size (entry); + gf_dirent_t *entry = NULL; + gf_dirent_t *tmp = NULL; - if (buf && (size + entry_size <= buf_size)) { - entry_nb = (void *) (buf + size); + if (!entries) + return; - entry_nb->d_ino = hton64 (entry->d_ino); - entry_nb->d_off = hton64 (entry->d_off); - entry_nb->d_len = hton32 (entry->d_len); - entry_nb->d_type = hton32 (entry->d_type); + if (list_empty(&entries->list)) + return; - strcpy (entry_nb->d_name, entry->d_name); - } - size += entry_size; - } - - return size; + list_for_each_entry_safe(entry, tmp, &entries->list, list) + { + gf_dirent_entry_free(entry); + } } - -int -gf_dirent_unserialize (gf_dirent_t *entries, const char *buf, size_t buf_size) +gf_dirent_t * +entry_copy(gf_dirent_t *source) { - struct gf_dirent_nb *entry_nb = NULL; - int remaining_size = 0; - int least_dirent_size = 0; - int count = 0; - gf_dirent_t *entry = NULL; - int entry_strlen = 0; - int entry_len = 0; + gf_dirent_t *sink = NULL; + sink = gf_dirent_for_name(source->d_name); + if (!sink) + return NULL; - remaining_size = buf_size; - least_dirent_size = (sizeof (struct gf_dirent_nb) + 2); + 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; - while (remaining_size >= least_dirent_size) { - entry_nb = (void *)(buf + (buf_size - remaining_size)); + if (source->inode) + sink->inode = inode_ref(source->inode); - entry_strlen = strnlen (entry_nb->d_name, remaining_size); - if (entry_strlen == remaining_size) { - break; - } + if (source->dict) + sink->dict = dict_ref(source->dict); + return sink; +} - entry_len = sizeof (gf_dirent_t) + entry_strlen + 1; - entry = CALLOC (1, entry_len); - if (!entry) { - break; - } +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; + + 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); +} - entry->d_ino = ntoh64 (entry_nb->d_ino); - entry->d_off = ntoh64 (entry_nb->d_off); - entry->d_len = ntoh32 (entry_nb->d_len); - entry->d_type = ntoh32 (entry_nb->d_type); - strcpy (entry->d_name, entry_nb->d_name); +/* TODO: Currently, with this function, we will be breaking the + policy of 1-1 mapping of kernel nlookup refs with our inode_t's + nlookup count. + Need more thoughts before finalizing this function +*/ +int +gf_link_inodes_from_dirent(xlator_t *this, inode_t *parent, + gf_dirent_t *entries) +{ + gf_dirent_t *entry = NULL; - list_add_tail (&entry->list, &entries->list); + list_for_each_entry(entry, &entries->list, list) + { + gf_link_inode_from_dirent(this, parent, entry); + } - remaining_size -= (sizeof (*entry_nb) + entry_strlen + 1); - count++; - } + return 0; +} - return count; +int +gf_fill_iatt_for_dirent(gf_dirent_t *entry, inode_t *parent, xlator_t *subvol) +{ + 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; } |
