aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorDarrick J. Wong <darrick.wong@oracle.com>2016-08-02 21:33:42 -0400
committerDave Chinner <david@fromorbit.com>2016-08-02 21:33:42 -0400
commit340785cca16246f82ccaf11740d885017a9e9341 (patch)
treec401236476bf4baa07846c2219fa3cdbdd52699d
parent8018026ef29756af6144e2e2e8dffc9c2ed0d6f7 (diff)
xfs: add owner field to extent allocation and freeing
For the rmap btree to work, we have to feed the extent owner information to the the allocation and freeing functions. This information is what will end up in the rmap btree that tracks allocated extents. While we technically don't need the owner information when freeing extents, passing it allows us to validate that the extent we are removing from the rmap btree actually belonged to the owner we expected it to belong to. We also define a special set of owner values for internal metadata that would otherwise have no owner. This allows us to tell the difference between metadata owned by different per-ag btrees, as well as static fs metadata (e.g. AG headers) and internal journal blocks. There are also a couple of special cases we need to take care of - during EFI recovery, we don't actually know who the original owner was, so we need to pass a wildcard to indicate that we aren't checking the owner for validity. We also need special handling in growfs, as we "free" the space in the last AG when extending it, but because it's new space it has no actual owner... While touching the xfs_bmap_add_free() function, re-order the parameters to put the struct xfs_mount first. Extend the owner field to include both the owner type and some sort of index within the owner. The index field will be used to support reverse mappings when reflink is enabled. When we're freeing extents from an EFI, we don't have the owner information available (rmap updates have their own redo items). xfs_free_extent therefore doesn't need to do an rmap update. Make sure that the log replay code signals this correctly. This is based upon a patch originally from Dave Chinner. It has been extended to add more owner information with the intent of helping recovery operations when things go wrong (e.g. offset of user data block in a file). [dchinner: de-shout the xfs_rmap_*_owner helpers] [darrick: minor style fixes suggested by Christoph Hellwig] Signed-off-by: Dave Chinner <dchinner@redhat.com> Signed-off-by: Darrick J. Wong <darrick.wong@oracle.com> Reviewed-by: Dave Chinner <dchinner@redhat.com> Signed-off-by: Dave Chinner <david@fromorbit.com>
-rw-r--r--fs/xfs/libxfs/xfs_alloc.c26
-rw-r--r--fs/xfs/libxfs/xfs_alloc.h8
-rw-r--r--fs/xfs/libxfs/xfs_bmap.c25
-rw-r--r--fs/xfs/libxfs/xfs_bmap.h4
-rw-r--r--fs/xfs/libxfs/xfs_bmap_btree.c7
-rw-r--r--fs/xfs/libxfs/xfs_format.h28
-rw-r--r--fs/xfs/libxfs/xfs_ialloc.c8
-rw-r--r--fs/xfs/libxfs/xfs_ialloc_btree.c8
-rw-r--r--fs/xfs/libxfs/xfs_rmap.h67
-rw-r--r--fs/xfs/xfs_extfree_item.c6
-rw-r--r--fs/xfs/xfs_fsops.c17
-rw-r--r--fs/xfs/xfs_trans.h2
-rw-r--r--fs/xfs/xfs_trans_extfree.c8
13 files changed, 181 insertions, 33 deletions
diff --git a/fs/xfs/libxfs/xfs_alloc.c b/fs/xfs/libxfs/xfs_alloc.c
index 43c7e53a6a8e..6335b8b85349 100644
--- a/fs/xfs/libxfs/xfs_alloc.c
+++ b/fs/xfs/libxfs/xfs_alloc.c
@@ -36,6 +36,7 @@
36#include "xfs_trans.h" 36#include "xfs_trans.h"
37#include "xfs_buf_item.h" 37#include "xfs_buf_item.h"
38#include "xfs_log.h" 38#include "xfs_log.h"
39#include "xfs_rmap.h"
39 40
40struct workqueue_struct *xfs_alloc_wq; 41struct workqueue_struct *xfs_alloc_wq;
41 42
@@ -1589,14 +1590,15 @@ error0:
1589/* 1590/*
1590 * Free the extent starting at agno/bno for length. 1591 * Free the extent starting at agno/bno for length.
1591 */ 1592 */
1592STATIC int /* error */ 1593STATIC int
1593xfs_free_ag_extent( 1594xfs_free_ag_extent(
1594 xfs_trans_t *tp, /* transaction pointer */ 1595 xfs_trans_t *tp,
1595 xfs_buf_t *agbp, /* buffer for a.g. freelist header */ 1596 xfs_buf_t *agbp,
1596 xfs_agnumber_t agno, /* allocation group number */ 1597 xfs_agnumber_t agno,
1597 xfs_agblock_t bno, /* starting block number */ 1598 xfs_agblock_t bno,
1598 xfs_extlen_t len, /* length of extent */ 1599 xfs_extlen_t len,
1599 int isfl) /* set if is freelist blocks - no sb acctg */ 1600 struct xfs_owner_info *oinfo,
1601 int isfl)
1600{ 1602{
1601 xfs_btree_cur_t *bno_cur; /* cursor for by-block btree */ 1603 xfs_btree_cur_t *bno_cur; /* cursor for by-block btree */
1602 xfs_btree_cur_t *cnt_cur; /* cursor for by-size btree */ 1604 xfs_btree_cur_t *cnt_cur; /* cursor for by-size btree */
@@ -2005,13 +2007,15 @@ xfs_alloc_fix_freelist(
2005 * back on the free list? Maybe we should only do this when space is 2007 * back on the free list? Maybe we should only do this when space is
2006 * getting low or the AGFL is more than half full? 2008 * getting low or the AGFL is more than half full?
2007 */ 2009 */
2010 xfs_rmap_ag_owner(&targs.oinfo, XFS_RMAP_OWN_AG);
2008 while (pag->pagf_flcount > need) { 2011 while (pag->pagf_flcount > need) {
2009 struct xfs_buf *bp; 2012 struct xfs_buf *bp;
2010 2013
2011 error = xfs_alloc_get_freelist(tp, agbp, &bno, 0); 2014 error = xfs_alloc_get_freelist(tp, agbp, &bno, 0);
2012 if (error) 2015 if (error)
2013 goto out_agbp_relse; 2016 goto out_agbp_relse;
2014 error = xfs_free_ag_extent(tp, agbp, args->agno, bno, 1, 1); 2017 error = xfs_free_ag_extent(tp, agbp, args->agno, bno, 1,
2018 &targs.oinfo, 1);
2015 if (error) 2019 if (error)
2016 goto out_agbp_relse; 2020 goto out_agbp_relse;
2017 bp = xfs_btree_get_bufs(mp, tp, args->agno, bno, 0); 2021 bp = xfs_btree_get_bufs(mp, tp, args->agno, bno, 0);
@@ -2021,6 +2025,7 @@ xfs_alloc_fix_freelist(
2021 memset(&targs, 0, sizeof(targs)); 2025 memset(&targs, 0, sizeof(targs));
2022 targs.tp = tp; 2026 targs.tp = tp;
2023 targs.mp = mp; 2027 targs.mp = mp;
2028 xfs_rmap_ag_owner(&targs.oinfo, XFS_RMAP_OWN_AG);
2024 targs.agbp = agbp; 2029 targs.agbp = agbp;
2025 targs.agno = args->agno; 2030 targs.agno = args->agno;
2026 targs.alignment = targs.minlen = targs.prod = targs.isfl = 1; 2031 targs.alignment = targs.minlen = targs.prod = targs.isfl = 1;
@@ -2709,7 +2714,8 @@ int /* error */
2709xfs_free_extent( 2714xfs_free_extent(
2710 struct xfs_trans *tp, /* transaction pointer */ 2715 struct xfs_trans *tp, /* transaction pointer */
2711 xfs_fsblock_t bno, /* starting block number of extent */ 2716 xfs_fsblock_t bno, /* starting block number of extent */
2712 xfs_extlen_t len) /* length of extent */ 2717 xfs_extlen_t len, /* length of extent */
2718 struct xfs_owner_info *oinfo) /* extent owner */
2713{ 2719{
2714 struct xfs_mount *mp = tp->t_mountp; 2720 struct xfs_mount *mp = tp->t_mountp;
2715 struct xfs_buf *agbp; 2721 struct xfs_buf *agbp;
@@ -2737,7 +2743,7 @@ xfs_free_extent(
2737 agbno + len <= be32_to_cpu(XFS_BUF_TO_AGF(agbp)->agf_length), 2743 agbno + len <= be32_to_cpu(XFS_BUF_TO_AGF(agbp)->agf_length),
2738 err); 2744 err);
2739 2745
2740 error = xfs_free_ag_extent(tp, agbp, agno, agbno, len, 0); 2746 error = xfs_free_ag_extent(tp, agbp, agno, agbno, len, oinfo, 0);
2741 if (error) 2747 if (error)
2742 goto err; 2748 goto err;
2743 2749
diff --git a/fs/xfs/libxfs/xfs_alloc.h b/fs/xfs/libxfs/xfs_alloc.h
index 20b54aa87026..88053422fda0 100644
--- a/fs/xfs/libxfs/xfs_alloc.h
+++ b/fs/xfs/libxfs/xfs_alloc.h
@@ -123,6 +123,7 @@ typedef struct xfs_alloc_arg {
123 char isfl; /* set if is freelist blocks - !acctg */ 123 char isfl; /* set if is freelist blocks - !acctg */
124 char userdata; /* mask defining userdata treatment */ 124 char userdata; /* mask defining userdata treatment */
125 xfs_fsblock_t firstblock; /* io first block allocated */ 125 xfs_fsblock_t firstblock; /* io first block allocated */
126 struct xfs_owner_info oinfo; /* owner of blocks being allocated */
126} xfs_alloc_arg_t; 127} xfs_alloc_arg_t;
127 128
128/* 129/*
@@ -208,9 +209,10 @@ xfs_alloc_vextent(
208 */ 209 */
209int /* error */ 210int /* error */
210xfs_free_extent( 211xfs_free_extent(
211 struct xfs_trans *tp, /* transaction pointer */ 212 struct xfs_trans *tp, /* transaction pointer */
212 xfs_fsblock_t bno, /* starting block number of extent */ 213 xfs_fsblock_t bno, /* starting block number of extent */
213 xfs_extlen_t len); /* length of extent */ 214 xfs_extlen_t len, /* length of extent */
215 struct xfs_owner_info *oinfo);/* extent owner */
214 216
215int /* error */ 217int /* error */
216xfs_alloc_lookup_ge( 218xfs_alloc_lookup_ge(
diff --git a/fs/xfs/libxfs/xfs_bmap.c b/fs/xfs/libxfs/xfs_bmap.c
index 8e14ff45c73a..919069fc7b23 100644
--- a/fs/xfs/libxfs/xfs_bmap.c
+++ b/fs/xfs/libxfs/xfs_bmap.c
@@ -46,6 +46,7 @@
46#include "xfs_symlink.h" 46#include "xfs_symlink.h"
47#include "xfs_attr_leaf.h" 47#include "xfs_attr_leaf.h"
48#include "xfs_filestream.h" 48#include "xfs_filestream.h"
49#include "xfs_rmap.h"
49 50
50 51
51kmem_zone_t *xfs_bmap_free_item_zone; 52kmem_zone_t *xfs_bmap_free_item_zone;
@@ -571,10 +572,11 @@ xfs_bmap_validate_ret(
571 */ 572 */
572void 573void
573xfs_bmap_add_free( 574xfs_bmap_add_free(
574 struct xfs_mount *mp, /* mount point structure */ 575 struct xfs_mount *mp,
575 struct xfs_defer_ops *dfops, /* list of extents */ 576 struct xfs_defer_ops *dfops,
576 xfs_fsblock_t bno, /* fs block number of extent */ 577 xfs_fsblock_t bno,
577 xfs_filblks_t len) /* length of extent */ 578 xfs_filblks_t len,
579 struct xfs_owner_info *oinfo)
578{ 580{
579 struct xfs_extent_free_item *new; /* new element */ 581 struct xfs_extent_free_item *new; /* new element */
580#ifdef DEBUG 582#ifdef DEBUG
@@ -593,9 +595,14 @@ xfs_bmap_add_free(
593 ASSERT(agbno + len <= mp->m_sb.sb_agblocks); 595 ASSERT(agbno + len <= mp->m_sb.sb_agblocks);
594#endif 596#endif
595 ASSERT(xfs_bmap_free_item_zone != NULL); 597 ASSERT(xfs_bmap_free_item_zone != NULL);
598
596 new = kmem_zone_alloc(xfs_bmap_free_item_zone, KM_SLEEP); 599 new = kmem_zone_alloc(xfs_bmap_free_item_zone, KM_SLEEP);
597 new->xefi_startblock = bno; 600 new->xefi_startblock = bno;
598 new->xefi_blockcount = (xfs_extlen_t)len; 601 new->xefi_blockcount = (xfs_extlen_t)len;
602 if (oinfo)
603 new->xefi_oinfo = *oinfo;
604 else
605 xfs_rmap_skip_owner_update(&new->xefi_oinfo);
599 trace_xfs_bmap_free_defer(mp, XFS_FSB_TO_AGNO(mp, bno), 0, 606 trace_xfs_bmap_free_defer(mp, XFS_FSB_TO_AGNO(mp, bno), 0,
600 XFS_FSB_TO_AGBNO(mp, bno), len); 607 XFS_FSB_TO_AGBNO(mp, bno), len);
601 xfs_defer_add(dfops, XFS_DEFER_OPS_TYPE_FREE, &new->xefi_list); 608 xfs_defer_add(dfops, XFS_DEFER_OPS_TYPE_FREE, &new->xefi_list);
@@ -628,6 +635,7 @@ xfs_bmap_btree_to_extents(
628 xfs_mount_t *mp; /* mount point structure */ 635 xfs_mount_t *mp; /* mount point structure */
629 __be64 *pp; /* ptr to block address */ 636 __be64 *pp; /* ptr to block address */
630 struct xfs_btree_block *rblock;/* root btree block */ 637 struct xfs_btree_block *rblock;/* root btree block */
638 struct xfs_owner_info oinfo;
631 639
632 mp = ip->i_mount; 640 mp = ip->i_mount;
633 ifp = XFS_IFORK_PTR(ip, whichfork); 641 ifp = XFS_IFORK_PTR(ip, whichfork);
@@ -651,7 +659,8 @@ xfs_bmap_btree_to_extents(
651 cblock = XFS_BUF_TO_BLOCK(cbp); 659 cblock = XFS_BUF_TO_BLOCK(cbp);
652 if ((error = xfs_btree_check_block(cur, cblock, 0, cbp))) 660 if ((error = xfs_btree_check_block(cur, cblock, 0, cbp)))
653 return error; 661 return error;
654 xfs_bmap_add_free(mp, cur->bc_private.b.dfops, cbno, 1); 662 xfs_rmap_ino_bmbt_owner(&oinfo, ip->i_ino, whichfork);
663 xfs_bmap_add_free(mp, cur->bc_private.b.dfops, cbno, 1, &oinfo);
655 ip->i_d.di_nblocks--; 664 ip->i_d.di_nblocks--;
656 xfs_trans_mod_dquot_byino(tp, ip, XFS_TRANS_DQ_BCOUNT, -1L); 665 xfs_trans_mod_dquot_byino(tp, ip, XFS_TRANS_DQ_BCOUNT, -1L);
657 xfs_trans_binval(tp, cbp); 666 xfs_trans_binval(tp, cbp);
@@ -732,6 +741,7 @@ xfs_bmap_extents_to_btree(
732 memset(&args, 0, sizeof(args)); 741 memset(&args, 0, sizeof(args));
733 args.tp = tp; 742 args.tp = tp;
734 args.mp = mp; 743 args.mp = mp;
744 xfs_rmap_ino_bmbt_owner(&args.oinfo, ip->i_ino, whichfork);
735 args.firstblock = *firstblock; 745 args.firstblock = *firstblock;
736 if (*firstblock == NULLFSBLOCK) { 746 if (*firstblock == NULLFSBLOCK) {
737 args.type = XFS_ALLOCTYPE_START_BNO; 747 args.type = XFS_ALLOCTYPE_START_BNO;
@@ -878,6 +888,7 @@ xfs_bmap_local_to_extents(
878 memset(&args, 0, sizeof(args)); 888 memset(&args, 0, sizeof(args));
879 args.tp = tp; 889 args.tp = tp;
880 args.mp = ip->i_mount; 890 args.mp = ip->i_mount;
891 xfs_rmap_ino_owner(&args.oinfo, ip->i_ino, whichfork, 0);
881 args.firstblock = *firstblock; 892 args.firstblock = *firstblock;
882 /* 893 /*
883 * Allocate a block. We know we need only one, since the 894 * Allocate a block. We know we need only one, since the
@@ -3660,6 +3671,7 @@ xfs_bmap_btalloc(
3660 args.tp = ap->tp; 3671 args.tp = ap->tp;
3661 args.mp = mp; 3672 args.mp = mp;
3662 args.fsbno = ap->blkno; 3673 args.fsbno = ap->blkno;
3674 xfs_rmap_skip_owner_update(&args.oinfo);
3663 3675
3664 /* Trim the allocation back to the maximum an AG can fit. */ 3676 /* Trim the allocation back to the maximum an AG can fit. */
3665 args.maxlen = MIN(ap->length, XFS_ALLOC_AG_MAX_USABLE(mp)); 3677 args.maxlen = MIN(ap->length, XFS_ALLOC_AG_MAX_USABLE(mp));
@@ -4839,6 +4851,7 @@ xfs_bmap_del_extent(
4839 nblks = 0; 4851 nblks = 0;
4840 do_fx = 0; 4852 do_fx = 0;
4841 } 4853 }
4854
4842 /* 4855 /*
4843 * Set flag value to use in switch statement. 4856 * Set flag value to use in switch statement.
4844 * Left-contig is 2, right-contig is 1. 4857 * Left-contig is 2, right-contig is 1.
@@ -5026,7 +5039,7 @@ xfs_bmap_del_extent(
5026 */ 5039 */
5027 if (do_fx) 5040 if (do_fx)
5028 xfs_bmap_add_free(mp, dfops, del->br_startblock, 5041 xfs_bmap_add_free(mp, dfops, del->br_startblock,
5029 del->br_blockcount); 5042 del->br_blockcount, NULL);
5030 /* 5043 /*
5031 * Adjust inode # blocks in the file. 5044 * Adjust inode # blocks in the file.
5032 */ 5045 */
diff --git a/fs/xfs/libxfs/xfs_bmap.h b/fs/xfs/libxfs/xfs_bmap.h
index dc01bb85a6e8..254034f96941 100644
--- a/fs/xfs/libxfs/xfs_bmap.h
+++ b/fs/xfs/libxfs/xfs_bmap.h
@@ -67,6 +67,7 @@ struct xfs_extent_free_item
67 xfs_fsblock_t xefi_startblock;/* starting fs block number */ 67 xfs_fsblock_t xefi_startblock;/* starting fs block number */
68 xfs_extlen_t xefi_blockcount;/* number of blocks in extent */ 68 xfs_extlen_t xefi_blockcount;/* number of blocks in extent */
69 struct list_head xefi_list; 69 struct list_head xefi_list;
70 struct xfs_owner_info xefi_oinfo; /* extent owner */
70}; 71};
71 72
72#define XFS_BMAP_MAX_NMAP 4 73#define XFS_BMAP_MAX_NMAP 4
@@ -165,7 +166,8 @@ void xfs_bmap_trace_exlist(struct xfs_inode *ip, xfs_extnum_t cnt,
165int xfs_bmap_add_attrfork(struct xfs_inode *ip, int size, int rsvd); 166int xfs_bmap_add_attrfork(struct xfs_inode *ip, int size, int rsvd);
166void xfs_bmap_local_to_extents_empty(struct xfs_inode *ip, int whichfork); 167void xfs_bmap_local_to_extents_empty(struct xfs_inode *ip, int whichfork);
167void xfs_bmap_add_free(struct xfs_mount *mp, struct xfs_defer_ops *dfops, 168void xfs_bmap_add_free(struct xfs_mount *mp, struct xfs_defer_ops *dfops,
168 xfs_fsblock_t bno, xfs_filblks_t len); 169 xfs_fsblock_t bno, xfs_filblks_t len,
170 struct xfs_owner_info *oinfo);
169void xfs_bmap_compute_maxlevels(struct xfs_mount *mp, int whichfork); 171void xfs_bmap_compute_maxlevels(struct xfs_mount *mp, int whichfork);
170int xfs_bmap_first_unused(struct xfs_trans *tp, struct xfs_inode *ip, 172int xfs_bmap_first_unused(struct xfs_trans *tp, struct xfs_inode *ip,
171 xfs_extlen_t len, xfs_fileoff_t *unused, int whichfork); 173 xfs_extlen_t len, xfs_fileoff_t *unused, int whichfork);
diff --git a/fs/xfs/libxfs/xfs_bmap_btree.c b/fs/xfs/libxfs/xfs_bmap_btree.c
index 0df5318cefff..9e34ca413e53 100644
--- a/fs/xfs/libxfs/xfs_bmap_btree.c
+++ b/fs/xfs/libxfs/xfs_bmap_btree.c
@@ -35,6 +35,7 @@
35#include "xfs_quota.h" 35#include "xfs_quota.h"
36#include "xfs_trace.h" 36#include "xfs_trace.h"
37#include "xfs_cksum.h" 37#include "xfs_cksum.h"
38#include "xfs_rmap.h"
38 39
39/* 40/*
40 * Determine the extent state. 41 * Determine the extent state.
@@ -447,6 +448,8 @@ xfs_bmbt_alloc_block(
447 args.mp = cur->bc_mp; 448 args.mp = cur->bc_mp;
448 args.fsbno = cur->bc_private.b.firstblock; 449 args.fsbno = cur->bc_private.b.firstblock;
449 args.firstblock = args.fsbno; 450 args.firstblock = args.fsbno;
451 xfs_rmap_ino_bmbt_owner(&args.oinfo, cur->bc_private.b.ip->i_ino,
452 cur->bc_private.b.whichfork);
450 453
451 if (args.fsbno == NULLFSBLOCK) { 454 if (args.fsbno == NULLFSBLOCK) {
452 args.fsbno = be64_to_cpu(start->l); 455 args.fsbno = be64_to_cpu(start->l);
@@ -526,8 +529,10 @@ xfs_bmbt_free_block(
526 struct xfs_inode *ip = cur->bc_private.b.ip; 529 struct xfs_inode *ip = cur->bc_private.b.ip;
527 struct xfs_trans *tp = cur->bc_tp; 530 struct xfs_trans *tp = cur->bc_tp;
528 xfs_fsblock_t fsbno = XFS_DADDR_TO_FSB(mp, XFS_BUF_ADDR(bp)); 531 xfs_fsblock_t fsbno = XFS_DADDR_TO_FSB(mp, XFS_BUF_ADDR(bp));
532 struct xfs_owner_info oinfo;
529 533
530 xfs_bmap_add_free(mp, cur->bc_private.b.dfops, fsbno, 1); 534 xfs_rmap_ino_bmbt_owner(&oinfo, ip->i_ino, cur->bc_private.b.whichfork);
535 xfs_bmap_add_free(mp, cur->bc_private.b.dfops, fsbno, 1, &oinfo);
531 ip->i_d.di_nblocks--; 536 ip->i_d.di_nblocks--;
532 537
533 xfs_trans_log_inode(tp, ip, XFS_ILOG_CORE); 538 xfs_trans_log_inode(tp, ip, XFS_ILOG_CORE);
diff --git a/fs/xfs/libxfs/xfs_format.h b/fs/xfs/libxfs/xfs_format.h
index 3dbed011c29a..eecfedf19be5 100644
--- a/fs/xfs/libxfs/xfs_format.h
+++ b/fs/xfs/libxfs/xfs_format.h
@@ -1319,6 +1319,34 @@ typedef __be32 xfs_inobt_ptr_t;
1319 */ 1319 */
1320#define XFS_RMAP_CRC_MAGIC 0x524d4233 /* 'RMB3' */ 1320#define XFS_RMAP_CRC_MAGIC 0x524d4233 /* 'RMB3' */
1321 1321
1322/*
1323 * Ownership info for an extent. This is used to create reverse-mapping
1324 * entries.
1325 */
1326#define XFS_OWNER_INFO_ATTR_FORK (1 << 0)
1327#define XFS_OWNER_INFO_BMBT_BLOCK (1 << 1)
1328struct xfs_owner_info {
1329 uint64_t oi_owner;
1330 xfs_fileoff_t oi_offset;
1331 unsigned int oi_flags;
1332};
1333
1334/*
1335 * Special owner types.
1336 *
1337 * Seeing as we only support up to 8EB, we have the upper bit of the owner field
1338 * to tell us we have a special owner value. We use these for static metadata
1339 * allocated at mkfs/growfs time, as well as for freespace management metadata.
1340 */
1341#define XFS_RMAP_OWN_NULL (-1ULL) /* No owner, for growfs */
1342#define XFS_RMAP_OWN_UNKNOWN (-2ULL) /* Unknown owner, for EFI recovery */
1343#define XFS_RMAP_OWN_FS (-3ULL) /* static fs metadata */
1344#define XFS_RMAP_OWN_LOG (-4ULL) /* static fs metadata */
1345#define XFS_RMAP_OWN_AG (-5ULL) /* AG freespace btree blocks */
1346#define XFS_RMAP_OWN_INOBT (-6ULL) /* Inode btree blocks */
1347#define XFS_RMAP_OWN_INODES (-7ULL) /* Inode chunk */
1348#define XFS_RMAP_OWN_MIN (-8ULL) /* guard */
1349
1322#define XFS_RMAP_BLOCK(mp) \ 1350#define XFS_RMAP_BLOCK(mp) \
1323 (xfs_sb_version_hasfinobt(&((mp)->m_sb)) ? \ 1351 (xfs_sb_version_hasfinobt(&((mp)->m_sb)) ? \
1324 XFS_FIBT_BLOCK(mp) + 1 : \ 1352 XFS_FIBT_BLOCK(mp) + 1 : \
diff --git a/fs/xfs/libxfs/xfs_ialloc.c b/fs/xfs/libxfs/xfs_ialloc.c
index f0e1f713b0be..51b4e0de1fdc 100644
--- a/fs/xfs/libxfs/xfs_ialloc.c
+++ b/fs/xfs/libxfs/xfs_ialloc.c
@@ -40,6 +40,7 @@
40#include "xfs_icache.h" 40#include "xfs_icache.h"
41#include "xfs_trace.h" 41#include "xfs_trace.h"
42#include "xfs_log.h" 42#include "xfs_log.h"
43#include "xfs_rmap.h"
43 44
44 45
45/* 46/*
@@ -615,6 +616,7 @@ xfs_ialloc_ag_alloc(
615 args.tp = tp; 616 args.tp = tp;
616 args.mp = tp->t_mountp; 617 args.mp = tp->t_mountp;
617 args.fsbno = NULLFSBLOCK; 618 args.fsbno = NULLFSBLOCK;
619 xfs_rmap_ag_owner(&args.oinfo, XFS_RMAP_OWN_INODES);
618 620
619#ifdef DEBUG 621#ifdef DEBUG
620 /* randomly do sparse inode allocations */ 622 /* randomly do sparse inode allocations */
@@ -1825,12 +1827,14 @@ xfs_difree_inode_chunk(
1825 int nextbit; 1827 int nextbit;
1826 xfs_agblock_t agbno; 1828 xfs_agblock_t agbno;
1827 int contigblk; 1829 int contigblk;
1830 struct xfs_owner_info oinfo;
1828 DECLARE_BITMAP(holemask, XFS_INOBT_HOLEMASK_BITS); 1831 DECLARE_BITMAP(holemask, XFS_INOBT_HOLEMASK_BITS);
1832 xfs_rmap_ag_owner(&oinfo, XFS_RMAP_OWN_INODES);
1829 1833
1830 if (!xfs_inobt_issparse(rec->ir_holemask)) { 1834 if (!xfs_inobt_issparse(rec->ir_holemask)) {
1831 /* not sparse, calculate extent info directly */ 1835 /* not sparse, calculate extent info directly */
1832 xfs_bmap_add_free(mp, dfops, XFS_AGB_TO_FSB(mp, agno, sagbno), 1836 xfs_bmap_add_free(mp, dfops, XFS_AGB_TO_FSB(mp, agno, sagbno),
1833 mp->m_ialloc_blks); 1837 mp->m_ialloc_blks, &oinfo);
1834 return; 1838 return;
1835 } 1839 }
1836 1840
@@ -1874,7 +1878,7 @@ xfs_difree_inode_chunk(
1874 ASSERT(agbno % mp->m_sb.sb_spino_align == 0); 1878 ASSERT(agbno % mp->m_sb.sb_spino_align == 0);
1875 ASSERT(contigblk % mp->m_sb.sb_spino_align == 0); 1879 ASSERT(contigblk % mp->m_sb.sb_spino_align == 0);
1876 xfs_bmap_add_free(mp, dfops, XFS_AGB_TO_FSB(mp, agno, agbno), 1880 xfs_bmap_add_free(mp, dfops, XFS_AGB_TO_FSB(mp, agno, agbno),
1877 contigblk); 1881 contigblk, &oinfo);
1878 1882
1879 /* reset range to current bit and carry on... */ 1883 /* reset range to current bit and carry on... */
1880 startidx = endidx = nextbit; 1884 startidx = endidx = nextbit;
diff --git a/fs/xfs/libxfs/xfs_ialloc_btree.c b/fs/xfs/libxfs/xfs_ialloc_btree.c
index a48f4482004c..c83691edf6b2 100644
--- a/fs/xfs/libxfs/xfs_ialloc_btree.c
+++ b/fs/xfs/libxfs/xfs_ialloc_btree.c
@@ -32,6 +32,7 @@
32#include "xfs_trace.h" 32#include "xfs_trace.h"
33#include "xfs_cksum.h" 33#include "xfs_cksum.h"
34#include "xfs_trans.h" 34#include "xfs_trans.h"
35#include "xfs_rmap.h"
35 36
36 37
37STATIC int 38STATIC int
@@ -96,6 +97,7 @@ xfs_inobt_alloc_block(
96 memset(&args, 0, sizeof(args)); 97 memset(&args, 0, sizeof(args));
97 args.tp = cur->bc_tp; 98 args.tp = cur->bc_tp;
98 args.mp = cur->bc_mp; 99 args.mp = cur->bc_mp;
100 xfs_rmap_ag_owner(&args.oinfo, XFS_RMAP_OWN_INOBT);
99 args.fsbno = XFS_AGB_TO_FSB(args.mp, cur->bc_private.a.agno, sbno); 101 args.fsbno = XFS_AGB_TO_FSB(args.mp, cur->bc_private.a.agno, sbno);
100 args.minlen = 1; 102 args.minlen = 1;
101 args.maxlen = 1; 103 args.maxlen = 1;
@@ -125,8 +127,12 @@ xfs_inobt_free_block(
125 struct xfs_btree_cur *cur, 127 struct xfs_btree_cur *cur,
126 struct xfs_buf *bp) 128 struct xfs_buf *bp)
127{ 129{
130 struct xfs_owner_info oinfo;
131
132 xfs_rmap_ag_owner(&oinfo, XFS_RMAP_OWN_INOBT);
128 return xfs_free_extent(cur->bc_tp, 133 return xfs_free_extent(cur->bc_tp,
129 XFS_DADDR_TO_FSB(cur->bc_mp, XFS_BUF_ADDR(bp)), 1); 134 XFS_DADDR_TO_FSB(cur->bc_mp, XFS_BUF_ADDR(bp)), 1,
135 &oinfo);
130} 136}
131 137
132STATIC int 138STATIC int
diff --git a/fs/xfs/libxfs/xfs_rmap.h b/fs/xfs/libxfs/xfs_rmap.h
new file mode 100644
index 000000000000..b30e7ad6c7cc
--- /dev/null
+++ b/fs/xfs/libxfs/xfs_rmap.h
@@ -0,0 +1,67 @@
1/*
2 * Copyright (C) 2016 Oracle. All Rights Reserved.
3 *
4 * Author: Darrick J. Wong <darrick.wong@oracle.com>
5 *
6 * This program is free software; you can redistribute it and/or
7 * modify it under the terms of the GNU General Public License
8 * as published by the Free Software Foundation; either version 2
9 * of the License, or (at your option) any later version.
10 *
11 * This program is distributed in the hope that it would be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 * GNU General Public License for more details.
15 *
16 * You should have received a copy of the GNU General Public License
17 * along with this program; if not, write the Free Software Foundation,
18 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA.
19 */
20#ifndef __XFS_RMAP_H__
21#define __XFS_RMAP_H__
22
23static inline void
24xfs_rmap_ag_owner(
25 struct xfs_owner_info *oi,
26 uint64_t owner)
27{
28 oi->oi_owner = owner;
29 oi->oi_offset = 0;
30 oi->oi_flags = 0;
31}
32
33static inline void
34xfs_rmap_ino_bmbt_owner(
35 struct xfs_owner_info *oi,
36 xfs_ino_t ino,
37 int whichfork)
38{
39 oi->oi_owner = ino;
40 oi->oi_offset = 0;
41 oi->oi_flags = XFS_OWNER_INFO_BMBT_BLOCK;
42 if (whichfork == XFS_ATTR_FORK)
43 oi->oi_flags |= XFS_OWNER_INFO_ATTR_FORK;
44}
45
46static inline void
47xfs_rmap_ino_owner(
48 struct xfs_owner_info *oi,
49 xfs_ino_t ino,
50 int whichfork,
51 xfs_fileoff_t offset)
52{
53 oi->oi_owner = ino;
54 oi->oi_offset = offset;
55 oi->oi_flags = 0;
56 if (whichfork == XFS_ATTR_FORK)
57 oi->oi_flags |= XFS_OWNER_INFO_ATTR_FORK;
58}
59
60static inline void
61xfs_rmap_skip_owner_update(
62 struct xfs_owner_info *oi)
63{
64 oi->oi_owner = XFS_RMAP_OWN_UNKNOWN;
65}
66
67#endif /* __XFS_RMAP_H__ */
diff --git a/fs/xfs/xfs_extfree_item.c b/fs/xfs/xfs_extfree_item.c
index 8c49f883934a..a8c461735ecb 100644
--- a/fs/xfs/xfs_extfree_item.c
+++ b/fs/xfs/xfs_extfree_item.c
@@ -27,6 +27,8 @@
27#include "xfs_buf_item.h" 27#include "xfs_buf_item.h"
28#include "xfs_extfree_item.h" 28#include "xfs_extfree_item.h"
29#include "xfs_log.h" 29#include "xfs_log.h"
30#include "xfs_btree.h"
31#include "xfs_rmap.h"
30 32
31 33
32kmem_zone_t *xfs_efi_zone; 34kmem_zone_t *xfs_efi_zone;
@@ -503,6 +505,7 @@ xfs_efi_recover(
503 int error = 0; 505 int error = 0;
504 xfs_extent_t *extp; 506 xfs_extent_t *extp;
505 xfs_fsblock_t startblock_fsb; 507 xfs_fsblock_t startblock_fsb;
508 struct xfs_owner_info oinfo;
506 509
507 ASSERT(!test_bit(XFS_EFI_RECOVERED, &efip->efi_flags)); 510 ASSERT(!test_bit(XFS_EFI_RECOVERED, &efip->efi_flags));
508 511
@@ -534,10 +537,11 @@ xfs_efi_recover(
534 return error; 537 return error;
535 efdp = xfs_trans_get_efd(tp, efip, efip->efi_format.efi_nextents); 538 efdp = xfs_trans_get_efd(tp, efip, efip->efi_format.efi_nextents);
536 539
540 xfs_rmap_skip_owner_update(&oinfo);
537 for (i = 0; i < efip->efi_format.efi_nextents; i++) { 541 for (i = 0; i < efip->efi_format.efi_nextents; i++) {
538 extp = &(efip->efi_format.efi_extents[i]); 542 extp = &(efip->efi_format.efi_extents[i]);
539 error = xfs_trans_free_extent(tp, efdp, extp->ext_start, 543 error = xfs_trans_free_extent(tp, efdp, extp->ext_start,
540 extp->ext_len); 544 extp->ext_len, &oinfo);
541 if (error) 545 if (error)
542 goto abort_error; 546 goto abort_error;
543 547
diff --git a/fs/xfs/xfs_fsops.c b/fs/xfs/xfs_fsops.c
index 0a3b822d9f8c..b625b61d1244 100644
--- a/fs/xfs/xfs_fsops.c
+++ b/fs/xfs/xfs_fsops.c
@@ -41,6 +41,7 @@
41#include "xfs_trace.h" 41#include "xfs_trace.h"
42#include "xfs_log.h" 42#include "xfs_log.h"
43#include "xfs_filestream.h" 43#include "xfs_filestream.h"
44#include "xfs_rmap.h"
44 45
45/* 46/*
46 * File system operations 47 * File system operations
@@ -436,6 +437,8 @@ xfs_growfs_data_private(
436 * There are new blocks in the old last a.g. 437 * There are new blocks in the old last a.g.
437 */ 438 */
438 if (new) { 439 if (new) {
440 struct xfs_owner_info oinfo;
441
439 /* 442 /*
440 * Change the agi length. 443 * Change the agi length.
441 */ 444 */
@@ -463,14 +466,20 @@ xfs_growfs_data_private(
463 be32_to_cpu(agi->agi_length)); 466 be32_to_cpu(agi->agi_length));
464 467
465 xfs_alloc_log_agf(tp, bp, XFS_AGF_LENGTH); 468 xfs_alloc_log_agf(tp, bp, XFS_AGF_LENGTH);
469
466 /* 470 /*
467 * Free the new space. 471 * Free the new space.
472 *
473 * XFS_RMAP_OWN_NULL is used here to tell the rmap btree that
474 * this doesn't actually exist in the rmap btree.
468 */ 475 */
469 error = xfs_free_extent(tp, XFS_AGB_TO_FSB(mp, agno, 476 xfs_rmap_ag_owner(&oinfo, XFS_RMAP_OWN_NULL);
470 be32_to_cpu(agf->agf_length) - new), new); 477 error = xfs_free_extent(tp,
471 if (error) { 478 XFS_AGB_TO_FSB(mp, agno,
479 be32_to_cpu(agf->agf_length) - new),
480 new, &oinfo);
481 if (error)
472 goto error0; 482 goto error0;
473 }
474 } 483 }
475 484
476 /* 485 /*
diff --git a/fs/xfs/xfs_trans.h b/fs/xfs/xfs_trans.h
index a5fe1874f02f..9bc368bb5eb4 100644
--- a/fs/xfs/xfs_trans.h
+++ b/fs/xfs/xfs_trans.h
@@ -217,7 +217,7 @@ struct xfs_efd_log_item *xfs_trans_get_efd(struct xfs_trans *,
217 uint); 217 uint);
218int xfs_trans_free_extent(struct xfs_trans *, 218int xfs_trans_free_extent(struct xfs_trans *,
219 struct xfs_efd_log_item *, xfs_fsblock_t, 219 struct xfs_efd_log_item *, xfs_fsblock_t,
220 xfs_extlen_t); 220 xfs_extlen_t, struct xfs_owner_info *);
221int xfs_trans_commit(struct xfs_trans *); 221int xfs_trans_commit(struct xfs_trans *);
222int __xfs_trans_roll(struct xfs_trans **, struct xfs_inode *, int *); 222int __xfs_trans_roll(struct xfs_trans **, struct xfs_inode *, int *);
223int xfs_trans_roll(struct xfs_trans **, struct xfs_inode *); 223int xfs_trans_roll(struct xfs_trans **, struct xfs_inode *);
diff --git a/fs/xfs/xfs_trans_extfree.c b/fs/xfs/xfs_trans_extfree.c
index b48490290b27..3aca3a7578c2 100644
--- a/fs/xfs/xfs_trans_extfree.c
+++ b/fs/xfs/xfs_trans_extfree.c
@@ -120,13 +120,14 @@ xfs_trans_free_extent(
120 struct xfs_trans *tp, 120 struct xfs_trans *tp,
121 struct xfs_efd_log_item *efdp, 121 struct xfs_efd_log_item *efdp,
122 xfs_fsblock_t start_block, 122 xfs_fsblock_t start_block,
123 xfs_extlen_t ext_len) 123 xfs_extlen_t ext_len,
124 struct xfs_owner_info *oinfo)
124{ 125{
125 uint next_extent; 126 uint next_extent;
126 struct xfs_extent *extp; 127 struct xfs_extent *extp;
127 int error; 128 int error;
128 129
129 error = xfs_free_extent(tp, start_block, ext_len); 130 error = xfs_free_extent(tp, start_block, ext_len, oinfo);
130 131
131 /* 132 /*
132 * Mark the transaction dirty, even on error. This ensures the 133 * Mark the transaction dirty, even on error. This ensures the
@@ -213,7 +214,8 @@ xfs_extent_free_finish_item(
213 free = container_of(item, struct xfs_extent_free_item, xefi_list); 214 free = container_of(item, struct xfs_extent_free_item, xefi_list);
214 error = xfs_trans_free_extent(tp, done_item, 215 error = xfs_trans_free_extent(tp, done_item,
215 free->xefi_startblock, 216 free->xefi_startblock,
216 free->xefi_blockcount); 217 free->xefi_blockcount,
218 &free->xefi_oinfo);
217 kmem_free(free); 219 kmem_free(free);
218 return error; 220 return error;
219} 221}