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 43bd3fc1cfd..e830a973b76 100644 --- a/xlators/storage/posix/src/posix.c +++ b/xlators/storage/posix/src/posix.c @@ -4842,6 +4842,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) { @@ -4904,6 +4915,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;                  }  | 
