/* Copyright (c) 2008-2012 Red Hat, Inc. This file is part of GlusterFS. 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 #include #include #include "compat.h" #include "xlator.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_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; 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); 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_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; 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 (source->inode) sink->inode = inode_ref (source->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; 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 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_for_each_entry (entry, &entries->list, list) { gf_link_inode_from_dirent (this, parent, entry); } return 0; }