summaryrefslogtreecommitdiffstats
path: root/xlators/cluster/ec/src/ec-heal.c
diff options
context:
space:
mode:
authorXavier Hernandez <xhernandez@datalab.es>2015-05-28 16:54:59 +0200
committerPranith Kumar Karampuri <pkarampu@redhat.com>2015-05-30 05:35:33 -0700
commit90ed7128dfd4d10e65efcc866cfd610ba3b0cc30 (patch)
tree446bf4ff0c06fb059dba65edf54bf819a6d4d0ca /xlators/cluster/ec/src/ec-heal.c
parent54b193760ce59569fa5813e64af7753afbf0d500 (diff)
cluster/ec: Ignore differences in non locked inodes
When ec combines iatt structures from multiple bricks, it checks for equality in important fields. This is ok for iatt related to inodes involved in the operation that have been locked before starting execution. However some fops return iatt information from other inodes. For example a rename locks source and destination parent directories, but it also returns an iatt from the entry itself. In these cases we ignore differences in some fields to avoid false detection of inconsistencies and trigger unnecessary self-heals. Another issue is solved in this patch that caused that the real size of the file stored into the inode context was lost during self-heal. Change-Id: I8b8eca30b2a6c39c7b9bbd3b3b6ba95228fcc041 BUG: 1225793 Signed-off-by: Xavier Hernandez <xhernandez@datalab.es> Reviewed-on: http://review.gluster.org/10974 Reviewed-by: Pranith Kumar Karampuri <pkarampu@redhat.com> Tested-by: NetBSD Build System
Diffstat (limited to 'xlators/cluster/ec/src/ec-heal.c')
-rw-r--r--xlators/cluster/ec/src/ec-heal.c35
1 files changed, 28 insertions, 7 deletions
diff --git a/xlators/cluster/ec/src/ec-heal.c b/xlators/cluster/ec/src/ec-heal.c
index 80725e5a9fa..af75c9551b8 100644
--- a/xlators/cluster/ec/src/ec-heal.c
+++ b/xlators/cluster/ec/src/ec-heal.c
@@ -546,10 +546,25 @@ out:
return error;
}
+int32_t ec_heal_lock_cbk(call_frame_t *frame, void *cookie, xlator_t *this,
+ int32_t op_ret, int32_t op_errno, dict_t *xdata)
+{
+ ec_fop_data_t *fop = cookie;
+ ec_heal_t *heal = fop->data;
+
+ if (op_ret >= 0) {
+ GF_ASSERT(ec_set_inode_size(heal->fop, heal->fd->inode,
+ heal->total_size));
+ }
+
+ return 0;
+}
+
void ec_heal_lock(ec_heal_t *heal, int32_t type, fd_t *fd, loc_t *loc,
off_t offset, size_t size)
{
struct gf_flock flock;
+ fop_inodelk_cbk_t cbk = NULL;
flock.l_type = type;
flock.l_whence = SEEK_SET;
@@ -558,22 +573,28 @@ void ec_heal_lock(ec_heal_t *heal, int32_t type, fd_t *fd, loc_t *loc,
flock.l_pid = 0;
flock.l_owner.len = 0;
- /* Remove inode size information before unlocking it. */
- if ((type == F_UNLCK) && (heal->loc.inode != NULL)) {
- ec_clear_inode_info(heal->fop, heal->loc.inode);
+ if (type == F_UNLCK) {
+ /* Remove inode size information before unlocking it. */
+ if (fd == NULL) {
+ ec_clear_inode_info(heal->fop, heal->loc.inode);
+ } else {
+ ec_clear_inode_info(heal->fop, heal->fd->inode);
+ }
+ } else {
+ /* Otherwise use the callback to update size information. */
+ cbk = ec_heal_lock_cbk;
}
if (fd != NULL)
{
ec_finodelk(heal->fop->frame, heal->xl, heal->fop->mask,
- EC_MINIMUM_ALL, NULL, NULL, heal->xl->name, fd,
- F_SETLKW, &flock, NULL);
+ EC_MINIMUM_ALL, cbk, heal, heal->xl->name, fd, F_SETLKW,
+ &flock, NULL);
}
else
{
ec_inodelk(heal->fop->frame, heal->xl, heal->fop->mask, EC_MINIMUM_ALL,
- NULL, NULL, heal->xl->name, loc, F_SETLKW, &flock,
- NULL);
+ cbk, heal, heal->xl->name, loc, F_SETLKW, &flock, NULL);
}
}