summaryrefslogtreecommitdiffstats
path: root/xlators/storage/posix/src/posix.c
diff options
context:
space:
mode:
authorAnand Avati <avati@redhat.com>2013-04-03 16:31:07 -0700
committerAnand Avati <avati@redhat.com>2013-04-03 23:02:39 -0700
commit5cdd09c3087e7f0581392dd06d4a1d587176abcb (patch)
tree811f2e91bc11d2971f54a9507c2bbe0811fe5335 /xlators/storage/posix/src/posix.c
parent4e00f0017d7a3f77cb8c753b665352e25a33e1fa (diff)
posix: fix dangerous "sharing" of fd in readdir between two requests
posix_fill_readdir() is a multi-step function which performs many readdir() calls, and expects the directory cursor to have not "seeked away" elsewhere between two successive iterations. Usually this is not a problem as each opendir() from an application has its own backend fd, and there is nobody else to "seek away" the directory cursor. However in case of NFS's use of anonymous fd, the same fd_t is shared between all NFS readdir requests, and two readdir loops can be executing in parallel on the same dir dragging away the cursor in a chaotic manner. The fix in this patch is to lock on the fd around the loop. Another approach could be to reimplement posix_fill_readdir() with a single getdents() call, but that's for another day. Change-Id: Ia42e9c7fbcde43af4c0d08c20cc0f7419b98bd3f BUG: 948086 Signed-off-by: Anand Avati <avati@redhat.com> Reviewed-on: http://review.gluster.org/4774 Reviewed-by: Jeff Darcy <jdarcy@redhat.com> Tested-by: Gluster Build System <jenkins@build.gluster.com>
Diffstat (limited to 'xlators/storage/posix/src/posix.c')
-rw-r--r--xlators/storage/posix/src/posix.c19
1 files changed, 17 insertions, 2 deletions
diff --git a/xlators/storage/posix/src/posix.c b/xlators/storage/posix/src/posix.c
index 4a786543..cd01a113 100644
--- a/xlators/storage/posix/src/posix.c
+++ b/xlators/storage/posix/src/posix.c
@@ -3897,8 +3897,23 @@ posix_do_readdir (call_frame_t *frame, xlator_t *this,
*/
ret = dict_get_int32 (dict, GF_READDIR_SKIP_DIRS, &skip_dirs);
- count = posix_fill_readdir (fd, dir, off, size, &entries, this,
- skip_dirs);
+ LOCK (&fd->lock);
+ {
+ /* posix_fill_readdir performs multiple separate individual
+ readdir() calls to fill up the buffer.
+
+ In case of NFS where the same anonymous FD is shared between
+ different applications, reading a common directory can
+ result in the anonymous fd getting re-used unsafely between
+ the two readdir requests (in two different io-threads).
+
+ It would also help, in the future, to replace the loop
+ around readdir() with a single large getdents() call.
+ */
+ count = posix_fill_readdir (fd, dir, off, size, &entries, this,
+ skip_dirs);
+ }
+ UNLOCK (&fd->lock);
/* pick ENOENT to indicate EOF */
op_errno = errno;