summaryrefslogtreecommitdiffstats
path: root/xlators/cluster/ec/src/ec-heal.c
diff options
context:
space:
mode:
authorXavier Hernandez <xhernandez@datalab.es>2015-02-09 09:26:46 +0100
committerVijay Bellur <vbellur@redhat.com>2015-02-23 23:58:11 -0800
commit46a2b9e48160c593a73756d91781298144528e50 (patch)
tree85b688676dbdd8e8d1bbc55343ef411ad80465da /xlators/cluster/ec/src/ec-heal.c
parenta4a760a3cf793857e5fac7d13f5ef7028d30f666 (diff)
ec: Add trusted.ec.dirty xattr
This xattr will be incremented before each data modifying operation and decremented after it. This will add the possibility to detect partially updated writes and refuse them on reads. It will also be useful for interacting with index xlator and have a way to heal dispersed files from the self-heal daemon. Change-Id: Ie644a8dd074ae0f254c809c5863bdb030be5486a BUG: 1190581 Signed-off-by: Xavier Hernandez <xhernandez@datalab.es> Reviewed-on: http://review.gluster.org/9607 Tested-by: Gluster Build System <jenkins@build.gluster.com> Reviewed-by: Pranith Kumar Karampuri <pkarampu@redhat.com> Reviewed-by: Vijay Bellur <vbellur@redhat.com>
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;