[Gluster-devel] Invalid DIR * usage in quota xlator
Emmanuel Dreyfus
manu at netbsd.org
Mon Oct 13 08:57:11 UTC 2014
On Mon, Oct 13, 2014 at 01:42:38PM +0530, Pranith Kumar Karampuri wrote:
> >No bug here, just suboptimal behavior, both in glusterfs and NetBSD FUSE.
> oh!, but shouldn't it get op_ret = 0 instead of op_ret -1, op_errno EINVAL?
It happens because of thei change I introduced:
seekdir (dir, (long)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 */
The idea is to catch wrong opendir/closedir usage, and the errno = EINVAL
is critical in such a situation to avoid an infinite loop. On the other
hand it also fires for last entry. I did not notice it before because
this EINVAL will not reach calling process, but it may cause trouble
for internal glusterfs usage.
I see an easy way yo fix it (patch below)
- when posix xlator detects EOF, return an offset of -1 in last entry.
- When called with an offset of -1, immediatly return op_ret = 0 with no entry
What do you think?
diff --git a/xlators/storage/posix/src/posix.c b/xlators/storage/posix/src/posix
index 6b12d39..3e539bb 100644
--- a/xlators/storage/posix/src/posix.c
+++ b/xlators/storage/posix/src/posix.c
@@ -79,6 +79,10 @@ extern char *marker_xattrs[];
#define SET_TO_OLD_FS_ID()
#endif
+
+/* offset < sizeof(struct dirent) cannot be valid */
+#define INVALID_DIRENT_OFFSET sizeof (void *)
+
int
posix_forget (xlator_t *this, inode_t *inode)
{
@@ -4851,6 +4855,10 @@ posix_fill_readdir (fd_t *fd, DIR *dir, off_t off, size_t
int len = 0;
int ret = 0;
+ /* EOF was previously detected */
+ if (off == INVALID_DIRENT_OFFSET)
+ goto out;
+
if (skip_dirs) {
len = posix_handle_path (this, fd->inode->gfid, NULL, NULL, 0);
hpath = alloca (len + 256); /* NAME_MAX */
@@ -4969,9 +4977,12 @@ posix_fill_readdir (fd_t *fd, DIR *dir, off_t off, size_t
count ++;
}
- if ((!readdir (dir) && (errno == 0)))
+ if ((!readdir (dir) && (errno == 0))) {
/* Indicate EOF */
errno = ENOENT;
+ /* Set invalid offset for later detection */
+ this_entry->d_off = INVALID_DIRENT_OFFSET;
+ }
out:
return count;
}
--
Emmanuel Dreyfus
manu at netbsd.org
More information about the Gluster-devel
mailing list