diff options
| -rw-r--r-- | xlators/features/bit-rot/src/bitd/bit-rot-bitd-messages.h | 18 | ||||
| -rw-r--r-- | xlators/features/bit-rot/src/bitd/bit-rot-scrub.c | 277 | ||||
| -rw-r--r-- | xlators/features/bit-rot/src/bitd/bit-rot.h | 4 | 
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__ */  | 
