summaryrefslogtreecommitdiffstats
path: root/xlators/cluster/ec/src/ec-common.c
diff options
context:
space:
mode:
authorXavier Hernandez <xhernandez@datalab.es>2014-11-08 21:46:41 +0100
committerPranith Kumar Karampuri <pkarampu@redhat.com>2015-01-28 19:49:29 -0800
commitb17122ffc75c65bda2cf3b3d99832bbf2718e8d3 (patch)
tree258ad51bcf7d08bccc96cd94b7440a0dce227f33 /xlators/cluster/ec/src/ec-common.c
parent88136b53f59e3b81aacc28df18bda575da35b02d (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.c54
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;
}