Merge branch 'devel' of master.kernel.org:/home/rmk/linux-2.6-mmc
[pandora-kernel.git] / fs / xfs / xfs_alloc.c
index 8558226..eef6763 100644 (file)
 #include "xfs_trans.h"
 #include "xfs_sb.h"
 #include "xfs_ag.h"
-#include "xfs_dir.h"
 #include "xfs_dir2.h"
 #include "xfs_dmapi.h"
 #include "xfs_mount.h"
 #include "xfs_bmap_btree.h"
 #include "xfs_alloc_btree.h"
 #include "xfs_ialloc_btree.h"
-#include "xfs_dir_sf.h"
 #include "xfs_dir2_sf.h"
 #include "xfs_attr_sf.h"
 #include "xfs_dinode.h"
@@ -1862,7 +1860,7 @@ xfs_alloc_fix_freelist(
                (pag->pagf_longest - delta) :
                (pag->pagf_flcount > 0 || pag->pagf_longest > 0);
        if (args->minlen + args->alignment + args->minalignslop - 1 > longest ||
-           (args->minleft &&
+           (!(flags & XFS_ALLOC_FLAG_FREEING) &&
             (int)(pag->pagf_freeblks + pag->pagf_flcount -
                   need - args->total) <
             (int)args->minleft)) {
@@ -1898,7 +1896,7 @@ xfs_alloc_fix_freelist(
        longest = (longest > delta) ? (longest - delta) :
                (be32_to_cpu(agf->agf_flcount) > 0 || longest > 0);
        if (args->minlen + args->alignment + args->minalignslop - 1 > longest ||
-            (args->minleft &&
+            (!(flags & XFS_ALLOC_FLAG_FREEING) &&
                (int)(be32_to_cpu(agf->agf_freeblks) +
                   be32_to_cpu(agf->agf_flcount) - need - args->total) <
             (int)args->minleft)) {
@@ -1951,8 +1949,14 @@ xfs_alloc_fix_freelist(
                 * the restrictions correctly.  Can happen for free calls
                 * on a completely full ag.
                 */
-               if (targs.agbno == NULLAGBLOCK)
+               if (targs.agbno == NULLAGBLOCK) {
+                       if (!(flags & XFS_ALLOC_FLAG_FREEING)) {
+                               xfs_trans_brelse(tp, agflbp);
+                               args->agbp = NULL;
+                               return 0;
+                       }
                        break;
+               }
                /*
                 * Put each allocated block on the list.
                 */
@@ -2360,8 +2364,19 @@ xfs_alloc_vextent(
                        if (args->agno == sagno &&
                            type == XFS_ALLOCTYPE_START_BNO)
                                args->type = XFS_ALLOCTYPE_THIS_AG;
-                       if (++(args->agno) == mp->m_sb.sb_agcount)
-                               args->agno = 0;
+                       /*
+                       * For the first allocation, we can try any AG to get
+                       * space.  However, if we already have allocated a
+                       * block, we don't want to try AGs whose number is below
+                       * sagno. Otherwise, we may end up with out-of-order
+                       * locking of AGF, which might cause deadlock.
+                       */
+                       if (++(args->agno) == mp->m_sb.sb_agcount) {
+                               if (args->firstblock != NULLFSBLOCK)
+                                       args->agno = sagno;
+                               else
+                                       args->agno = 0;
+                       }
                        /*
                         * Reached the starting a.g., must either be done
                         * or switch to non-trylock mode.
@@ -2443,7 +2458,7 @@ xfs_free_extent(
        args.minlen = args.minleft = args.minalignslop = 0;
        down_read(&args.mp->m_peraglock);
        args.pag = &args.mp->m_perag[args.agno];
-       if ((error = xfs_alloc_fix_freelist(&args, 0)))
+       if ((error = xfs_alloc_fix_freelist(&args, XFS_ALLOC_FLAG_FREEING)))
                goto error0;
 #ifdef DEBUG
        ASSERT(args.agbp != NULL);