summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorRaghavendra Bhat <raghavendra@redhat.com>2015-11-17 14:45:30 +0530
committerVenky Shankar <vshankar@redhat.com>2015-11-22 23:20:06 -0800
commitf12efd1827077292eba08a109d212a25c62476fe (patch)
treedb98fcd24c077f42c82ea32104576a95dc4e6576
parent8805a4c65bf9c725cb26bb6979f3ebd62748138f (diff)
features/bit-rot: scrubber changes for getting the list of bad objects from stub
Change-Id: I62885e4aba4a9b345db3c78c3291d563ff3d3567 BUG: 1207627 Signed-off-by: Raghavendra Bhat <raghavendra@redhat.com> Reviewed-on: http://review.gluster.org/12654 Tested-by: NetBSD Build System <jenkins@build.gluster.org> Tested-by: Gluster Build System <jenkins@build.gluster.com> Reviewed-by: Venky Shankar <vshankar@redhat.com>
-rw-r--r--xlators/features/bit-rot/src/bitd/bit-rot-bitd-messages.h18
-rw-r--r--xlators/features/bit-rot/src/bitd/bit-rot-scrub.c277
-rw-r--r--xlators/features/bit-rot/src/bitd/bit-rot.h4
3 files changed, 297 insertions, 2 deletions
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 4a74bbf7eef..f776347e6d5 100644
--- a/xlators/features/bit-rot/src/bitd/bit-rot-scrub.c
+++ b/xlators/features/bit-rot/src/bitd/bit-rot-scrub.c
@@ -1343,6 +1343,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 7def0606726..16892a7e3fd 100644
--- a/xlators/features/bit-rot/src/bitd/bit-rot.h
+++ b/xlators/features/bit-rot/src/bitd/bit-rot.h
@@ -264,4 +264,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__ */