diff options
author | Xavier Hernandez <xhernandez@datalab.es> | 2014-11-08 21:46:41 +0100 |
---|---|---|
committer | Pranith Kumar Karampuri <pkarampu@redhat.com> | 2015-01-28 19:49:29 -0800 |
commit | b17122ffc75c65bda2cf3b3d99832bbf2718e8d3 (patch) | |
tree | 258ad51bcf7d08bccc96cd94b7440a0dce227f33 /xlators/cluster/ec/src/ec-common.c | |
parent | 88136b53f59e3b81aacc28df18bda575da35b02d (diff) |
ec: Fix posix compliance failures
This patch solves some problems that caused dispersed volumes to not
pass posix smoke tests:
* Problems in open/create with O_WRONLY
Opening files with -w- permissions using O_WRONLY returned an EACCES
error because internally O_WRONLY was replaced with O_RDWR.
* Problems with entrylk on renames.
When source and destination were the same, ec tried to acquire
the same entrylk twice, causing a deadlock.
* Overwrite of a variable when reordering locks.
On a rename, if the second lock needed to be placed at the beggining
of the list, the 'lock' variable was overwritten and later its timer
was cancelled, cancelling the incorrect one.
* Handle O_TRUNC in open.
When O_TRUNC was received in an open call, it was blindly propagated
to child subvolumes. This caused a discrepancy between real file
size and the size stored into trusted.ec.size xattr. This has been
solved by removing O_TRUNC from open and later calling ftruncate.
Change-Id: I20c3d6e1c11be314be86879be54b728e01013798
BUG: 1161886
Signed-off-by: Xavier Hernandez <xhernandez@datalab.es>
Reviewed-on: http://review.gluster.org/9420
Reviewed-by: Dan Lambright <dlambrig@redhat.com>
Tested-by: Gluster Build System <jenkins@build.gluster.com>
Reviewed-by: Pranith Kumar Karampuri <pkarampu@redhat.com>
Tested-by: Pranith Kumar Karampuri <pkarampu@redhat.com>
Diffstat (limited to 'xlators/cluster/ec/src/ec-common.c')
-rw-r--r-- | xlators/cluster/ec/src/ec-common.c | 54 |
1 files changed, 31 insertions, 23 deletions
diff --git a/xlators/cluster/ec/src/ec-common.c b/xlators/cluster/ec/src/ec-common.c index 89c78c69bae..fcae083aa84 100644 --- a/xlators/cluster/ec/src/ec-common.c +++ b/xlators/cluster/ec/src/ec-common.c @@ -232,6 +232,16 @@ void ec_fop_set_error(ec_fop_data_t * fop, int32_t error) UNLOCK(&fop->lock); } +void ec_sleep(ec_fop_data_t *fop) +{ + LOCK(&fop->lock); + + fop->refs++; + fop->jobs++; + + UNLOCK(&fop->lock); +} + int32_t ec_check_complete(ec_fop_data_t * fop, ec_resume_f resume) { int32_t error = -1; @@ -435,12 +445,7 @@ int32_t ec_child_select(ec_fop_data_t * fop) return 0; } - LOCK(&fop->lock); - - fop->jobs++; - fop->refs++; - - UNLOCK(&fop->lock); + ec_sleep(fop); return 1; } @@ -637,22 +642,23 @@ int32_t ec_lock_compare(ec_lock_t * lock1, ec_lock_t * lock2) ec_lock_link_t *ec_lock_insert(ec_fop_data_t *fop, ec_lock_t *lock, int32_t update) { - ec_lock_t * tmp; + ec_lock_t *new_lock, *tmp; ec_lock_link_t *link = NULL; int32_t tmp_update; + new_lock = lock; if ((fop->lock_count > 0) && - (ec_lock_compare(fop->locks[0].lock, lock) > 0)) + (ec_lock_compare(fop->locks[0].lock, new_lock) > 0)) { tmp = fop->locks[0].lock; - fop->locks[0].lock = lock; - lock = tmp; + fop->locks[0].lock = new_lock; + new_lock = tmp; tmp_update = fop->locks_update; fop->locks_update = update; update = tmp_update; } - fop->locks[fop->lock_count].lock = lock; + fop->locks[fop->lock_count].lock = new_lock; fop->locks[fop->lock_count].fop = fop; fop->locks_update |= update << fop->lock_count; @@ -693,6 +699,16 @@ void ec_lock_prepare_entry(ec_fop_data_t *fop, loc_t *loc, int32_t update) return; } + + /* If there's another lock, make sure that it's not the same. Otherwise + * do not insert it. + * + * This can only happen on renames where source and target names are + * in the same directory. */ + if ((fop->lock_count > 0) && + (fop->locks[0].lock->loc.inode == tmp.inode)) { + goto wipe; + } } else { if (ec_loc_from_loc(fop->xl, &tmp, loc) != 0) { ec_fop_set_error(fop, EIO); @@ -742,6 +758,7 @@ insert: unlock: UNLOCK(&tmp.inode->lock); +wipe: loc_wipe(&tmp); if (link != NULL) { @@ -870,12 +887,7 @@ void ec_lock(ec_fop_data_t * fop) list_add_tail(&fop->locks[fop->locked].wait_list, &lock->waiting); - LOCK(&fop->lock); - - fop->jobs++; - fop->refs++; - - UNLOCK(&fop->lock); + ec_sleep(fop); UNLOCK(&lock->loc.inode->lock); @@ -1332,12 +1344,7 @@ void ec_unlock_timer_add(ec_lock_link_t *link) delay.tv_sec = 1; delay.tv_nsec = 0; - LOCK(&fop->lock); - - fop->jobs++; - fop->refs++; - - UNLOCK(&fop->lock); + ec_sleep(fop); /* If healing is needed, do not delay lock release to let self-heal * start working as soon as possible. */ @@ -1356,6 +1363,7 @@ void ec_unlock_timer_add(ec_lock_link_t *link) refs = 0; } } else { + ec_trace("UNLOCK_FORCE", fop, "lock=%p", lock); *lock->plock = NULL; refs = 0; } |