aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorDarrick J. Wong <darrick.wong@oracle.com>2016-10-03 12:11:45 -0400
committerDarrick J. Wong <darrick.wong@oracle.com>2016-10-05 19:26:27 -0400
commit6fa164b865e44ac1d1ffc9a24ccd442f17acc4f6 (patch)
tree62b863d4de68d47af16edcfac1e2a5fa0b2f437f
parent84d6961910ea7b3ae8d8338f5b4df25dea68cee9 (diff)
xfs: don't allow reflink when the AG is low on space
If the AG free space is down to the reserves, refuse to reflink our way out of space. Hopefully userspace will make a real copy and/or go elsewhere. Signed-off-by: Darrick J. Wong <darrick.wong@oracle.com> Reviewed-by: Christoph Hellwig <hch@lst.de>
-rw-r--r--fs/xfs/xfs_reflink.c35
1 files changed, 35 insertions, 0 deletions
diff --git a/fs/xfs/xfs_reflink.c b/fs/xfs/xfs_reflink.c
index 8e894118295f..e92ccd316391 100644
--- a/fs/xfs/xfs_reflink.c
+++ b/fs/xfs/xfs_reflink.c
@@ -54,6 +54,8 @@
54#include "xfs_reflink.h" 54#include "xfs_reflink.h"
55#include "xfs_iomap.h" 55#include "xfs_iomap.h"
56#include "xfs_rmap_btree.h" 56#include "xfs_rmap_btree.h"
57#include "xfs_sb.h"
58#include "xfs_ag_resv.h"
57 59
58/* 60/*
59 * Copy on Write of Shared Blocks 61 * Copy on Write of Shared Blocks
@@ -978,6 +980,31 @@ out_error:
978} 980}
979 981
980/* 982/*
983 * Do we have enough reserve in this AG to handle a reflink? The refcount
984 * btree already reserved all the space it needs, but the rmap btree can grow
985 * infinitely, so we won't allow more reflinks when the AG is down to the
986 * btree reserves.
987 */
988static int
989xfs_reflink_ag_has_free_space(
990 struct xfs_mount *mp,
991 xfs_agnumber_t agno)
992{
993 struct xfs_perag *pag;
994 int error = 0;
995
996 if (!xfs_sb_version_hasrmapbt(&mp->m_sb))
997 return 0;
998
999 pag = xfs_perag_get(mp, agno);
1000 if (xfs_ag_resv_critical(pag, XFS_AG_RESV_AGFL) ||
1001 xfs_ag_resv_critical(pag, XFS_AG_RESV_METADATA))
1002 error = -ENOSPC;
1003 xfs_perag_put(pag);
1004 return error;
1005}
1006
1007/*
981 * Unmap a range of blocks from a file, then map other blocks into the hole. 1008 * Unmap a range of blocks from a file, then map other blocks into the hole.
982 * The range to unmap is (destoff : destoff + srcioff + irec->br_blockcount). 1009 * The range to unmap is (destoff : destoff + srcioff + irec->br_blockcount).
983 * The extent irec is mapped into dest at irec->br_startoff. 1010 * The extent irec is mapped into dest at irec->br_startoff.
@@ -1009,6 +1036,14 @@ xfs_reflink_remap_extent(
1009 irec->br_startblock != DELAYSTARTBLOCK && 1036 irec->br_startblock != DELAYSTARTBLOCK &&
1010 !ISUNWRITTEN(irec)); 1037 !ISUNWRITTEN(irec));
1011 1038
1039 /* No reflinking if we're low on space */
1040 if (real_extent) {
1041 error = xfs_reflink_ag_has_free_space(mp,
1042 XFS_FSB_TO_AGNO(mp, irec->br_startblock));
1043 if (error)
1044 goto out;
1045 }
1046
1012 /* Start a rolling transaction to switch the mappings */ 1047 /* Start a rolling transaction to switch the mappings */
1013 resblks = XFS_EXTENTADD_SPACE_RES(ip->i_mount, XFS_DATA_FORK); 1048 resblks = XFS_EXTENTADD_SPACE_RES(ip->i_mount, XFS_DATA_FORK);
1014 error = xfs_trans_alloc(mp, &M_RES(mp)->tr_write, resblks, 0, 0, &tp); 1049 error = xfs_trans_alloc(mp, &M_RES(mp)->tr_write, resblks, 0, 0, &tp);