summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorShehjar Tikoo <shehjart@zresearch.com>2009-05-06 12:23:14 +0530
committerAnand V. Avati <avati@amp.gluster.com>2009-05-06 12:36:35 +0530
commitf82651ef4ff5a9e94fa9c0d1f9cf091345440b56 (patch)
tree34199e659114cff02f917e94191bae62fcd6e757
parent8d1b62393b58ff3ac5b157e0adea15578c949bbf (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-xlibglusterfsclient/src/libglusterfsclient.c19
1 files changed, 16 insertions, 3 deletions
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;
}
}