diff options
| -rw-r--r-- | libglusterfs/src/syncop-utils.c | 18 | ||||
| -rw-r--r-- | tests/bugs/posix/bug-gfid-path.t | 70 | ||||
| -rw-r--r-- | xlators/features/bit-rot/src/stub/bit-rot-stub-helpers.c | 38 | ||||
| -rw-r--r-- | xlators/storage/posix/src/posix-gfid-path.c | 26 | ||||
| -rw-r--r-- | xlators/storage/posix/src/posix-gfid-path.h | 1 | 
5 files changed, 127 insertions, 26 deletions
diff --git a/libglusterfs/src/syncop-utils.c b/libglusterfs/src/syncop-utils.c index 40ced03cb45..1ccda55e4c5 100644 --- a/libglusterfs/src/syncop-utils.c +++ b/libglusterfs/src/syncop-utils.c @@ -591,9 +591,21 @@ syncop_gfid_to_path_hard (inode_table_t *itable, xlator_t *subvol, uuid_t gfid,          if (ret < 0)                  goto out; -        ret = dict_get_str (xattr, hard_resolve ? -                            GFID2PATH_VIRT_XATTR_KEY : GFID_TO_PATH_KEY, -                            &path); + +        /* +         * posix will do dict_set_dynstr for GFID_TO_PATH_KEY i.e. +         * for in memory search for the path. And for on disk xattr +         * fetching of the path for the key GFID2PATH_VIRT_XATTR_KEY +         * it uses dict_set_dynptr. So, for GFID2PATH_VIRT_XATTR_KEY +         * use dict_get_ptr to avoid dict complaining about type +         * mismatch (i.e. str vs ptr) +         */ +        if (!hard_resolve) +                ret = dict_get_str (xattr, GFID_TO_PATH_KEY, &path); +        else +                ret = dict_get_ptr (xattr, GFID2PATH_VIRT_XATTR_KEY, +                                    (void **)&path); +          if (ret || !path) {                  ret = -EINVAL;                  goto out; diff --git a/tests/bugs/posix/bug-gfid-path.t b/tests/bugs/posix/bug-gfid-path.t new file mode 100644 index 00000000000..1bbbe9f0670 --- /dev/null +++ b/tests/bugs/posix/bug-gfid-path.t @@ -0,0 +1,70 @@ +#!/bin/bash + +# This test case is for the bug where, even though a file is +# created when gfid2path option is turned off (default is ON), +# getfattr of "glusterfs.gfidtopath" was succeeding for that +# file. Ideally the getfattr should fail, as the file does not +# have its path(s) stored as a extended attribute (because it +# was created when gfid2path option was off) + +. $(dirname $0)/../../include.rc +. $(dirname $0)/../../volume.rc + +cleanup; + +TEST glusterd +TEST pidof glusterd +TEST $CLI volume info; + +TEST $CLI volume create $V0 $H0:$B0/${V0}{1,2,3,4}; + +EXPECT "$V0" volinfo_field $V0 'Volume Name'; +EXPECT 'Created' volinfo_field $V0 'Status'; +EXPECT '4' brick_count $V0 + +TEST $CLI volume start $V0; +EXPECT 'Started' volinfo_field $V0 'Status'; + +TEST glusterfs -s $H0 --volfile-id $V0 $M0; + +TEST mkdir $M0/dir +TEST mkdir $M0/new +TEST mkdir $M0/3 + +TEST touch $M0/dir/file + +# except success as by default gfid2path is enabled +# and the glusterfs.gfidtopath xattr should give the +# path of the object as the value + +TEST getfattr -n glusterfs.gfidtopath $M0/dir/file + +# turn off gfid2path feature +TEST $CLI volume set $V0 storage.gfid2path off + +TEST touch $M0/new/foo + +# again enable gfid2path. This has to be enabled before +# trying the getfattr. Because, glusterfs.gfidtopath xattr +# request is handled only if gfid2path is enabled. If not, +# then getxattr on glusterfs.gfid2path fails anyways. In this +# context we want getfattr to fail, because the file was created +# when gfid2path feature was disabled and not because gfid2path +# feature itself is disabled. +TEST $CLI volume set $V0 storage.gfid2path on + +# getfattr should fail as it is attempted on a file +# which does not have its path stored as a xattr +# (because file got created after disabling gfid2path) +TEST ! getfattr -n glusterfs.gfidtopath $M0/new/foo; + + + +TEST touch $M0/3/new + +# should be successful +TEST getfattr -n glusterfs.gfidtopath $M0/3/new + +TEST rm -rf $M0/* + +cleanup; diff --git a/xlators/features/bit-rot/src/stub/bit-rot-stub-helpers.c b/xlators/features/bit-rot/src/stub/bit-rot-stub-helpers.c index 24aa9aa5ff4..fff7a7eedf2 100644 --- a/xlators/features/bit-rot/src/stub/bit-rot-stub-helpers.c +++ b/xlators/features/bit-rot/src/stub/bit-rot-stub-helpers.c @@ -722,35 +722,21 @@ br_stub_get_path_of_gfid (xlator_t *this, inode_t *parent, inode_t *inode,          GF_VALIDATE_OR_GOTO (this->name, parent, out);          GF_VALIDATE_OR_GOTO (this->name, path, out); -        /* No need to validate the @inode for hard resolution. Because inode -         * can be NULL and if it is NULL, then syncop_gfid_to_path_hard will -         * allocate a new inode and proceed. So no need to bother about +        /* Above, No need to validate the @inode for hard resolution. Because +         * inode can be NULL and if it is NULL, then syncop_gfid_to_path_hard +         * will allocate a new inode and proceed. So no need to bother about           * @inode. Because we need it only to send a syncop_getxattr call           * from inside syncop_gfid_to_path_hard. And getxattr fetches the           * path from the backend.           */ +          ret = syncop_gfid_to_path_hard (parent->table, FIRST_CHILD (this), gfid,                                          inode, path, _gf_true); - -        /* -         * This is to handle those corrupted files which does not contain -         * the gfid2path xattr in the backend (because they were created -         * when the option was OFF OR it was upgraded from a version before -         * gfid2path was brought in. -         * Ideally posix should be returning ret < 0 i.e. error if the -         * gfid2path xattr is not present. But for some reason it is -         * returning success and path as "". THis is causing problems. -         * For now handling it by adding extra checks. But the better way -         * is to make posix return error if gfid2path xattr is absent. -         * When that is done remove below if block and also this entire -         * comment. -         */ -        if (ret >= 0 && !strlen (*path)) { +        if (ret < 0)                  gf_msg (this->name, GF_LOG_WARNING, 0, BRS_MSG_PATH_GET_FAILED, -                        "path for the object %s is %s. Going for in memory path", -                        uuid_utoa_r (gfid, gfid_str), *path); -                ret = -1; -        } +                        "failed to get the path xattr from disk for the " +                        " gfid %s. Trying to get path from the memory", +                        uuid_utoa_r (gfid, gfid_str));          /*           * Try with soft resolution of path if hard resolve fails. Because @@ -767,10 +753,16 @@ br_stub_get_path_of_gfid (xlator_t *this, inode_t *parent, inode_t *inode,           * found in the inode table and better not to do inode_path() on the           * inode which has not been linked.           */ -        if (ret < 0 && inode) +        if (ret < 0 && inode) {                  ret = syncop_gfid_to_path_hard (parent->table,                                                  FIRST_CHILD (this), gfid, inode,                                                  path, _gf_false); +                if (ret < 0) +                        gf_msg (this->name, GF_LOG_WARNING, 0, +                                BRS_MSG_PATH_GET_FAILED, +                                "failed to get the path from the memory for gfid %s", +                                uuid_utoa_r (gfid, gfid_str)); +        }  out:          return ret; diff --git a/xlators/storage/posix/src/posix-gfid-path.c b/xlators/storage/posix/src/posix-gfid-path.c index 2834c2fc4fd..9873e7e5a84 100644 --- a/xlators/storage/posix/src/posix-gfid-path.c +++ b/xlators/storage/posix/src/posix-gfid-path.c @@ -123,6 +123,7 @@ posix_get_gfid2path (xlator_t *this, inode_t *inode, const char *real_path,          gf_boolean_t           have_val                        = _gf_false;          struct posix_private  *priv                            = NULL;          char                   pargfid_str[UUID_CANONICAL_FORM_LEN + 1] = {0,}; +        gf_boolean_t           found                           = _gf_false;          priv = this->private; @@ -141,6 +142,7 @@ posix_get_gfid2path (xlator_t *this, inode_t *inode, const char *real_path,                                  "value for key (%s)", GFID2PATH_VIRT_XATTR_KEY);                          goto err;                  } +                found = _gf_true;          } else {                  have_val = _gf_false;                  memset (value_buf, '\0', sizeof(value_buf)); @@ -202,6 +204,7 @@ posix_get_gfid2path (xlator_t *this, inode_t *inode, const char *real_path,                                  goto ignore;                          } +                        found = _gf_true;                          memset (value_buf, '\0', sizeof(value_buf));                          size = sys_lgetxattr (real_path, keybuffer, value_buf,                                                sizeof (value_buf) - 1); @@ -231,6 +234,29 @@ ignore:                          list_offset += strlen (keybuffer) + 1;                  } /* while (remaining_size > 0) */ +                /* gfid2path xattr is absent in the list of xattrs */ +                if (!found) { +                        ret = -1; +                        /* +                         * ENODATA because xattr is not present in the +                         * list of xattrs. Thus the consumer should +                         * face error instead of a success and a empty +                         * string in the dict for the key. +                         */ +                        *op_errno = ENODATA; +                        goto err; +                } + +                /* +                 * gfid2path xattr is found in list of xattrs, but getxattr +                 * on the 1st gfid2path xattr itself failed and the while +                 * loop above broke. So there is nothing in the value. So +                 * it would be better not to send "" as the value for any +                 * key, as it is not true. +                 */ +                if (found && !i) +                        goto err; /* both errno and ret are set before beak */ +                  /* Calculate memory to be allocated */                  for (j = 0; j < i; j++) {                          bytes += strlen(paths[j]); diff --git a/xlators/storage/posix/src/posix-gfid-path.h b/xlators/storage/posix/src/posix-gfid-path.h index ac3d03e14c3..59799125bbb 100644 --- a/xlators/storage/posix/src/posix-gfid-path.h +++ b/xlators/storage/posix/src/posix-gfid-path.h @@ -13,6 +13,7 @@  #include "xlator.h"  #include "common-utils.h" +#include "compat-errno.h"  #define MAX_GFID2PATH_LINK_SUP 500  | 
