xfs: define the on-disk rmap btree format
[deliverable/linux.git] / fs / xfs / libxfs / xfs_rmap_btree.c
CommitLineData
035e00ac
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 "xfs.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#include "xfs_error.h"
36#include "xfs_extent_busy.h"
37
38static struct xfs_btree_cur *
39xfs_rmapbt_dup_cursor(
40 struct xfs_btree_cur *cur)
41{
42 return xfs_rmapbt_init_cursor(cur->bc_mp, cur->bc_tp,
43 cur->bc_private.a.agbp, cur->bc_private.a.agno);
44}
45
46static bool
47xfs_rmapbt_verify(
48 struct xfs_buf *bp)
49{
50 struct xfs_mount *mp = bp->b_target->bt_mount;
51 struct xfs_btree_block *block = XFS_BUF_TO_BLOCK(bp);
52 struct xfs_perag *pag = bp->b_pag;
53 unsigned int level;
54
55 /*
56 * magic number and level verification
57 *
58 * During growfs operations, we can't verify the exact level or owner as
59 * the perag is not fully initialised and hence not attached to the
60 * buffer. In this case, check against the maximum tree depth.
61 *
62 * Similarly, during log recovery we will have a perag structure
63 * attached, but the agf information will not yet have been initialised
64 * from the on disk AGF. Again, we can only check against maximum limits
65 * in this case.
66 */
67 if (block->bb_magic != cpu_to_be32(XFS_RMAP_CRC_MAGIC))
68 return false;
69
70 if (!xfs_sb_version_hasrmapbt(&mp->m_sb))
71 return false;
72 if (!xfs_btree_sblock_v5hdr_verify(bp))
73 return false;
74
75 level = be16_to_cpu(block->bb_level);
76 if (pag && pag->pagf_init) {
77 if (level >= pag->pagf_levels[XFS_BTNUM_RMAPi])
78 return false;
79 } else if (level >= mp->m_rmap_maxlevels)
80 return false;
81
82 return xfs_btree_sblock_verify(bp, mp->m_rmap_mxr[level != 0]);
83}
84
85static void
86xfs_rmapbt_read_verify(
87 struct xfs_buf *bp)
88{
89 if (!xfs_btree_sblock_verify_crc(bp))
90 xfs_buf_ioerror(bp, -EFSBADCRC);
91 else if (!xfs_rmapbt_verify(bp))
92 xfs_buf_ioerror(bp, -EFSCORRUPTED);
93
94 if (bp->b_error) {
95 trace_xfs_btree_corrupt(bp, _RET_IP_);
96 xfs_verifier_error(bp);
97 }
98}
99
100static void
101xfs_rmapbt_write_verify(
102 struct xfs_buf *bp)
103{
104 if (!xfs_rmapbt_verify(bp)) {
105 trace_xfs_btree_corrupt(bp, _RET_IP_);
106 xfs_buf_ioerror(bp, -EFSCORRUPTED);
107 xfs_verifier_error(bp);
108 return;
109 }
110 xfs_btree_sblock_calc_crc(bp);
111
112}
113
114const struct xfs_buf_ops xfs_rmapbt_buf_ops = {
115 .name = "xfs_rmapbt",
116 .verify_read = xfs_rmapbt_read_verify,
117 .verify_write = xfs_rmapbt_write_verify,
118};
119
120static const struct xfs_btree_ops xfs_rmapbt_ops = {
121 .rec_len = sizeof(struct xfs_rmap_rec),
122 .key_len = 2 * sizeof(struct xfs_rmap_key),
123
124 .dup_cursor = xfs_rmapbt_dup_cursor,
125 .buf_ops = &xfs_rmapbt_buf_ops,
126
127 .get_leaf_keys = xfs_btree_get_leaf_keys_overlapped,
128 .get_node_keys = xfs_btree_get_node_keys_overlapped,
129 .update_keys = xfs_btree_update_keys_overlapped,
130};
131
132/*
133 * Allocate a new allocation btree cursor.
134 */
135struct xfs_btree_cur *
136xfs_rmapbt_init_cursor(
137 struct xfs_mount *mp,
138 struct xfs_trans *tp,
139 struct xfs_buf *agbp,
140 xfs_agnumber_t agno)
141{
142 struct xfs_agf *agf = XFS_BUF_TO_AGF(agbp);
143 struct xfs_btree_cur *cur;
144
145 cur = kmem_zone_zalloc(xfs_btree_cur_zone, KM_NOFS);
146 cur->bc_tp = tp;
147 cur->bc_mp = mp;
148 cur->bc_btnum = XFS_BTNUM_RMAP;
149 cur->bc_flags = XFS_BTREE_CRC_BLOCKS;
150 cur->bc_blocklog = mp->m_sb.sb_blocklog;
151 cur->bc_ops = &xfs_rmapbt_ops;
152 cur->bc_nlevels = be32_to_cpu(agf->agf_levels[XFS_BTNUM_RMAP]);
153
154 cur->bc_private.a.agbp = agbp;
155 cur->bc_private.a.agno = agno;
156
157 return cur;
158}
159
160/*
161 * Calculate number of records in an rmap btree block.
162 */
163int
164xfs_rmapbt_maxrecs(
165 struct xfs_mount *mp,
166 int blocklen,
167 int leaf)
168{
169 blocklen -= XFS_RMAP_BLOCK_LEN;
170
171 if (leaf)
172 return blocklen / sizeof(struct xfs_rmap_rec);
173 return blocklen /
174 (sizeof(struct xfs_rmap_key) + sizeof(xfs_rmap_ptr_t));
175}
176
177/* Compute the maximum height of an rmap btree. */
178void
179xfs_rmapbt_compute_maxlevels(
180 struct xfs_mount *mp)
181{
182 mp->m_rmap_maxlevels = xfs_btree_compute_maxlevels(mp,
183 mp->m_rmap_mnr, mp->m_sb.sb_agblocks);
184}
This page took 0.030991 seconds and 5 git commands to generate.