summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--heal/src/glfs-heal.c26
-rw-r--r--libglusterfs/src/common-utils.h1
-rw-r--r--tests/basic/afr/self-heald.t4
-rw-r--r--tests/basic/pump.t4
-rw-r--r--tests/include.rc18
-rw-r--r--xlators/cluster/afr/src/afr-self-heald.c46
-rw-r--r--xlators/features/index/src/index.c42
-rw-r--r--xlators/features/index/src/index.h1
-rw-r--r--xlators/storage/posix/src/posix.c26
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;