diff options
| author | Anand Avati <avati@gluster.com> | 2011-07-12 02:10:50 +0000 | 
|---|---|---|
| committer | Anand Avati <avati@gluster.com> | 2011-07-12 02:25:03 -0700 | 
| commit | 7685cec5832a0b9dd947ed126cdef0098117bba8 (patch) | |
| tree | c035918d5d73c34bcac7b883a8d789516cc99890 | |
| parent | a2de8fc7ad0aab1715fb4e0a23e12bfc1595bf88 (diff) | |
cluster/dht: fix race between two directory renamesv3.2.2qa5
let the race get arbitrated at the dst_hashed subvolume.
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 | 86 | 
1 files changed, 79 insertions, 7 deletions
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:  | 
