diff options
-rw-r--r-- | xlators/cluster/afr/src/afr-self-heald.c | 39 | ||||
-rw-r--r-- | xlators/features/index/src/index.c | 44 | ||||
-rw-r--r-- | xlators/storage/posix/src/posix.c | 23 |
3 files changed, 103 insertions, 3 deletions
diff --git a/xlators/cluster/afr/src/afr-self-heald.c b/xlators/cluster/afr/src/afr-self-heald.c index 9627b906b56..10e19964ed9 100644 --- a/xlators/cluster/afr/src/afr-self-heald.c +++ b/xlators/cluster/afr/src/afr-self-heald.c @@ -229,6 +229,7 @@ afr_shd_index_opendir (xlator_t *this, int child) int ret = 0; dict_t *xattr = NULL; void *index_gfid = NULL; + loc_t loc = {0, }; priv = this->private; subvol = priv->children[child]; @@ -253,11 +254,43 @@ afr_shd_index_opendir (xlator_t *this, int child) inode = afr_shd_inode_find (this, subvol, index_gfid); if (!inode) goto out; - fd = fd_anonymous (inode); + + fd = fd_create (inode, GF_CLIENT_PID_AFR_SELF_HEALD); + if (!fd) + goto out; + + uuid_copy (loc.gfid, index_gfid); + loc.inode = inode; + + ret = syncop_opendir(this, &loc, fd); + if (ret) { + /* + * On Linux, if the brick was not updated, opendir will + * fail. We therefore use backward compatible code + * that violate the standards by reusing offsets + * in seekdir() from different DIR *, but it works on Linux. + * + * On other systems it never worked, hence we do not need + * to provide backward-compatibility. + */ +#ifdef GF_LINUX_HOST_OS + fd_unref (fd); + fd = fd_anonymous (inode); +#else /* GF_LINUX_HOST_OS */ + gf_log(this->name, GF_LOG_ERROR, + "opendir of %s for %s failed: %s", + uuid_utoa (index_gfid), subvol->name, strerror(errno)); + fd_unref (fd); + fd = NULL; + goto out; +#endif /* GF_LINUX_HOST_OS */ + } + out: loc_wipe (&rootloc); - if (inode) - inode_unref (inode); + + if (inode) + inode_unref (inode); if (xattr) dict_unref (xattr); diff --git a/xlators/features/index/src/index.c b/xlators/features/index/src/index.c index 2b80e718607..c342da8274c 100644 --- a/xlators/features/index/src/index.c +++ b/xlators/features/index/src/index.c @@ -285,6 +285,17 @@ index_fill_readdir (fd_t *fd, DIR *dir, off_t off, rewinddir (dir); } else { seekdir (dir, off); +#ifndef GF_LINUX_HOST_OS + if (telldir(dir) != off) { + gf_log (THIS->name, GF_LOG_ERROR, + "seekdir(%ld) failed on dir=%p: " + "Invalid argument (offset reused from " + "another DIR * structure?)", (long)off, dir); + errno = EINVAL; + count = -1; + goto out; + } +#endif /* GF_LINUX_HOST_OS */ } while (filled <= size) { @@ -323,6 +334,18 @@ 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) { + gf_log (THIS->name, GF_LOG_ERROR, + "seekdir(%ld) failed on dir=%p: " + "Invalid argument (offset reused from " + "another DIR * structure?)", + (long)in_case, dir); + errno = EINVAL; + count = -1; + goto out; + } +#endif /* GF_LINUX_HOST_OS */ break; } @@ -1043,6 +1066,26 @@ normal: } int32_t +index_opendir (call_frame_t *frame, xlator_t *this, + loc_t *loc, fd_t *fd, dict_t *xdata) +{ + index_priv_t *priv = NULL; + + priv = this->private; + if (uuid_compare (fd->inode->gfid, priv->xattrop_vgfid)) + goto normal; + + frame->local = NULL; + STACK_UNWIND_STRICT (opendir, frame, 0, 0, fd, NULL); + return 0; + +normal: + STACK_WIND (frame, default_opendir_cbk, FIRST_CHILD(this), + FIRST_CHILD(this)->fops->opendir, loc, fd, xdata); + return 0; +} + +int32_t index_readdir (call_frame_t *frame, xlator_t *this, fd_t *fd, size_t size, off_t off, dict_t *xdata) { @@ -1267,6 +1310,7 @@ struct xlator_fops fops = { //interface functions follow .getxattr = index_getxattr, .lookup = index_lookup, + .opendir = index_opendir, .readdir = index_readdir, .unlink = index_unlink }; diff --git a/xlators/storage/posix/src/posix.c b/xlators/storage/posix/src/posix.c index 549f1c4dc01..59b2535105b 100644 --- a/xlators/storage/posix/src/posix.c +++ b/xlators/storage/posix/src/posix.c @@ -4862,6 +4862,17 @@ posix_fill_readdir (fd_t *fd, DIR *dir, off_t off, size_t size, rewinddir (dir); } else { seekdir (dir, off); +#ifndef GF_LINUX_HOST_OS + if (telldir(dir) != off) { + gf_log (THIS->name, GF_LOG_ERROR, + "seekdir(%ld) failed on dir=%p: " + "Invalid argument (offset reused from " + "another DIR * structure?)", (long)off, dir); + errno = EINVAL; + count = -1; + goto out; + } +#endif /* GF_LINUX_HOST_OS */ } while (filled <= size) { @@ -4924,6 +4935,18 @@ 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) != in_case) { + gf_log (THIS->name, GF_LOG_ERROR, + "seekdir(%ld) failed on dir=%p: " + "Invalid argument (offset reused from " + "another DIR * structure?)", + (long)in_case, dir); + errno = EINVAL; + count = -1; + goto out; + } +#endif /* GF_LINUX_HOST_OS */ break; } |