summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-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
4 files changed, 87 insertions, 28 deletions
diff --git a/xlators/cluster/afr/src/afr-self-heald.c b/xlators/cluster/afr/src/afr-self-heald.c
index 10e19964ed9..6ce52aad1c4 100644
--- a/xlators/cluster/afr/src/afr-self-heald.c
+++ b/xlators/cluster/afr/src/afr-self-heald.c
@@ -276,6 +276,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",
@@ -429,7 +431,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;
@@ -503,11 +505,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;
@@ -516,9 +519,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);
@@ -560,6 +592,8 @@ afr_shd_full_sweep (struct subvol_healer *healer, inode_t *inode)
break;
}
+out:
+ loc_wipe (&loc);
if (fd)
fd_unref (fd);
return ret;
@@ -949,7 +983,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 c342da8274c..50e2e0ab54d 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) {
@@ -949,7 +962,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;
@@ -1270,8 +1283,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 d8599881fb7..c1730e8d337 100644
--- a/xlators/storage/posix/src/posix.c
+++ b/xlators/storage/posix/src/posix.c
@@ -4853,6 +4853,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];
@@ -4888,11 +4889,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;
@@ -4901,7 +4902,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,
@@ -4961,13 +4962,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;
@@ -4984,7 +4985,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;
@@ -4998,7 +5006,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;