xfs
[Top] [All Lists]

Re: [Bug 335] New: XFS Oops with 2.6.7-rc3

To: linux-xfs@xxxxxxxxxxx
Subject: Re: [Bug 335] New: XFS Oops with 2.6.7-rc3
From: evilninja <evilninja@xxxxxxx>
Date: Wed, 09 Jun 2004 19:21:26 +0200
In-reply-to: <m3k6yhknae.fsf@averell.firstfloor.org>
References: <200406090934.i599YaKP022234@oss.sgi.com> <m3k6yhknae.fsf@averell.firstfloor.org>
Sender: linux-xfs-bounce@xxxxxxxxxxx
User-agent: Mozilla Thunderbird 0.6 (X11/20040528)
-----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;
 
        /*
<Prev in Thread] Current Thread [Next in Thread>