diff options
| -rw-r--r-- | tests/bugs/bug-862967.t | 57 | ||||
| -rw-r--r-- | xlators/cluster/dht/src/dht-common.c | 42 | ||||
| -rw-r--r-- | xlators/cluster/dht/src/dht-common.h | 7 | ||||
| -rw-r--r-- | xlators/cluster/dht/src/dht-layout.c | 10 | ||||
| -rw-r--r-- | xlators/cluster/dht/src/dht-selfheal.c | 47 | 
5 files changed, 162 insertions, 1 deletions
diff --git a/tests/bugs/bug-862967.t b/tests/bugs/bug-862967.t new file mode 100644 index 00000000..73f5826f --- /dev/null +++ b/tests/bugs/bug-862967.t @@ -0,0 +1,57 @@ +#!/bin/bash + +. $(dirname $0)/../include.rc + +cleanup; + +function uid_gid_compare() +{ +        val=1 + +        if [ "$1" == "$3" ] +        then +                if [ "$2" == "$4" ] +                        then +                                val=0 +                fi +        fi +        echo "$val" +} + +BRICK_COUNT=3 + +TEST glusterd +TEST pidof glusterd + +TEST $CLI volume create $V0 $H0:$B0/${V0}0 $H0:$B0/${V0}1 $H0:$B0/${V0}2 +TEST $CLI volume set $V0 stat-prefetch off +TEST $CLI volume start $V0 + +## Mount FUSE +TEST glusterfs --attribute-timeout=0 --entry-timeout=0 --gid-timeout=-1 -s $H0 --volfile-id $V0 $M0; + +# change dir permissions +mkdir $M0/dir; +chown 1:1 $M0/dir; + +# Kill a brick process + +kill -9 `cat /var/lib/glusterd/vols/$V0/run/$H0-d-backends-${V0}1.pid`; +# change dir ownership +NEW_UID=36; +NEW_GID=36; +chown $NEW_UID:$NEW_GID $M0/dir; + +# bring the brick back up +TEST $CLI volume start $V0 force + +sleep 10; + +ls -l $M0/dir; + +# check if uid/gid is healed on backend brick which was taken down +BACKEND_UID=`stat --printf=%u $B0/${V0}1/dir`; +BACKEND_GID=`stat --printf=%g $B0/${V0}1/dir`; + + +EXPECT "0" uid_gid_compare $NEW_UID $NEW_GID $BACKEND_UID $BACKEND_GID diff --git a/xlators/cluster/dht/src/dht-common.c b/xlators/cluster/dht/src/dht-common.c index 98560685..0925b6d2 100644 --- a/xlators/cluster/dht/src/dht-common.c +++ b/xlators/cluster/dht/src/dht-common.c @@ -525,6 +525,8 @@ dht_revalidate_cbk (call_frame_t *frame, void *cookie, xlator_t *this,          int           ret  = -1;          int           is_dir = 0;          int           is_linkfile = 0; +        call_frame_t *copy          = NULL; +        dht_local_t  *copy_local    = NULL;          GF_VALIDATE_OR_GOTO ("dht", frame, err);          GF_VALIDATE_OR_GOTO ("dht", this, err); @@ -595,6 +597,23 @@ dht_revalidate_cbk (call_frame_t *frame, void *cookie, xlator_t *this,                  }                  if (is_dir) { +                        ret = dht_dir_has_layout (xattr); +                        if (ret >= 0) { +                                if (is_greater_time(local->stbuf.ia_ctime, +                                                    local->stbuf.ia_ctime_nsec, +                                                    stbuf->ia_ctime, +                                                    stbuf->ia_ctime_nsec)) { +                                        local->prebuf.ia_gid = stbuf->ia_gid; +                                        local->prebuf.ia_uid = stbuf->ia_uid; +                                } +                        } +                        if (local->stbuf.ia_type != IA_INVAL) +                        { +                                if ((local->stbuf.ia_gid != stbuf->ia_gid) || +                                    (local->stbuf.ia_uid != stbuf->ia_uid)) { +                                        local->need_selfheal = 1; +                                } +                        }                          ret = dht_layout_dir_mismatch (this, layout,                                                         prev->this, &local->loc,                                                         xattr); @@ -633,7 +652,28 @@ out:                      && (conf && conf->unhashed_sticky_bit)) {                          local->stbuf.ia_prot.sticky = 1;                  } -                if (local->layout_mismatch) { +                if (local->need_selfheal) { +                        local->need_selfheal = 0; +                        uuid_copy (local->gfid, local->stbuf.ia_gfid); +                        local->stbuf.ia_gid = local->prebuf.ia_gid; +                        local->stbuf.ia_uid = local->prebuf.ia_uid; +                        copy = create_frame (this, this->ctx->pool); +                        if (copy) { +                                copy_local = dht_local_init (copy, &local->loc, +                                                             NULL, 0); +                                if (!copy_local) +                                        goto cont; +                                copy_local->stbuf = local->stbuf; +                                copy->local = copy_local; +                                FRAME_SU_DO (copy, dht_local_t); +                                ret = synctask_new (this->ctx->env, +                                                    dht_dir_attr_heal, +                                                    dht_dir_attr_heal_done, +                                                    copy, copy); +                        } +                } +cont: +		if (local->layout_mismatch) {                          /* Found layout mismatch in the directory, need to                             fix this in the inode context */                          dht_layout_unref (this, local->layout); diff --git a/xlators/cluster/dht/src/dht-common.h b/xlators/cluster/dht/src/dht-common.h index 0f2df514..1a69feba 100644 --- a/xlators/cluster/dht/src/dht-common.h +++ b/xlators/cluster/dht/src/dht-common.h @@ -370,6 +370,7 @@ typedef enum {                  UNLOCK (&inode->lock);                                  \          } while (0) +#define is_greater_time(a, an, b, bn) (((a) < (b)) || (((a) == (b)) && ((an) < (bn))))  dht_layout_t                            *dht_layout_new (xlator_t *this, int cnt);  dht_layout_t                            *dht_layout_get (xlator_t *this, inode_t *inode);  dht_layout_t                            *dht_layout_for_subvol (xlator_t *this, xlator_t *subvol); @@ -715,4 +716,10 @@ dht_inode_ctx_time_update (inode_t *inode, xlator_t *this, struct iatt *stat,  int dht_inode_ctx_get (inode_t *inode, xlator_t *this, dht_inode_ctx_t **ctx);  int dht_inode_ctx_set (inode_t *inode, xlator_t *this, dht_inode_ctx_t *ctx); +int +dht_dir_attr_heal (void *data); +int +dht_dir_attr_heal_done (int ret, call_frame_t *sync_frame, void *data); +int +dht_dir_has_layout (dict_t *xattr);  #endif/* _DHT_H */ diff --git a/xlators/cluster/dht/src/dht-layout.c b/xlators/cluster/dht/src/dht-layout.c index 19807607..993f6166 100644 --- a/xlators/cluster/dht/src/dht-layout.c +++ b/xlators/cluster/dht/src/dht-layout.c @@ -615,6 +615,16 @@ out:          return ret;  } +int +dht_dir_has_layout (dict_t *xattr) +{ + +        void     *disk_layout_raw = NULL; + +        return dict_get_ptr (xattr, "trusted.glusterfs.dht", +                             &disk_layout_raw); + +}  int  dht_layout_dir_mismatch (xlator_t *this, dht_layout_t *layout, xlator_t *subvol, diff --git a/xlators/cluster/dht/src/dht-selfheal.c b/xlators/cluster/dht/src/dht-selfheal.c index 8ac5a9e9..7a5d4d11 100644 --- a/xlators/cluster/dht/src/dht-selfheal.c +++ b/xlators/cluster/dht/src/dht-selfheal.c @@ -858,3 +858,50 @@ dht_selfheal_restore (call_frame_t *frame, dht_selfheal_dir_cbk_t dir_cbk,          return ret;  } + +int +dht_dir_attr_heal (void *data) +{ +        call_frame_t    *frame = NULL; +        dht_local_t     *local = NULL; +        xlator_t        *subvol = NULL; +        xlator_t        *this  = NULL; +        dht_conf_t      *conf  = NULL; +        int              call_cnt = 0; +        int              ret   = -1; +        int              i     = 0; + +        GF_VALIDATE_OR_GOTO ("dht", data, out); + +        frame = data; +        local = frame->local; +        this = frame->this; +        GF_VALIDATE_OR_GOTO ("dht", this, out); +        GF_VALIDATE_OR_GOTO ("dht", local, out); +        conf = this->private; +        GF_VALIDATE_OR_GOTO ("dht", conf, out); + +        call_cnt = conf->subvolume_cnt; + +        for (i = 0; i < call_cnt; i++) { +                subvol = conf->subvolumes[i]; +                if (!subvol || (subvol == dht_first_up_subvol (this))) +                        continue; +                ret = syncop_setattr (subvol, &local->loc, &local->stbuf, +                                      (GF_SET_ATTR_UID | GF_SET_ATTR_GID), +                                      NULL, NULL); +                if (ret) +                        gf_log ("dht", GF_LOG_ERROR, "Failed to set uid/gid on" +                                " %s on %s subvol (%s)", local->loc.path, +                                subvol->name, strerror (errno)); +        } +out: +        return 0; +} + +int +dht_dir_attr_heal_done (int ret, call_frame_t *sync_frame, void *data) +{ +        DHT_STACK_DESTROY (sync_frame); +        return 0; +}  | 
