From abff11e77918a355550fdc3591743cee6cc7103d Mon Sep 17 00:00:00 2001 From: Raghavendra Bhat Date: Tue, 17 Nov 2015 14:45:30 +0530 Subject: features/bit-rot: scrubber changes for getting the list of bad objects from stub Backport of http://review.gluster.org/12654 > Change-Id: I62885e4aba4a9b345db3c78c3291d563ff3d3567 > BUG: 1207627 > Signed-off-by: Raghavendra Bhat > Reviewed-on: http://review.gluster.org/12654 > Tested-by: NetBSD Build System > Tested-by: Gluster Build System > Reviewed-by: Venky Shankar > Signed-off-by: Raghavendra Bhat Change-Id: I8e1f04f3f730cbd90bdf3cdc7b2149d0de53ea37 BUG: 1283881 Signed-off-by: Raghavendra Bhat Reviewed-on: http://review.gluster.org/12716 Tested-by: Gluster Build System Tested-by: NetBSD Build System Reviewed-by: Venky Shankar --- .../bit-rot/src/bitd/bit-rot-bitd-messages.h | 18 +- xlators/features/bit-rot/src/bitd/bit-rot-scrub.c | 277 +++++++++++++++++++++ xlators/features/bit-rot/src/bitd/bit-rot.h | 4 + 3 files changed, 297 insertions(+), 2 deletions(-) (limited to 'xlators/features/bit-rot') diff --git a/xlators/features/bit-rot/src/bitd/bit-rot-bitd-messages.h b/xlators/features/bit-rot/src/bitd/bit-rot-bitd-messages.h index b4746bb5ecb..c0b83c681d7 100644 --- a/xlators/features/bit-rot/src/bitd/bit-rot-bitd-messages.h +++ b/xlators/features/bit-rot/src/bitd/bit-rot-bitd-messages.h @@ -40,7 +40,7 @@ */ #define GLFS_BITROT_BITD_BASE GLFS_MSGID_COMP_BITROT_BITD -#define GLFS_BITROT_BITD_NUM_MESSAGES 48 +#define GLFS_BITROT_BITD_NUM_MESSAGES 53 #define GLFS_MSGID_END (GLFS_BITROT_BITD_BASE + \ GLFS_BITROT_BITD_NUM_MESSAGES + 1) /* Messaged with message IDs */ @@ -404,7 +404,6 @@ */ /*------------*/ #define BRB_MSG_GENERIC_SSM_INFO (GLFS_BITROT_BITD_BASE + 51) - /*! * @messageid * @diagnosis @@ -413,6 +412,21 @@ */ /*------------*/ #define BRB_MSG_ZERO_TIMEOUT_BUG (GLFS_BITROT_BITD_BASE + 52) +/*! + * @messageid + * @diagnosis + * @recommendedaction + * + */ +/*------------*/ +#define BRB_MSG_BAD_OBJ_READDIR_FAIL (GLFS_BITROT_BITD_BASE + 53) +/*! + * @messageid + * @diagnosis + * @recommendedaction + * + */ +/*------------*/ #define glfs_msg_end_x GLFS_MSGID_END, "Invalid: End of messages" #endif /* !_BITROT_BITD_MESSAGES_H_ */ diff --git a/xlators/features/bit-rot/src/bitd/bit-rot-scrub.c b/xlators/features/bit-rot/src/bitd/bit-rot-scrub.c index a311e2e6da8..768b3bc98cd 100644 --- a/xlators/features/bit-rot/src/bitd/bit-rot-scrub.c +++ b/xlators/features/bit-rot/src/bitd/bit-rot-scrub.c @@ -1345,6 +1345,283 @@ br_scrubber_handle_options (xlator_t *this, br_private_t *priv, dict_t *options) return -1; } +inode_t * +br_lookup_bad_obj_dir (xlator_t *this, br_child_t *child, uuid_t gfid) +{ + struct iatt statbuf = {0, }; + inode_table_t *table = NULL; + int32_t ret = -1; + loc_t loc = {0, }; + inode_t *linked_inode = NULL; + int32_t op_errno = 0; + + GF_VALIDATE_OR_GOTO ("bit-rot-scrubber", this, out); + GF_VALIDATE_OR_GOTO (this->name, this->private, out); + GF_VALIDATE_OR_GOTO (this->name, child, out); + + table = child->table; + + loc.inode = inode_new (table); + if (!loc.inode) { + gf_msg (this->name, GF_LOG_ERROR, ENOMEM, + BRB_MSG_NO_MEMORY, "failed to allocate a new inode for" + "bad object directory"); + goto out; + } + + gf_uuid_copy (loc.gfid, gfid); + + ret = syncop_lookup (child->xl, &loc, &statbuf, NULL, NULL, NULL); + if (ret < 0) { + op_errno = -ret; + gf_msg (this->name, GF_LOG_ERROR, 0, + BRB_MSG_LOOKUP_FAILED, "failed to lookup the bad " + "objects directory (gfid: %s (%s))", uuid_utoa (gfid), + strerror (op_errno)); + goto out; + } + + linked_inode = inode_link (loc.inode, NULL, NULL, &statbuf); + if (linked_inode) + inode_lookup (linked_inode); + +out: + loc_wipe (&loc); + return linked_inode; +} + +int32_t +br_read_bad_object_dir (xlator_t *this, br_child_t *child, fd_t *fd, + dict_t *dict) +{ + gf_dirent_t entries; + gf_dirent_t *entry = NULL; + int32_t ret = -1; + off_t offset = 0; + int32_t count = 0; + char key[PATH_MAX] = {0, }; + + INIT_LIST_HEAD (&entries.list); + + while ((ret = syncop_readdir (child->xl, fd, 131072, offset, &entries, + NULL, NULL))) { + if (ret < 0) + goto out; + if (ret == 0) + break; + list_for_each_entry (entry, &entries.list, list) { + offset = entry->d_off; + + snprintf (key, sizeof (key), "quarantine-%d", count); + + /* + * ignore the dict_set errors for now. The intention is + * to get as many bad objects as possible instead of + * erroring out at the first failure. + */ + ret = dict_set_dynstr_with_alloc (dict, key, + entry->d_name); + if (!ret) + count++; + } + + gf_dirent_free (&entries); + } + + ret = count; + ret = dict_set_int32 (dict, "count", count); + +out: + return ret; +} + +int32_t +br_get_bad_objects_from_child (xlator_t *this, dict_t *dict, br_child_t *child) +{ + inode_t *inode = NULL; + inode_table_t *table = NULL; + fd_t *fd = NULL; + int32_t ret = -1; + loc_t loc = {0, }; + int32_t op_errno = 0; + + GF_VALIDATE_OR_GOTO ("bit-rot-scrubber", this, out); + GF_VALIDATE_OR_GOTO (this->name, this->private, out); + GF_VALIDATE_OR_GOTO (this->name, child, out); + GF_VALIDATE_OR_GOTO (this->name, dict, out); + + table = child->table; + + inode = inode_find (table, BR_BAD_OBJ_CONTAINER); + if (!inode) { + inode = br_lookup_bad_obj_dir (this, child, + BR_BAD_OBJ_CONTAINER); + if (!inode) + goto out; + } + + fd = fd_create (inode, 0); + if (!fd) { + gf_msg (this->name, GF_LOG_ERROR, ENOMEM, + BRB_MSG_FD_CREATE_FAILED, "fd creation for the bad " + "objects directory failed (gfid: %s)", + uuid_utoa (BR_BAD_OBJ_CONTAINER)); + goto out; + } + + loc.inode = inode; + gf_uuid_copy (loc.gfid, inode->gfid); + + ret = syncop_opendir (child->xl, &loc, fd, NULL, NULL); + if (ret < 0) { + op_errno = -ret; + fd_unref (fd); + fd = NULL; + gf_msg (this->name, GF_LOG_ERROR, op_errno, + BRB_MSG_FD_CREATE_FAILED, "failed to open the bad " + "objects directory %s", + uuid_utoa (BR_BAD_OBJ_CONTAINER)); + goto out; + } + + fd_bind (fd); + + ret = br_read_bad_object_dir (this, child, fd, dict); + if (ret < 0) { + gf_msg (this->name, GF_LOG_ERROR, 0, + BRB_MSG_BAD_OBJ_READDIR_FAIL, "readdir of the bad " + "objects directory (%s) failed ", + uuid_utoa (BR_BAD_OBJ_CONTAINER)); + goto out; + } + + ret = 0; + +out: + loc_wipe (&loc); + if (fd) + fd_unref (fd); + return ret; +} + +int32_t +br_collect_bad_objects_of_child (xlator_t *this, br_child_t *child, + dict_t *dict, dict_t *child_dict, + int32_t total_count) +{ + + int32_t ret = -1; + int32_t count = 0; + char key[PATH_MAX] = {0, }; + char main_key[PATH_MAX] = {0, }; + int32_t j = 0; + int32_t tmp_count = 0; + char *entry = NULL; + + ret = dict_get_int32 (child_dict, "count", &count); + if (ret) + goto out; + + tmp_count = total_count; + + for (j = 0; j < count; j++) { + snprintf (key, PATH_MAX, "quarantine-%d", j); + ret = dict_get_str (child_dict, key, &entry); + if (ret) + continue; + snprintf (main_key, PATH_MAX, "quarantine-%d", + tmp_count); + ret = dict_set_dynstr_with_alloc (dict, main_key, entry); + if (!ret) + tmp_count++; + } + + ret = tmp_count; + +out: + return ret; +} + +int32_t +br_collect_bad_objects_from_children (xlator_t *this, dict_t *dict) +{ + int32_t ret = -1; + dict_t *child_dict = NULL; + int32_t i = 0; + int32_t total_count = 0; + br_child_t *child = NULL; + br_private_t *priv = NULL; + dict_t *tmp_dict = NULL; + + priv = this->private; + tmp_dict = dict; + + for (i = 0; i < priv->child_count; i++) { + child = &priv->children[i]; + GF_ASSERT (child); + if (!_br_is_child_connected (child)) + continue; + + child_dict = dict_new (); + if (!child_dict) { + gf_msg (this->name, GF_LOG_ERROR, ENOMEM, + BRB_MSG_NO_MEMORY, "failed to allocate dict"); + continue; + } + ret = br_get_bad_objects_from_child (this, child_dict, child); + /* + * Continue asking the remaining children for the list of + * bad objects even though getting the list from one of them + * fails. + */ + if (ret) { + dict_unref (child_dict); + continue; + } + + ret = br_collect_bad_objects_of_child (this, child, tmp_dict, + child_dict, total_count); + if (ret < 0) { + dict_unref (child_dict); + continue; + } + + total_count = ret; + dict_unref (child_dict); + child_dict = NULL; + } + + ret = dict_set_int32 (tmp_dict, "total-count", total_count); + + return ret; +} + +int32_t +br_get_bad_objects_list (xlator_t *this, dict_t **dict) +{ + int32_t ret = -1; + dict_t *tmp_dict = NULL; + + GF_VALIDATE_OR_GOTO ("bir-rot-scrubber", this, out); + GF_VALIDATE_OR_GOTO (this->name, dict, out); + + tmp_dict = *dict; + if (!tmp_dict) { + tmp_dict = dict_new (); + if (!tmp_dict) { + gf_msg (this->name, GF_LOG_ERROR, ENOMEM, + BRB_MSG_NO_MEMORY, "failed to allocate dict"); + goto out; + } + *dict = tmp_dict; + } + + ret = br_collect_bad_objects_from_children (this, tmp_dict); + +out: + return ret; +} + int32_t br_scrubber_init (xlator_t *this, br_private_t *priv) { diff --git a/xlators/features/bit-rot/src/bitd/bit-rot.h b/xlators/features/bit-rot/src/bitd/bit-rot.h index ebf847665f6..647ea5a3fae 100644 --- a/xlators/features/bit-rot/src/bitd/bit-rot.h +++ b/xlators/features/bit-rot/src/bitd/bit-rot.h @@ -269,4 +269,8 @@ _br_child_get_scrub_event (struct br_scrubber *fsscrub) ? BR_SCRUB_EVENT_PAUSE : BR_SCRUB_EVENT_SCHEDULE; } +int32_t +br_get_bad_objects_list (xlator_t *this, dict_t **dict); + + #endif /* __BIT_ROT_H__ */ -- cgit