diff options
author | Shehjar Tikoo <shehjart@zresearch.com> | 2009-05-06 12:23:14 +0530 |
---|---|---|
committer | Anand V. Avati <avati@amp.gluster.com> | 2009-05-06 12:36:35 +0530 |
commit | f82651ef4ff5a9e94fa9c0d1f9cf091345440b56 (patch) | |
tree | 34199e659114cff02f917e94191bae62fcd6e757 | |
parent | 8d1b62393b58ff3ac5b157e0adea15578c949bbf (diff) |
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 <avati@amp.gluster.com>
-rwxr-xr-x | libglusterfsclient/src/libglusterfsclient.c | 19 |
1 files changed, 16 insertions, 3 deletions
diff --git a/libglusterfsclient/src/libglusterfsclient.c b/libglusterfsclient/src/libglusterfsclient.c index 09fd5e2468d..70e063040c3 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; } } |