From 7685cec5832a0b9dd947ed126cdef0098117bba8 Mon Sep 17 00:00:00 2001 From: Anand Avati Date: Tue, 12 Jul 2011 02:10:50 +0000 Subject: cluster/dht: fix race between two directory renames let the race get arbitrated at the dst_hashed subvolume. Signed-off-by: Anand Avati BUG: 2522 ([glusterfs-3.1.3qa8]: rm -rf shows invalid argument) URL: http://bugs.gluster.com/cgi-bin/bugzilla3/show_bug.cgi?id=2522 --- xlators/cluster/dht/src/dht-rename.c | 86 +++++++++++++++++++++++++++++++++--- 1 file changed, 79 insertions(+), 7 deletions(-) (limited to 'xlators/cluster/dht/src/dht-rename.c') diff --git a/xlators/cluster/dht/src/dht-rename.c b/xlators/cluster/dht/src/dht-rename.c index cef4a7b6fbc..e786a6da925 100644 --- a/xlators/cluster/dht/src/dht-rename.c +++ b/xlators/cluster/dht/src/dht-rename.c @@ -98,30 +98,102 @@ unwind: } - int -dht_rename_dir_do (call_frame_t *frame, xlator_t *this) +dht_rename_hashed_dir_cbk (call_frame_t *frame, void *cookie, xlator_t *this, + int32_t op_ret, int32_t op_errno, struct iatt *stbuf, + struct iatt *preoldparent, + struct iatt *postoldparent, + struct iatt *prenewparent, + struct iatt *postnewparent) { - dht_local_t *local = NULL; dht_conf_t *conf = NULL; + dht_local_t *local = NULL; + int call_cnt = 0; + call_frame_t *prev = NULL; int i = 0; conf = this->private; local = frame->local; + prev = cookie; - if (local->op_ret == -1) - goto err; + if (op_ret == -1) { + /* TODO: undo the damage */ - local->call_cnt = conf->subvolume_cnt; - local->op_ret = 0; + gf_log (this->name, GF_LOG_INFO, + "rename %s -> %s on %s failed (%s)", + local->loc.path, local->loc2.path, + prev->this->name, strerror (op_errno)); + + local->op_ret = op_ret; + local->op_errno = op_errno; + goto unwind; + } + /* TODO: construct proper stbuf for dir */ + /* + * FIXME: is this the correct way to build stbuf and + * parent bufs? + */ + dht_iatt_merge (this, &local->stbuf, stbuf, prev->this); + dht_iatt_merge (this, &local->preoldparent, preoldparent, + prev->this); + dht_iatt_merge (this, &local->postoldparent, postoldparent, + prev->this); + dht_iatt_merge (this, &local->preparent, prenewparent, + prev->this); + dht_iatt_merge (this, &local->postparent, postnewparent, + prev->this); + + call_cnt = local->call_cnt = conf->subvolume_cnt - 1; + + if (!local->call_cnt) + goto unwind; for (i = 0; i < conf->subvolume_cnt; i++) { + if (conf->subvolumes[i] == local->dst_hashed) + continue; STACK_WIND (frame, dht_rename_dir_cbk, conf->subvolumes[i], conf->subvolumes[i]->fops->rename, &local->loc, &local->loc2); + if (!--call_cnt) + break; } + + return 0; +unwind: + WIPE (&local->preoldparent); + WIPE (&local->postoldparent); + WIPE (&local->preparent); + WIPE (&local->postparent); + + DHT_STACK_UNWIND (rename, frame, local->op_ret, local->op_errno, + &local->stbuf, &local->preoldparent, + &local->postoldparent, + &local->preparent, &local->postparent); + + return 0; +} + + +int +dht_rename_dir_do (call_frame_t *frame, xlator_t *this) +{ + dht_local_t *local = NULL; + dht_conf_t *conf = NULL; + + conf = this->private; + local = frame->local; + + if (local->op_ret == -1) + goto err; + + local->op_ret = 0; + + STACK_WIND (frame, dht_rename_hashed_dir_cbk, + local->dst_hashed, + local->dst_hashed->fops->rename, + &local->loc, &local->loc2); return 0; err: -- cgit