[Gluster-devel] Invalid DIR * usage in quota xlator
Pranith Kumar Karampuri
pkarampu at redhat.com
Mon Oct 13 09:09:32 UTC 2014
On 10/13/2014 02:37 PM, Pranith Kumar Karampuri wrote:
>
> On 10/13/2014 02:27 PM, Emmanuel Dreyfus wrote:
>> 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?
> I am not aware of backend filesystems that much, may be someone with
> that knowledge can comment here, what happens when new entries are
> created in the directory after this readdir is responded with '-1'?
>
>> 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;
> Now I understand why you kept saying ENOENT ;-). This may not be a
> good idea IMO. Code all through gluster doesn't care what errno it
> unwinds upwards.
In case op_ret is zero I mean :-)
Pranith
>> + /* Set invalid offset for later detection */
>> + this_entry->d_off = INVALID_DIRENT_OFFSET;
>> + }
>> out:
>> return count;
>> }
>>
>>
>
> _______________________________________________
> Gluster-devel mailing list
> Gluster-devel at gluster.org
> http://supercolony.gluster.org/mailman/listinfo/gluster-devel
More information about the Gluster-devel
mailing list