public inbox for linux-kernel@vger.kernel.org
 help / color / mirror / Atom feed
* btrfs: readdir problem workaround for 32-bit off_t
@ 2009-01-17 19:39 Jan Engelhardt
  2009-01-17 21:27 ` Chris Mason
  0 siblings, 1 reply; 2+ messages in thread
From: Jan Engelhardt @ 2009-01-17 19:39 UTC (permalink / raw)
  To: linux-btrfs; +Cc: bug-glibc, Linux Kernel Mailing List

Hi,



I am seeing abnormal kernel<->userland interaction for range-exceeding 
offsets during readdir.
A suggested patch for btrfs is below, but I think there could also
be involvement of (read: a bug in) Glibc.
Would the copied parties please have a look, as it may spans both glibc 
and btrfs.


Thanks,
Jan

parent 81841fa96da5597a411f5f274a664f186b2d2549 (v2.6.29-rc2-21-g81841fa)
commit fa8ea6611fedecba8e5fdf2a5dfd82affa5a982e
Author: Jan Engelhardt <jengelh@medozas.de>
Date:   Sat Jan 17 20:26:25 2009 +0100

btrfs: readdir problem workaround for 32-bit off_t

Kernel is i586, as is the userland.

btrfs sets filp->f_pos == (2^63-1) when it has reached the
end of a directory. This is problematic.

In obtuse 32-bit mode (no _FILE_OFFSET_BITS), readdir(3) will not return 
the last entry.

However, when compiled with -D_FILE_OFFSET_BITS=64, it will return the 
last entry. But telldir() will return (uint32_t)-1, which does not quite 
match up with the 2^63-1.

	$ cat test.c
	#include <dirent.h>
	#include <stdio.h>

	int main(int argc, const char **argv)
	{
		DIR *r = opendir(argv[1]);
		struct dirent *de;

		while ((de = readdir(r)) != NULL)
			printf("%lld %s\n", (long long)telldir(r), de->d_name);
		return 0;
	}
	$ gcc test.c -o test -ggdb3
	$ ./test /tmp/z
	2 .
	2 ..
	3 a
	4 b
	5 lib

	$ gcc test.c -o test -ggdb3 -D_FILE_OFFSET_BITS=64
	$ ./test /tmp/z
	2 .
	2 ..
	3 a
	4 b
	5 lib
	4294967295 strace.log

This has deep effects and my boot hangs. (Got btrfs as the root fs.)

I have no idea who exactly of Glibc and btrfs is at fault with what,
but this change makes btrfs usable for the moment.

Signed-off-by: Jan Engelhardt <jengelh@medozas.de>
---
 fs/btrfs/inode.c |    5 +----
 1 files changed, 1 insertions(+), 4 deletions(-)

diff --git a/fs/btrfs/inode.c b/fs/btrfs/inode.c
index 8adfe05..901be02 100644
--- a/fs/btrfs/inode.c
+++ b/fs/btrfs/inode.c
@@ -3264,10 +3264,7 @@ skip:
 	}
 
 	/* Reached end of directory/root. Bump pos past the last item. */
-	if (key_type == BTRFS_DIR_INDEX_KEY)
-		filp->f_pos = INT_LIMIT(typeof(filp->f_pos));
-	else
-		filp->f_pos++;
+	filp->f_pos++;
 nopos:
 	ret = 0;
 err:
-- 
# Created with git-export-patch


^ permalink raw reply related	[flat|nested] 2+ messages in thread

* Re: btrfs: readdir problem workaround for 32-bit off_t
  2009-01-17 19:39 btrfs: readdir problem workaround for 32-bit off_t Jan Engelhardt
@ 2009-01-17 21:27 ` Chris Mason
  0 siblings, 0 replies; 2+ messages in thread
From: Chris Mason @ 2009-01-17 21:27 UTC (permalink / raw)
  To: Jan Engelhardt; +Cc: linux-btrfs, bug-glibc, Linux Kernel Mailing List

On Sat, 2009-01-17 at 20:39 +0100, Jan Engelhardt wrote:
> Hi,
> 
> 
> 
> I am seeing abnormal kernel<->userland interaction for range-exceeding 
> offsets during readdir.
> A suggested patch for btrfs is below, but I think there could also
> be involvement of (read: a bug in) Glibc.
> Would the copied parties please have a look, as it may spans both glibc 
> and btrfs.
> 

Thanks for looking into this.

Your patch is how the code originally looked, but it can lead to loops
in buggy userland (a git bug hit this).   My plan was to mask off the
limit the same way XFS now does.

This is a btrfs bug, not glibc.

-chris



^ permalink raw reply	[flat|nested] 2+ messages in thread

end of thread, other threads:[~2009-01-17 21:27 UTC | newest]

Thread overview: 2+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2009-01-17 19:39 btrfs: readdir problem workaround for 32-bit off_t Jan Engelhardt
2009-01-17 21:27 ` Chris Mason

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox