diff options
-rw-r--r-- | xlators/cluster/ec/src/ec-combine.c | 75 | ||||
-rw-r--r-- | xlators/cluster/ec/src/ec-combine.h | 3 | ||||
-rw-r--r-- | xlators/cluster/ec/src/ec-generic.c | 6 | ||||
-rw-r--r-- | xlators/cluster/ec/src/ec-heal.c | 35 | ||||
-rw-r--r-- | xlators/cluster/ec/src/ec-inode-read.c | 9 |
5 files changed, 100 insertions, 28 deletions
diff --git a/xlators/cluster/ec/src/ec-combine.c b/xlators/cluster/ec/src/ec-combine.c index 5842a4dd0a8..a8cfabc011e 100644 --- a/xlators/cluster/ec/src/ec-combine.c +++ b/xlators/cluster/ec/src/ec-combine.c @@ -84,7 +84,7 @@ ec_combine_write (ec_fop_data_t *fop, ec_cbk_data_t *dst, break; } - if (!ec_iatt_combine(dst->iatt, src->iatt, valid)) { + if (!ec_iatt_combine(fop, dst->iatt, src->iatt, valid)) { gf_log(fop->xl->name, GF_LOG_NOTICE, "Mismatching iatt in " "answers of '%s'", gf_fop_list[fop->id]); @@ -104,23 +104,78 @@ void ec_iatt_time_merge(uint32_t * dst_sec, uint32_t * dst_nsec, } } -int32_t ec_iatt_combine(struct iatt * dst, struct iatt * src, int32_t count) +static +uint64_t +gfid_to_ino(uuid_t gfid) { + uint64_t ino = 0; int32_t i; + for (i = 8; i < 16; i++) { + ino <<= 8; + ino += (uint8_t)gfid[i]; + } + + return ino; +} + +static +gf_boolean_t +ec_iatt_is_trusted(ec_fop_data_t *fop, struct iatt *iatt) +{ + uint64_t ino; + int32_t i; + + /* Only the top level fop will have fop->locks filled. */ + while (fop->parent != NULL) { + fop = fop->parent; + } + + /* Check if the iatt references an inode locked by the current fop */ + for (i = 0; i < fop->lock_count; i++) { + ino = gfid_to_ino(fop->locks[i].lock->loc.inode->gfid); + if (iatt->ia_ino == ino) { + return _gf_true; + } + } + + return _gf_false; +} + +int32_t ec_iatt_combine(ec_fop_data_t *fop, struct iatt *dst, struct iatt *src, + int32_t count) +{ + int32_t i; + gf_boolean_t failed = _gf_false; + for (i = 0; i < count; i++) { + /* Check for basic fields. These fields must be equal always, even if + * the inode is not locked because in these cases the parent inode + * will be locked and differences in these fields require changes in + * the parent directory. */ if ((dst[i].ia_ino != src[i].ia_ino) || - (dst[i].ia_uid != src[i].ia_uid) || - (dst[i].ia_gid != src[i].ia_gid) || (((dst[i].ia_type == IA_IFBLK) || (dst[i].ia_type == IA_IFCHR)) && (dst[i].ia_rdev != src[i].ia_rdev)) || - ((dst[i].ia_type == IA_IFREG) && - (dst[i].ia_size != src[i].ia_size)) || - (st_mode_from_ia(dst[i].ia_prot, dst[i].ia_type) != - st_mode_from_ia(src[i].ia_prot, src[i].ia_type)) || - (gf_uuid_compare(dst[i].ia_gfid, src[i].ia_gfid) != 0)) - { + (gf_uuid_compare(dst[i].ia_gfid, src[i].ia_gfid) != 0)) { + failed = _gf_true; + } + /* Check for not so stable fields. These fields can change if the + * inode is not locked. */ + if (!failed && ((dst[i].ia_uid != src[i].ia_uid) || + (dst[i].ia_gid != src[i].ia_gid) || + ((dst[i].ia_type == IA_IFREG) && + (dst[i].ia_size != src[i].ia_size)) || + (st_mode_from_ia(dst[i].ia_prot, dst[i].ia_type) != + st_mode_from_ia(src[i].ia_prot, src[i].ia_type)))) { + if (!ec_iatt_is_trusted(fop, dst)) { + /* If the iatt contains information from an inode that is not + * locked, we ignore these differences and don't care which + * data is returned. */ + failed = _gf_false; + } + } + if (failed) { gf_log(THIS->name, GF_LOG_WARNING, "Failed to combine iatt (inode: %lu-%lu, links: %u-%u, " "uid: %u-%u, gid: %u-%u, rdev: %lu-%lu, size: %lu-%lu, " diff --git a/xlators/cluster/ec/src/ec-combine.h b/xlators/cluster/ec/src/ec-combine.h index cae2bb9274f..19a42ded706 100644 --- a/xlators/cluster/ec/src/ec-combine.h +++ b/xlators/cluster/ec/src/ec-combine.h @@ -20,7 +20,8 @@ typedef int32_t (* ec_combine_f)(ec_fop_data_t * fop, ec_cbk_data_t * dst, void ec_iatt_rebuild(ec_t * ec, struct iatt * iatt, int32_t count, int32_t answers); -int32_t ec_iatt_combine(struct iatt * dst, struct iatt * src, int32_t count); +int32_t ec_iatt_combine(ec_fop_data_t *fop, struct iatt *dst, struct iatt *src, + int32_t count); int32_t ec_dict_compare(dict_t * dict1, dict_t * dict2); int32_t ec_vector_compare(struct iovec * dst_vector, int32_t dst_count, struct iovec * src_vector, int32_t src_count); diff --git a/xlators/cluster/ec/src/ec-generic.c b/xlators/cluster/ec/src/ec-generic.c index f50c7a70560..a455dad9f6b 100644 --- a/xlators/cluster/ec/src/ec-generic.c +++ b/xlators/cluster/ec/src/ec-generic.c @@ -235,8 +235,7 @@ out: int32_t ec_combine_fsync(ec_fop_data_t * fop, ec_cbk_data_t * dst, ec_cbk_data_t * src) { - if (!ec_iatt_combine(dst->iatt, src->iatt, 2)) - { + if (!ec_iatt_combine(fop, dst->iatt, src->iatt, 2)) { gf_log(fop->xl->name, GF_LOG_NOTICE, "Mismatching iatt in " "answers of 'GF_FOP_FSYNC'"); @@ -813,8 +812,7 @@ void ec_lookup_rebuild(ec_t * ec, ec_fop_data_t * fop, ec_cbk_data_t * cbk) int32_t ec_combine_lookup(ec_fop_data_t * fop, ec_cbk_data_t * dst, ec_cbk_data_t * src) { - if (!ec_iatt_combine(dst->iatt, src->iatt, 2)) - { + if (!ec_iatt_combine(fop, dst->iatt, src->iatt, 2)) { gf_log(fop->xl->name, GF_LOG_NOTICE, "Mismatching iatt in " "answers of 'GF_FOP_LOOKUP'"); 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); } } diff --git a/xlators/cluster/ec/src/ec-inode-read.c b/xlators/cluster/ec/src/ec-inode-read.c index 853d914148b..ae02e964c3d 100644 --- a/xlators/cluster/ec/src/ec-inode-read.c +++ b/xlators/cluster/ec/src/ec-inode-read.c @@ -936,8 +936,7 @@ out: int32_t ec_combine_readlink(ec_fop_data_t * fop, ec_cbk_data_t * dst, ec_cbk_data_t * src) { - if (!ec_iatt_combine(dst->iatt, src->iatt, 1)) - { + if (!ec_iatt_combine(fop, dst->iatt, src->iatt, 1)) { gf_log(fop->xl->name, GF_LOG_NOTICE, "Mismatching iatt in " "answers of 'GF_FOP_READLINK'"); @@ -1210,8 +1209,7 @@ int32_t ec_combine_readv(ec_fop_data_t * fop, ec_cbk_data_t * dst, return 0; } - if (!ec_iatt_combine(dst->iatt, src->iatt, 1)) - { + if (!ec_iatt_combine(fop, dst->iatt, src->iatt, 1)) { gf_log(fop->xl->name, GF_LOG_NOTICE, "Mismatching iatt in " "answers of 'GF_FOP_READ'"); @@ -1493,8 +1491,7 @@ out: int32_t ec_combine_stat(ec_fop_data_t * fop, ec_cbk_data_t * dst, ec_cbk_data_t * src) { - if (!ec_iatt_combine(dst->iatt, src->iatt, 1)) - { + if (!ec_iatt_combine(fop, dst->iatt, src->iatt, 1)) { gf_log(fop->xl->name, GF_LOG_NOTICE, "Mismatching iatt in " "answers of 'GF_FOP_STAT'"); |