]> git.ipfire.org Git - thirdparty/xfsprogs-dev.git/blame - libxfs/xfs_rmap_btree.c
xfs: define the on-disk rmap btree format
[thirdparty/xfsprogs-dev.git] / libxfs / xfs_rmap_btree.c
CommitLineData
b3a96b46
DW
1/*
2 * Copyright (c) 2014 Red Hat, Inc.
3 * All Rights Reserved.
4 *
5 * This program is free software; you can redistribute it and/or
6 * modify it under the terms of the GNU General Public License as
7 * published by the Free Software Foundation.
8 *
9 * This program is distributed in the hope that it would be useful,
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 * GNU General Public License for more details.
13 *
14 * You should have received a copy of the GNU General Public License
15 * along with this program; if not, write the Free Software Foundation,
16 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
17 */
18#include "libxfs_priv.h"
19#include "xfs_fs.h"
20#include "xfs_shared.h"
21#include "xfs_format.h"
22#include "xfs_log_format.h"
23#include "xfs_trans_resv.h"
24#include "xfs_bit.h"
25#include "xfs_sb.h"
26#include "xfs_mount.h"
27#include "xfs_defer.h"
28#include "xfs_inode.h"
29#include "xfs_trans.h"
30#include "xfs_alloc.h"
31#include "xfs_btree.h"
32#include "xfs_rmap_btree.h"
33#include "xfs_trace.h"
34#include "xfs_cksum.h"
35
36static struct xfs_btree_cur *
37xfs_rmapbt_dup_cursor(
38 struct xfs_btree_cur *cur)
39{
40 return xfs_rmapbt_init_cursor(cur->bc_mp, cur->bc_tp,
41 cur->bc_private.a.agbp, cur->bc_private.a.agno);
42}
43
44static bool
45xfs_rmapbt_verify(
46 struct xfs_buf *bp)
47{
48 struct xfs_mount *mp = bp->b_target->bt_mount;
49 struct xfs_btree_block *block = XFS_BUF_TO_BLOCK(bp);
50 struct xfs_perag *pag = bp->b_pag;
51 unsigned int level;
52
53 /*
54 * magic number and level verification
55 *
56 * During growfs operations, we can't verify the exact level or owner as
57 * the perag is not fully initialised and hence not attached to the
58 * buffer. In this case, check against the maximum tree depth.
59 *
60 * Similarly, during log recovery we will have a perag structure
61 * attached, but the agf information will not yet have been initialised
62 * from the on disk AGF. Again, we can only check against maximum limits
63 * in this case.
64 */
65 if (block->bb_magic != cpu_to_be32(XFS_RMAP_CRC_MAGIC))
66 return false;
67
68 if (!xfs_sb_version_hasrmapbt(&mp->m_sb))
69 return false;
70 if (!xfs_btree_sblock_v5hdr_verify(bp))
71 return false;
72
73 level = be16_to_cpu(block->bb_level);
74 if (pag && pag->pagf_init) {
75 if (level >= pag->pagf_levels[XFS_BTNUM_RMAPi])
76 return false;
77 } else if (level >= mp->m_rmap_maxlevels)
78 return false;
79
80 return xfs_btree_sblock_verify(bp, mp->m_rmap_mxr[level != 0]);
81}
82
83static void
84xfs_rmapbt_read_verify(
85 struct xfs_buf *bp)
86{
87 if (!xfs_btree_sblock_verify_crc(bp))
88 xfs_buf_ioerror(bp, -EFSBADCRC);
89 else if (!xfs_rmapbt_verify(bp))
90 xfs_buf_ioerror(bp, -EFSCORRUPTED);
91
92 if (bp->b_error) {
93 trace_xfs_btree_corrupt(bp, _RET_IP_);
94 xfs_verifier_error(bp);
95 }
96}
97
98static void
99xfs_rmapbt_write_verify(
100 struct xfs_buf *bp)
101{
102 if (!xfs_rmapbt_verify(bp)) {
103 trace_xfs_btree_corrupt(bp, _RET_IP_);
104 xfs_buf_ioerror(bp, -EFSCORRUPTED);
105 xfs_verifier_error(bp);
106 return;
107 }
108 xfs_btree_sblock_calc_crc(bp);
109
110}
111
112const struct xfs_buf_ops xfs_rmapbt_buf_ops = {
113 .name = "xfs_rmapbt",
114 .verify_read = xfs_rmapbt_read_verify,
115 .verify_write = xfs_rmapbt_write_verify,
116};
117
118static const struct xfs_btree_ops xfs_rmapbt_ops = {
119 .rec_len = sizeof(struct xfs_rmap_rec),
120 .key_len = 2 * sizeof(struct xfs_rmap_key),
121
122 .dup_cursor = xfs_rmapbt_dup_cursor,
123 .buf_ops = &xfs_rmapbt_buf_ops,
124
125 .get_leaf_keys = xfs_btree_get_leaf_keys_overlapped,
126 .get_node_keys = xfs_btree_get_node_keys_overlapped,
127 .update_keys = xfs_btree_update_keys_overlapped,
128};
129
130/*
131 * Allocate a new allocation btree cursor.
132 */
133struct xfs_btree_cur *
134xfs_rmapbt_init_cursor(
135 struct xfs_mount *mp,
136 struct xfs_trans *tp,
137 struct xfs_buf *agbp,
138 xfs_agnumber_t agno)
139{
140 struct xfs_agf *agf = XFS_BUF_TO_AGF(agbp);
141 struct xfs_btree_cur *cur;
142
143 cur = kmem_zone_zalloc(xfs_btree_cur_zone, KM_NOFS);
144 cur->bc_tp = tp;
145 cur->bc_mp = mp;
146 cur->bc_btnum = XFS_BTNUM_RMAP;
147 cur->bc_flags = XFS_BTREE_CRC_BLOCKS;
148 cur->bc_blocklog = mp->m_sb.sb_blocklog;
149 cur->bc_ops = &xfs_rmapbt_ops;
150 cur->bc_nlevels = be32_to_cpu(agf->agf_levels[XFS_BTNUM_RMAP]);
151
152 cur->bc_private.a.agbp = agbp;
153 cur->bc_private.a.agno = agno;
154
155 return cur;
156}
157
158/*
159 * Calculate number of records in an rmap btree block.
160 */
161int
162xfs_rmapbt_maxrecs(
163 struct xfs_mount *mp,
164 int blocklen,
165 int leaf)
166{
167 blocklen -= XFS_RMAP_BLOCK_LEN;
168
169 if (leaf)
170 return blocklen / sizeof(struct xfs_rmap_rec);
171 return blocklen /
172 (sizeof(struct xfs_rmap_key) + sizeof(xfs_rmap_ptr_t));
173}
174
175/* Compute the maximum height of an rmap btree. */
176void
177xfs_rmapbt_compute_maxlevels(
178 struct xfs_mount *mp)
179{
180 mp->m_rmap_maxlevels = xfs_btree_compute_maxlevels(mp,
181 mp->m_rmap_mnr, mp->m_sb.sb_agblocks);
182}