diff options
| author | Anand Avati <avati@gluster.com> | 2011-07-12 02:16:29 +0000 | 
|---|---|---|
| committer | Anand Avati <avati@gluster.com> | 2011-07-12 02:24:37 -0700 | 
| commit | 08f8f7ab1f6d45f1711d54660bcaa37aa0dcc877 (patch) | |
| tree | ed805041fd6ec717aa37699fa0e5ee13d31e3226 | |
| parent | bed94fc008b3446ce390eded41aab5cda297cf4b (diff) | |
cluster/dht: fix race between two directory renames
let the race get arbitrated at the dst_hashed subvolume.
Change-Id: I140fc5b0176ee752ebef648c539b404653e91bdd
Signed-off-by: Anand Avati <avati@gluster.com>
BUG: 2522 ([glusterfs-3.1.3qa8]: rm -rf shows invalid argument)
URL: http://bugs.gluster.com/cgi-bin/bugzilla3/show_bug.cgi?id=2522
| -rw-r--r-- | xlators/cluster/dht/src/dht-rename.c | 106 | 
1 files changed, 89 insertions, 17 deletions
diff --git a/xlators/cluster/dht/src/dht-rename.c b/xlators/cluster/dht/src/dht-rename.c index fce313d1e..b421d0344 100644 --- a/xlators/cluster/dht/src/dht-rename.c +++ b/xlators/cluster/dht/src/dht-rename.c @@ -97,31 +97,103 @@ dht_rename_dir_cbk (call_frame_t *frame, void *cookie, xlator_t *this,  } +int +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_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 (op_ret == -1) { +                /* TODO: undo the damage */ + +                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; -	int           i = 0; +        dht_local_t  *local = NULL; +        dht_conf_t   *conf = NULL; -	conf = this->private; -	local = frame->local; +        conf = this->private; +        local = frame->local; -	if (local->op_ret == -1) -		goto err; +        if (local->op_ret == -1) +                goto err; -	local->call_cnt = conf->subvolume_cnt; -	local->op_ret = 0; - -	for (i = 0; i < conf->subvolume_cnt; i++) { -		STACK_WIND (frame, dht_rename_dir_cbk, -			    conf->subvolumes[i], -			    conf->subvolumes[i]->fops->rename, -			    &local->loc, &local->loc2); -	} +        local->op_ret = 0; -	return 0; +        STACK_WIND (frame, dht_rename_hashed_dir_cbk, +                    local->dst_hashed, +                    local->dst_hashed->fops->rename, +                    &local->loc, &local->loc2); +        return 0;  err:  	DHT_STACK_UNWIND (rename, frame, local->op_ret, local->op_errno, NULL, NULL,  | 
