summaryrefslogtreecommitdiffstats
path: root/xlators/cluster/ec/src/ec-heal.c
diff options
context:
space:
mode:
Diffstat (limited to 'xlators/cluster/ec/src/ec-heal.c')
-rw-r--r--xlators/cluster/ec/src/ec-heal.c93
1 files changed, 57 insertions, 36 deletions
diff --git a/xlators/cluster/ec/src/ec-heal.c b/xlators/cluster/ec/src/ec-heal.c
index c49ccf3fd72..a121bb43e5c 100644
--- a/xlators/cluster/ec/src/ec-heal.c
+++ b/xlators/cluster/ec/src/ec-heal.c
@@ -868,6 +868,28 @@ int32_t ec_heal_open_others(ec_heal_t * heal)
return (open != 0);
}
+uintptr_t ec_heal_needs_data_rebuild(ec_heal_t *heal)
+{
+ ec_fop_data_t *fop = heal->lookup;
+ ec_cbk_data_t *cbk = NULL;
+ uintptr_t bad = 0;
+
+ if ((heal->fop->error != 0) || (heal->good == 0) ||
+ (heal->iatt.ia_type != IA_IFREG)) {
+ return 0;
+ }
+
+ list_for_each_entry(cbk, &fop->cbk_list, list) {
+ if ((cbk->op_ret >= 0) &&
+ ((cbk->size != heal->raw_size) ||
+ (cbk->version != heal->version))) {
+ bad |= cbk->mask;
+ }
+ }
+
+ return bad;
+}
+
void ec_heal_setxattr_others(ec_heal_t * heal)
{
ec_cbk_data_t * cbk;
@@ -892,9 +914,12 @@ void ec_heal_setxattr_others(ec_heal_t * heal)
}
if (cbk->iatt[0].ia_type == IA_IFREG)
{
- if (ec_dict_set_number(xdata, EC_XATTR_SIZE,
- cbk->iatt[0].ia_size) != 0)
- {
+ uint64_t dirty;
+
+ dirty = ec_heal_needs_data_rebuild(heal) != 0;
+ if ((ec_dict_set_number(xdata, EC_XATTR_SIZE,
+ cbk->iatt[0].ia_size) != 0) ||
+ (ec_dict_set_number(xdata, EC_XATTR_DIRTY, dirty) != 0)) {
goto out;
}
}
@@ -968,40 +993,10 @@ void ec_heal_attr(ec_heal_t * heal)
}
}
-int32_t ec_heal_needs_data_rebuild(ec_heal_t * heal)
-{
- ec_fop_data_t * fop = heal->lookup;
- ec_cbk_data_t * cbk = NULL;
- uintptr_t bad = 0;
-
- if ((heal->fop->error != 0) || (heal->good == 0) ||
- (heal->iatt.ia_type != IA_IFREG))
- {
- return 0;
- }
-
- list_for_each_entry(cbk, &fop->cbk_list, list)
- {
- if ((cbk->op_ret >= 0) &&
- ((cbk->size != heal->raw_size) || (cbk->version != heal->version)))
- {
- bad |= cbk->mask;
- }
- }
-
- /* This function can only be called concurrently with entrylk, which do
- * not modify heal structure, so it's safe to access heal->bad without
- * acquiring any lock.
- */
- heal->bad = bad;
-
- return (bad != 0);
-}
-
void ec_heal_open(ec_heal_t * heal)
{
- if (!ec_heal_needs_data_rebuild(heal))
- {
+ heal->bad = ec_heal_needs_data_rebuild(heal);
+ if (heal->bad == 0) {
return;
}
@@ -1115,6 +1110,30 @@ void ec_heal_data(ec_heal_t * heal)
}
}
+void ec_heal_update_dirty(ec_heal_t *heal, uintptr_t mask)
+{
+ dict_t *dict;
+
+ dict = dict_new();
+ if (dict == NULL) {
+ ec_fop_set_error(heal->fop, EIO);
+
+ return;
+ }
+
+ if (ec_dict_set_number(dict, EC_XATTR_DIRTY, -1) != 0) {
+ dict_unref(dict);
+ ec_fop_set_error(heal->fop, EIO);
+
+ return;
+ }
+
+ ec_fxattrop(heal->fop->frame, heal->xl, mask, EC_MINIMUM_ONE, NULL, NULL,
+ heal->fd, GF_XATTROP_ADD_ARRAY64, dict, NULL);
+
+ dict_unref(dict);
+}
+
void ec_heal_dispatch(ec_heal_t *heal)
{
ec_fop_data_t *fop;
@@ -1347,7 +1366,8 @@ int32_t ec_manager_heal(ec_fop_data_t * fop, int32_t state)
case EC_STATE_HEAL_UNLOCK_ENTRY:
ec_heal_entrylk(heal, ENTRYLK_UNLOCK);
- if (ec_heal_needs_data_rebuild(heal))
+ heal->bad = ec_heal_needs_data_rebuild(heal);
+ if (heal->bad != 0)
{
return EC_STATE_HEAL_DATA_LOCK;
}
@@ -1385,6 +1405,7 @@ int32_t ec_manager_heal(ec_fop_data_t * fop, int32_t state)
case EC_STATE_HEAL_POST_INODE_LOOKUP:
heal->fixed = heal->bad;
+ ec_heal_update_dirty(heal, heal->bad);
ec_heal_lookup(heal, heal->good);
return EC_STATE_HEAL_SETATTR;