From f82651ef4ff5a9e94fa9c0d1f9cf091345440b56 Mon Sep 17 00:00:00 2001 From: Shehjar Tikoo Date: Wed, 6 May 2009 12:23:14 +0530 Subject: libglusterfsclient: Fix large directory reading bug As of now, we use 1024 bytes as the buffer for reading directory entries. If a directory as many files, then its possible that it does not fit into this buffer, thereby requiring more than one call to readdir. Now suppose the last bunch of directories fit more or less exactly int the 1024 byte buffer. If this happens, the offset extracted by the current logic(in libgf_client_readdir) never gets updated beyond the first entry in this last block, because the last block's first entry always remains same. This explanation is convoluted, I know, but I too found out the hard way. Signed-off-by: Anand V. Avati --- libglusterfsclient/src/libglusterfsclient.c | 19 ++++++++++++++++--- 1 file changed, 16 insertions(+), 3 deletions(-) (limited to 'libglusterfsclient') diff --git a/libglusterfsclient/src/libglusterfsclient.c b/libglusterfsclient/src/libglusterfsclient.c index 09fd5e246..70e063040 100755 --- a/libglusterfsclient/src/libglusterfsclient.c +++ b/libglusterfsclient/src/libglusterfsclient.c @@ -3302,7 +3302,10 @@ libgf_client_readdir (libglusterfs_client_ctx_t *ctx, + strlen (entry->d_name) + 1; if ((size < entry_size) || (count == num_entries)) { - break; + if (*offset == entry->d_off) + count--; + else + break; } size -= entry_size; @@ -3317,19 +3320,29 @@ libgf_client_readdir (libglusterfs_client_ctx_t *ctx, #endif */ - *offset = dirp->d_off = entry->d_off; /* dirp->d_type = entry->d_type; */ dirp->d_reclen = entry->d_len; strncpy (dirp->d_name, entry->d_name, dirp->d_reclen); dirp->d_name[dirp->d_reclen] = '\0'; dirp = (struct dirent *) (((char *) dirp) + entry_size); - count++; /* FIXME: Someday, we'll enable processing * more than one dirent. The reason we should * break here is that the offset must not be * updated beyond one entry. + * + * FIXME2: This offset value check is somewhat + * better than not having any support for + * multiple entry extraction. Suppose we're + * reading a large directory. */ + if (*offset == entry->d_off) + continue; + else { + *offset = dirp->d_off = entry->d_off; + break; + } + break; } } -- cgit