diff options
| -rw-r--r-- | libglusterfs/src/glusterfs.h | 1 | ||||
| -rw-r--r-- | libglusterfs/src/xlator.c | 11 | ||||
| -rw-r--r-- | libglusterfs/src/xlator.h | 1 | ||||
| -rw-r--r-- | tests/bugs/bug-886998.t | 52 | ||||
| -rw-r--r-- | xlators/cluster/afr/src/afr-common.c | 7 | ||||
| -rw-r--r-- | xlators/cluster/afr/src/afr-dir-read.c | 30 | ||||
| -rw-r--r-- | xlators/cluster/afr/src/afr-self-heal-entry.c | 28 | 
7 files changed, 117 insertions, 13 deletions
diff --git a/libglusterfs/src/glusterfs.h b/libglusterfs/src/glusterfs.h index ac0c81267..b3ff1fd38 100644 --- a/libglusterfs/src/glusterfs.h +++ b/libglusterfs/src/glusterfs.h @@ -143,6 +143,7 @@  					       ZR_FILE_CONTENT_STRLEN))  #define DEFAULT_VAR_RUN_DIRECTORY    DATADIR "/run/gluster" +#define GF_REPLICATE_TRASH_DIR          ".landfill"  /* GlusterFS's maximum supported Auxilary GIDs */  /* TODO: Keeping it to 200, so that we can fit in 2KB buffer for auth data diff --git a/libglusterfs/src/xlator.c b/libglusterfs/src/xlator.c index b1c090c1e..a7caedf02 100644 --- a/libglusterfs/src/xlator.c +++ b/libglusterfs/src/xlator.c @@ -684,6 +684,17 @@ err:          return ret;  } +gf_boolean_t +loc_is_root (loc_t *loc) +{ +        if (loc && __is_root_gfid (loc->gfid)) { +                return _gf_true; +        } else if (loc && loc->inode && __is_root_gfid (loc->inode->gfid)) { +                return _gf_true; +        } +        return _gf_false; +} +  int  xlator_list_destroy (xlator_list_t *list)  { diff --git a/libglusterfs/src/xlator.h b/libglusterfs/src/xlator.h index 817eaddec..d23ee0c25 100644 --- a/libglusterfs/src/xlator.h +++ b/libglusterfs/src/xlator.h @@ -922,6 +922,7 @@ void loc_wipe (loc_t *loc);  int loc_path (loc_t *loc, const char *bname);  void loc_gfid (loc_t *loc, uuid_t gfid);  char* loc_gfid_utoa (loc_t *loc); +gf_boolean_t loc_is_root (loc_t *loc);  int xlator_mem_acct_init (xlator_t *xl, int num_types);  int is_gf_log_command (xlator_t *trans, const char *name, char *value);  int glusterd_check_log_level (const char *value); diff --git a/tests/bugs/bug-886998.t b/tests/bugs/bug-886998.t new file mode 100644 index 000000000..7a905a113 --- /dev/null +++ b/tests/bugs/bug-886998.t @@ -0,0 +1,52 @@ +#!/bin/bash + +. $(dirname $0)/../include.rc +. $(dirname $0)/../volume.rc + +cleanup; + +# This tests that the replicate trash directory(.landfill) has following +# properties. +# Note: This is to have backward compatibility with 3.3 glusterfs +#       In the latest releases this dir is present inside .glusterfs of brick. +# 1) lookup of trash dir fails +# 2) readdir does not show this directory +# 3) Self-heal does not do any self-heal of these directories. +gfid1="0xc2e75dde97f346e7842d1076a8e699f8" +TEST glusterd +TEST pidof glusterd +TEST $CLI volume create $V0 replica 2 $H0:$B0/${V0}0 $H0:$B0/${V0}1 +TEST $CLI volume start $V0 +TEST glusterfs --volfile-id=/$V0 --volfile-server=$H0 $M0 --attribute-timeout=0 --entry-timeout=0 --direct-io-mode=enable + +TEST mkdir $B0/${V0}1/.landfill +TEST setfattr -n trusted.gfid -v $gfid1 $B0/${V0}1/.landfill +TEST mkdir $B0/${V0}0/.landfill +TEST setfattr -n trusted.gfid -v $gfid1 $B0/${V0}0/.landfill + +TEST ! stat $M0/.landfill +EXPECT "" echo $(ls -a $M0 | grep ".landfill") + +TEST rmdir $B0/${V0}0/.landfill +#Force a conservative merge and it should not create .landfill +TEST setfattr -n trusted.afr.$V0-client-0 -v 0x000000000000000000000000 $B0/${V0}0/ +TEST setfattr -n trusted.afr.$V0-client-1 -v 0x000000000000000000000001 $B0/${V0}0/ + +TEST setfattr -n trusted.afr.$V0-client-0 -v 0x000000000000000000000001 $B0/${V0}1/ +TEST setfattr -n trusted.afr.$V0-client-1 -v 0x000000000000000000000000 $B0/${V0}1/ + +EXPECT "" echo $(ls -a $M0 | grep ".landfill") +TEST ! stat $B0/${V0}0/.landfill +TEST stat $B0/${V0}1/.landfill + +#TEST that the dir is not deleted even when xattrs suggest to delete +TEST setfattr -n trusted.afr.$V0-client-0 -v 0x000000000000000000000000 $B0/${V0}0/ +TEST setfattr -n trusted.afr.$V0-client-1 -v 0x000000000000000000000001 $B0/${V0}0/ + +TEST setfattr -n trusted.afr.$V0-client-0 -v 0x000000000000000000000000 $B0/${V0}1/ +TEST setfattr -n trusted.afr.$V0-client-1 -v 0x000000000000000000000000 $B0/${V0}1/ + +EXPECT "" echo $(ls -a $M0 | grep ".landfill") +TEST ! stat $B0/${V0}0/.landfill +TEST stat $B0/${V0}1/.landfill +cleanup; diff --git a/xlators/cluster/afr/src/afr-common.c b/xlators/cluster/afr/src/afr-common.c index 48b4c1a42..d2b3e46e5 100644 --- a/xlators/cluster/afr/src/afr-common.c +++ b/xlators/cluster/afr/src/afr-common.c @@ -2351,6 +2351,13 @@ afr_lookup (call_frame_t *frame, xlator_t *this,                  goto out;          } +        if (local->loc.path && +            (strcmp (local->loc.path, "/" GF_REPLICATE_TRASH_DIR) == 0)) { +                op_errno = EPERM; +                ret = -1; +                goto out; +        } +          ret = inode_ctx_get (local->loc.inode, this, &ctx);          if (ret == 0) {                  /* lookup is a revalidate */ diff --git a/xlators/cluster/afr/src/afr-dir-read.c b/xlators/cluster/afr/src/afr-dir-read.c index 0e1718814..2bb707853 100644 --- a/xlators/cluster/afr/src/afr-dir-read.c +++ b/xlators/cluster/afr/src/afr-dir-read.c @@ -383,14 +383,36 @@ afr_forget_entries (fd_t *fd)          }  } +static void +afr_readdir_filter_trash_dir (gf_dirent_t *entries, fd_t *fd) +{ +        gf_dirent_t *   entry       = NULL; +        gf_dirent_t *   tmp         = NULL; + +        list_for_each_entry_safe (entry, tmp, &entries->list, list) { +                if (__is_root_gfid (fd->inode->gfid) && +                    !strcmp (entry->d_name, GF_REPLICATE_TRASH_DIR)) { +                        list_del_init (&entry->list); +                        GF_FREE (entry); +                } +        } +}  int32_t  afr_readdir_cbk (call_frame_t *frame, void *cookie,                   xlator_t *this, int32_t op_ret, int32_t op_errno,                   gf_dirent_t *entries, dict_t *xdata)  { +        afr_local_t     *local = NULL; + +        if (op_ret == -1) +                goto out; + +        local = frame->local; +        afr_readdir_filter_trash_dir (entries, local->fd);          AFR_STACK_UNWIND (readdir, frame, op_ret, op_errno, entries, NULL); +out:          return 0;  } @@ -400,8 +422,16 @@ afr_readdirp_cbk (call_frame_t *frame, void *cookie, xlator_t *this,                    int32_t op_ret, int32_t op_errno, gf_dirent_t *entries,                    dict_t *xdata)  { +        afr_local_t     *local = NULL; + +        if (op_ret == -1) +                goto out; + +        local = frame->local; +        afr_readdir_filter_trash_dir (entries, local->fd);          AFR_STACK_UNWIND (readdirp, frame, op_ret, op_errno, entries, NULL); +out:          return 0;  } diff --git a/xlators/cluster/afr/src/afr-self-heal-entry.c b/xlators/cluster/afr/src/afr-self-heal-entry.c index db17052cb..60d1a5f47 100644 --- a/xlators/cluster/afr/src/afr-self-heal-entry.c +++ b/xlators/cluster/afr/src/afr-self-heal-entry.c @@ -613,6 +613,19 @@ out:          return 0;  } +static gf_boolean_t +can_skip_entry_self_heal (char *name, loc_t *parent_loc) +{ +        if (strcmp (name, ".") == 0) { +                return _gf_true; +        } else if (strcmp (name, "..") == 0) { +                return _gf_true; +        } else if (loc_is_root (parent_loc) && +                   (strcmp (name, GF_REPLICATE_TRASH_DIR) == 0)) { +                return _gf_true; +        } +        return _gf_false; +}  int  afr_sh_entry_expunge_entry (call_frame_t *frame, xlator_t *this, @@ -640,13 +653,7 @@ afr_sh_entry_expunge_entry (call_frame_t *frame, xlator_t *this,          sh->expunge_done = afr_sh_entry_expunge_entry_done;          name = entry->d_name; - -        if ((strcmp (name, ".") == 0) -            || (strcmp (name, "..") == 0)) { - -                gf_log (this->name, GF_LOG_TRACE, -                        "skipping inspection of %s under %s", -                        name, local->loc.path); +        if (can_skip_entry_self_heal (name, &local->loc)) {                  op_ret = 0;                  goto out;          } @@ -1901,12 +1908,7 @@ afr_sh_entry_impunge_entry (call_frame_t *frame, xlator_t *this,          active_src = sh->active_source;          sh->impunge_done = afr_sh_entry_impunge_entry_done; -        if ((strcmp (entry->d_name, ".") == 0) -            || (strcmp (entry->d_name, "..") == 0)) { - -                gf_log (this->name, GF_LOG_TRACE, -                        "skipping inspection of %s under %s", -                        entry->d_name, local->loc.path); +        if (can_skip_entry_self_heal (entry->d_name, &local->loc)) {                  op_ret = 0;                  goto out;          }  | 
