summaryrefslogtreecommitdiffstats
path: root/xlators/features/bit-rot
diff options
context:
space:
mode:
Diffstat (limited to 'xlators/features/bit-rot')
-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 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__ */