diff options
Diffstat (limited to 'xlators/cluster/map/src/map-helper.c')
-rw-r--r-- | xlators/cluster/map/src/map-helper.c | 357 |
1 files changed, 357 insertions, 0 deletions
diff --git a/xlators/cluster/map/src/map-helper.c b/xlators/cluster/map/src/map-helper.c new file mode 100644 index 000000000..4e51219d4 --- /dev/null +++ b/xlators/cluster/map/src/map-helper.c @@ -0,0 +1,357 @@ +/* + Copyright (c) 2009 Z RESEARCH, Inc. <http://www.zresearch.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/>. +*/ + +#ifndef _CONFIG_H +#define _CONFIG_H +#include "config.h" +#endif + +#include "xlator.h" +#include "map.h" + + +xlator_t * +map_subvol_next (xlator_t *this, xlator_t *prev) +{ + map_private_t *priv = NULL; + xlator_t *next = NULL; + int i = 0; + + priv = this->private; + + for (i = 0; i < priv->child_count; i++) { + if (priv->xlarray[i].xl == prev) { + if ((i + 1) < priv->child_count) + next = priv->xlarray[i + 1].xl; + break; + } + } + + return next; +} + +int +map_subvol_cnt (xlator_t *this, xlator_t *subvol) +{ + int i = 0; + int ret = -1; + map_private_t *priv = NULL; + + priv = this->private; + + for (i = 0; i < priv->child_count; i++) { + if (subvol == priv->xlarray[i].xl) { + ret = i; + break; + } + } + + return ret; +} + +int +map_itransform (xlator_t *this, xlator_t *subvol, uint64_t x, uint64_t *y_p) +{ + map_private_t *priv = NULL; + int cnt = 0; + int max = 0; + uint64_t y = 0; + + if (x == ((uint64_t) -1)) { + y = (uint64_t) -1; + goto out; + } + + priv = this->private; + + max = priv->child_count; + cnt = map_subvol_cnt (this, subvol); + + y = ((x * max) + cnt); + +out: + if (y_p) + *y_p = y; + + return 0; +} + + +int +map_deitransform (xlator_t *this, uint64_t y, xlator_t **subvol_p, + uint64_t *x_p) +{ + int cnt = 0; + int max = 0; + uint64_t x = 0; + xlator_t *subvol = 0; + map_private_t *priv = NULL; + + priv = this->private; + max = priv->child_count; + + cnt = y % max; + x = y / max; + + subvol = priv->xlarray[cnt].xl; + + if (subvol_p) + *subvol_p = subvol; + + if (x_p) + *x_p = x; + + return 0; +} + + +xlator_t * +get_mapping_subvol_from_path (xlator_t *this, const char *path) +{ + map_private_t *priv = NULL; + struct map_pattern *map = NULL; + + /* To make sure we handle '/' properly */ + if (!strcmp (path, "/")) + return NULL; + + priv = this->private; + + map = priv->map; + while (map) { + if (!strncmp (map->directory, path, map->dir_len)) { + if ((path[map->dir_len] == '/') || + (path[map->dir_len] == '\0')) { + return map->xl; + } + } + + map = map->next; + } + + return priv->default_xl; +} + +xlator_t * +get_mapping_subvol_from_ctx (xlator_t *this, inode_t *inode) +{ + uint64_t subvol = 0; + int ret = -1; + + ret = inode_ctx_get (inode, this, &subvol); + if (ret != 0) + return NULL; + + return (xlator_t *)(long)subvol; +} + +int +check_multiple_volume_entry (xlator_t *this, + xlator_t *subvol) +{ + int ret = -1; + int idx = 0; + map_private_t *priv = NULL; + + priv = this->private; + + for (idx = 0; idx < priv->child_count; idx++) { + if (priv->xlarray[idx].xl == subvol) { + if (priv->xlarray[idx].mapped) { + gf_log (this->name, GF_LOG_ERROR, + "subvolume '%s' is already mapped", + subvol->name); + goto out; + } + priv->xlarray[idx].mapped = 1; + ret = 0; + goto out; + } + } + + gf_log (this->name, GF_LOG_ERROR, + "subvolume '%s' is not found", + subvol->name); + + out: + return ret; +} + +int +verify_dir_and_assign_subvol (xlator_t *this, + const char *directory, + const char *subvol) +{ + int default_flag = 0; + int ret = -1; + int idx = 0; + map_private_t *priv = NULL; + xlator_list_t *trav = NULL; + struct map_pattern *tmp_map = NULL; + + priv = this->private; + + /* check if directory is valid, ie, its a top level dir, and + * not includes a '*' in it. + */ + if (!strcmp ("*", directory)) { + default_flag = 1; + } else { + if (directory[0] != '/') { + gf_log (this->name, GF_LOG_ERROR, + "map takes absolute path, starting with '/'. " + "not '%s'", directory); + goto out; + } + for (idx = 1; idx < (strlen (directory) - 1); idx++) { + if (directory[idx] == '/') { + gf_log (this->name, GF_LOG_ERROR, + "map takes only top level directory, " + "not '%s'", directory); + goto out; + } + } + } + + /* Assign proper subvolume */ + trav = this->children; + while (trav) { + if (!strcmp (trav->xlator->name, subvol)) { + + /* Check if there is another directory for + * same volume, if yes, return error. + */ + ret = check_multiple_volume_entry (this, + trav->xlator); + if (ret != 0) { + goto out; + } + + ret = 0; + if (default_flag) { + if (priv->default_xl) { + ret = -1; + gf_log (this->name, GF_LOG_ERROR, + "'*' specified more than " + "once. don't confuse me!!!"); + } + + priv->default_xl = trav->xlator; + goto out; + } + + tmp_map = CALLOC (1, sizeof (struct map_pattern)); + tmp_map->xl = trav->xlator; + tmp_map->dir_len = strlen (directory); + + /* make sure that the top level directory starts + * with '/' and ends without '/' + */ + tmp_map->directory = strdup (directory); + if (directory[tmp_map->dir_len - 1] == '/') { + tmp_map->dir_len--; + } + + if (!priv->map) + priv->map = tmp_map; + else { + struct map_pattern *trav_map = NULL; + trav_map = priv->map; + while (trav_map->next) + trav_map = trav_map->next; + trav_map->next = tmp_map; + } + + goto out; + } + + trav = trav->next; + } + + gf_log (this->name, GF_LOG_ERROR, + "map volume '%s' is not proper subvolume", subvol); + + out: + return ret; +} + +int +assign_default_subvol (xlator_t *this, const char *default_xl) +{ + int ret = -1; + map_private_t *priv = NULL; + xlator_list_t *trav = NULL; + + priv = this->private; + trav = this->children; + + while (trav) { + if (!strcmp (trav->xlator->name, default_xl)) { + ret = check_multiple_volume_entry (this, + trav->xlator); + if (ret != 0) { + goto out; + } + if (priv->default_xl) + gf_log (this->name, GF_LOG_WARNING, + "default-volume option provided, " + "overriding earlier '*' option"); + priv->default_xl = trav->xlator; + return 0; + } + trav = trav->next; + } + + gf_log (this->name, GF_LOG_ERROR, + "default-volume value is not an valid subvolume. check again"); + out: + return -1; +} + +void +verify_if_all_subvolumes_got_used (xlator_t *this) +{ + int idx = 0; + map_private_t *priv = NULL; + + priv = this->private; + + for (idx = 0; idx < priv->child_count; idx++) { + if (!priv->xlarray[idx].mapped) { + if (!priv->default_xl) { + priv->default_xl = priv->xlarray[idx].xl; + priv->xlarray[idx].mapped = 1; + } else { + gf_log (this->name, GF_LOG_WARNING, + "subvolume '%s' is not mapped to " + "any directory", + priv->xlarray[idx].xl->name); + } + } + } + + if (!priv->default_xl) { + gf_log (this->name, GF_LOG_WARNING, + "default subvolume not specified, filesystem " + "may not work properly. Check 'map' translator " + "documentation for more info"); + } + + return ; +} |