diff options
-rw-r--r-- | heal/src/glfs-heal.c | 26 | ||||
-rw-r--r-- | libglusterfs/src/common-utils.h | 1 | ||||
-rw-r--r-- | tests/basic/afr/self-heald.t | 4 | ||||
-rw-r--r-- | tests/basic/pump.t | 4 | ||||
-rw-r--r-- | tests/include.rc | 18 | ||||
-rw-r--r-- | xlators/cluster/afr/src/afr-self-heald.c | 46 | ||||
-rw-r--r-- | xlators/features/index/src/index.c | 42 | ||||
-rw-r--r-- | xlators/features/index/src/index.h | 1 | ||||
-rw-r--r-- | xlators/storage/posix/src/posix.c | 26 |
9 files changed, 137 insertions, 31 deletions
diff --git a/heal/src/glfs-heal.c b/heal/src/glfs-heal.c index 1056ea467c4..9416316458d 100644 --- a/heal/src/glfs-heal.c +++ b/heal/src/glfs-heal.c @@ -284,7 +284,7 @@ _get_afr_ancestor (xlator_t *xl) static int glfsh_process_entries (xlator_t *xl, fd_t *fd, gf_dirent_t *entries, - off_t *offset, uint64_t *num_entries) + uint64_t *offset, uint64_t *num_entries) { gf_dirent_t *entry = NULL; gf_dirent_t *tmp = NULL; @@ -359,7 +359,7 @@ out: static int glfsh_crawl_directory (xlator_t *readdir_xl, fd_t *fd, loc_t *loc) { - off_t offset = 0; + uint64_t offset = 0; gf_dirent_t entries; int ret = 0; gf_boolean_t free_entries = _gf_false; @@ -472,7 +472,27 @@ glfsh_print_pending_heals (xlator_t *xl, loc_t *rootloc) goto out; } - fd = fd_anonymous (dirloc.inode); + fd = fd_create (dirloc.inode, GF_CLIENT_PID_GLFS_HEAL); + if (!fd) { + printf ("fd_create failed: %s", strerror(errno)); + goto out; + } + ret = syncop_opendir (xl, &dirloc, fd); + if (ret) { + fd_unref(fd); +#ifdef GF_LINUX_HOST_OS /* See comment in afr_shd_index_opendir() */ + fd = fd_anonymous (dirloc.inode); + if (!fd) { + printf ("fd_anonymous failed: %s", + strerror(errno)); + goto out; + } +#else + printf ("opendir failed: %s", strerror(errno)); + goto out; +#endif + } + ret = glfsh_crawl_directory (xl, fd, &dirloc); if (fd) fd_unref (fd); diff --git a/libglusterfs/src/common-utils.h b/libglusterfs/src/common-utils.h index 2493ba10816..23a932b71aa 100644 --- a/libglusterfs/src/common-utils.h +++ b/libglusterfs/src/common-utils.h @@ -115,6 +115,7 @@ enum _gf_client_pid GF_CLIENT_PID_NO_ROOT_SQUASH = -4, GF_CLIENT_PID_QUOTA_MOUNT = -5, GF_CLIENT_PID_AFR_SELF_HEALD = -6, + GF_CLIENT_PID_GLFS_HEAL = -7, }; typedef enum _gf_boolean gf_boolean_t; diff --git a/tests/basic/afr/self-heald.t b/tests/basic/afr/self-heald.t index 37e10b254c1..6937cf227d7 100644 --- a/tests/basic/afr/self-heald.t +++ b/tests/basic/afr/self-heald.t @@ -4,6 +4,7 @@ . $(dirname $0)/../../volume.rc cleanup; +START_TIMESTAMP=`date +%s` function disconnected_brick_count { local vol=$1 @@ -162,4 +163,7 @@ TEST $CLI volume create $V0 $H0:$B0/${V0}{6} TEST $CLI volume start $V0 TEST ! $CLI volume heal $V0 info +# Check for non Linux systems that we did not mess with directory offsets +TEST ! log_newer $START_TIMESTAMP "offset reused from another DIR" + cleanup diff --git a/tests/basic/pump.t b/tests/basic/pump.t index 6e81ddde6cd..e9e54a7a9ea 100644 --- a/tests/basic/pump.t +++ b/tests/basic/pump.t @@ -4,6 +4,7 @@ . $(dirname $0)/../volume.rc cleanup; +START_TIMESTAMP=`date +%s` TEST glusterd TEST pidof glusterd @@ -41,4 +42,7 @@ done EXPECT "" echo $files +# Check for non Linux systems that we did not mess with directory offsets +TEST ! log_newer $START_TIMESTAMP "offset reused from another DIR" + cleanup diff --git a/tests/include.rc b/tests/include.rc index 75db2d10d0e..7c31eb65402 100644 --- a/tests/include.rc +++ b/tests/include.rc @@ -783,6 +783,24 @@ function MKFS_LOOP () esac } +# usage: log_newer timestamp "string" +# search in glusterfs logs for "string" logged after timestamp seconds +# since the Epoch (usually obtained by date +%s) +log_newer() +{ + ts=$1 + msg=$2 + logdir=`$CLI --print-logdir` + + IFS="[" + for date in `grep -hr "$msg" $logdir | awk -F '[\]]' '{print $1}'` ; do + if [ `date -d "$date" +%s` -gt $ts ] ; then + return 0; + fi + done 2>/dev/null + return 1 +} + function MOUNT_LOOP () { if [ $# != 2 ] ; then diff --git a/xlators/cluster/afr/src/afr-self-heald.c b/xlators/cluster/afr/src/afr-self-heald.c index a341015303c..29f34107481 100644 --- a/xlators/cluster/afr/src/afr-self-heald.c +++ b/xlators/cluster/afr/src/afr-self-heald.c @@ -274,6 +274,8 @@ afr_shd_index_opendir (xlator_t *this, int child) #ifdef GF_LINUX_HOST_OS fd_unref (fd); fd = fd_anonymous (inode); + if (!fd) + goto out; #else /* GF_LINUX_HOST_OS */ gf_log(this->name, GF_LOG_ERROR, "opendir of %s for %s failed: %s", @@ -427,7 +429,7 @@ afr_shd_index_sweep (struct subvol_healer *healer) fd_t *fd = NULL; xlator_t *subvol = NULL; afr_private_t *priv = NULL; - off_t offset = 0; + uint64_t offset = 0; gf_dirent_t entries; gf_dirent_t *entry = NULL; uuid_t gfid; @@ -501,11 +503,12 @@ afr_shd_index_sweep (struct subvol_healer *healer) int afr_shd_full_sweep (struct subvol_healer *healer, inode_t *inode) { + loc_t loc = {0, }; fd_t *fd = NULL; xlator_t *this = NULL; xlator_t *subvol = NULL; afr_private_t *priv = NULL; - off_t offset = 0; + uint64_t offset = 0; gf_dirent_t entries; gf_dirent_t *entry = NULL; int ret = 0; @@ -514,9 +517,38 @@ afr_shd_full_sweep (struct subvol_healer *healer, inode_t *inode) priv = this->private; subvol = priv->children[healer->subvol]; - fd = fd_anonymous (inode); - if (!fd) - return -errno; + uuid_copy (loc.gfid, inode->gfid); + loc.inode = inode_ref(inode); + + fd = fd_create (inode, GF_CLIENT_PID_AFR_SELF_HEALD); + if (!fd) { + gf_log(this->name, GF_LOG_ERROR, + "fd_create of %s failed: %s", + uuid_utoa (loc.gfid), strerror(errno)); + ret = -errno; + goto out; + } + + ret = syncop_opendir (subvol, &loc, fd); + if (ret) { +#ifdef GF_LINUX_HOST_OS /* See comment in afr_shd_index_opendir() */ + fd_unref(fd); + fd = fd_anonymous (inode); + if (!fd) { + gf_log(this->name, GF_LOG_ERROR, + "fd_anonymous of %s failed: %s", + uuid_utoa (loc.gfid), strerror(errno)); + ret = -errno; + goto out; + } +#else /* GF_LINUX_HOST_OS */ + gf_log(this->name, GF_LOG_ERROR, + "opendir of %s failed: %s", + uuid_utoa (loc.gfid), strerror(errno)); + ret = -errno; + goto out; +#endif /* GF_LINUX_HOST_OS */ + } INIT_LIST_HEAD (&entries.list); @@ -558,6 +590,8 @@ afr_shd_full_sweep (struct subvol_healer *healer, inode_t *inode) break; } +out: + loc_wipe (&loc); if (fd) fd_unref (fd); return ret; @@ -947,7 +981,7 @@ afr_shd_gather_index_entries (xlator_t *this, int child, dict_t *output) fd_t *fd = NULL; xlator_t *subvol = NULL; afr_private_t *priv = NULL; - off_t offset = 0; + uint64_t offset = 0; gf_dirent_t entries; gf_dirent_t *entry = NULL; uuid_t gfid; diff --git a/xlators/features/index/src/index.c b/xlators/features/index/src/index.c index 5892f741629..f7408c1308f 100644 --- a/xlators/features/index/src/index.c +++ b/xlators/features/index/src/index.c @@ -268,10 +268,11 @@ check_delete_stale_index_file (xlator_t *this, char *filename) } static int -index_fill_readdir (fd_t *fd, DIR *dir, off_t off, +index_fill_readdir (fd_t *fd, index_fd_ctx_t *fctx, DIR *dir, off_t off, size_t size, gf_dirent_t *entries) { off_t in_case = -1; + off_t last_off = 0; size_t filled = 0; int count = 0; char entrybuf[sizeof(struct dirent) + 256 + 8]; @@ -286,11 +287,11 @@ index_fill_readdir (fd_t *fd, DIR *dir, off_t off, } else { seekdir (dir, off); #ifndef GF_LINUX_HOST_OS - if (telldir(dir) != off) { + if ((u_long)telldir(dir) != off && off != fctx->dir_eof) { gf_log (THIS->name, GF_LOG_ERROR, - "seekdir(%ld) failed on dir=%p: " + "seekdir(0x%llx) failed on dir=%p: " "Invalid argument (offset reused from " - "another DIR * structure?)", (long)off, dir); + "another DIR * structure?)", off, dir); errno = EINVAL; count = -1; goto out; @@ -299,7 +300,7 @@ index_fill_readdir (fd_t *fd, DIR *dir, off_t off, } while (filled <= size) { - in_case = telldir (dir); + in_case = (u_long)telldir (dir); if (in_case == -1) { gf_log (THIS->name, GF_LOG_ERROR, @@ -335,12 +336,13 @@ index_fill_readdir (fd_t *fd, DIR *dir, off_t off, if (this_size + filled > size) { seekdir (dir, in_case); #ifndef GF_LINUX_HOST_OS - if (telldir(dir) != in_case) { + if ((u_long)telldir(dir) != in_case && + in_case != fctx->dir_eof) { gf_log (THIS->name, GF_LOG_ERROR, - "seekdir(%ld) failed on dir=%p: " + "seekdir(0x%llx) failed on dir=%p: " "Invalid argument (offset reused from " "another DIR * structure?)", - (long)in_case, dir); + in_case, dir); errno = EINVAL; count = -1; goto out; @@ -357,7 +359,14 @@ index_fill_readdir (fd_t *fd, DIR *dir, off_t off, entry->d_name, strerror (errno)); goto out; } - this_entry->d_off = telldir (dir); + /* + * we store the offset of next entry here, which is + * probably not intended, but code using syncop_readdir() + * (glfs-heal.c, afr-self-heald.c, pump.c) rely on it + * for directory read resumption. + */ + last_off = (u_long)telldir(dir); + this_entry->d_off = last_off; this_entry->d_ino = entry->d_ino; list_add_tail (&this_entry->list, &entries->list); @@ -366,9 +375,12 @@ index_fill_readdir (fd_t *fd, DIR *dir, off_t off, count ++; } - if ((!readdir (dir) && (errno == 0))) + if ((!readdir (dir) && (errno == 0))) { /* Indicate EOF */ errno = ENOENT; + /* Remember EOF offset for later detection */ + fctx->dir_eof = last_off; + } out: return count; } @@ -581,6 +593,7 @@ __index_fd_ctx_get (fd_t *fd, xlator_t *this, index_fd_ctx_t **ctx) fctx = NULL; goto out; } + fctx->dir_eof = -1; ret = __fd_ctx_set (fd, this, (uint64_t)(long)fctx); if (ret) { @@ -950,7 +963,7 @@ index_readdir_wrapper (call_frame_t *frame, xlator_t *this, goto done; } - count = index_fill_readdir (fd, dir, off, size, &entries); + count = index_fill_readdir (fd, fctx, dir, off, size, &entries); /* pick ENOENT to indicate EOF */ op_errno = errno; @@ -1271,8 +1284,11 @@ index_releasedir (xlator_t *this, fd_t *fd) goto out; fctx = (index_fd_ctx_t*) (long) ctx; - if (fctx->dir) - closedir (fctx->dir); + if (fctx->dir) { + ret = closedir (fctx->dir); + if (ret) + gf_log (this->name, GF_LOG_ERROR, "closedir error: %s", strerror (errno)); + } GF_FREE (fctx); out: diff --git a/xlators/features/index/src/index.h b/xlators/features/index/src/index.h index 661dcdbc417..206d280e519 100644 --- a/xlators/features/index/src/index.h +++ b/xlators/features/index/src/index.h @@ -34,6 +34,7 @@ typedef struct index_inode_ctx { typedef struct index_fd_ctx { DIR *dir; + off_t dir_eof; } index_fd_ctx_t; typedef struct index_priv { diff --git a/xlators/storage/posix/src/posix.c b/xlators/storage/posix/src/posix.c index a3aa57a0153..638e0f59202 100644 --- a/xlators/storage/posix/src/posix.c +++ b/xlators/storage/posix/src/posix.c @@ -4857,6 +4857,7 @@ posix_fill_readdir (fd_t *fd, DIR *dir, off_t off, size_t size, gf_dirent_t *entries, xlator_t *this, int32_t skip_dirs) { off_t in_case = -1; + off_t last_off = 0; size_t filled = 0; int count = 0; char entrybuf[sizeof(struct dirent) + 256 + 8]; @@ -4892,11 +4893,11 @@ posix_fill_readdir (fd_t *fd, DIR *dir, off_t off, size_t size, } else { seekdir (dir, off); #ifndef GF_LINUX_HOST_OS - if (telldir(dir) != (long)off && off != pfd->dir_eof) { + if ((u_long)telldir(dir) != off && off != pfd->dir_eof) { gf_log (THIS->name, GF_LOG_ERROR, - "seekdir(%ld) failed on dir=%p: " + "seekdir(0x%llx) failed on dir=%p: " "Invalid argument (offset reused from " - "another DIR * structure?)", (long)off, dir); + "another DIR * structure?)", off, dir); errno = EINVAL; count = -1; goto out; @@ -4905,7 +4906,7 @@ posix_fill_readdir (fd_t *fd, DIR *dir, off_t off, size_t size, } while (filled <= size) { - in_case = telldir (dir); + in_case = (u_long)telldir (dir); if (in_case == -1) { gf_log (THIS->name, GF_LOG_ERROR, @@ -4965,13 +4966,13 @@ posix_fill_readdir (fd_t *fd, DIR *dir, off_t off, size_t size, if (this_size + filled > size) { seekdir (dir, in_case); #ifndef GF_LINUX_HOST_OS - if (telldir(dir) != (long)in_case && + if ((u_long)telldir(dir) != in_case && in_case != pfd->dir_eof) { gf_log (THIS->name, GF_LOG_ERROR, - "seekdir(%ld) failed on dir=%p: " + "seekdir(0x%llx) failed on dir=%p: " "Invalid argument (offset reused from " "another DIR * structure?)", - (long)in_case, dir); + in_case, dir); errno = EINVAL; count = -1; goto out; @@ -4988,7 +4989,14 @@ posix_fill_readdir (fd_t *fd, DIR *dir, off_t off, size_t size, entry->d_name, strerror (errno)); goto out; } - this_entry->d_off = telldir (dir); + /* + * we store the offset of next entry here, which is + * probably not intended, but code using syncop_readdir() + * (glfs-heal.c, afr-self-heald.c, pump.c) rely on it + * for directory read resumption. + */ + last_off = (u_long)telldir(dir); + this_entry->d_off = last_off; this_entry->d_ino = entry->d_ino; this_entry->d_type = entry->d_type; @@ -5002,7 +5010,7 @@ posix_fill_readdir (fd_t *fd, DIR *dir, off_t off, size_t size, /* Indicate EOF */ errno = ENOENT; /* Remember EOF offset for later detection */ - pfd->dir_eof = telldir (dir); + pfd->dir_eof = (u_long)last_off; } out: return count; |