diff options
Diffstat (limited to 'xlators/cluster/dht/src/dht-selfheal.c')
| -rw-r--r-- | xlators/cluster/dht/src/dht-selfheal.c | 454 |
1 files changed, 72 insertions, 382 deletions
diff --git a/xlators/cluster/dht/src/dht-selfheal.c b/xlators/cluster/dht/src/dht-selfheal.c index 8b7d15ce5..ddd043dc8 100644 --- a/xlators/cluster/dht/src/dht-selfheal.c +++ b/xlators/cluster/dht/src/dht-selfheal.c @@ -1,11 +1,20 @@ /* - Copyright (c) 2008-2012 Red Hat, Inc. <http://www.redhat.com> + Copyright (c) 2008-2010 Gluster, Inc. <http://www.gluster.com> 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. + GlusterFS is free software; you can redistribute it and/or modify + it under the terms of the GNU Affero 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 + Affero General Public License for more details. + + You should have received a copy of the GNU Affero General Public License + along with this program. If not, see + <http://www.gnu.org/licenses/>. */ #ifndef _CONFIG_H @@ -18,51 +27,6 @@ #include "xlator.h" #include "dht-common.h" -#define DHT_SET_LAYOUT_RANGE(layout,i,srt,chunk,cnt,path) do { \ - layout->list[i].start = srt; \ - layout->list[i].stop = srt + chunk - 1; \ - \ - gf_log (this->name, GF_LOG_TRACE, \ - "gave fix: %u - %u on %s for %s", \ - layout->list[i].start, layout->list[i].stop, \ - layout->list[i].xlator->name, path); \ - } while (0) - -static inline uint32_t -dht_find_overlap (int idx, int cnk_idx, uint32_t start, uint32_t stop, - uint32_t chunk_size) -{ - uint32_t overlap = 0; - uint32_t chunk_begin = 0; - - chunk_begin = cnk_idx * chunk_size; - - /* There is no chance of overlap */ - if ((chunk_begin > stop) || - ((chunk_begin + chunk_size) < start)) - goto out; - - if ((chunk_begin <= start) && - ((chunk_begin + chunk_size) <= stop)) { - overlap = ((chunk_begin + chunk_size) - start); - goto out; - } - - if ((chunk_begin <= start) && - ((chunk_begin + chunk_size) >= stop)) { - overlap = (stop - start); - goto out; - } - - if ((chunk_begin < stop) && - ((chunk_begin + chunk_size) >= stop)) { - overlap = (stop - chunk_begin); - goto out; - } - -out: - return overlap; -} int dht_selfheal_dir_finish (call_frame_t *frame, xlator_t *this, int ret) @@ -71,7 +35,7 @@ dht_selfheal_dir_finish (call_frame_t *frame, xlator_t *this, int ret) local = frame->local; local->selfheal.dir_cbk (frame, NULL, frame->this, ret, - local->op_errno, NULL); + local->op_errno); return 0; } @@ -79,7 +43,7 @@ dht_selfheal_dir_finish (call_frame_t *frame, xlator_t *this, int ret) int dht_selfheal_dir_xattr_cbk (call_frame_t *frame, void *cookie, xlator_t *this, - int op_ret, int op_errno, dict_t *xdata) + int op_ret, int op_errno) { dht_local_t *local = NULL; call_frame_t *prev = NULL; @@ -125,18 +89,11 @@ dht_selfheal_dir_xattr_persubvol (call_frame_t *frame, loc_t *loc, int ret = 0; xlator_t *this = NULL; int32_t *disk_layout = NULL; - dht_local_t *local = NULL; - local = frame->local; subvol = layout->list[i].xlator; this = frame->this; - GF_VALIDATE_OR_GOTO ("", this, err); - GF_VALIDATE_OR_GOTO (this->name, layout, err); - GF_VALIDATE_OR_GOTO (this->name, local, err); - GF_VALIDATE_OR_GOTO (this->name, subvol, err); - xattr = get_new_dict (); if (!xattr) { goto err; @@ -167,12 +124,9 @@ dht_selfheal_dir_xattr_persubvol (call_frame_t *frame, loc_t *loc, dict_ref (xattr); - if (!uuid_is_null (local->gfid)) - uuid_copy (loc->gfid, local->gfid); - STACK_WIND (frame, dht_selfheal_dir_xattr_cbk, subvol, subvol->fops->setxattr, - loc, xattr, 0, NULL); + loc, xattr, 0); dict_unref (xattr); @@ -182,37 +136,14 @@ err: if (xattr) dict_destroy (xattr); - GF_FREE (disk_layout); + if (disk_layout) + GF_FREE (disk_layout); dht_selfheal_dir_xattr_cbk (frame, subvol, frame->this, - -1, ENOMEM, NULL); + -1, ENOMEM); return 0; } -int -dht_fix_dir_xattr (call_frame_t *frame, loc_t *loc, dht_layout_t *layout) -{ - dht_local_t *local = NULL; - int i = 0; - int count = 0; - xlator_t *this = NULL; - - local = frame->local; - this = frame->this; - - gf_log (this->name, GF_LOG_DEBUG, - "writing the new range for all subvolumes"); - - local->call_cnt = count = layout->cnt; - - for (i = 0; i < layout->cnt; i++) { - dht_selfheal_dir_xattr_persubvol (frame, loc, layout, i); - - if (--count == 0) - break; - } - return 0; -} int dht_selfheal_dir_xattr (call_frame_t *frame, loc_t *loc, dht_layout_t *layout) @@ -228,7 +159,7 @@ dht_selfheal_dir_xattr (call_frame_t *frame, loc_t *loc, dht_layout_t *layout) for (i = 0; i < layout->cnt; i++) { if (layout->list[i].err != -1 || !layout->list[i].stop) { /* err != -1 would mean xattr present on the directory - * or the directory is non existent. + * or the directory is itself non existant. * !layout->list[i].stop would mean layout absent */ @@ -263,7 +194,7 @@ dht_selfheal_dir_xattr (call_frame_t *frame, loc_t *loc, dht_layout_t *layout) int dht_selfheal_dir_setattr_cbk (call_frame_t *frame, void *cookie, xlator_t *this, int op_ret, int op_errno, struct iatt *statpre, - struct iatt *statpost, dict_t *xdata) + struct iatt *statpost) { dht_local_t *local = NULL; dht_layout_t *layout = NULL; @@ -304,9 +235,6 @@ dht_selfheal_dir_setattr (call_frame_t *frame, loc_t *loc, struct iatt *stbuf, return 0; } - if (!uuid_is_null (local->gfid)) - uuid_copy (loc->gfid, local->gfid); - local->call_cnt = missing_attr; for (i = 0; i < layout->cnt; i++) { if (layout->list[i].err == -1) { @@ -317,7 +245,7 @@ dht_selfheal_dir_setattr (call_frame_t *frame, loc_t *loc, struct iatt *stbuf, STACK_WIND (frame, dht_selfheal_dir_setattr_cbk, layout->list[i].xlator, layout->list[i].xlator->fops->setattr, - loc, stbuf, valid, NULL); + loc, stbuf, valid); } } @@ -328,8 +256,7 @@ int dht_selfheal_dir_mkdir_cbk (call_frame_t *frame, void *cookie, xlator_t *this, int op_ret, int op_errno, inode_t *inode, struct iatt *stbuf, - struct iatt *preparent, struct iatt *postparent, - dict_t *xdata) + struct iatt *preparent, struct iatt *postparent) { dht_local_t *local = NULL; dht_layout_t *layout = NULL; @@ -362,6 +289,9 @@ dht_selfheal_dir_mkdir_cbk (call_frame_t *frame, void *cookie, xlator_t *this, } dht_iatt_merge (this, &local->stbuf, stbuf, prev->this); + if (prev->this == local->hashed_subvol) + local->ia_ino = local->stbuf.ia_ino; + dht_iatt_merge (this, &local->preparent, preparent, prev->this); dht_iatt_merge (this, &local->postparent, postparent, prev->this); @@ -375,46 +305,6 @@ out: return 0; } -void -dht_selfheal_dir_mkdir_setacl (dict_t *xattr, dict_t *dict) -{ - data_t *acl_default = NULL; - data_t *acl_access = NULL; - xlator_t *this = NULL; - int ret = -1; - - GF_ASSERT (xattr); - GF_ASSERT (dict); - - this = THIS; - GF_ASSERT (this); - - acl_default = dict_get (xattr, POSIX_ACL_DEFAULT_XATTR); - - if (!acl_default) { - gf_log (this->name, GF_LOG_DEBUG, - "ACL_DEFAULT xattr not present"); - goto cont; - } - ret = dict_set (dict, POSIX_ACL_DEFAULT_XATTR, acl_default); - if (ret) - gf_log (this->name, GF_LOG_WARNING, - "Could not set ACL_DEFAULT xattr"); -cont: - acl_access = dict_get (xattr, POSIX_ACL_ACCESS_XATTR); - if (!acl_access) { - gf_log (this->name, GF_LOG_DEBUG, - "ACL_ACCESS xattr not present"); - goto out; - } - ret = dict_set (dict, POSIX_ACL_ACCESS_XATTR, acl_access); - if (ret) - gf_log (this->name, GF_LOG_WARNING, - "Could not set ACL_ACCESS xattr"); - -out: - return; -} int dht_selfheal_dir_mkdir (call_frame_t *frame, loc_t *loc, @@ -448,19 +338,16 @@ dht_selfheal_dir_mkdir (call_frame_t *frame, loc_t *loc, ret = dict_set_static_bin (dict, "gfid-req", local->gfid, 16); if (ret) - gf_log (this->name, GF_LOG_WARNING, + gf_log (this->name, GF_LOG_INFO, "%s: failed to set gfid in dict", loc->path); } else if (local->params) { /* Send the dictionary from higher layers directly */ dict = dict_ref (local->params); } - /* Set acls */ - if (local->xattr && dict) - dht_selfheal_dir_mkdir_setacl (local->xattr, dict); if (!dict) - gf_log (this->name, GF_LOG_WARNING, - "dict is NULL, need to make sure gfids are same"); + gf_log (this->name, GF_LOG_DEBUG, + "dict is NULL, need to make sure gfid's are same"); for (i = 0; i < layout->cnt; i++) { if (layout->list[i].err == ENOENT || force) { @@ -474,7 +361,7 @@ dht_selfheal_dir_mkdir (call_frame_t *frame, loc_t *loc, loc, st_mode_from_ia (local->stbuf.ia_prot, local->stbuf.ia_type), - 0, dict); + dict); } } @@ -501,229 +388,40 @@ dht_selfheal_layout_alloc_start (xlator_t *this, loc_t *loc, return start; } -static inline int -dht_get_layout_count (xlator_t *this, dht_layout_t *layout, int new_layout) + +void +dht_selfheal_layout_new_directory (call_frame_t *frame, loc_t *loc, + dht_layout_t *layout) { - int i = 0; - int j = 0; - int err = 0; - int count = 0; - dht_conf_t *conf = NULL; + xlator_t *this = NULL; + uint32_t chunk = 0; + int i = 0; + uint32_t start = 0; + int cnt = 0; + int err = 0; + int start_subvol = 0; - /* Gets in use only for replace-brick, remove-brick */ - conf = this->private; - for (i = 0; i < layout->cnt; i++) { - for (j = 0; j < conf->subvolume_cnt; j++) { - if (conf->decommissioned_bricks[j] && - conf->decommissioned_bricks[j] == layout->list[i].xlator) { - layout->list[i].err = -EINVAL; - break; - } - } - } + this = frame->this; for (i = 0; i < layout->cnt; i++) { err = layout->list[i].err; if (err == -1 || err == 0) { layout->list[i].err = -1; - count++; + cnt++; } } /* no subvolume has enough space, but can't stop directory creation */ - if (!count || !new_layout) { + if (!cnt) { for (i = 0; i < layout->cnt; i++) { err = layout->list[i].err; if (err == ENOSPC) { layout->list[i].err = -1; - count++; - } - } - } - - count = ((layout->spread_cnt) ? layout->spread_cnt : - ((count) ? count : 1)); - - return count; -} - - -dht_layout_t * -dht_fix_layout_of_directory (call_frame_t *frame, loc_t *loc, - dht_layout_t *layout) -{ - uint32_t chunk = 0; - uint32_t start = 0; - uint32_t stop = 0; - uint32_t overlap = 0; - uint32_t max_overlap = 0; - uint32_t chunk_begin = 0; - int count = 0; - int cnt = 0; - int i = 0; - int j = 0; - int k = 0; - int loop_cnt = 0; - int start_subvol = 0; - int *fix_array = NULL; - xlator_t *this = NULL; - dht_layout_t *new_layout = NULL; - dht_conf_t *priv = NULL; - dht_local_t *local = NULL; - - this = frame->this; - priv = this->private; - local = frame->local; - - if (layout->type == DHT_HASH_TYPE_DM_USER) { - gf_log (THIS->name, GF_LOG_DEBUG, "leaving %s alone", - loc->path); - goto done; - } - - count = cnt = dht_get_layout_count (this, layout, 0); - - chunk = ((unsigned long) 0xffffffff) / ((cnt) ? cnt : 1); - - start_subvol = dht_selfheal_layout_alloc_start (this, loc, layout); - - fix_array = GF_CALLOC (sizeof (int), layout->cnt, gf_common_mt_char); - if (!fix_array) { - /* No fix, use the existing layout itself */ - goto done; - } - - new_layout = dht_layout_new (this, priv->subvolume_cnt); - if (!new_layout) - goto done; - - for (i = 0; i < new_layout->cnt; i++) { - /* TODO: fix this in layout_alloc() itself */ - new_layout->list[i].err = -ENOENT; - if (i < layout->cnt) - new_layout->list[i].xlator = layout->list[i].xlator; - } - - /* Check if there are any overlap in layout, and give the proper fix */ - for (i = 0; i < layout->cnt; i++) { - /* No need to fix if 'err' is not '-1' */ - if (layout->list[i].err != -1) - continue; - - /* If already existing layout is having no range, skip it */ - start = layout->list[i].start; - stop = layout->list[i].stop; - if ((stop - start) == 0) - continue; - - max_overlap = 0; - - /* 'j' is used as starting point of each chunk */ - for (j = 1; j <= count; j++) { - /* if chunk is already used, don't use it again */ - for (k = 0; k < i; k++) - if (j == fix_array[k]) - break; - if (k < i) - continue; - - overlap = dht_find_overlap (i, (j-1), start, stop, chunk); - if (max_overlap < overlap) { - max_overlap = overlap; - fix_array[i] = j; + cnt++; } } - - /* If we have any overlap, then use that itself as new - layout for the subvolume */ - if (fix_array[i]) { - chunk_begin = chunk * (fix_array[i] - 1); - new_layout->list[i].err = -1; - DHT_SET_LAYOUT_RANGE (new_layout, i, chunk_begin, - chunk, cnt, loc->path); - /* make sure to give (max - 1) as 'stop' range, - if it is last chunk */ - if (fix_array[i] == count) - new_layout->list[i].stop = 0xffffffff; - if (--cnt == 0) - goto done; - - } } - /* Now, look for layouts which are not having any overlaps - and give it a fix */ - for (loop_cnt = 0, i = start_subvol; loop_cnt < new_layout->cnt; - i++, loop_cnt++) { - if (i == new_layout->cnt) - i = 0; - - /* If 'fix_array[i]' is set, the layout is already fixed. */ - if (fix_array[i]) - continue; - - if (layout->list[i].err != -1) { - new_layout->list[i].err = layout->list[i].err; - continue; - } - - for (k = 1; k <= count; k++) { - for (j = 0; j < new_layout->cnt; j++) { - if (k == fix_array[j]) - break; - } - /* Didn't find any of the list begining with 'k' */ - if (j == new_layout->cnt) - break; - } - - fix_array[i] = k; - chunk_begin = (k - 1) * chunk; - new_layout->list[i].err = -1; - DHT_SET_LAYOUT_RANGE (new_layout, i, chunk_begin, chunk, cnt, - loc->path); - /* make sure to give (max - 1) as 'stop' range, - if it is last chunk */ - if (k == count) - new_layout->list[i].stop = 0xffffffff; - if (--cnt == 0) - goto done; - } - -done: - if (new_layout) { - /* Now that the new layout has all the proper layout, change the - inode context */ - dht_layout_set (this, loc->inode, new_layout); - - /* Make sure the extra 'ref' for existing layout is removed */ - dht_layout_unref (this, local->layout); - - local->layout = new_layout; - } - - GF_FREE (fix_array); - - return local->layout; -} - - -void -dht_selfheal_layout_new_directory (call_frame_t *frame, loc_t *loc, - dht_layout_t *layout) -{ - xlator_t *this = NULL; - uint32_t chunk = 0; - int i = 0; - uint32_t start = 0; - int cnt = 0; - int err = 0; - int start_subvol = 0; - - this = frame->this; - - cnt = dht_get_layout_count (this, layout, 1); - chunk = ((unsigned long) 0xffffffff) / ((cnt) ? cnt : 1); start_subvol = dht_selfheal_layout_alloc_start (this, loc, layout); @@ -731,33 +429,43 @@ dht_selfheal_layout_new_directory (call_frame_t *frame, loc_t *loc, for (i = start_subvol; i < layout->cnt; i++) { err = layout->list[i].err; if (err == -1) { - DHT_SET_LAYOUT_RANGE(layout, i, start, chunk, - cnt, loc->path); + layout->list[i].start = start; + layout->list[i].stop = start + chunk - 1; + + start = start + chunk; + + gf_log (this->name, GF_LOG_TRACE, + "gave fix: %u - %u on %s for %s", + layout->list[i].start, layout->list[i].stop, + layout->list[i].xlator->name, loc->path); if (--cnt == 0) { layout->list[i].stop = 0xffffffff; - goto done; + break; } - start += chunk; } } for (i = 0; i < start_subvol; i++) { err = layout->list[i].err; if (err == -1) { - DHT_SET_LAYOUT_RANGE(layout, i, start, chunk, - cnt, loc->path); + layout->list[i].start = start; + layout->list[i].stop = start + chunk - 1; + + start = start + chunk; + + gf_log (this->name, GF_LOG_TRACE, + "gave fix: %u - %u on %s for %s", + layout->list[i].start, layout->list[i].stop, + layout->list[i].xlator->name, loc->path); if (--cnt == 0) { layout->list[i].stop = 0xffffffff; - goto done; + break; } - start += chunk; } } - -done: - return; } + int dht_selfheal_dir_getafix (call_frame_t *frame, loc_t *loc, dht_layout_t *layout) @@ -827,32 +535,13 @@ dht_selfheal_new_directory (call_frame_t *frame, return 0; } -int -dht_fix_directory_layout (call_frame_t *frame, - dht_selfheal_dir_cbk_t dir_cbk, - dht_layout_t *layout) -{ - dht_local_t *local = NULL; - dht_layout_t *tmp_layout = NULL; - - local = frame->local; - - local->selfheal.dir_cbk = dir_cbk; - local->selfheal.layout = dht_layout_ref (frame->this, layout); - - /* No layout sorting required here */ - tmp_layout = dht_fix_layout_of_directory (frame, &local->loc, layout); - dht_fix_dir_xattr (frame, &local->loc, tmp_layout); - - return 0; -} - int dht_selfheal_directory (call_frame_t *frame, dht_selfheal_dir_cbk_t dir_cbk, loc_t *loc, dht_layout_t *layout) { dht_local_t *local = NULL; + uint32_t holes = 0; uint32_t down = 0; uint32_t misc = 0; int ret = 0; @@ -868,6 +557,7 @@ dht_selfheal_directory (call_frame_t *frame, dht_selfheal_dir_cbk_t dir_cbk, &local->selfheal.down, &local->selfheal.misc); + holes = local->selfheal.hole_cnt; down = local->selfheal.down; misc = local->selfheal.misc; @@ -875,14 +565,14 @@ dht_selfheal_directory (call_frame_t *frame, dht_selfheal_dir_cbk_t dir_cbk, local->selfheal.layout = dht_layout_ref (this, layout); if (down) { - gf_log (this->name, GF_LOG_WARNING, + gf_log (this->name, GF_LOG_INFO, "%d subvolumes down -- not fixing", down); ret = 0; goto sorry_no_fix; } if (misc) { - gf_log (this->name, GF_LOG_WARNING, + gf_log (this->name, GF_LOG_INFO, "%d subvolumes have unrecoverable errors", misc); ret = 0; goto sorry_no_fix; @@ -892,7 +582,7 @@ dht_selfheal_directory (call_frame_t *frame, dht_selfheal_dir_cbk_t dir_cbk, ret = dht_selfheal_dir_getafix (frame, loc, layout); if (ret == -1) { - gf_log (this->name, GF_LOG_WARNING, + gf_log (this->name, GF_LOG_INFO, "not able to form layout for the directory"); goto sorry_no_fix; } |
