-----BEGIN PGP SIGNED MESSAGE-----
Hash: SHA1
Andi Kleen wrote:
~ > This patch fixes it. The problem is that XFS expects __GFP_NOFAIL
| to never return NULL, but it returns NULL anyways when PF_MEMALLOC
| is set for the current process. This patch just readds looping
| in the XFS allocator.
|
| In addition it stops recursions inside PF_MEMALLOC.
Thanks. i must admit, that i could not reproduce this bug yet. i've
mv'ed a similiar amount of data from xfs->xfs and no oops occured, which
is good.
um, the patch itsself would not apply, using vanilla kernel sources,
there is no directory fs/xfs/linux but a directory called
fs/xfs/linux-2.6. so i applied the attached "re-patch".
Thank you very much,
Christian.
- --
BOFH excuse #271:
The kernel license has expired
- --
BOFH excuse #271:
The kernel license has expired
-----BEGIN PGP SIGNATURE-----
Version: GnuPG v1.2.4 (GNU/Linux)
Comment: Using GnuPG with Thunderbird - http://enigmail.mozdev.org
iD8DBQFAx0cVC/PVm5+NVoYRAlX0AJ9PM7S6tlWsaXpurpeaP8sp6tmVtQCeMfGD
i4TXj5Z/zRRhJUH9O3Siklo=
=hJ+n
-----END PGP SIGNATURE-----
diff -u linux/fs/xfs/linux-2.6/kmem.h-o linux/fs/xfs/linux-2.6/kmem.h
--- linux/fs/xfs/linux-2.6/kmem.h-o 2004-05-24 14:01:42.000000000 +0200
+++ linux/fs/xfs/linux-2.6/kmem.h 2004-05-24 14:12:14.000000000 +0200
@@ -56,7 +56,8 @@
typedef unsigned long xfs_pflags_t;
-#define PFLAGS_TEST_FSTRANS() (current->flags & PF_FSTRANS)
+#define PFLAGS_NO_RECURSION() \
+ (current->flags & (PF_FSTRANS|PF_MEMALLOC|PF_MEMDIE))
/* these could be nested, so we save state */
#define PFLAGS_SET_FSTRANS(STATEP) do { \
@@ -98,7 +99,7 @@
lflags = GFP_KERNEL;
/* avoid recusive callbacks to filesystem during transactions */
- if (PFLAGS_TEST_FSTRANS() || (flags & KM_NOFS))
+ if (PFLAGS_NO_RECURSION() || (flags & KM_NOFS))
lflags &= ~__GFP_FS;
if (!(flags & KM_MAYFAIL))
@@ -159,7 +160,20 @@
static __inline void *
kmem_zone_alloc(kmem_zone_t *zone, int flags)
{
- return kmem_cache_alloc(zone, kmem_flags_convert(flags));
+ /* __GFP_NOFAIL doesn't work properly when PF_MEMALLOC is already
+ set, and this can happen in XFS when it is called in low memory
+ situations to free up some cached data. Loop on our own.
+
+ This has some deadlock potential in extreme OOM cases.
+
+ It would be better to use mempools for the allocations that
+ are used from the low memory paths (iput, writepage); like
+ for the transactions. */
+ void *p;
+ do {
+ p = kmem_cache_alloc(zone, kmem_flags_convert(flags));
+ } while (!p && !(flags & KM_MAYFAIL));
+ return p;
}
static __inline void *
diff -u linux/fs/xfs/linux-2.6/xfs_aops.c-o linux/fs/xfs/linux-2.6/xfs_aops.c
--- linux/fs/xfs/linux-2.6/xfs_aops.c-o 2004-05-25 02:52:54.211070280 +0200
+++ linux/fs/xfs/linux-2.6/xfs_aops.c 2004-05-25 02:53:41.662856512 +0200
@@ -1168,7 +1168,7 @@
* then mark the page dirty again and leave the page
* as is.
*/
- if (PFLAGS_TEST_FSTRANS() && need_trans)
+ if (PFLAGS_NO_RECURSION() && need_trans)
goto out_fail;
/*
@@ -1242,7 +1242,7 @@
/* If we are already inside a transaction or the thread cannot
* do I/O, we cannot release this page.
*/
- if (PFLAGS_TEST_FSTRANS())
+ if (PFLAGS_NO_RECURSION())
return 0;
/*
|