diff options
| -rw-r--r-- | tests/basic/ctime/ctime-readdir.c | 29 | ||||
| -rw-r--r-- | tests/basic/ctime/ctime-readdir.t | 50 | ||||
| -rw-r--r-- | xlators/storage/posix/src/posix-helpers.c | 29 | ||||
| -rw-r--r-- | xlators/storage/posix/src/posix-metadata.c | 41 | 
4 files changed, 123 insertions, 26 deletions
diff --git a/tests/basic/ctime/ctime-readdir.c b/tests/basic/ctime/ctime-readdir.c new file mode 100644 index 00000000000..8760db29ae8 --- /dev/null +++ b/tests/basic/ctime/ctime-readdir.c @@ -0,0 +1,29 @@ +#include <stdio.h> +#include <dirent.h> +#include <string.h> +#include <assert.h> + +int +main(int argc, char **argv) +{ +    DIR *dir = NULL; +    struct dirent *entry = NULL; +    int ret = 0; +    char *path = NULL; + +    assert(argc == 2); +    path = argv[1]; + +    dir = opendir(path); +    if (!dir) { +        printf("opendir(%s) failed.\n", path); +        return -1; +    } + +    while ((entry = readdir(dir)) != NULL) { +    } +    if (dir) +        closedir(dir); + +    return ret; +} diff --git a/tests/basic/ctime/ctime-readdir.t b/tests/basic/ctime/ctime-readdir.t new file mode 100644 index 00000000000..4564fc1b667 --- /dev/null +++ b/tests/basic/ctime/ctime-readdir.t @@ -0,0 +1,50 @@ +#!/bin/bash + +. $(dirname $0)/../../include.rc +. $(dirname $0)/../../volume.rc + +cleanup; + +TEST glusterd + +TEST $CLI volume create $V0 replica 3 ${H0}:$B0/brick{1,2,3}; +TEST $CLI volume set $V0 performance.stat-prefetch on +TEST $CLI volume set $V0 performance.readdir-ahead off +TEST $CLI volume start $V0; + +TEST glusterfs --volfile-id=$V0 --volfile-server=$H0 --entry-timeout=0 $M0; + +TEST mkdir $M0/dir0 +TEST "echo hello_world > $M0/dir0/FILE" + +ctime1=$(stat -c %Z $M0/dir0/FILE) +echo "Mount change time: $ctime1" + +sleep 2 + +#Write to back end directly to modify ctime of backend file +TEST "echo write_from_backend >> $B0/brick1/dir0/FILE" +TEST "echo write_from_backend >> $B0/brick2/dir0/FILE" +TEST "echo write_from_backend >> $B0/brick3/dir0/FILE" +echo "Backend change time" +echo "brick1: $(stat -c %Z $B0/brick1/dir0/FILE)" +echo "brick2: $(stat -c %Z $B0/brick2/dir0/FILE)" +echo "brick3: $(stat -c %Z $B0/brick3/dir0/FILE)" + +#Stop and start to hit the case of no inode for readdir +TEST umount $M0 +TEST $CLI volume stop $V0 +TEST $CLI volume start $V0 +TEST glusterfs --volfile-id=$V0 --volfile-server=$H0 --entry-timeout=0 $M0; + +TEST build_tester $(dirname $0)/ctime-readdir.c + +#Do readdir +TEST ./$(dirname $0)/ctime-readdir $M0/dir0 + +EXPECT "$ctime1" stat -c %Z $M0/dir0/FILE +echo "Mount change time after readdir $(stat -c %Z $M0/dir0/FILE)" + +cleanup_tester $(dirname $0)/ctime-readdir + +cleanup; diff --git a/xlators/storage/posix/src/posix-helpers.c b/xlators/storage/posix/src/posix-helpers.c index c7ab13d1163..d0fd45a805a 100644 --- a/xlators/storage/posix/src/posix-helpers.c +++ b/xlators/storage/posix/src/posix-helpers.c @@ -832,17 +832,26 @@ posix_pstat(xlator_t *this, inode_t *inode, uuid_t gfid, const char *path,      iatt_from_stat(&stbuf, &lstatbuf); -    if (inode && priv->ctime) { -        if (!inode_locked) { -            ret = posix_get_mdata_xattr(this, path, -1, inode, &stbuf); +    if (priv->ctime) { +        if (inode) { +            if (!inode_locked) { +                ret = posix_get_mdata_xattr(this, path, -1, inode, &stbuf); +            } else { +                ret = __posix_get_mdata_xattr(this, path, -1, inode, &stbuf); +            } +            if (ret) { +                gf_msg(this->name, GF_LOG_WARNING, errno, P_MSG_GETMDATA_FAILED, +                       "posix get mdata failed on gfid: %s", +                       uuid_utoa(inode->gfid)); +                goto out; +            }          } else { -            ret = __posix_get_mdata_xattr(this, path, -1, inode, &stbuf); -        } -        if (ret) { -            gf_msg(this->name, GF_LOG_WARNING, errno, P_MSG_GETMDATA_FAILED, -                   "posix get mdata failed on gfid: %s", -                   uuid_utoa(inode->gfid)); -            goto out; +            ret = __posix_get_mdata_xattr(this, path, -1, NULL, &stbuf); +            if (ret) { +                gf_msg(this->name, GF_LOG_WARNING, errno, P_MSG_GETMDATA_FAILED, +                       "posix get mdata failed on path: %s", path); +                goto out; +            }          }      } diff --git a/xlators/storage/posix/src/posix-metadata.c b/xlators/storage/posix/src/posix-metadata.c index 0ea90992714..7ff522519d8 100644 --- a/xlators/storage/posix/src/posix-metadata.c +++ b/xlators/storage/posix/src/posix-metadata.c @@ -79,6 +79,7 @@ posix_fetch_mdata_xattr(xlator_t *this, const char *real_path_arg, int _fd,          fd_based_fop = _gf_true;      }      if (!(fd_based_fop || real_path_arg)) { +        GF_VALIDATE_OR_GOTO(this->name, inode, out);          MAKE_HANDLE_PATH(real_path, this, inode->gfid, NULL);          if (!real_path) {              uuid_utoa_r(inode->gfid, gfid_str); @@ -114,14 +115,14 @@ posix_fetch_mdata_xattr(xlator_t *this, const char *real_path_arg, int _fd,                           key,                           real_path ? real_path                                     : (real_path_arg ? real_path_arg : "null"), -                         uuid_utoa(inode->gfid)); +                         inode ? uuid_utoa(inode->gfid) : "null");          } else {              gf_msg(this->name, GF_LOG_DEBUG, *op_errno, P_MSG_XATTR_FAILED,                     "getxattr failed"                     " on %s gfid: %s key: %s ",                     real_path ? real_path                               : (real_path_arg ? real_path_arg : "null"), -                   uuid_utoa(inode->gfid), key); +                   inode ? uuid_utoa(inode->gfid) : "null", key);          }          op_ret = -1;          goto out; @@ -148,7 +149,7 @@ posix_fetch_mdata_xattr(xlator_t *this, const char *real_path_arg, int _fd,                 "getxattr failed on "                 " on %s gfid: %s key: %s ",                 real_path ? real_path : (real_path_arg ? real_path_arg : "null"), -               uuid_utoa(inode->gfid), key); +               inode ? uuid_utoa(inode->gfid) : "null", key);          goto out;      } @@ -233,9 +234,14 @@ __posix_get_mdata_xattr(xlator_t *this, const char *real_path, int _fd,      int ret = -1;      int op_errno = 0; -    GF_VALIDATE_OR_GOTO(this->name, inode, out); +    /* Handle readdirp: inode might be null, time attributes should be served +     * from xattr not from backend's file attributes */ +    if (inode) { +        ret = __inode_ctx_get1(inode, this, (uint64_t *)&mdata); +    } else { +        ret = -1; +    } -    ret = __inode_ctx_get1(inode, this, (uint64_t *)&mdata);      if (ret == -1 || !mdata) {          mdata = GF_CALLOC(1, sizeof(posix_mdata_t), gf_posix_mt_mdata_attr);          if (!mdata) { @@ -251,7 +257,9 @@ __posix_get_mdata_xattr(xlator_t *this, const char *real_path, int _fd,               * is hit when in-memory status is lost due to brick               * down scenario               */ -            __inode_ctx_set1(inode, this, (uint64_t *)&mdata); +            if (inode) { +                __inode_ctx_set1(inode, this, (uint64_t *)&mdata); +            }          } else {              /* Failed to get mdata from disk, xattr missing.               * This happens on two cases. @@ -278,7 +286,8 @@ __posix_get_mdata_xattr(xlator_t *this, const char *real_path, int _fd,                   */                  gf_msg(this->name, GF_LOG_WARNING, op_errno,                         P_MSG_FETCHMDATA_FAILED, "file: %s: gfid: %s key:%s ", -                       real_path ? real_path : "null", uuid_utoa(inode->gfid), +                       real_path ? real_path : "null", +                       inode ? uuid_utoa(inode->gfid) : "null",                         GF_XATTR_MDATA_KEY);                  GF_FREE(mdata);                  ret = 0; @@ -297,6 +306,10 @@ __posix_get_mdata_xattr(xlator_t *this, const char *real_path, int _fd,          stbuf->ia_atime = mdata->atime.tv_sec;          stbuf->ia_atime_nsec = mdata->atime.tv_nsec;      } +    /* Not set in inode context, hence free mdata */ +    if (!inode) { +        GF_FREE(mdata); +    }  out:      return ret; @@ -416,6 +429,11 @@ posix_set_mdata_xattr(xlator_t *this, const char *real_path, int fd,              }          } +        if ((flag->ctime == 0) && (flag->mtime == 0) && (flag->atime == 0)) { +            ret = 0; +            goto unlock; +        } +          /* Earlier, mdata was updated only if the existing time is less           * than the time to be updated. This would fail the scenarios           * where mtime can be set to any time using the syscall. Hence @@ -486,7 +504,6 @@ out:          stbuf->ia_atime_nsec = mdata->atime.tv_nsec;      } -      return ret;  } @@ -604,10 +621,6 @@ posix_set_ctime(call_frame_t *frame, xlator_t *this, const char *real_path,      if (priv->ctime) {          (void)posix_get_mdata_flag(frame->root->flags, &flag); -        if ((flag.ctime == 0) && (flag.mtime == 0) && (flag.atime == 0)) { -            goto out; -        } -          if (frame->root->ctime.tv_sec == 0) {              gf_msg(this->name, GF_LOG_WARNING, errno, P_MSG_SETMDATA_FAILED,                     "posix set mdata failed, No ctime : %s gfid:%s", real_path, @@ -643,9 +656,6 @@ posix_set_parent_ctime(call_frame_t *frame, xlator_t *this,      if (inode && priv->ctime) {          (void)posix_get_parent_mdata_flag(frame->root->flags, &flag); -        if ((flag.ctime == 0) && (flag.mtime == 0) && (flag.atime == 0)) { -            goto out; -        }          ret = posix_set_mdata_xattr(this, real_path, fd, inode,                                      &frame->root->ctime, stbuf, &flag,                                      _gf_false); @@ -655,7 +665,6 @@ posix_set_parent_ctime(call_frame_t *frame, xlator_t *this,                     uuid_utoa(inode->gfid));          }      } -out:      return;  }  | 
