[<prev] [next>] [<thread-prev] [thread-next>] [day] [month] [year] [list]
Message-Id: <20090114134417.e6b29b52.akpm@linux-foundation.org>
Date: Wed, 14 Jan 2009 13:44:17 -0800
From: Andrew Morton <akpm@...ux-foundation.org>
To: Eric Sandeen <sandeen@...deen.net>
Cc: chris.mason@...cle.com, handygewinnspiel@....de, matthew@....cx,
rjw@...k.pl, HWerner4@....de, viro@...iv.linux.org.uk,
linux-kernel@...r.kernel.org, linux-fsdevel@...r.kernel.org,
mchehab@...radead.org, stable@...nel.org,
Christoph Hellwig <hch@....de>,
Lachlan McIlroy <lachlan@....com>,
Timothy Shimmin <tes@....com>
Subject: Re: [linux-dvb] compiling on 2.6.28 broken?
On Wed, 14 Jan 2009 15:35:46 -0600
Eric Sandeen <sandeen@...deen.net> wrote:
> Chris Mason wrote:
> > On Wed, 2009-01-14 at 22:19 +0100, wk wrote:
> ...
> >> I cannot fully understand what strace -v outputs (see attachment), but
> >> what i see is that 'find' stops after finding a file with d_off = 4294967295
> >> 4294967295 = 0xFFFFFFFF, adding any number greater that zero will be
> >> greater that 32bits, so this could be the reason for the message "value
> >> too large".
> >>
> >>
> >>
> >> I also noticed that i cannot access these files through samba if i boot
> >> from 2.6.28 - really strange.
> >> If i reboot older kernels these are visible in samba again and fully
> >> accessible.
> >>
> >> Attached the log from stracing the command which was ivoked by the
> >> Makefile from v4l-dvb.
> >> I guess this is all i could contribute to that problem. Thats stuff for
> >> xfs filesystem experts now..
> >
> > Seems suspect indeed. Could you please attach the strace for the run
> > that works on the older kernel?
>
> Chris got my attention on this one; you probably want this fix from hch:
>
> http://oss.sgi.com/archives/xfs/2009-01/msg00158.html
>
Looks likely. It is below, for anyone who would like to test it.
It is in linux-next. Guys, do we plan to merge this into 2.6.29?
(cc's stable@...nel.org)
This patch applies OK to 2.6.27 and 2.6.28. Is it also needed there?
If so, it should have had "Cc: <stable@...nel.org>" in the changelog so
that it doesn't get lost.
commit 15440319767942a363f282d6585303d3d75088ba
Author: Christoph Hellwig <hch@...radead.org>
AuthorDate: Thu Jan 8 14:00:00 2009 -0500
Commit: Lachlan McIlroy <lachlan@...back.melbourne.sgi.com>
CommitDate: Fri Jan 9 16:18:24 2009 +1100
[XFS] truncate readdir offsets to signed 32 bit values
John Stanley reported EOVERFLOW errors in readdir from his self-build
glibc. I traced this down to glibc enabling d_off overflow checks
in one of the about five million different getdents implementations.
In 2.6.28 Dave Woodhouse moved our readdir double buffering required
for NFS4 readdirplus into nfsd and at that point we lost the capping
of the directory offsets to 32 bit signed values. Johns glibc used
getdents64 to even implement readdir for normal 32 bit offset dirents,
and failed with EOVERFLOW only if this happens on the first dirent in
a getdents call. I managed to come up with a testcase that uses
raw getdents and does the EOVERFLOW check manually. We always hit
it with our last entry due to the special end of directory marker.
The patch below is a dumb version of just putting back the masking,
to make sure we have the same behavior as in 2.6.27 and earlier.
I will work on a better and cleaner fix for 2.6.30.
Reported-by: John Stanley <jpsinthemix@...izon.net>
Tested-by: John Stanley <jpsinthemix@...izon.net>
Signed-off-by: Christoph Hellwig <hch@....de>
Reviewed-by: Dave Chinner <david@...morbit.com>
Signed-off-by: Lachlan McIlroy <lachlan@....com>
diff --git a/fs/xfs/xfs_dir2_block.c b/fs/xfs/xfs_dir2_block.c
index e2fa0a1..e1f0a06 100644
--- a/fs/xfs/xfs_dir2_block.c
+++ b/fs/xfs/xfs_dir2_block.c
@@ -517,9 +517,9 @@ xfs_dir2_block_getdents(
/*
* If it didn't fit, set the final offset to here & return.
*/
- if (filldir(dirent, dep->name, dep->namelen, cook,
+ if (filldir(dirent, dep->name, dep->namelen, cook & 0x7fffffff,
ino, DT_UNKNOWN)) {
- *offset = cook;
+ *offset = cook & 0x7fffffff;
xfs_da_brelse(NULL, bp);
return 0;
}
@@ -529,7 +529,8 @@ xfs_dir2_block_getdents(
* Reached the end of the block.
* Set the offset to a non-existent block 1 and return.
*/
- *offset = xfs_dir2_db_off_to_dataptr(mp, mp->m_dirdatablk + 1, 0);
+ *offset = xfs_dir2_db_off_to_dataptr(mp, mp->m_dirdatablk + 1, 0) &
+ 0x7fffffff;
xfs_da_brelse(NULL, bp);
return 0;
}
diff --git a/fs/xfs/xfs_dir2_leaf.c b/fs/xfs/xfs_dir2_leaf.c
index 9353599..ef805a3 100644
--- a/fs/xfs/xfs_dir2_leaf.c
+++ b/fs/xfs/xfs_dir2_leaf.c
@@ -1092,7 +1092,7 @@ xfs_dir2_leaf_getdents(
* Won't fit. Return to caller.
*/
if (filldir(dirent, dep->name, dep->namelen,
- xfs_dir2_byte_to_dataptr(mp, curoff),
+ xfs_dir2_byte_to_dataptr(mp, curoff) & 0x7fffffff,
ino, DT_UNKNOWN))
break;
@@ -1108,9 +1108,9 @@ xfs_dir2_leaf_getdents(
* All done. Set output offset value to current offset.
*/
if (curoff > xfs_dir2_dataptr_to_byte(mp, XFS_DIR2_MAX_DATAPTR))
- *offset = XFS_DIR2_MAX_DATAPTR;
+ *offset = XFS_DIR2_MAX_DATAPTR & 0x7fffffff;
else
- *offset = xfs_dir2_byte_to_dataptr(mp, curoff);
+ *offset = xfs_dir2_byte_to_dataptr(mp, curoff) & 0x7fffffff;
kmem_free(map);
if (bp)
xfs_da_brelse(NULL, bp);
diff --git a/fs/xfs/xfs_dir2_sf.c b/fs/xfs/xfs_dir2_sf.c
index b46af00..a8a8a6e 100644
--- a/fs/xfs/xfs_dir2_sf.c
+++ b/fs/xfs/xfs_dir2_sf.c
@@ -752,8 +752,8 @@ xfs_dir2_sf_getdents(
#if XFS_BIG_INUMS
ino += mp->m_inoadd;
#endif
- if (filldir(dirent, ".", 1, dot_offset, ino, DT_DIR)) {
- *offset = dot_offset;
+ if (filldir(dirent, ".", 1, dot_offset & 0x7fffffff, ino, DT_DIR)) {
+ *offset = dot_offset & 0x7fffffff;
return 0;
}
}
@@ -766,8 +766,8 @@ xfs_dir2_sf_getdents(
#if XFS_BIG_INUMS
ino += mp->m_inoadd;
#endif
- if (filldir(dirent, "..", 2, dotdot_offset, ino, DT_DIR)) {
- *offset = dotdot_offset;
+ if (filldir(dirent, "..", 2, dotdot_offset & 0x7fffffff, ino, DT_DIR)) {
+ *offset = dotdot_offset & 0x7fffffff;
return 0;
}
}
@@ -791,14 +791,15 @@ xfs_dir2_sf_getdents(
#endif
if (filldir(dirent, sfep->name, sfep->namelen,
- off, ino, DT_UNKNOWN)) {
- *offset = off;
+ off & 0x7fffffff, ino, DT_UNKNOWN)) {
+ *offset = off & 0x7fffffff;
return 0;
}
sfep = xfs_dir2_sf_nextentry(sfp, sfep);
}
- *offset = xfs_dir2_db_off_to_dataptr(mp, mp->m_dirdatablk + 1, 0);
+ *offset = xfs_dir2_db_off_to_dataptr(mp, mp->m_dirdatablk + 1, 0) &
+ 0x7fffffff;
return 0;
}
--
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to majordomo@...r.kernel.org
More majordomo info at http://vger.kernel.org/majordomo-info.html
Please read the FAQ at http://www.tux.org/lkml/
Powered by blists - more mailing lists