aboutsummaryrefslogtreecommitdiffstats
path: root/fs/xfs
diff options
context:
space:
mode:
authorDave Chinner <dchinner@redhat.com>2014-12-03 17:42:21 -0500
committerDave Chinner <david@fromorbit.com>2014-12-03 17:42:21 -0500
commit7a1df1561609c14ac457d65d9a4a2b6c0f4204ad (patch)
treed5b2edc1316624cd6d3539ecfee4ba7adc86a63d /fs/xfs
parent76b57302526ae289e8094a51d6a71031ff3d058b (diff)
xfs: fix premature enospc on inode allocation
After growing a filesystem, XFS can fail to allocate inodes even though there is a large amount of space available in the filesystem for inodes. The issue is caused by a nearly full allocation group having enough free space in it to be considered for inode allocation, but not enough contiguous free space to actually allocation inodes. This situation results in successful selection of the AG for allocation, then failure of the allocation resulting in ENOSPC being reported to the caller. It is caused by two possible issues. Firstly, we only consider the lognest free extent and whether it would fit an inode chunk. If the extent is not correctly aligned, then we can't allocate an inode chunk in it regardless of the fact that it is large enough. This tends to be a permanent error until space in the AG is freed. The second issue is that we don't actually lock the AGI or AGF when we are doing these checks, and so by the time we get to actually allocating the inode chunk the space we thought we had in the AG may have been allocated. This tends to be a spurious error as it requires a race to trigger. Hence this case is ignored in this patch as the reported problem is for permanent errors. The first issue could be addressed by simply taking into account the alignment when checking the longest extent. This, however, would prevent allocation in AGs that have aligned, exact sized extents free. However, this case should be fairly rare compared to the number of allocations that occur near ENOSPC that would trigger this condition. Hence, when selecting the inode AG, take into account the inode cluster alignment when checking the lognest free extent in the AG. If we can't find any AGs with a contiguous free space large enough to be aligned, drop the alignment addition and just try for an AG that has enough contiguous free space available for an inode chunk. This won't prevent issues from occurring, but should avoid situations where other AGs have lots of free space but the selected AG can't allocate due to alignment constraints. Reported-by: Arkadiusz Miskiewicz <arekm@maven.pl> Signed-off-by: Dave Chinner <dchinner@redhat.com> Reviewed-by: Brian Foster <bfoster@redhat.com> Signed-off-by: Dave Chinner <david@fromorbit.com>
Diffstat (limited to 'fs/xfs')
-rw-r--r--fs/xfs/libxfs/xfs_ialloc.c34
1 files changed, 24 insertions, 10 deletions
diff --git a/fs/xfs/libxfs/xfs_ialloc.c b/fs/xfs/libxfs/xfs_ialloc.c
index 705a7530176e..277a46f96f54 100644
--- a/fs/xfs/libxfs/xfs_ialloc.c
+++ b/fs/xfs/libxfs/xfs_ialloc.c
@@ -48,12 +48,12 @@
48 */ 48 */
49static inline int 49static inline int
50xfs_ialloc_cluster_alignment( 50xfs_ialloc_cluster_alignment(
51 xfs_alloc_arg_t *args) 51 struct xfs_mount *mp)
52{ 52{
53 if (xfs_sb_version_hasalign(&args->mp->m_sb) && 53 if (xfs_sb_version_hasalign(&mp->m_sb) &&
54 args->mp->m_sb.sb_inoalignmt >= 54 mp->m_sb.sb_inoalignmt >=
55 XFS_B_TO_FSBT(args->mp, args->mp->m_inode_cluster_size)) 55 XFS_B_TO_FSBT(mp, mp->m_inode_cluster_size))
56 return args->mp->m_sb.sb_inoalignmt; 56 return mp->m_sb.sb_inoalignmt;
57 return 1; 57 return 1;
58} 58}
59 59
@@ -412,7 +412,7 @@ xfs_ialloc_ag_alloc(
412 * but not to use them in the actual exact allocation. 412 * but not to use them in the actual exact allocation.
413 */ 413 */
414 args.alignment = 1; 414 args.alignment = 1;
415 args.minalignslop = xfs_ialloc_cluster_alignment(&args) - 1; 415 args.minalignslop = xfs_ialloc_cluster_alignment(args.mp) - 1;
416 416
417 /* Allow space for the inode btree to split. */ 417 /* Allow space for the inode btree to split. */
418 args.minleft = args.mp->m_in_maxlevels - 1; 418 args.minleft = args.mp->m_in_maxlevels - 1;
@@ -448,7 +448,7 @@ xfs_ialloc_ag_alloc(
448 args.alignment = args.mp->m_dalign; 448 args.alignment = args.mp->m_dalign;
449 isaligned = 1; 449 isaligned = 1;
450 } else 450 } else
451 args.alignment = xfs_ialloc_cluster_alignment(&args); 451 args.alignment = xfs_ialloc_cluster_alignment(args.mp);
452 /* 452 /*
453 * Need to figure out where to allocate the inode blocks. 453 * Need to figure out where to allocate the inode blocks.
454 * Ideally they should be spaced out through the a.g. 454 * Ideally they should be spaced out through the a.g.
@@ -477,7 +477,7 @@ xfs_ialloc_ag_alloc(
477 args.type = XFS_ALLOCTYPE_NEAR_BNO; 477 args.type = XFS_ALLOCTYPE_NEAR_BNO;
478 args.agbno = be32_to_cpu(agi->agi_root); 478 args.agbno = be32_to_cpu(agi->agi_root);
479 args.fsbno = XFS_AGB_TO_FSB(args.mp, agno, args.agbno); 479 args.fsbno = XFS_AGB_TO_FSB(args.mp, agno, args.agbno);
480 args.alignment = xfs_ialloc_cluster_alignment(&args); 480 args.alignment = xfs_ialloc_cluster_alignment(args.mp);
481 if ((error = xfs_alloc_vextent(&args))) 481 if ((error = xfs_alloc_vextent(&args)))
482 return error; 482 return error;
483 } 483 }
@@ -632,10 +632,24 @@ xfs_ialloc_ag_select(
632 } 632 }
633 633
634 /* 634 /*
635 * Is there enough free space for the file plus a block of 635 * Check that there is enough free space for the file plus a
636 * inodes? (if we need to allocate some)? 636 * chunk of inodes if we need to allocate some. If this is the
637 * first pass across the AGs, take into account the potential
638 * space needed for alignment of inode chunks when checking the
639 * longest contiguous free space in the AG - this prevents us
640 * from getting ENOSPC because we have free space larger than
641 * m_ialloc_blks but alignment constraints prevent us from using
642 * it.
643 *
644 * If we can't find an AG with space for full alignment slack to
645 * be taken into account, we must be near ENOSPC in all AGs.
646 * Hence we don't include alignment for the second pass and so
647 * if we fail allocation due to alignment issues then it is most
648 * likely a real ENOSPC condition.
637 */ 649 */
638 ineed = mp->m_ialloc_blks; 650 ineed = mp->m_ialloc_blks;
651 if (flags && ineed > 1)
652 ineed += xfs_ialloc_cluster_alignment(mp);
639 longest = pag->pagf_longest; 653 longest = pag->pagf_longest;
640 if (!longest) 654 if (!longest)
641 longest = pag->pagf_flcount > 0; 655 longest = pag->pagf_flcount > 0;