Commit 687b890a184fef263ebb773926e1f4aa69240d01
Committed by
Lachlan McIlroy
1 parent
9eaead51be
Exists in
master
and in
20 other branches
[XFS] implement generic xfs_btree_lshift
Make the btree left shift code generic. Based on a patch from David Chinner with lots of changes to follow the original btree implementations more closely. While this loses some of the generic helper routines for inserting/moving/removing records it also solves some of the one off bugs in the original code and makes it easier to verify. SGI-PV: 985583 SGI-Modid: xfs-linux-melb:xfs-kern:32197a Signed-off-by: Christoph Hellwig <hch@infradead.org> Signed-off-by: Lachlan McIlroy <lachlan@sgi.com> Signed-off-by: Bill O'Donnell <billodo@sgi.com> Signed-off-by: David Chinner <david@fromorbit.com>
Showing 5 changed files with 192 additions and 425 deletions Inline Diff
fs/xfs/xfs_alloc_btree.c
1 | /* | 1 | /* |
2 | * Copyright (c) 2000-2001,2005 Silicon Graphics, Inc. | 2 | * Copyright (c) 2000-2001,2005 Silicon Graphics, Inc. |
3 | * All Rights Reserved. | 3 | * All Rights Reserved. |
4 | * | 4 | * |
5 | * This program is free software; you can redistribute it and/or | 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 | 6 | * modify it under the terms of the GNU General Public License as |
7 | * published by the Free Software Foundation. | 7 | * published by the Free Software Foundation. |
8 | * | 8 | * |
9 | * This program is distributed in the hope that it would be useful, | 9 | * This program is distributed in the hope that it would be useful, |
10 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | 10 | * but WITHOUT ANY WARRANTY; without even the implied warranty of |
11 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | 11 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
12 | * GNU General Public License for more details. | 12 | * GNU General Public License for more details. |
13 | * | 13 | * |
14 | * You should have received a copy of the GNU General Public License | 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, | 15 | * along with this program; if not, write the Free Software Foundation, |
16 | * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA | 16 | * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA |
17 | */ | 17 | */ |
18 | #include "xfs.h" | 18 | #include "xfs.h" |
19 | #include "xfs_fs.h" | 19 | #include "xfs_fs.h" |
20 | #include "xfs_types.h" | 20 | #include "xfs_types.h" |
21 | #include "xfs_bit.h" | 21 | #include "xfs_bit.h" |
22 | #include "xfs_log.h" | 22 | #include "xfs_log.h" |
23 | #include "xfs_inum.h" | 23 | #include "xfs_inum.h" |
24 | #include "xfs_trans.h" | 24 | #include "xfs_trans.h" |
25 | #include "xfs_sb.h" | 25 | #include "xfs_sb.h" |
26 | #include "xfs_ag.h" | 26 | #include "xfs_ag.h" |
27 | #include "xfs_dir2.h" | 27 | #include "xfs_dir2.h" |
28 | #include "xfs_dmapi.h" | 28 | #include "xfs_dmapi.h" |
29 | #include "xfs_mount.h" | 29 | #include "xfs_mount.h" |
30 | #include "xfs_bmap_btree.h" | 30 | #include "xfs_bmap_btree.h" |
31 | #include "xfs_alloc_btree.h" | 31 | #include "xfs_alloc_btree.h" |
32 | #include "xfs_ialloc_btree.h" | 32 | #include "xfs_ialloc_btree.h" |
33 | #include "xfs_dir2_sf.h" | 33 | #include "xfs_dir2_sf.h" |
34 | #include "xfs_attr_sf.h" | 34 | #include "xfs_attr_sf.h" |
35 | #include "xfs_dinode.h" | 35 | #include "xfs_dinode.h" |
36 | #include "xfs_inode.h" | 36 | #include "xfs_inode.h" |
37 | #include "xfs_btree.h" | 37 | #include "xfs_btree.h" |
38 | #include "xfs_ialloc.h" | 38 | #include "xfs_ialloc.h" |
39 | #include "xfs_alloc.h" | 39 | #include "xfs_alloc.h" |
40 | #include "xfs_error.h" | 40 | #include "xfs_error.h" |
41 | 41 | ||
42 | /* | 42 | /* |
43 | * Prototypes for internal functions. | 43 | * Prototypes for internal functions. |
44 | */ | 44 | */ |
45 | 45 | ||
46 | STATIC void xfs_alloc_log_block(xfs_trans_t *, xfs_buf_t *, int); | 46 | STATIC void xfs_alloc_log_block(xfs_trans_t *, xfs_buf_t *, int); |
47 | STATIC void xfs_alloc_log_keys(xfs_btree_cur_t *, xfs_buf_t *, int, int); | 47 | STATIC void xfs_alloc_log_keys(xfs_btree_cur_t *, xfs_buf_t *, int, int); |
48 | STATIC void xfs_alloc_log_ptrs(xfs_btree_cur_t *, xfs_buf_t *, int, int); | 48 | STATIC void xfs_alloc_log_ptrs(xfs_btree_cur_t *, xfs_buf_t *, int, int); |
49 | STATIC void xfs_alloc_log_recs(xfs_btree_cur_t *, xfs_buf_t *, int, int); | 49 | STATIC void xfs_alloc_log_recs(xfs_btree_cur_t *, xfs_buf_t *, int, int); |
50 | STATIC int xfs_alloc_lshift(xfs_btree_cur_t *, int, int *); | ||
51 | STATIC int xfs_alloc_newroot(xfs_btree_cur_t *, int *); | 50 | STATIC int xfs_alloc_newroot(xfs_btree_cur_t *, int *); |
52 | STATIC int xfs_alloc_split(xfs_btree_cur_t *, int, xfs_agblock_t *, | 51 | STATIC int xfs_alloc_split(xfs_btree_cur_t *, int, xfs_agblock_t *, |
53 | xfs_alloc_key_t *, xfs_btree_cur_t **, int *); | 52 | xfs_alloc_key_t *, xfs_btree_cur_t **, int *); |
54 | 53 | ||
55 | /* | 54 | /* |
56 | * Internal functions. | 55 | * Internal functions. |
57 | */ | 56 | */ |
58 | 57 | ||
59 | /* | 58 | /* |
60 | * Single level of the xfs_alloc_delete record deletion routine. | 59 | * Single level of the xfs_alloc_delete record deletion routine. |
61 | * Delete record pointed to by cur/level. | 60 | * Delete record pointed to by cur/level. |
62 | * Remove the record from its block then rebalance the tree. | 61 | * Remove the record from its block then rebalance the tree. |
63 | * Return 0 for error, 1 for done, 2 to go on to the next level. | 62 | * Return 0 for error, 1 for done, 2 to go on to the next level. |
64 | */ | 63 | */ |
65 | STATIC int /* error */ | 64 | STATIC int /* error */ |
66 | xfs_alloc_delrec( | 65 | xfs_alloc_delrec( |
67 | xfs_btree_cur_t *cur, /* btree cursor */ | 66 | xfs_btree_cur_t *cur, /* btree cursor */ |
68 | int level, /* level removing record from */ | 67 | int level, /* level removing record from */ |
69 | int *stat) /* fail/done/go-on */ | 68 | int *stat) /* fail/done/go-on */ |
70 | { | 69 | { |
71 | xfs_agf_t *agf; /* allocation group freelist header */ | 70 | xfs_agf_t *agf; /* allocation group freelist header */ |
72 | xfs_alloc_block_t *block; /* btree block record/key lives in */ | 71 | xfs_alloc_block_t *block; /* btree block record/key lives in */ |
73 | xfs_agblock_t bno; /* btree block number */ | 72 | xfs_agblock_t bno; /* btree block number */ |
74 | xfs_buf_t *bp; /* buffer for block */ | 73 | xfs_buf_t *bp; /* buffer for block */ |
75 | int error; /* error return value */ | 74 | int error; /* error return value */ |
76 | int i; /* loop index */ | 75 | int i; /* loop index */ |
77 | xfs_alloc_key_t key; /* kp points here if block is level 0 */ | 76 | xfs_alloc_key_t key; /* kp points here if block is level 0 */ |
78 | xfs_agblock_t lbno; /* left block's block number */ | 77 | xfs_agblock_t lbno; /* left block's block number */ |
79 | xfs_buf_t *lbp; /* left block's buffer pointer */ | 78 | xfs_buf_t *lbp; /* left block's buffer pointer */ |
80 | xfs_alloc_block_t *left; /* left btree block */ | 79 | xfs_alloc_block_t *left; /* left btree block */ |
81 | xfs_alloc_key_t *lkp=NULL; /* left block key pointer */ | 80 | xfs_alloc_key_t *lkp=NULL; /* left block key pointer */ |
82 | xfs_alloc_ptr_t *lpp=NULL; /* left block address pointer */ | 81 | xfs_alloc_ptr_t *lpp=NULL; /* left block address pointer */ |
83 | int lrecs=0; /* number of records in left block */ | 82 | int lrecs=0; /* number of records in left block */ |
84 | xfs_alloc_rec_t *lrp; /* left block record pointer */ | 83 | xfs_alloc_rec_t *lrp; /* left block record pointer */ |
85 | xfs_mount_t *mp; /* mount structure */ | 84 | xfs_mount_t *mp; /* mount structure */ |
86 | int ptr; /* index in btree block for this rec */ | 85 | int ptr; /* index in btree block for this rec */ |
87 | xfs_agblock_t rbno; /* right block's block number */ | 86 | xfs_agblock_t rbno; /* right block's block number */ |
88 | xfs_buf_t *rbp; /* right block's buffer pointer */ | 87 | xfs_buf_t *rbp; /* right block's buffer pointer */ |
89 | xfs_alloc_block_t *right; /* right btree block */ | 88 | xfs_alloc_block_t *right; /* right btree block */ |
90 | xfs_alloc_key_t *rkp; /* right block key pointer */ | 89 | xfs_alloc_key_t *rkp; /* right block key pointer */ |
91 | xfs_alloc_ptr_t *rpp; /* right block address pointer */ | 90 | xfs_alloc_ptr_t *rpp; /* right block address pointer */ |
92 | int rrecs=0; /* number of records in right block */ | 91 | int rrecs=0; /* number of records in right block */ |
93 | int numrecs; | 92 | int numrecs; |
94 | xfs_alloc_rec_t *rrp; /* right block record pointer */ | 93 | xfs_alloc_rec_t *rrp; /* right block record pointer */ |
95 | xfs_btree_cur_t *tcur; /* temporary btree cursor */ | 94 | xfs_btree_cur_t *tcur; /* temporary btree cursor */ |
96 | 95 | ||
97 | /* | 96 | /* |
98 | * Get the index of the entry being deleted, check for nothing there. | 97 | * Get the index of the entry being deleted, check for nothing there. |
99 | */ | 98 | */ |
100 | ptr = cur->bc_ptrs[level]; | 99 | ptr = cur->bc_ptrs[level]; |
101 | if (ptr == 0) { | 100 | if (ptr == 0) { |
102 | *stat = 0; | 101 | *stat = 0; |
103 | return 0; | 102 | return 0; |
104 | } | 103 | } |
105 | /* | 104 | /* |
106 | * Get the buffer & block containing the record or key/ptr. | 105 | * Get the buffer & block containing the record or key/ptr. |
107 | */ | 106 | */ |
108 | bp = cur->bc_bufs[level]; | 107 | bp = cur->bc_bufs[level]; |
109 | block = XFS_BUF_TO_ALLOC_BLOCK(bp); | 108 | block = XFS_BUF_TO_ALLOC_BLOCK(bp); |
110 | #ifdef DEBUG | 109 | #ifdef DEBUG |
111 | if ((error = xfs_btree_check_sblock(cur, block, level, bp))) | 110 | if ((error = xfs_btree_check_sblock(cur, block, level, bp))) |
112 | return error; | 111 | return error; |
113 | #endif | 112 | #endif |
114 | /* | 113 | /* |
115 | * Fail if we're off the end of the block. | 114 | * Fail if we're off the end of the block. |
116 | */ | 115 | */ |
117 | numrecs = be16_to_cpu(block->bb_numrecs); | 116 | numrecs = be16_to_cpu(block->bb_numrecs); |
118 | if (ptr > numrecs) { | 117 | if (ptr > numrecs) { |
119 | *stat = 0; | 118 | *stat = 0; |
120 | return 0; | 119 | return 0; |
121 | } | 120 | } |
122 | XFS_STATS_INC(xs_abt_delrec); | 121 | XFS_STATS_INC(xs_abt_delrec); |
123 | /* | 122 | /* |
124 | * It's a nonleaf. Excise the key and ptr being deleted, by | 123 | * It's a nonleaf. Excise the key and ptr being deleted, by |
125 | * sliding the entries past them down one. | 124 | * sliding the entries past them down one. |
126 | * Log the changed areas of the block. | 125 | * Log the changed areas of the block. |
127 | */ | 126 | */ |
128 | if (level > 0) { | 127 | if (level > 0) { |
129 | lkp = XFS_ALLOC_KEY_ADDR(block, 1, cur); | 128 | lkp = XFS_ALLOC_KEY_ADDR(block, 1, cur); |
130 | lpp = XFS_ALLOC_PTR_ADDR(block, 1, cur); | 129 | lpp = XFS_ALLOC_PTR_ADDR(block, 1, cur); |
131 | #ifdef DEBUG | 130 | #ifdef DEBUG |
132 | for (i = ptr; i < numrecs; i++) { | 131 | for (i = ptr; i < numrecs; i++) { |
133 | if ((error = xfs_btree_check_sptr(cur, be32_to_cpu(lpp[i]), level))) | 132 | if ((error = xfs_btree_check_sptr(cur, be32_to_cpu(lpp[i]), level))) |
134 | return error; | 133 | return error; |
135 | } | 134 | } |
136 | #endif | 135 | #endif |
137 | if (ptr < numrecs) { | 136 | if (ptr < numrecs) { |
138 | memmove(&lkp[ptr - 1], &lkp[ptr], | 137 | memmove(&lkp[ptr - 1], &lkp[ptr], |
139 | (numrecs - ptr) * sizeof(*lkp)); | 138 | (numrecs - ptr) * sizeof(*lkp)); |
140 | memmove(&lpp[ptr - 1], &lpp[ptr], | 139 | memmove(&lpp[ptr - 1], &lpp[ptr], |
141 | (numrecs - ptr) * sizeof(*lpp)); | 140 | (numrecs - ptr) * sizeof(*lpp)); |
142 | xfs_alloc_log_ptrs(cur, bp, ptr, numrecs - 1); | 141 | xfs_alloc_log_ptrs(cur, bp, ptr, numrecs - 1); |
143 | xfs_alloc_log_keys(cur, bp, ptr, numrecs - 1); | 142 | xfs_alloc_log_keys(cur, bp, ptr, numrecs - 1); |
144 | } | 143 | } |
145 | } | 144 | } |
146 | /* | 145 | /* |
147 | * It's a leaf. Excise the record being deleted, by sliding the | 146 | * It's a leaf. Excise the record being deleted, by sliding the |
148 | * entries past it down one. Log the changed areas of the block. | 147 | * entries past it down one. Log the changed areas of the block. |
149 | */ | 148 | */ |
150 | else { | 149 | else { |
151 | lrp = XFS_ALLOC_REC_ADDR(block, 1, cur); | 150 | lrp = XFS_ALLOC_REC_ADDR(block, 1, cur); |
152 | if (ptr < numrecs) { | 151 | if (ptr < numrecs) { |
153 | memmove(&lrp[ptr - 1], &lrp[ptr], | 152 | memmove(&lrp[ptr - 1], &lrp[ptr], |
154 | (numrecs - ptr) * sizeof(*lrp)); | 153 | (numrecs - ptr) * sizeof(*lrp)); |
155 | xfs_alloc_log_recs(cur, bp, ptr, numrecs - 1); | 154 | xfs_alloc_log_recs(cur, bp, ptr, numrecs - 1); |
156 | } | 155 | } |
157 | /* | 156 | /* |
158 | * If it's the first record in the block, we'll need a key | 157 | * If it's the first record in the block, we'll need a key |
159 | * structure to pass up to the next level (updkey). | 158 | * structure to pass up to the next level (updkey). |
160 | */ | 159 | */ |
161 | if (ptr == 1) { | 160 | if (ptr == 1) { |
162 | key.ar_startblock = lrp->ar_startblock; | 161 | key.ar_startblock = lrp->ar_startblock; |
163 | key.ar_blockcount = lrp->ar_blockcount; | 162 | key.ar_blockcount = lrp->ar_blockcount; |
164 | lkp = &key; | 163 | lkp = &key; |
165 | } | 164 | } |
166 | } | 165 | } |
167 | /* | 166 | /* |
168 | * Decrement and log the number of entries in the block. | 167 | * Decrement and log the number of entries in the block. |
169 | */ | 168 | */ |
170 | numrecs--; | 169 | numrecs--; |
171 | block->bb_numrecs = cpu_to_be16(numrecs); | 170 | block->bb_numrecs = cpu_to_be16(numrecs); |
172 | xfs_alloc_log_block(cur->bc_tp, bp, XFS_BB_NUMRECS); | 171 | xfs_alloc_log_block(cur->bc_tp, bp, XFS_BB_NUMRECS); |
173 | /* | 172 | /* |
174 | * See if the longest free extent in the allocation group was | 173 | * See if the longest free extent in the allocation group was |
175 | * changed by this operation. True if it's the by-size btree, and | 174 | * changed by this operation. True if it's the by-size btree, and |
176 | * this is the leaf level, and there is no right sibling block, | 175 | * this is the leaf level, and there is no right sibling block, |
177 | * and this was the last record. | 176 | * and this was the last record. |
178 | */ | 177 | */ |
179 | agf = XFS_BUF_TO_AGF(cur->bc_private.a.agbp); | 178 | agf = XFS_BUF_TO_AGF(cur->bc_private.a.agbp); |
180 | mp = cur->bc_mp; | 179 | mp = cur->bc_mp; |
181 | 180 | ||
182 | if (level == 0 && | 181 | if (level == 0 && |
183 | cur->bc_btnum == XFS_BTNUM_CNT && | 182 | cur->bc_btnum == XFS_BTNUM_CNT && |
184 | be32_to_cpu(block->bb_rightsib) == NULLAGBLOCK && | 183 | be32_to_cpu(block->bb_rightsib) == NULLAGBLOCK && |
185 | ptr > numrecs) { | 184 | ptr > numrecs) { |
186 | ASSERT(ptr == numrecs + 1); | 185 | ASSERT(ptr == numrecs + 1); |
187 | /* | 186 | /* |
188 | * There are still records in the block. Grab the size | 187 | * There are still records in the block. Grab the size |
189 | * from the last one. | 188 | * from the last one. |
190 | */ | 189 | */ |
191 | if (numrecs) { | 190 | if (numrecs) { |
192 | rrp = XFS_ALLOC_REC_ADDR(block, numrecs, cur); | 191 | rrp = XFS_ALLOC_REC_ADDR(block, numrecs, cur); |
193 | agf->agf_longest = rrp->ar_blockcount; | 192 | agf->agf_longest = rrp->ar_blockcount; |
194 | } | 193 | } |
195 | /* | 194 | /* |
196 | * No free extents left. | 195 | * No free extents left. |
197 | */ | 196 | */ |
198 | else | 197 | else |
199 | agf->agf_longest = 0; | 198 | agf->agf_longest = 0; |
200 | mp->m_perag[be32_to_cpu(agf->agf_seqno)].pagf_longest = | 199 | mp->m_perag[be32_to_cpu(agf->agf_seqno)].pagf_longest = |
201 | be32_to_cpu(agf->agf_longest); | 200 | be32_to_cpu(agf->agf_longest); |
202 | xfs_alloc_log_agf(cur->bc_tp, cur->bc_private.a.agbp, | 201 | xfs_alloc_log_agf(cur->bc_tp, cur->bc_private.a.agbp, |
203 | XFS_AGF_LONGEST); | 202 | XFS_AGF_LONGEST); |
204 | } | 203 | } |
205 | /* | 204 | /* |
206 | * Is this the root level? If so, we're almost done. | 205 | * Is this the root level? If so, we're almost done. |
207 | */ | 206 | */ |
208 | if (level == cur->bc_nlevels - 1) { | 207 | if (level == cur->bc_nlevels - 1) { |
209 | /* | 208 | /* |
210 | * If this is the root level, | 209 | * If this is the root level, |
211 | * and there's only one entry left, | 210 | * and there's only one entry left, |
212 | * and it's NOT the leaf level, | 211 | * and it's NOT the leaf level, |
213 | * then we can get rid of this level. | 212 | * then we can get rid of this level. |
214 | */ | 213 | */ |
215 | if (numrecs == 1 && level > 0) { | 214 | if (numrecs == 1 && level > 0) { |
216 | /* | 215 | /* |
217 | * lpp is still set to the first pointer in the block. | 216 | * lpp is still set to the first pointer in the block. |
218 | * Make it the new root of the btree. | 217 | * Make it the new root of the btree. |
219 | */ | 218 | */ |
220 | bno = be32_to_cpu(agf->agf_roots[cur->bc_btnum]); | 219 | bno = be32_to_cpu(agf->agf_roots[cur->bc_btnum]); |
221 | agf->agf_roots[cur->bc_btnum] = *lpp; | 220 | agf->agf_roots[cur->bc_btnum] = *lpp; |
222 | be32_add_cpu(&agf->agf_levels[cur->bc_btnum], -1); | 221 | be32_add_cpu(&agf->agf_levels[cur->bc_btnum], -1); |
223 | mp->m_perag[be32_to_cpu(agf->agf_seqno)].pagf_levels[cur->bc_btnum]--; | 222 | mp->m_perag[be32_to_cpu(agf->agf_seqno)].pagf_levels[cur->bc_btnum]--; |
224 | /* | 223 | /* |
225 | * Put this buffer/block on the ag's freelist. | 224 | * Put this buffer/block on the ag's freelist. |
226 | */ | 225 | */ |
227 | error = xfs_alloc_put_freelist(cur->bc_tp, | 226 | error = xfs_alloc_put_freelist(cur->bc_tp, |
228 | cur->bc_private.a.agbp, NULL, bno, 1); | 227 | cur->bc_private.a.agbp, NULL, bno, 1); |
229 | if (error) | 228 | if (error) |
230 | return error; | 229 | return error; |
231 | /* | 230 | /* |
232 | * Since blocks move to the free list without the | 231 | * Since blocks move to the free list without the |
233 | * coordination used in xfs_bmap_finish, we can't allow | 232 | * coordination used in xfs_bmap_finish, we can't allow |
234 | * block to be available for reallocation and | 233 | * block to be available for reallocation and |
235 | * non-transaction writing (user data) until we know | 234 | * non-transaction writing (user data) until we know |
236 | * that the transaction that moved it to the free list | 235 | * that the transaction that moved it to the free list |
237 | * is permanently on disk. We track the blocks by | 236 | * is permanently on disk. We track the blocks by |
238 | * declaring these blocks as "busy"; the busy list is | 237 | * declaring these blocks as "busy"; the busy list is |
239 | * maintained on a per-ag basis and each transaction | 238 | * maintained on a per-ag basis and each transaction |
240 | * records which entries should be removed when the | 239 | * records which entries should be removed when the |
241 | * iclog commits to disk. If a busy block is | 240 | * iclog commits to disk. If a busy block is |
242 | * allocated, the iclog is pushed up to the LSN | 241 | * allocated, the iclog is pushed up to the LSN |
243 | * that freed the block. | 242 | * that freed the block. |
244 | */ | 243 | */ |
245 | xfs_alloc_mark_busy(cur->bc_tp, | 244 | xfs_alloc_mark_busy(cur->bc_tp, |
246 | be32_to_cpu(agf->agf_seqno), bno, 1); | 245 | be32_to_cpu(agf->agf_seqno), bno, 1); |
247 | 246 | ||
248 | xfs_trans_agbtree_delta(cur->bc_tp, -1); | 247 | xfs_trans_agbtree_delta(cur->bc_tp, -1); |
249 | xfs_alloc_log_agf(cur->bc_tp, cur->bc_private.a.agbp, | 248 | xfs_alloc_log_agf(cur->bc_tp, cur->bc_private.a.agbp, |
250 | XFS_AGF_ROOTS | XFS_AGF_LEVELS); | 249 | XFS_AGF_ROOTS | XFS_AGF_LEVELS); |
251 | /* | 250 | /* |
252 | * Update the cursor so there's one fewer level. | 251 | * Update the cursor so there's one fewer level. |
253 | */ | 252 | */ |
254 | xfs_btree_setbuf(cur, level, NULL); | 253 | xfs_btree_setbuf(cur, level, NULL); |
255 | cur->bc_nlevels--; | 254 | cur->bc_nlevels--; |
256 | } else if (level > 0 && | 255 | } else if (level > 0 && |
257 | (error = xfs_btree_decrement(cur, level, &i))) | 256 | (error = xfs_btree_decrement(cur, level, &i))) |
258 | return error; | 257 | return error; |
259 | *stat = 1; | 258 | *stat = 1; |
260 | return 0; | 259 | return 0; |
261 | } | 260 | } |
262 | /* | 261 | /* |
263 | * If we deleted the leftmost entry in the block, update the | 262 | * If we deleted the leftmost entry in the block, update the |
264 | * key values above us in the tree. | 263 | * key values above us in the tree. |
265 | */ | 264 | */ |
266 | if (ptr == 1 && (error = xfs_btree_updkey(cur, (union xfs_btree_key *)lkp, level + 1))) | 265 | if (ptr == 1 && (error = xfs_btree_updkey(cur, (union xfs_btree_key *)lkp, level + 1))) |
267 | return error; | 266 | return error; |
268 | /* | 267 | /* |
269 | * If the number of records remaining in the block is at least | 268 | * If the number of records remaining in the block is at least |
270 | * the minimum, we're done. | 269 | * the minimum, we're done. |
271 | */ | 270 | */ |
272 | if (numrecs >= XFS_ALLOC_BLOCK_MINRECS(level, cur)) { | 271 | if (numrecs >= XFS_ALLOC_BLOCK_MINRECS(level, cur)) { |
273 | if (level > 0 && (error = xfs_btree_decrement(cur, level, &i))) | 272 | if (level > 0 && (error = xfs_btree_decrement(cur, level, &i))) |
274 | return error; | 273 | return error; |
275 | *stat = 1; | 274 | *stat = 1; |
276 | return 0; | 275 | return 0; |
277 | } | 276 | } |
278 | /* | 277 | /* |
279 | * Otherwise, we have to move some records around to keep the | 278 | * Otherwise, we have to move some records around to keep the |
280 | * tree balanced. Look at the left and right sibling blocks to | 279 | * tree balanced. Look at the left and right sibling blocks to |
281 | * see if we can re-balance by moving only one record. | 280 | * see if we can re-balance by moving only one record. |
282 | */ | 281 | */ |
283 | rbno = be32_to_cpu(block->bb_rightsib); | 282 | rbno = be32_to_cpu(block->bb_rightsib); |
284 | lbno = be32_to_cpu(block->bb_leftsib); | 283 | lbno = be32_to_cpu(block->bb_leftsib); |
285 | bno = NULLAGBLOCK; | 284 | bno = NULLAGBLOCK; |
286 | ASSERT(rbno != NULLAGBLOCK || lbno != NULLAGBLOCK); | 285 | ASSERT(rbno != NULLAGBLOCK || lbno != NULLAGBLOCK); |
287 | /* | 286 | /* |
288 | * Duplicate the cursor so our btree manipulations here won't | 287 | * Duplicate the cursor so our btree manipulations here won't |
289 | * disrupt the next level up. | 288 | * disrupt the next level up. |
290 | */ | 289 | */ |
291 | if ((error = xfs_btree_dup_cursor(cur, &tcur))) | 290 | if ((error = xfs_btree_dup_cursor(cur, &tcur))) |
292 | return error; | 291 | return error; |
293 | /* | 292 | /* |
294 | * If there's a right sibling, see if it's ok to shift an entry | 293 | * If there's a right sibling, see if it's ok to shift an entry |
295 | * out of it. | 294 | * out of it. |
296 | */ | 295 | */ |
297 | if (rbno != NULLAGBLOCK) { | 296 | if (rbno != NULLAGBLOCK) { |
298 | /* | 297 | /* |
299 | * Move the temp cursor to the last entry in the next block. | 298 | * Move the temp cursor to the last entry in the next block. |
300 | * Actually any entry but the first would suffice. | 299 | * Actually any entry but the first would suffice. |
301 | */ | 300 | */ |
302 | i = xfs_btree_lastrec(tcur, level); | 301 | i = xfs_btree_lastrec(tcur, level); |
303 | XFS_WANT_CORRUPTED_GOTO(i == 1, error0); | 302 | XFS_WANT_CORRUPTED_GOTO(i == 1, error0); |
304 | if ((error = xfs_btree_increment(tcur, level, &i))) | 303 | if ((error = xfs_btree_increment(tcur, level, &i))) |
305 | goto error0; | 304 | goto error0; |
306 | XFS_WANT_CORRUPTED_GOTO(i == 1, error0); | 305 | XFS_WANT_CORRUPTED_GOTO(i == 1, error0); |
307 | i = xfs_btree_lastrec(tcur, level); | 306 | i = xfs_btree_lastrec(tcur, level); |
308 | XFS_WANT_CORRUPTED_GOTO(i == 1, error0); | 307 | XFS_WANT_CORRUPTED_GOTO(i == 1, error0); |
309 | /* | 308 | /* |
310 | * Grab a pointer to the block. | 309 | * Grab a pointer to the block. |
311 | */ | 310 | */ |
312 | rbp = tcur->bc_bufs[level]; | 311 | rbp = tcur->bc_bufs[level]; |
313 | right = XFS_BUF_TO_ALLOC_BLOCK(rbp); | 312 | right = XFS_BUF_TO_ALLOC_BLOCK(rbp); |
314 | #ifdef DEBUG | 313 | #ifdef DEBUG |
315 | if ((error = xfs_btree_check_sblock(cur, right, level, rbp))) | 314 | if ((error = xfs_btree_check_sblock(cur, right, level, rbp))) |
316 | goto error0; | 315 | goto error0; |
317 | #endif | 316 | #endif |
318 | /* | 317 | /* |
319 | * Grab the current block number, for future use. | 318 | * Grab the current block number, for future use. |
320 | */ | 319 | */ |
321 | bno = be32_to_cpu(right->bb_leftsib); | 320 | bno = be32_to_cpu(right->bb_leftsib); |
322 | /* | 321 | /* |
323 | * If right block is full enough so that removing one entry | 322 | * If right block is full enough so that removing one entry |
324 | * won't make it too empty, and left-shifting an entry out | 323 | * won't make it too empty, and left-shifting an entry out |
325 | * of right to us works, we're done. | 324 | * of right to us works, we're done. |
326 | */ | 325 | */ |
327 | if (be16_to_cpu(right->bb_numrecs) - 1 >= | 326 | if (be16_to_cpu(right->bb_numrecs) - 1 >= |
328 | XFS_ALLOC_BLOCK_MINRECS(level, cur)) { | 327 | XFS_ALLOC_BLOCK_MINRECS(level, cur)) { |
329 | if ((error = xfs_alloc_lshift(tcur, level, &i))) | 328 | if ((error = xfs_btree_lshift(tcur, level, &i))) |
330 | goto error0; | 329 | goto error0; |
331 | if (i) { | 330 | if (i) { |
332 | ASSERT(be16_to_cpu(block->bb_numrecs) >= | 331 | ASSERT(be16_to_cpu(block->bb_numrecs) >= |
333 | XFS_ALLOC_BLOCK_MINRECS(level, cur)); | 332 | XFS_ALLOC_BLOCK_MINRECS(level, cur)); |
334 | xfs_btree_del_cursor(tcur, | 333 | xfs_btree_del_cursor(tcur, |
335 | XFS_BTREE_NOERROR); | 334 | XFS_BTREE_NOERROR); |
336 | if (level > 0 && | 335 | if (level > 0 && |
337 | (error = xfs_btree_decrement(cur, level, | 336 | (error = xfs_btree_decrement(cur, level, |
338 | &i))) | 337 | &i))) |
339 | return error; | 338 | return error; |
340 | *stat = 1; | 339 | *stat = 1; |
341 | return 0; | 340 | return 0; |
342 | } | 341 | } |
343 | } | 342 | } |
344 | /* | 343 | /* |
345 | * Otherwise, grab the number of records in right for | 344 | * Otherwise, grab the number of records in right for |
346 | * future reference, and fix up the temp cursor to point | 345 | * future reference, and fix up the temp cursor to point |
347 | * to our block again (last record). | 346 | * to our block again (last record). |
348 | */ | 347 | */ |
349 | rrecs = be16_to_cpu(right->bb_numrecs); | 348 | rrecs = be16_to_cpu(right->bb_numrecs); |
350 | if (lbno != NULLAGBLOCK) { | 349 | if (lbno != NULLAGBLOCK) { |
351 | i = xfs_btree_firstrec(tcur, level); | 350 | i = xfs_btree_firstrec(tcur, level); |
352 | XFS_WANT_CORRUPTED_GOTO(i == 1, error0); | 351 | XFS_WANT_CORRUPTED_GOTO(i == 1, error0); |
353 | if ((error = xfs_btree_decrement(tcur, level, &i))) | 352 | if ((error = xfs_btree_decrement(tcur, level, &i))) |
354 | goto error0; | 353 | goto error0; |
355 | XFS_WANT_CORRUPTED_GOTO(i == 1, error0); | 354 | XFS_WANT_CORRUPTED_GOTO(i == 1, error0); |
356 | } | 355 | } |
357 | } | 356 | } |
358 | /* | 357 | /* |
359 | * If there's a left sibling, see if it's ok to shift an entry | 358 | * If there's a left sibling, see if it's ok to shift an entry |
360 | * out of it. | 359 | * out of it. |
361 | */ | 360 | */ |
362 | if (lbno != NULLAGBLOCK) { | 361 | if (lbno != NULLAGBLOCK) { |
363 | /* | 362 | /* |
364 | * Move the temp cursor to the first entry in the | 363 | * Move the temp cursor to the first entry in the |
365 | * previous block. | 364 | * previous block. |
366 | */ | 365 | */ |
367 | i = xfs_btree_firstrec(tcur, level); | 366 | i = xfs_btree_firstrec(tcur, level); |
368 | XFS_WANT_CORRUPTED_GOTO(i == 1, error0); | 367 | XFS_WANT_CORRUPTED_GOTO(i == 1, error0); |
369 | if ((error = xfs_btree_decrement(tcur, level, &i))) | 368 | if ((error = xfs_btree_decrement(tcur, level, &i))) |
370 | goto error0; | 369 | goto error0; |
371 | XFS_WANT_CORRUPTED_GOTO(i == 1, error0); | 370 | XFS_WANT_CORRUPTED_GOTO(i == 1, error0); |
372 | xfs_btree_firstrec(tcur, level); | 371 | xfs_btree_firstrec(tcur, level); |
373 | /* | 372 | /* |
374 | * Grab a pointer to the block. | 373 | * Grab a pointer to the block. |
375 | */ | 374 | */ |
376 | lbp = tcur->bc_bufs[level]; | 375 | lbp = tcur->bc_bufs[level]; |
377 | left = XFS_BUF_TO_ALLOC_BLOCK(lbp); | 376 | left = XFS_BUF_TO_ALLOC_BLOCK(lbp); |
378 | #ifdef DEBUG | 377 | #ifdef DEBUG |
379 | if ((error = xfs_btree_check_sblock(cur, left, level, lbp))) | 378 | if ((error = xfs_btree_check_sblock(cur, left, level, lbp))) |
380 | goto error0; | 379 | goto error0; |
381 | #endif | 380 | #endif |
382 | /* | 381 | /* |
383 | * Grab the current block number, for future use. | 382 | * Grab the current block number, for future use. |
384 | */ | 383 | */ |
385 | bno = be32_to_cpu(left->bb_rightsib); | 384 | bno = be32_to_cpu(left->bb_rightsib); |
386 | /* | 385 | /* |
387 | * If left block is full enough so that removing one entry | 386 | * If left block is full enough so that removing one entry |
388 | * won't make it too empty, and right-shifting an entry out | 387 | * won't make it too empty, and right-shifting an entry out |
389 | * of left to us works, we're done. | 388 | * of left to us works, we're done. |
390 | */ | 389 | */ |
391 | if (be16_to_cpu(left->bb_numrecs) - 1 >= | 390 | if (be16_to_cpu(left->bb_numrecs) - 1 >= |
392 | XFS_ALLOC_BLOCK_MINRECS(level, cur)) { | 391 | XFS_ALLOC_BLOCK_MINRECS(level, cur)) { |
393 | if ((error = xfs_btree_rshift(tcur, level, &i))) | 392 | if ((error = xfs_btree_rshift(tcur, level, &i))) |
394 | goto error0; | 393 | goto error0; |
395 | if (i) { | 394 | if (i) { |
396 | ASSERT(be16_to_cpu(block->bb_numrecs) >= | 395 | ASSERT(be16_to_cpu(block->bb_numrecs) >= |
397 | XFS_ALLOC_BLOCK_MINRECS(level, cur)); | 396 | XFS_ALLOC_BLOCK_MINRECS(level, cur)); |
398 | xfs_btree_del_cursor(tcur, | 397 | xfs_btree_del_cursor(tcur, |
399 | XFS_BTREE_NOERROR); | 398 | XFS_BTREE_NOERROR); |
400 | if (level == 0) | 399 | if (level == 0) |
401 | cur->bc_ptrs[0]++; | 400 | cur->bc_ptrs[0]++; |
402 | *stat = 1; | 401 | *stat = 1; |
403 | return 0; | 402 | return 0; |
404 | } | 403 | } |
405 | } | 404 | } |
406 | /* | 405 | /* |
407 | * Otherwise, grab the number of records in right for | 406 | * Otherwise, grab the number of records in right for |
408 | * future reference. | 407 | * future reference. |
409 | */ | 408 | */ |
410 | lrecs = be16_to_cpu(left->bb_numrecs); | 409 | lrecs = be16_to_cpu(left->bb_numrecs); |
411 | } | 410 | } |
412 | /* | 411 | /* |
413 | * Delete the temp cursor, we're done with it. | 412 | * Delete the temp cursor, we're done with it. |
414 | */ | 413 | */ |
415 | xfs_btree_del_cursor(tcur, XFS_BTREE_NOERROR); | 414 | xfs_btree_del_cursor(tcur, XFS_BTREE_NOERROR); |
416 | /* | 415 | /* |
417 | * If here, we need to do a join to keep the tree balanced. | 416 | * If here, we need to do a join to keep the tree balanced. |
418 | */ | 417 | */ |
419 | ASSERT(bno != NULLAGBLOCK); | 418 | ASSERT(bno != NULLAGBLOCK); |
420 | /* | 419 | /* |
421 | * See if we can join with the left neighbor block. | 420 | * See if we can join with the left neighbor block. |
422 | */ | 421 | */ |
423 | if (lbno != NULLAGBLOCK && | 422 | if (lbno != NULLAGBLOCK && |
424 | lrecs + numrecs <= XFS_ALLOC_BLOCK_MAXRECS(level, cur)) { | 423 | lrecs + numrecs <= XFS_ALLOC_BLOCK_MAXRECS(level, cur)) { |
425 | /* | 424 | /* |
426 | * Set "right" to be the starting block, | 425 | * Set "right" to be the starting block, |
427 | * "left" to be the left neighbor. | 426 | * "left" to be the left neighbor. |
428 | */ | 427 | */ |
429 | rbno = bno; | 428 | rbno = bno; |
430 | right = block; | 429 | right = block; |
431 | rrecs = be16_to_cpu(right->bb_numrecs); | 430 | rrecs = be16_to_cpu(right->bb_numrecs); |
432 | rbp = bp; | 431 | rbp = bp; |
433 | if ((error = xfs_btree_read_bufs(mp, cur->bc_tp, | 432 | if ((error = xfs_btree_read_bufs(mp, cur->bc_tp, |
434 | cur->bc_private.a.agno, lbno, 0, &lbp, | 433 | cur->bc_private.a.agno, lbno, 0, &lbp, |
435 | XFS_ALLOC_BTREE_REF))) | 434 | XFS_ALLOC_BTREE_REF))) |
436 | return error; | 435 | return error; |
437 | left = XFS_BUF_TO_ALLOC_BLOCK(lbp); | 436 | left = XFS_BUF_TO_ALLOC_BLOCK(lbp); |
438 | lrecs = be16_to_cpu(left->bb_numrecs); | 437 | lrecs = be16_to_cpu(left->bb_numrecs); |
439 | if ((error = xfs_btree_check_sblock(cur, left, level, lbp))) | 438 | if ((error = xfs_btree_check_sblock(cur, left, level, lbp))) |
440 | return error; | 439 | return error; |
441 | } | 440 | } |
442 | /* | 441 | /* |
443 | * If that won't work, see if we can join with the right neighbor block. | 442 | * If that won't work, see if we can join with the right neighbor block. |
444 | */ | 443 | */ |
445 | else if (rbno != NULLAGBLOCK && | 444 | else if (rbno != NULLAGBLOCK && |
446 | rrecs + numrecs <= XFS_ALLOC_BLOCK_MAXRECS(level, cur)) { | 445 | rrecs + numrecs <= XFS_ALLOC_BLOCK_MAXRECS(level, cur)) { |
447 | /* | 446 | /* |
448 | * Set "left" to be the starting block, | 447 | * Set "left" to be the starting block, |
449 | * "right" to be the right neighbor. | 448 | * "right" to be the right neighbor. |
450 | */ | 449 | */ |
451 | lbno = bno; | 450 | lbno = bno; |
452 | left = block; | 451 | left = block; |
453 | lrecs = be16_to_cpu(left->bb_numrecs); | 452 | lrecs = be16_to_cpu(left->bb_numrecs); |
454 | lbp = bp; | 453 | lbp = bp; |
455 | if ((error = xfs_btree_read_bufs(mp, cur->bc_tp, | 454 | if ((error = xfs_btree_read_bufs(mp, cur->bc_tp, |
456 | cur->bc_private.a.agno, rbno, 0, &rbp, | 455 | cur->bc_private.a.agno, rbno, 0, &rbp, |
457 | XFS_ALLOC_BTREE_REF))) | 456 | XFS_ALLOC_BTREE_REF))) |
458 | return error; | 457 | return error; |
459 | right = XFS_BUF_TO_ALLOC_BLOCK(rbp); | 458 | right = XFS_BUF_TO_ALLOC_BLOCK(rbp); |
460 | rrecs = be16_to_cpu(right->bb_numrecs); | 459 | rrecs = be16_to_cpu(right->bb_numrecs); |
461 | if ((error = xfs_btree_check_sblock(cur, right, level, rbp))) | 460 | if ((error = xfs_btree_check_sblock(cur, right, level, rbp))) |
462 | return error; | 461 | return error; |
463 | } | 462 | } |
464 | /* | 463 | /* |
465 | * Otherwise, we can't fix the imbalance. | 464 | * Otherwise, we can't fix the imbalance. |
466 | * Just return. This is probably a logic error, but it's not fatal. | 465 | * Just return. This is probably a logic error, but it's not fatal. |
467 | */ | 466 | */ |
468 | else { | 467 | else { |
469 | if (level > 0 && (error = xfs_btree_decrement(cur, level, &i))) | 468 | if (level > 0 && (error = xfs_btree_decrement(cur, level, &i))) |
470 | return error; | 469 | return error; |
471 | *stat = 1; | 470 | *stat = 1; |
472 | return 0; | 471 | return 0; |
473 | } | 472 | } |
474 | /* | 473 | /* |
475 | * We're now going to join "left" and "right" by moving all the stuff | 474 | * We're now going to join "left" and "right" by moving all the stuff |
476 | * in "right" to "left" and deleting "right". | 475 | * in "right" to "left" and deleting "right". |
477 | */ | 476 | */ |
478 | if (level > 0) { | 477 | if (level > 0) { |
479 | /* | 478 | /* |
480 | * It's a non-leaf. Move keys and pointers. | 479 | * It's a non-leaf. Move keys and pointers. |
481 | */ | 480 | */ |
482 | lkp = XFS_ALLOC_KEY_ADDR(left, lrecs + 1, cur); | 481 | lkp = XFS_ALLOC_KEY_ADDR(left, lrecs + 1, cur); |
483 | lpp = XFS_ALLOC_PTR_ADDR(left, lrecs + 1, cur); | 482 | lpp = XFS_ALLOC_PTR_ADDR(left, lrecs + 1, cur); |
484 | rkp = XFS_ALLOC_KEY_ADDR(right, 1, cur); | 483 | rkp = XFS_ALLOC_KEY_ADDR(right, 1, cur); |
485 | rpp = XFS_ALLOC_PTR_ADDR(right, 1, cur); | 484 | rpp = XFS_ALLOC_PTR_ADDR(right, 1, cur); |
486 | #ifdef DEBUG | 485 | #ifdef DEBUG |
487 | for (i = 0; i < rrecs; i++) { | 486 | for (i = 0; i < rrecs; i++) { |
488 | if ((error = xfs_btree_check_sptr(cur, be32_to_cpu(rpp[i]), level))) | 487 | if ((error = xfs_btree_check_sptr(cur, be32_to_cpu(rpp[i]), level))) |
489 | return error; | 488 | return error; |
490 | } | 489 | } |
491 | #endif | 490 | #endif |
492 | memcpy(lkp, rkp, rrecs * sizeof(*lkp)); | 491 | memcpy(lkp, rkp, rrecs * sizeof(*lkp)); |
493 | memcpy(lpp, rpp, rrecs * sizeof(*lpp)); | 492 | memcpy(lpp, rpp, rrecs * sizeof(*lpp)); |
494 | xfs_alloc_log_keys(cur, lbp, lrecs + 1, lrecs + rrecs); | 493 | xfs_alloc_log_keys(cur, lbp, lrecs + 1, lrecs + rrecs); |
495 | xfs_alloc_log_ptrs(cur, lbp, lrecs + 1, lrecs + rrecs); | 494 | xfs_alloc_log_ptrs(cur, lbp, lrecs + 1, lrecs + rrecs); |
496 | } else { | 495 | } else { |
497 | /* | 496 | /* |
498 | * It's a leaf. Move records. | 497 | * It's a leaf. Move records. |
499 | */ | 498 | */ |
500 | lrp = XFS_ALLOC_REC_ADDR(left, lrecs + 1, cur); | 499 | lrp = XFS_ALLOC_REC_ADDR(left, lrecs + 1, cur); |
501 | rrp = XFS_ALLOC_REC_ADDR(right, 1, cur); | 500 | rrp = XFS_ALLOC_REC_ADDR(right, 1, cur); |
502 | memcpy(lrp, rrp, rrecs * sizeof(*lrp)); | 501 | memcpy(lrp, rrp, rrecs * sizeof(*lrp)); |
503 | xfs_alloc_log_recs(cur, lbp, lrecs + 1, lrecs + rrecs); | 502 | xfs_alloc_log_recs(cur, lbp, lrecs + 1, lrecs + rrecs); |
504 | } | 503 | } |
505 | /* | 504 | /* |
506 | * If we joined with the left neighbor, set the buffer in the | 505 | * If we joined with the left neighbor, set the buffer in the |
507 | * cursor to the left block, and fix up the index. | 506 | * cursor to the left block, and fix up the index. |
508 | */ | 507 | */ |
509 | if (bp != lbp) { | 508 | if (bp != lbp) { |
510 | xfs_btree_setbuf(cur, level, lbp); | 509 | xfs_btree_setbuf(cur, level, lbp); |
511 | cur->bc_ptrs[level] += lrecs; | 510 | cur->bc_ptrs[level] += lrecs; |
512 | } | 511 | } |
513 | /* | 512 | /* |
514 | * If we joined with the right neighbor and there's a level above | 513 | * If we joined with the right neighbor and there's a level above |
515 | * us, increment the cursor at that level. | 514 | * us, increment the cursor at that level. |
516 | */ | 515 | */ |
517 | else if (level + 1 < cur->bc_nlevels && | 516 | else if (level + 1 < cur->bc_nlevels && |
518 | (error = xfs_btree_increment(cur, level + 1, &i))) | 517 | (error = xfs_btree_increment(cur, level + 1, &i))) |
519 | return error; | 518 | return error; |
520 | /* | 519 | /* |
521 | * Fix up the number of records in the surviving block. | 520 | * Fix up the number of records in the surviving block. |
522 | */ | 521 | */ |
523 | lrecs += rrecs; | 522 | lrecs += rrecs; |
524 | left->bb_numrecs = cpu_to_be16(lrecs); | 523 | left->bb_numrecs = cpu_to_be16(lrecs); |
525 | /* | 524 | /* |
526 | * Fix up the right block pointer in the surviving block, and log it. | 525 | * Fix up the right block pointer in the surviving block, and log it. |
527 | */ | 526 | */ |
528 | left->bb_rightsib = right->bb_rightsib; | 527 | left->bb_rightsib = right->bb_rightsib; |
529 | xfs_alloc_log_block(cur->bc_tp, lbp, XFS_BB_NUMRECS | XFS_BB_RIGHTSIB); | 528 | xfs_alloc_log_block(cur->bc_tp, lbp, XFS_BB_NUMRECS | XFS_BB_RIGHTSIB); |
530 | /* | 529 | /* |
531 | * If there is a right sibling now, make it point to the | 530 | * If there is a right sibling now, make it point to the |
532 | * remaining block. | 531 | * remaining block. |
533 | */ | 532 | */ |
534 | if (be32_to_cpu(left->bb_rightsib) != NULLAGBLOCK) { | 533 | if (be32_to_cpu(left->bb_rightsib) != NULLAGBLOCK) { |
535 | xfs_alloc_block_t *rrblock; | 534 | xfs_alloc_block_t *rrblock; |
536 | xfs_buf_t *rrbp; | 535 | xfs_buf_t *rrbp; |
537 | 536 | ||
538 | if ((error = xfs_btree_read_bufs(mp, cur->bc_tp, | 537 | if ((error = xfs_btree_read_bufs(mp, cur->bc_tp, |
539 | cur->bc_private.a.agno, be32_to_cpu(left->bb_rightsib), 0, | 538 | cur->bc_private.a.agno, be32_to_cpu(left->bb_rightsib), 0, |
540 | &rrbp, XFS_ALLOC_BTREE_REF))) | 539 | &rrbp, XFS_ALLOC_BTREE_REF))) |
541 | return error; | 540 | return error; |
542 | rrblock = XFS_BUF_TO_ALLOC_BLOCK(rrbp); | 541 | rrblock = XFS_BUF_TO_ALLOC_BLOCK(rrbp); |
543 | if ((error = xfs_btree_check_sblock(cur, rrblock, level, rrbp))) | 542 | if ((error = xfs_btree_check_sblock(cur, rrblock, level, rrbp))) |
544 | return error; | 543 | return error; |
545 | rrblock->bb_leftsib = cpu_to_be32(lbno); | 544 | rrblock->bb_leftsib = cpu_to_be32(lbno); |
546 | xfs_alloc_log_block(cur->bc_tp, rrbp, XFS_BB_LEFTSIB); | 545 | xfs_alloc_log_block(cur->bc_tp, rrbp, XFS_BB_LEFTSIB); |
547 | } | 546 | } |
548 | /* | 547 | /* |
549 | * Free the deleting block by putting it on the freelist. | 548 | * Free the deleting block by putting it on the freelist. |
550 | */ | 549 | */ |
551 | error = xfs_alloc_put_freelist(cur->bc_tp, | 550 | error = xfs_alloc_put_freelist(cur->bc_tp, |
552 | cur->bc_private.a.agbp, NULL, rbno, 1); | 551 | cur->bc_private.a.agbp, NULL, rbno, 1); |
553 | if (error) | 552 | if (error) |
554 | return error; | 553 | return error; |
555 | /* | 554 | /* |
556 | * Since blocks move to the free list without the coordination | 555 | * Since blocks move to the free list without the coordination |
557 | * used in xfs_bmap_finish, we can't allow block to be available | 556 | * used in xfs_bmap_finish, we can't allow block to be available |
558 | * for reallocation and non-transaction writing (user data) | 557 | * for reallocation and non-transaction writing (user data) |
559 | * until we know that the transaction that moved it to the free | 558 | * until we know that the transaction that moved it to the free |
560 | * list is permanently on disk. We track the blocks by declaring | 559 | * list is permanently on disk. We track the blocks by declaring |
561 | * these blocks as "busy"; the busy list is maintained on a | 560 | * these blocks as "busy"; the busy list is maintained on a |
562 | * per-ag basis and each transaction records which entries | 561 | * per-ag basis and each transaction records which entries |
563 | * should be removed when the iclog commits to disk. If a | 562 | * should be removed when the iclog commits to disk. If a |
564 | * busy block is allocated, the iclog is pushed up to the | 563 | * busy block is allocated, the iclog is pushed up to the |
565 | * LSN that freed the block. | 564 | * LSN that freed the block. |
566 | */ | 565 | */ |
567 | xfs_alloc_mark_busy(cur->bc_tp, be32_to_cpu(agf->agf_seqno), bno, 1); | 566 | xfs_alloc_mark_busy(cur->bc_tp, be32_to_cpu(agf->agf_seqno), bno, 1); |
568 | xfs_trans_agbtree_delta(cur->bc_tp, -1); | 567 | xfs_trans_agbtree_delta(cur->bc_tp, -1); |
569 | 568 | ||
570 | /* | 569 | /* |
571 | * Adjust the current level's cursor so that we're left referring | 570 | * Adjust the current level's cursor so that we're left referring |
572 | * to the right node, after we're done. | 571 | * to the right node, after we're done. |
573 | * If this leaves the ptr value 0 our caller will fix it up. | 572 | * If this leaves the ptr value 0 our caller will fix it up. |
574 | */ | 573 | */ |
575 | if (level > 0) | 574 | if (level > 0) |
576 | cur->bc_ptrs[level]--; | 575 | cur->bc_ptrs[level]--; |
577 | /* | 576 | /* |
578 | * Return value means the next level up has something to do. | 577 | * Return value means the next level up has something to do. |
579 | */ | 578 | */ |
580 | *stat = 2; | 579 | *stat = 2; |
581 | return 0; | 580 | return 0; |
582 | 581 | ||
583 | error0: | 582 | error0: |
584 | xfs_btree_del_cursor(tcur, XFS_BTREE_ERROR); | 583 | xfs_btree_del_cursor(tcur, XFS_BTREE_ERROR); |
585 | return error; | 584 | return error; |
586 | } | 585 | } |
587 | 586 | ||
588 | /* | 587 | /* |
589 | * Insert one record/level. Return information to the caller | 588 | * Insert one record/level. Return information to the caller |
590 | * allowing the next level up to proceed if necessary. | 589 | * allowing the next level up to proceed if necessary. |
591 | */ | 590 | */ |
592 | STATIC int /* error */ | 591 | STATIC int /* error */ |
593 | xfs_alloc_insrec( | 592 | xfs_alloc_insrec( |
594 | xfs_btree_cur_t *cur, /* btree cursor */ | 593 | xfs_btree_cur_t *cur, /* btree cursor */ |
595 | int level, /* level to insert record at */ | 594 | int level, /* level to insert record at */ |
596 | xfs_agblock_t *bnop, /* i/o: block number inserted */ | 595 | xfs_agblock_t *bnop, /* i/o: block number inserted */ |
597 | xfs_alloc_rec_t *recp, /* i/o: record data inserted */ | 596 | xfs_alloc_rec_t *recp, /* i/o: record data inserted */ |
598 | xfs_btree_cur_t **curp, /* output: new cursor replacing cur */ | 597 | xfs_btree_cur_t **curp, /* output: new cursor replacing cur */ |
599 | int *stat) /* output: success/failure */ | 598 | int *stat) /* output: success/failure */ |
600 | { | 599 | { |
601 | xfs_agf_t *agf; /* allocation group freelist header */ | 600 | xfs_agf_t *agf; /* allocation group freelist header */ |
602 | xfs_alloc_block_t *block; /* btree block record/key lives in */ | 601 | xfs_alloc_block_t *block; /* btree block record/key lives in */ |
603 | xfs_buf_t *bp; /* buffer for block */ | 602 | xfs_buf_t *bp; /* buffer for block */ |
604 | int error; /* error return value */ | 603 | int error; /* error return value */ |
605 | int i; /* loop index */ | 604 | int i; /* loop index */ |
606 | xfs_alloc_key_t key; /* key value being inserted */ | 605 | xfs_alloc_key_t key; /* key value being inserted */ |
607 | xfs_alloc_key_t *kp; /* pointer to btree keys */ | 606 | xfs_alloc_key_t *kp; /* pointer to btree keys */ |
608 | xfs_agblock_t nbno; /* block number of allocated block */ | 607 | xfs_agblock_t nbno; /* block number of allocated block */ |
609 | xfs_btree_cur_t *ncur; /* new cursor to be used at next lvl */ | 608 | xfs_btree_cur_t *ncur; /* new cursor to be used at next lvl */ |
610 | xfs_alloc_key_t nkey; /* new key value, from split */ | 609 | xfs_alloc_key_t nkey; /* new key value, from split */ |
611 | xfs_alloc_rec_t nrec; /* new record value, for caller */ | 610 | xfs_alloc_rec_t nrec; /* new record value, for caller */ |
612 | int numrecs; | 611 | int numrecs; |
613 | int optr; /* old ptr value */ | 612 | int optr; /* old ptr value */ |
614 | xfs_alloc_ptr_t *pp; /* pointer to btree addresses */ | 613 | xfs_alloc_ptr_t *pp; /* pointer to btree addresses */ |
615 | int ptr; /* index in btree block for this rec */ | 614 | int ptr; /* index in btree block for this rec */ |
616 | xfs_alloc_rec_t *rp; /* pointer to btree records */ | 615 | xfs_alloc_rec_t *rp; /* pointer to btree records */ |
617 | 616 | ||
618 | ASSERT(be32_to_cpu(recp->ar_blockcount) > 0); | 617 | ASSERT(be32_to_cpu(recp->ar_blockcount) > 0); |
619 | 618 | ||
620 | /* | 619 | /* |
621 | * GCC doesn't understand the (arguably complex) control flow in | 620 | * GCC doesn't understand the (arguably complex) control flow in |
622 | * this function and complains about uninitialized structure fields | 621 | * this function and complains about uninitialized structure fields |
623 | * without this. | 622 | * without this. |
624 | */ | 623 | */ |
625 | memset(&nrec, 0, sizeof(nrec)); | 624 | memset(&nrec, 0, sizeof(nrec)); |
626 | 625 | ||
627 | /* | 626 | /* |
628 | * If we made it to the root level, allocate a new root block | 627 | * If we made it to the root level, allocate a new root block |
629 | * and we're done. | 628 | * and we're done. |
630 | */ | 629 | */ |
631 | if (level >= cur->bc_nlevels) { | 630 | if (level >= cur->bc_nlevels) { |
632 | XFS_STATS_INC(xs_abt_insrec); | 631 | XFS_STATS_INC(xs_abt_insrec); |
633 | if ((error = xfs_alloc_newroot(cur, &i))) | 632 | if ((error = xfs_alloc_newroot(cur, &i))) |
634 | return error; | 633 | return error; |
635 | *bnop = NULLAGBLOCK; | 634 | *bnop = NULLAGBLOCK; |
636 | *stat = i; | 635 | *stat = i; |
637 | return 0; | 636 | return 0; |
638 | } | 637 | } |
639 | /* | 638 | /* |
640 | * Make a key out of the record data to be inserted, and save it. | 639 | * Make a key out of the record data to be inserted, and save it. |
641 | */ | 640 | */ |
642 | key.ar_startblock = recp->ar_startblock; | 641 | key.ar_startblock = recp->ar_startblock; |
643 | key.ar_blockcount = recp->ar_blockcount; | 642 | key.ar_blockcount = recp->ar_blockcount; |
644 | optr = ptr = cur->bc_ptrs[level]; | 643 | optr = ptr = cur->bc_ptrs[level]; |
645 | /* | 644 | /* |
646 | * If we're off the left edge, return failure. | 645 | * If we're off the left edge, return failure. |
647 | */ | 646 | */ |
648 | if (ptr == 0) { | 647 | if (ptr == 0) { |
649 | *stat = 0; | 648 | *stat = 0; |
650 | return 0; | 649 | return 0; |
651 | } | 650 | } |
652 | XFS_STATS_INC(xs_abt_insrec); | 651 | XFS_STATS_INC(xs_abt_insrec); |
653 | /* | 652 | /* |
654 | * Get pointers to the btree buffer and block. | 653 | * Get pointers to the btree buffer and block. |
655 | */ | 654 | */ |
656 | bp = cur->bc_bufs[level]; | 655 | bp = cur->bc_bufs[level]; |
657 | block = XFS_BUF_TO_ALLOC_BLOCK(bp); | 656 | block = XFS_BUF_TO_ALLOC_BLOCK(bp); |
658 | numrecs = be16_to_cpu(block->bb_numrecs); | 657 | numrecs = be16_to_cpu(block->bb_numrecs); |
659 | #ifdef DEBUG | 658 | #ifdef DEBUG |
660 | if ((error = xfs_btree_check_sblock(cur, block, level, bp))) | 659 | if ((error = xfs_btree_check_sblock(cur, block, level, bp))) |
661 | return error; | 660 | return error; |
662 | /* | 661 | /* |
663 | * Check that the new entry is being inserted in the right place. | 662 | * Check that the new entry is being inserted in the right place. |
664 | */ | 663 | */ |
665 | if (ptr <= numrecs) { | 664 | if (ptr <= numrecs) { |
666 | if (level == 0) { | 665 | if (level == 0) { |
667 | rp = XFS_ALLOC_REC_ADDR(block, ptr, cur); | 666 | rp = XFS_ALLOC_REC_ADDR(block, ptr, cur); |
668 | xfs_btree_check_rec(cur->bc_btnum, recp, rp); | 667 | xfs_btree_check_rec(cur->bc_btnum, recp, rp); |
669 | } else { | 668 | } else { |
670 | kp = XFS_ALLOC_KEY_ADDR(block, ptr, cur); | 669 | kp = XFS_ALLOC_KEY_ADDR(block, ptr, cur); |
671 | xfs_btree_check_key(cur->bc_btnum, &key, kp); | 670 | xfs_btree_check_key(cur->bc_btnum, &key, kp); |
672 | } | 671 | } |
673 | } | 672 | } |
674 | #endif | 673 | #endif |
675 | nbno = NULLAGBLOCK; | 674 | nbno = NULLAGBLOCK; |
676 | ncur = NULL; | 675 | ncur = NULL; |
677 | /* | 676 | /* |
678 | * If the block is full, we can't insert the new entry until we | 677 | * If the block is full, we can't insert the new entry until we |
679 | * make the block un-full. | 678 | * make the block un-full. |
680 | */ | 679 | */ |
681 | if (numrecs == XFS_ALLOC_BLOCK_MAXRECS(level, cur)) { | 680 | if (numrecs == XFS_ALLOC_BLOCK_MAXRECS(level, cur)) { |
682 | /* | 681 | /* |
683 | * First, try shifting an entry to the right neighbor. | 682 | * First, try shifting an entry to the right neighbor. |
684 | */ | 683 | */ |
685 | if ((error = xfs_btree_rshift(cur, level, &i))) | 684 | if ((error = xfs_btree_rshift(cur, level, &i))) |
686 | return error; | 685 | return error; |
687 | if (i) { | 686 | if (i) { |
688 | /* nothing */ | 687 | /* nothing */ |
689 | } | 688 | } |
690 | /* | 689 | /* |
691 | * Next, try shifting an entry to the left neighbor. | 690 | * Next, try shifting an entry to the left neighbor. |
692 | */ | 691 | */ |
693 | else { | 692 | else { |
694 | if ((error = xfs_alloc_lshift(cur, level, &i))) | 693 | if ((error = xfs_btree_lshift(cur, level, &i))) |
695 | return error; | 694 | return error; |
696 | if (i) | 695 | if (i) |
697 | optr = ptr = cur->bc_ptrs[level]; | 696 | optr = ptr = cur->bc_ptrs[level]; |
698 | else { | 697 | else { |
699 | /* | 698 | /* |
700 | * Next, try splitting the current block in | 699 | * Next, try splitting the current block in |
701 | * half. If this works we have to re-set our | 700 | * half. If this works we have to re-set our |
702 | * variables because we could be in a | 701 | * variables because we could be in a |
703 | * different block now. | 702 | * different block now. |
704 | */ | 703 | */ |
705 | if ((error = xfs_alloc_split(cur, level, &nbno, | 704 | if ((error = xfs_alloc_split(cur, level, &nbno, |
706 | &nkey, &ncur, &i))) | 705 | &nkey, &ncur, &i))) |
707 | return error; | 706 | return error; |
708 | if (i) { | 707 | if (i) { |
709 | bp = cur->bc_bufs[level]; | 708 | bp = cur->bc_bufs[level]; |
710 | block = XFS_BUF_TO_ALLOC_BLOCK(bp); | 709 | block = XFS_BUF_TO_ALLOC_BLOCK(bp); |
711 | #ifdef DEBUG | 710 | #ifdef DEBUG |
712 | if ((error = | 711 | if ((error = |
713 | xfs_btree_check_sblock(cur, | 712 | xfs_btree_check_sblock(cur, |
714 | block, level, bp))) | 713 | block, level, bp))) |
715 | return error; | 714 | return error; |
716 | #endif | 715 | #endif |
717 | ptr = cur->bc_ptrs[level]; | 716 | ptr = cur->bc_ptrs[level]; |
718 | nrec.ar_startblock = nkey.ar_startblock; | 717 | nrec.ar_startblock = nkey.ar_startblock; |
719 | nrec.ar_blockcount = nkey.ar_blockcount; | 718 | nrec.ar_blockcount = nkey.ar_blockcount; |
720 | } | 719 | } |
721 | /* | 720 | /* |
722 | * Otherwise the insert fails. | 721 | * Otherwise the insert fails. |
723 | */ | 722 | */ |
724 | else { | 723 | else { |
725 | *stat = 0; | 724 | *stat = 0; |
726 | return 0; | 725 | return 0; |
727 | } | 726 | } |
728 | } | 727 | } |
729 | } | 728 | } |
730 | } | 729 | } |
731 | /* | 730 | /* |
732 | * At this point we know there's room for our new entry in the block | 731 | * At this point we know there's room for our new entry in the block |
733 | * we're pointing at. | 732 | * we're pointing at. |
734 | */ | 733 | */ |
735 | numrecs = be16_to_cpu(block->bb_numrecs); | 734 | numrecs = be16_to_cpu(block->bb_numrecs); |
736 | if (level > 0) { | 735 | if (level > 0) { |
737 | /* | 736 | /* |
738 | * It's a non-leaf entry. Make a hole for the new data | 737 | * It's a non-leaf entry. Make a hole for the new data |
739 | * in the key and ptr regions of the block. | 738 | * in the key and ptr regions of the block. |
740 | */ | 739 | */ |
741 | kp = XFS_ALLOC_KEY_ADDR(block, 1, cur); | 740 | kp = XFS_ALLOC_KEY_ADDR(block, 1, cur); |
742 | pp = XFS_ALLOC_PTR_ADDR(block, 1, cur); | 741 | pp = XFS_ALLOC_PTR_ADDR(block, 1, cur); |
743 | #ifdef DEBUG | 742 | #ifdef DEBUG |
744 | for (i = numrecs; i >= ptr; i--) { | 743 | for (i = numrecs; i >= ptr; i--) { |
745 | if ((error = xfs_btree_check_sptr(cur, be32_to_cpu(pp[i - 1]), level))) | 744 | if ((error = xfs_btree_check_sptr(cur, be32_to_cpu(pp[i - 1]), level))) |
746 | return error; | 745 | return error; |
747 | } | 746 | } |
748 | #endif | 747 | #endif |
749 | memmove(&kp[ptr], &kp[ptr - 1], | 748 | memmove(&kp[ptr], &kp[ptr - 1], |
750 | (numrecs - ptr + 1) * sizeof(*kp)); | 749 | (numrecs - ptr + 1) * sizeof(*kp)); |
751 | memmove(&pp[ptr], &pp[ptr - 1], | 750 | memmove(&pp[ptr], &pp[ptr - 1], |
752 | (numrecs - ptr + 1) * sizeof(*pp)); | 751 | (numrecs - ptr + 1) * sizeof(*pp)); |
753 | #ifdef DEBUG | 752 | #ifdef DEBUG |
754 | if ((error = xfs_btree_check_sptr(cur, *bnop, level))) | 753 | if ((error = xfs_btree_check_sptr(cur, *bnop, level))) |
755 | return error; | 754 | return error; |
756 | #endif | 755 | #endif |
757 | /* | 756 | /* |
758 | * Now stuff the new data in, bump numrecs and log the new data. | 757 | * Now stuff the new data in, bump numrecs and log the new data. |
759 | */ | 758 | */ |
760 | kp[ptr - 1] = key; | 759 | kp[ptr - 1] = key; |
761 | pp[ptr - 1] = cpu_to_be32(*bnop); | 760 | pp[ptr - 1] = cpu_to_be32(*bnop); |
762 | numrecs++; | 761 | numrecs++; |
763 | block->bb_numrecs = cpu_to_be16(numrecs); | 762 | block->bb_numrecs = cpu_to_be16(numrecs); |
764 | xfs_alloc_log_keys(cur, bp, ptr, numrecs); | 763 | xfs_alloc_log_keys(cur, bp, ptr, numrecs); |
765 | xfs_alloc_log_ptrs(cur, bp, ptr, numrecs); | 764 | xfs_alloc_log_ptrs(cur, bp, ptr, numrecs); |
766 | #ifdef DEBUG | 765 | #ifdef DEBUG |
767 | if (ptr < numrecs) | 766 | if (ptr < numrecs) |
768 | xfs_btree_check_key(cur->bc_btnum, kp + ptr - 1, | 767 | xfs_btree_check_key(cur->bc_btnum, kp + ptr - 1, |
769 | kp + ptr); | 768 | kp + ptr); |
770 | #endif | 769 | #endif |
771 | } else { | 770 | } else { |
772 | /* | 771 | /* |
773 | * It's a leaf entry. Make a hole for the new record. | 772 | * It's a leaf entry. Make a hole for the new record. |
774 | */ | 773 | */ |
775 | rp = XFS_ALLOC_REC_ADDR(block, 1, cur); | 774 | rp = XFS_ALLOC_REC_ADDR(block, 1, cur); |
776 | memmove(&rp[ptr], &rp[ptr - 1], | 775 | memmove(&rp[ptr], &rp[ptr - 1], |
777 | (numrecs - ptr + 1) * sizeof(*rp)); | 776 | (numrecs - ptr + 1) * sizeof(*rp)); |
778 | /* | 777 | /* |
779 | * Now stuff the new record in, bump numrecs | 778 | * Now stuff the new record in, bump numrecs |
780 | * and log the new data. | 779 | * and log the new data. |
781 | */ | 780 | */ |
782 | rp[ptr - 1] = *recp; | 781 | rp[ptr - 1] = *recp; |
783 | numrecs++; | 782 | numrecs++; |
784 | block->bb_numrecs = cpu_to_be16(numrecs); | 783 | block->bb_numrecs = cpu_to_be16(numrecs); |
785 | xfs_alloc_log_recs(cur, bp, ptr, numrecs); | 784 | xfs_alloc_log_recs(cur, bp, ptr, numrecs); |
786 | #ifdef DEBUG | 785 | #ifdef DEBUG |
787 | if (ptr < numrecs) | 786 | if (ptr < numrecs) |
788 | xfs_btree_check_rec(cur->bc_btnum, rp + ptr - 1, | 787 | xfs_btree_check_rec(cur->bc_btnum, rp + ptr - 1, |
789 | rp + ptr); | 788 | rp + ptr); |
790 | #endif | 789 | #endif |
791 | } | 790 | } |
792 | /* | 791 | /* |
793 | * Log the new number of records in the btree header. | 792 | * Log the new number of records in the btree header. |
794 | */ | 793 | */ |
795 | xfs_alloc_log_block(cur->bc_tp, bp, XFS_BB_NUMRECS); | 794 | xfs_alloc_log_block(cur->bc_tp, bp, XFS_BB_NUMRECS); |
796 | /* | 795 | /* |
797 | * If we inserted at the start of a block, update the parents' keys. | 796 | * If we inserted at the start of a block, update the parents' keys. |
798 | */ | 797 | */ |
799 | if (optr == 1 && (error = xfs_btree_updkey(cur, (union xfs_btree_key *)&key, level + 1))) | 798 | if (optr == 1 && (error = xfs_btree_updkey(cur, (union xfs_btree_key *)&key, level + 1))) |
800 | return error; | 799 | return error; |
801 | /* | 800 | /* |
802 | * Look to see if the longest extent in the allocation group | 801 | * Look to see if the longest extent in the allocation group |
803 | * needs to be updated. | 802 | * needs to be updated. |
804 | */ | 803 | */ |
805 | 804 | ||
806 | agf = XFS_BUF_TO_AGF(cur->bc_private.a.agbp); | 805 | agf = XFS_BUF_TO_AGF(cur->bc_private.a.agbp); |
807 | if (level == 0 && | 806 | if (level == 0 && |
808 | cur->bc_btnum == XFS_BTNUM_CNT && | 807 | cur->bc_btnum == XFS_BTNUM_CNT && |
809 | be32_to_cpu(block->bb_rightsib) == NULLAGBLOCK && | 808 | be32_to_cpu(block->bb_rightsib) == NULLAGBLOCK && |
810 | be32_to_cpu(recp->ar_blockcount) > be32_to_cpu(agf->agf_longest)) { | 809 | be32_to_cpu(recp->ar_blockcount) > be32_to_cpu(agf->agf_longest)) { |
811 | /* | 810 | /* |
812 | * If this is a leaf in the by-size btree and there | 811 | * If this is a leaf in the by-size btree and there |
813 | * is no right sibling block and this block is bigger | 812 | * is no right sibling block and this block is bigger |
814 | * than the previous longest block, update it. | 813 | * than the previous longest block, update it. |
815 | */ | 814 | */ |
816 | agf->agf_longest = recp->ar_blockcount; | 815 | agf->agf_longest = recp->ar_blockcount; |
817 | cur->bc_mp->m_perag[be32_to_cpu(agf->agf_seqno)].pagf_longest | 816 | cur->bc_mp->m_perag[be32_to_cpu(agf->agf_seqno)].pagf_longest |
818 | = be32_to_cpu(recp->ar_blockcount); | 817 | = be32_to_cpu(recp->ar_blockcount); |
819 | xfs_alloc_log_agf(cur->bc_tp, cur->bc_private.a.agbp, | 818 | xfs_alloc_log_agf(cur->bc_tp, cur->bc_private.a.agbp, |
820 | XFS_AGF_LONGEST); | 819 | XFS_AGF_LONGEST); |
821 | } | 820 | } |
822 | /* | 821 | /* |
823 | * Return the new block number, if any. | 822 | * Return the new block number, if any. |
824 | * If there is one, give back a record value and a cursor too. | 823 | * If there is one, give back a record value and a cursor too. |
825 | */ | 824 | */ |
826 | *bnop = nbno; | 825 | *bnop = nbno; |
827 | if (nbno != NULLAGBLOCK) { | 826 | if (nbno != NULLAGBLOCK) { |
828 | *recp = nrec; | 827 | *recp = nrec; |
829 | *curp = ncur; | 828 | *curp = ncur; |
830 | } | 829 | } |
831 | *stat = 1; | 830 | *stat = 1; |
832 | return 0; | 831 | return 0; |
833 | } | 832 | } |
834 | 833 | ||
835 | /* | 834 | /* |
836 | * Log header fields from a btree block. | 835 | * Log header fields from a btree block. |
837 | */ | 836 | */ |
838 | STATIC void | 837 | STATIC void |
839 | xfs_alloc_log_block( | 838 | xfs_alloc_log_block( |
840 | xfs_trans_t *tp, /* transaction pointer */ | 839 | xfs_trans_t *tp, /* transaction pointer */ |
841 | xfs_buf_t *bp, /* buffer containing btree block */ | 840 | xfs_buf_t *bp, /* buffer containing btree block */ |
842 | int fields) /* mask of fields: XFS_BB_... */ | 841 | int fields) /* mask of fields: XFS_BB_... */ |
843 | { | 842 | { |
844 | int first; /* first byte offset logged */ | 843 | int first; /* first byte offset logged */ |
845 | int last; /* last byte offset logged */ | 844 | int last; /* last byte offset logged */ |
846 | static const short offsets[] = { /* table of offsets */ | 845 | static const short offsets[] = { /* table of offsets */ |
847 | offsetof(xfs_alloc_block_t, bb_magic), | 846 | offsetof(xfs_alloc_block_t, bb_magic), |
848 | offsetof(xfs_alloc_block_t, bb_level), | 847 | offsetof(xfs_alloc_block_t, bb_level), |
849 | offsetof(xfs_alloc_block_t, bb_numrecs), | 848 | offsetof(xfs_alloc_block_t, bb_numrecs), |
850 | offsetof(xfs_alloc_block_t, bb_leftsib), | 849 | offsetof(xfs_alloc_block_t, bb_leftsib), |
851 | offsetof(xfs_alloc_block_t, bb_rightsib), | 850 | offsetof(xfs_alloc_block_t, bb_rightsib), |
852 | sizeof(xfs_alloc_block_t) | 851 | sizeof(xfs_alloc_block_t) |
853 | }; | 852 | }; |
854 | 853 | ||
855 | xfs_btree_offsets(fields, offsets, XFS_BB_NUM_BITS, &first, &last); | 854 | xfs_btree_offsets(fields, offsets, XFS_BB_NUM_BITS, &first, &last); |
856 | xfs_trans_log_buf(tp, bp, first, last); | 855 | xfs_trans_log_buf(tp, bp, first, last); |
857 | } | 856 | } |
858 | 857 | ||
859 | /* | 858 | /* |
860 | * Log keys from a btree block (nonleaf). | 859 | * Log keys from a btree block (nonleaf). |
861 | */ | 860 | */ |
862 | STATIC void | 861 | STATIC void |
863 | xfs_alloc_log_keys( | 862 | xfs_alloc_log_keys( |
864 | xfs_btree_cur_t *cur, /* btree cursor */ | 863 | xfs_btree_cur_t *cur, /* btree cursor */ |
865 | xfs_buf_t *bp, /* buffer containing btree block */ | 864 | xfs_buf_t *bp, /* buffer containing btree block */ |
866 | int kfirst, /* index of first key to log */ | 865 | int kfirst, /* index of first key to log */ |
867 | int klast) /* index of last key to log */ | 866 | int klast) /* index of last key to log */ |
868 | { | 867 | { |
869 | xfs_alloc_block_t *block; /* btree block to log from */ | 868 | xfs_alloc_block_t *block; /* btree block to log from */ |
870 | int first; /* first byte offset logged */ | 869 | int first; /* first byte offset logged */ |
871 | xfs_alloc_key_t *kp; /* key pointer in btree block */ | 870 | xfs_alloc_key_t *kp; /* key pointer in btree block */ |
872 | int last; /* last byte offset logged */ | 871 | int last; /* last byte offset logged */ |
873 | 872 | ||
874 | block = XFS_BUF_TO_ALLOC_BLOCK(bp); | 873 | block = XFS_BUF_TO_ALLOC_BLOCK(bp); |
875 | kp = XFS_ALLOC_KEY_ADDR(block, 1, cur); | 874 | kp = XFS_ALLOC_KEY_ADDR(block, 1, cur); |
876 | first = (int)((xfs_caddr_t)&kp[kfirst - 1] - (xfs_caddr_t)block); | 875 | first = (int)((xfs_caddr_t)&kp[kfirst - 1] - (xfs_caddr_t)block); |
877 | last = (int)(((xfs_caddr_t)&kp[klast] - 1) - (xfs_caddr_t)block); | 876 | last = (int)(((xfs_caddr_t)&kp[klast] - 1) - (xfs_caddr_t)block); |
878 | xfs_trans_log_buf(cur->bc_tp, bp, first, last); | 877 | xfs_trans_log_buf(cur->bc_tp, bp, first, last); |
879 | } | 878 | } |
880 | 879 | ||
881 | /* | 880 | /* |
882 | * Log block pointer fields from a btree block (nonleaf). | 881 | * Log block pointer fields from a btree block (nonleaf). |
883 | */ | 882 | */ |
884 | STATIC void | 883 | STATIC void |
885 | xfs_alloc_log_ptrs( | 884 | xfs_alloc_log_ptrs( |
886 | xfs_btree_cur_t *cur, /* btree cursor */ | 885 | xfs_btree_cur_t *cur, /* btree cursor */ |
887 | xfs_buf_t *bp, /* buffer containing btree block */ | 886 | xfs_buf_t *bp, /* buffer containing btree block */ |
888 | int pfirst, /* index of first pointer to log */ | 887 | int pfirst, /* index of first pointer to log */ |
889 | int plast) /* index of last pointer to log */ | 888 | int plast) /* index of last pointer to log */ |
890 | { | 889 | { |
891 | xfs_alloc_block_t *block; /* btree block to log from */ | 890 | xfs_alloc_block_t *block; /* btree block to log from */ |
892 | int first; /* first byte offset logged */ | 891 | int first; /* first byte offset logged */ |
893 | int last; /* last byte offset logged */ | 892 | int last; /* last byte offset logged */ |
894 | xfs_alloc_ptr_t *pp; /* block-pointer pointer in btree blk */ | 893 | xfs_alloc_ptr_t *pp; /* block-pointer pointer in btree blk */ |
895 | 894 | ||
896 | block = XFS_BUF_TO_ALLOC_BLOCK(bp); | 895 | block = XFS_BUF_TO_ALLOC_BLOCK(bp); |
897 | pp = XFS_ALLOC_PTR_ADDR(block, 1, cur); | 896 | pp = XFS_ALLOC_PTR_ADDR(block, 1, cur); |
898 | first = (int)((xfs_caddr_t)&pp[pfirst - 1] - (xfs_caddr_t)block); | 897 | first = (int)((xfs_caddr_t)&pp[pfirst - 1] - (xfs_caddr_t)block); |
899 | last = (int)(((xfs_caddr_t)&pp[plast] - 1) - (xfs_caddr_t)block); | 898 | last = (int)(((xfs_caddr_t)&pp[plast] - 1) - (xfs_caddr_t)block); |
900 | xfs_trans_log_buf(cur->bc_tp, bp, first, last); | 899 | xfs_trans_log_buf(cur->bc_tp, bp, first, last); |
901 | } | 900 | } |
902 | 901 | ||
903 | /* | 902 | /* |
904 | * Log records from a btree block (leaf). | 903 | * Log records from a btree block (leaf). |
905 | */ | 904 | */ |
906 | STATIC void | 905 | STATIC void |
907 | xfs_alloc_log_recs( | 906 | xfs_alloc_log_recs( |
908 | xfs_btree_cur_t *cur, /* btree cursor */ | 907 | xfs_btree_cur_t *cur, /* btree cursor */ |
909 | xfs_buf_t *bp, /* buffer containing btree block */ | 908 | xfs_buf_t *bp, /* buffer containing btree block */ |
910 | int rfirst, /* index of first record to log */ | 909 | int rfirst, /* index of first record to log */ |
911 | int rlast) /* index of last record to log */ | 910 | int rlast) /* index of last record to log */ |
912 | { | 911 | { |
913 | xfs_alloc_block_t *block; /* btree block to log from */ | 912 | xfs_alloc_block_t *block; /* btree block to log from */ |
914 | int first; /* first byte offset logged */ | 913 | int first; /* first byte offset logged */ |
915 | int last; /* last byte offset logged */ | 914 | int last; /* last byte offset logged */ |
916 | xfs_alloc_rec_t *rp; /* record pointer for btree block */ | 915 | xfs_alloc_rec_t *rp; /* record pointer for btree block */ |
917 | 916 | ||
918 | 917 | ||
919 | block = XFS_BUF_TO_ALLOC_BLOCK(bp); | 918 | block = XFS_BUF_TO_ALLOC_BLOCK(bp); |
920 | rp = XFS_ALLOC_REC_ADDR(block, 1, cur); | 919 | rp = XFS_ALLOC_REC_ADDR(block, 1, cur); |
921 | #ifdef DEBUG | 920 | #ifdef DEBUG |
922 | { | 921 | { |
923 | xfs_agf_t *agf; | 922 | xfs_agf_t *agf; |
924 | xfs_alloc_rec_t *p; | 923 | xfs_alloc_rec_t *p; |
925 | 924 | ||
926 | agf = XFS_BUF_TO_AGF(cur->bc_private.a.agbp); | 925 | agf = XFS_BUF_TO_AGF(cur->bc_private.a.agbp); |
927 | for (p = &rp[rfirst - 1]; p <= &rp[rlast - 1]; p++) | 926 | for (p = &rp[rfirst - 1]; p <= &rp[rlast - 1]; p++) |
928 | ASSERT(be32_to_cpu(p->ar_startblock) + | 927 | ASSERT(be32_to_cpu(p->ar_startblock) + |
929 | be32_to_cpu(p->ar_blockcount) <= | 928 | be32_to_cpu(p->ar_blockcount) <= |
930 | be32_to_cpu(agf->agf_length)); | 929 | be32_to_cpu(agf->agf_length)); |
931 | } | 930 | } |
932 | #endif | 931 | #endif |
933 | first = (int)((xfs_caddr_t)&rp[rfirst - 1] - (xfs_caddr_t)block); | 932 | first = (int)((xfs_caddr_t)&rp[rfirst - 1] - (xfs_caddr_t)block); |
934 | last = (int)(((xfs_caddr_t)&rp[rlast] - 1) - (xfs_caddr_t)block); | 933 | last = (int)(((xfs_caddr_t)&rp[rlast] - 1) - (xfs_caddr_t)block); |
935 | xfs_trans_log_buf(cur->bc_tp, bp, first, last); | 934 | xfs_trans_log_buf(cur->bc_tp, bp, first, last); |
936 | } | ||
937 | |||
938 | /* | ||
939 | * Move 1 record left from cur/level if possible. | ||
940 | * Update cur to reflect the new path. | ||
941 | */ | ||
942 | STATIC int /* error */ | ||
943 | xfs_alloc_lshift( | ||
944 | xfs_btree_cur_t *cur, /* btree cursor */ | ||
945 | int level, /* level to shift record on */ | ||
946 | int *stat) /* success/failure */ | ||
947 | { | ||
948 | int error; /* error return value */ | ||
949 | #ifdef DEBUG | ||
950 | int i; /* loop index */ | ||
951 | #endif | ||
952 | xfs_alloc_key_t key; /* key value for leaf level upward */ | ||
953 | xfs_buf_t *lbp; /* buffer for left neighbor block */ | ||
954 | xfs_alloc_block_t *left; /* left neighbor btree block */ | ||
955 | int nrec; /* new number of left block entries */ | ||
956 | xfs_buf_t *rbp; /* buffer for right (current) block */ | ||
957 | xfs_alloc_block_t *right; /* right (current) btree block */ | ||
958 | xfs_alloc_key_t *rkp=NULL; /* key pointer for right block */ | ||
959 | xfs_alloc_ptr_t *rpp=NULL; /* address pointer for right block */ | ||
960 | xfs_alloc_rec_t *rrp=NULL; /* record pointer for right block */ | ||
961 | |||
962 | /* | ||
963 | * Set up variables for this block as "right". | ||
964 | */ | ||
965 | rbp = cur->bc_bufs[level]; | ||
966 | right = XFS_BUF_TO_ALLOC_BLOCK(rbp); | ||
967 | #ifdef DEBUG | ||
968 | if ((error = xfs_btree_check_sblock(cur, right, level, rbp))) | ||
969 | return error; | ||
970 | #endif | ||
971 | /* | ||
972 | * If we've got no left sibling then we can't shift an entry left. | ||
973 | */ | ||
974 | if (be32_to_cpu(right->bb_leftsib) == NULLAGBLOCK) { | ||
975 | *stat = 0; | ||
976 | return 0; | ||
977 | } | ||
978 | /* | ||
979 | * If the cursor entry is the one that would be moved, don't | ||
980 | * do it... it's too complicated. | ||
981 | */ | ||
982 | if (cur->bc_ptrs[level] <= 1) { | ||
983 | *stat = 0; | ||
984 | return 0; | ||
985 | } | ||
986 | /* | ||
987 | * Set up the left neighbor as "left". | ||
988 | */ | ||
989 | if ((error = xfs_btree_read_bufs(cur->bc_mp, cur->bc_tp, | ||
990 | cur->bc_private.a.agno, be32_to_cpu(right->bb_leftsib), | ||
991 | 0, &lbp, XFS_ALLOC_BTREE_REF))) | ||
992 | return error; | ||
993 | left = XFS_BUF_TO_ALLOC_BLOCK(lbp); | ||
994 | if ((error = xfs_btree_check_sblock(cur, left, level, lbp))) | ||
995 | return error; | ||
996 | /* | ||
997 | * If it's full, it can't take another entry. | ||
998 | */ | ||
999 | if (be16_to_cpu(left->bb_numrecs) == XFS_ALLOC_BLOCK_MAXRECS(level, cur)) { | ||
1000 | *stat = 0; | ||
1001 | return 0; | ||
1002 | } | ||
1003 | nrec = be16_to_cpu(left->bb_numrecs) + 1; | ||
1004 | /* | ||
1005 | * If non-leaf, copy a key and a ptr to the left block. | ||
1006 | */ | ||
1007 | if (level > 0) { | ||
1008 | xfs_alloc_key_t *lkp; /* key pointer for left block */ | ||
1009 | xfs_alloc_ptr_t *lpp; /* address pointer for left block */ | ||
1010 | |||
1011 | lkp = XFS_ALLOC_KEY_ADDR(left, nrec, cur); | ||
1012 | rkp = XFS_ALLOC_KEY_ADDR(right, 1, cur); | ||
1013 | *lkp = *rkp; | ||
1014 | xfs_alloc_log_keys(cur, lbp, nrec, nrec); | ||
1015 | lpp = XFS_ALLOC_PTR_ADDR(left, nrec, cur); | ||
1016 | rpp = XFS_ALLOC_PTR_ADDR(right, 1, cur); | ||
1017 | #ifdef DEBUG | ||
1018 | if ((error = xfs_btree_check_sptr(cur, be32_to_cpu(*rpp), level))) | ||
1019 | return error; | ||
1020 | #endif | ||
1021 | *lpp = *rpp; | ||
1022 | xfs_alloc_log_ptrs(cur, lbp, nrec, nrec); | ||
1023 | xfs_btree_check_key(cur->bc_btnum, lkp - 1, lkp); | ||
1024 | } | ||
1025 | /* | ||
1026 | * If leaf, copy a record to the left block. | ||
1027 | */ | ||
1028 | else { | ||
1029 | xfs_alloc_rec_t *lrp; /* record pointer for left block */ | ||
1030 | |||
1031 | lrp = XFS_ALLOC_REC_ADDR(left, nrec, cur); | ||
1032 | rrp = XFS_ALLOC_REC_ADDR(right, 1, cur); | ||
1033 | *lrp = *rrp; | ||
1034 | xfs_alloc_log_recs(cur, lbp, nrec, nrec); | ||
1035 | xfs_btree_check_rec(cur->bc_btnum, lrp - 1, lrp); | ||
1036 | } | ||
1037 | /* | ||
1038 | * Bump and log left's numrecs, decrement and log right's numrecs. | ||
1039 | */ | ||
1040 | be16_add_cpu(&left->bb_numrecs, 1); | ||
1041 | xfs_alloc_log_block(cur->bc_tp, lbp, XFS_BB_NUMRECS); | ||
1042 | be16_add_cpu(&right->bb_numrecs, -1); | ||
1043 | xfs_alloc_log_block(cur->bc_tp, rbp, XFS_BB_NUMRECS); | ||
1044 | /* | ||
1045 | * Slide the contents of right down one entry. | ||
1046 | */ | ||
1047 | if (level > 0) { | ||
1048 | #ifdef DEBUG | ||
1049 | for (i = 0; i < be16_to_cpu(right->bb_numrecs); i++) { | ||
1050 | if ((error = xfs_btree_check_sptr(cur, be32_to_cpu(rpp[i + 1]), | ||
1051 | level))) | ||
1052 | return error; | ||
1053 | } | ||
1054 | #endif | ||
1055 | memmove(rkp, rkp + 1, be16_to_cpu(right->bb_numrecs) * sizeof(*rkp)); | ||
1056 | memmove(rpp, rpp + 1, be16_to_cpu(right->bb_numrecs) * sizeof(*rpp)); | ||
1057 | xfs_alloc_log_keys(cur, rbp, 1, be16_to_cpu(right->bb_numrecs)); | ||
1058 | xfs_alloc_log_ptrs(cur, rbp, 1, be16_to_cpu(right->bb_numrecs)); | ||
1059 | } else { | ||
1060 | memmove(rrp, rrp + 1, be16_to_cpu(right->bb_numrecs) * sizeof(*rrp)); | ||
1061 | xfs_alloc_log_recs(cur, rbp, 1, be16_to_cpu(right->bb_numrecs)); | ||
1062 | key.ar_startblock = rrp->ar_startblock; | ||
1063 | key.ar_blockcount = rrp->ar_blockcount; | ||
1064 | rkp = &key; | ||
1065 | } | ||
1066 | /* | ||
1067 | * Update the parent key values of right. | ||
1068 | */ | ||
1069 | if ((error = xfs_btree_updkey(cur, (union xfs_btree_key *)rkp, level + 1))) | ||
1070 | return error; | ||
1071 | /* | ||
1072 | * Slide the cursor value left one. | ||
1073 | */ | ||
1074 | cur->bc_ptrs[level]--; | ||
1075 | *stat = 1; | ||
1076 | return 0; | ||
1077 | } | 935 | } |
1078 | 936 | ||
1079 | /* | 937 | /* |
1080 | * Allocate a new root block, fill it in. | 938 | * Allocate a new root block, fill it in. |
1081 | */ | 939 | */ |
1082 | STATIC int /* error */ | 940 | STATIC int /* error */ |
1083 | xfs_alloc_newroot( | 941 | xfs_alloc_newroot( |
1084 | xfs_btree_cur_t *cur, /* btree cursor */ | 942 | xfs_btree_cur_t *cur, /* btree cursor */ |
1085 | int *stat) /* success/failure */ | 943 | int *stat) /* success/failure */ |
1086 | { | 944 | { |
1087 | int error; /* error return value */ | 945 | int error; /* error return value */ |
1088 | xfs_agblock_t lbno; /* left block number */ | 946 | xfs_agblock_t lbno; /* left block number */ |
1089 | xfs_buf_t *lbp; /* left btree buffer */ | 947 | xfs_buf_t *lbp; /* left btree buffer */ |
1090 | xfs_alloc_block_t *left; /* left btree block */ | 948 | xfs_alloc_block_t *left; /* left btree block */ |
1091 | xfs_mount_t *mp; /* mount structure */ | 949 | xfs_mount_t *mp; /* mount structure */ |
1092 | xfs_agblock_t nbno; /* new block number */ | 950 | xfs_agblock_t nbno; /* new block number */ |
1093 | xfs_buf_t *nbp; /* new (root) buffer */ | 951 | xfs_buf_t *nbp; /* new (root) buffer */ |
1094 | xfs_alloc_block_t *new; /* new (root) btree block */ | 952 | xfs_alloc_block_t *new; /* new (root) btree block */ |
1095 | int nptr; /* new value for key index, 1 or 2 */ | 953 | int nptr; /* new value for key index, 1 or 2 */ |
1096 | xfs_agblock_t rbno; /* right block number */ | 954 | xfs_agblock_t rbno; /* right block number */ |
1097 | xfs_buf_t *rbp; /* right btree buffer */ | 955 | xfs_buf_t *rbp; /* right btree buffer */ |
1098 | xfs_alloc_block_t *right; /* right btree block */ | 956 | xfs_alloc_block_t *right; /* right btree block */ |
1099 | 957 | ||
1100 | mp = cur->bc_mp; | 958 | mp = cur->bc_mp; |
1101 | 959 | ||
1102 | ASSERT(cur->bc_nlevels < XFS_AG_MAXLEVELS(mp)); | 960 | ASSERT(cur->bc_nlevels < XFS_AG_MAXLEVELS(mp)); |
1103 | /* | 961 | /* |
1104 | * Get a buffer from the freelist blocks, for the new root. | 962 | * Get a buffer from the freelist blocks, for the new root. |
1105 | */ | 963 | */ |
1106 | error = xfs_alloc_get_freelist(cur->bc_tp, | 964 | error = xfs_alloc_get_freelist(cur->bc_tp, |
1107 | cur->bc_private.a.agbp, &nbno, 1); | 965 | cur->bc_private.a.agbp, &nbno, 1); |
1108 | if (error) | 966 | if (error) |
1109 | return error; | 967 | return error; |
1110 | /* | 968 | /* |
1111 | * None available, we fail. | 969 | * None available, we fail. |
1112 | */ | 970 | */ |
1113 | if (nbno == NULLAGBLOCK) { | 971 | if (nbno == NULLAGBLOCK) { |
1114 | *stat = 0; | 972 | *stat = 0; |
1115 | return 0; | 973 | return 0; |
1116 | } | 974 | } |
1117 | xfs_trans_agbtree_delta(cur->bc_tp, 1); | 975 | xfs_trans_agbtree_delta(cur->bc_tp, 1); |
1118 | nbp = xfs_btree_get_bufs(mp, cur->bc_tp, cur->bc_private.a.agno, nbno, | 976 | nbp = xfs_btree_get_bufs(mp, cur->bc_tp, cur->bc_private.a.agno, nbno, |
1119 | 0); | 977 | 0); |
1120 | new = XFS_BUF_TO_ALLOC_BLOCK(nbp); | 978 | new = XFS_BUF_TO_ALLOC_BLOCK(nbp); |
1121 | /* | 979 | /* |
1122 | * Set the root data in the a.g. freespace structure. | 980 | * Set the root data in the a.g. freespace structure. |
1123 | */ | 981 | */ |
1124 | { | 982 | { |
1125 | xfs_agf_t *agf; /* a.g. freespace header */ | 983 | xfs_agf_t *agf; /* a.g. freespace header */ |
1126 | xfs_agnumber_t seqno; | 984 | xfs_agnumber_t seqno; |
1127 | 985 | ||
1128 | agf = XFS_BUF_TO_AGF(cur->bc_private.a.agbp); | 986 | agf = XFS_BUF_TO_AGF(cur->bc_private.a.agbp); |
1129 | agf->agf_roots[cur->bc_btnum] = cpu_to_be32(nbno); | 987 | agf->agf_roots[cur->bc_btnum] = cpu_to_be32(nbno); |
1130 | be32_add_cpu(&agf->agf_levels[cur->bc_btnum], 1); | 988 | be32_add_cpu(&agf->agf_levels[cur->bc_btnum], 1); |
1131 | seqno = be32_to_cpu(agf->agf_seqno); | 989 | seqno = be32_to_cpu(agf->agf_seqno); |
1132 | mp->m_perag[seqno].pagf_levels[cur->bc_btnum]++; | 990 | mp->m_perag[seqno].pagf_levels[cur->bc_btnum]++; |
1133 | xfs_alloc_log_agf(cur->bc_tp, cur->bc_private.a.agbp, | 991 | xfs_alloc_log_agf(cur->bc_tp, cur->bc_private.a.agbp, |
1134 | XFS_AGF_ROOTS | XFS_AGF_LEVELS); | 992 | XFS_AGF_ROOTS | XFS_AGF_LEVELS); |
1135 | } | 993 | } |
1136 | /* | 994 | /* |
1137 | * At the previous root level there are now two blocks: the old | 995 | * At the previous root level there are now two blocks: the old |
1138 | * root, and the new block generated when it was split. | 996 | * root, and the new block generated when it was split. |
1139 | * We don't know which one the cursor is pointing at, so we | 997 | * We don't know which one the cursor is pointing at, so we |
1140 | * set up variables "left" and "right" for each case. | 998 | * set up variables "left" and "right" for each case. |
1141 | */ | 999 | */ |
1142 | lbp = cur->bc_bufs[cur->bc_nlevels - 1]; | 1000 | lbp = cur->bc_bufs[cur->bc_nlevels - 1]; |
1143 | left = XFS_BUF_TO_ALLOC_BLOCK(lbp); | 1001 | left = XFS_BUF_TO_ALLOC_BLOCK(lbp); |
1144 | #ifdef DEBUG | 1002 | #ifdef DEBUG |
1145 | if ((error = xfs_btree_check_sblock(cur, left, cur->bc_nlevels - 1, lbp))) | 1003 | if ((error = xfs_btree_check_sblock(cur, left, cur->bc_nlevels - 1, lbp))) |
1146 | return error; | 1004 | return error; |
1147 | #endif | 1005 | #endif |
1148 | if (be32_to_cpu(left->bb_rightsib) != NULLAGBLOCK) { | 1006 | if (be32_to_cpu(left->bb_rightsib) != NULLAGBLOCK) { |
1149 | /* | 1007 | /* |
1150 | * Our block is left, pick up the right block. | 1008 | * Our block is left, pick up the right block. |
1151 | */ | 1009 | */ |
1152 | lbno = XFS_DADDR_TO_AGBNO(mp, XFS_BUF_ADDR(lbp)); | 1010 | lbno = XFS_DADDR_TO_AGBNO(mp, XFS_BUF_ADDR(lbp)); |
1153 | rbno = be32_to_cpu(left->bb_rightsib); | 1011 | rbno = be32_to_cpu(left->bb_rightsib); |
1154 | if ((error = xfs_btree_read_bufs(mp, cur->bc_tp, | 1012 | if ((error = xfs_btree_read_bufs(mp, cur->bc_tp, |
1155 | cur->bc_private.a.agno, rbno, 0, &rbp, | 1013 | cur->bc_private.a.agno, rbno, 0, &rbp, |
1156 | XFS_ALLOC_BTREE_REF))) | 1014 | XFS_ALLOC_BTREE_REF))) |
1157 | return error; | 1015 | return error; |
1158 | right = XFS_BUF_TO_ALLOC_BLOCK(rbp); | 1016 | right = XFS_BUF_TO_ALLOC_BLOCK(rbp); |
1159 | if ((error = xfs_btree_check_sblock(cur, right, | 1017 | if ((error = xfs_btree_check_sblock(cur, right, |
1160 | cur->bc_nlevels - 1, rbp))) | 1018 | cur->bc_nlevels - 1, rbp))) |
1161 | return error; | 1019 | return error; |
1162 | nptr = 1; | 1020 | nptr = 1; |
1163 | } else { | 1021 | } else { |
1164 | /* | 1022 | /* |
1165 | * Our block is right, pick up the left block. | 1023 | * Our block is right, pick up the left block. |
1166 | */ | 1024 | */ |
1167 | rbp = lbp; | 1025 | rbp = lbp; |
1168 | right = left; | 1026 | right = left; |
1169 | rbno = XFS_DADDR_TO_AGBNO(mp, XFS_BUF_ADDR(rbp)); | 1027 | rbno = XFS_DADDR_TO_AGBNO(mp, XFS_BUF_ADDR(rbp)); |
1170 | lbno = be32_to_cpu(right->bb_leftsib); | 1028 | lbno = be32_to_cpu(right->bb_leftsib); |
1171 | if ((error = xfs_btree_read_bufs(mp, cur->bc_tp, | 1029 | if ((error = xfs_btree_read_bufs(mp, cur->bc_tp, |
1172 | cur->bc_private.a.agno, lbno, 0, &lbp, | 1030 | cur->bc_private.a.agno, lbno, 0, &lbp, |
1173 | XFS_ALLOC_BTREE_REF))) | 1031 | XFS_ALLOC_BTREE_REF))) |
1174 | return error; | 1032 | return error; |
1175 | left = XFS_BUF_TO_ALLOC_BLOCK(lbp); | 1033 | left = XFS_BUF_TO_ALLOC_BLOCK(lbp); |
1176 | if ((error = xfs_btree_check_sblock(cur, left, | 1034 | if ((error = xfs_btree_check_sblock(cur, left, |
1177 | cur->bc_nlevels - 1, lbp))) | 1035 | cur->bc_nlevels - 1, lbp))) |
1178 | return error; | 1036 | return error; |
1179 | nptr = 2; | 1037 | nptr = 2; |
1180 | } | 1038 | } |
1181 | /* | 1039 | /* |
1182 | * Fill in the new block's btree header and log it. | 1040 | * Fill in the new block's btree header and log it. |
1183 | */ | 1041 | */ |
1184 | new->bb_magic = cpu_to_be32(xfs_magics[cur->bc_btnum]); | 1042 | new->bb_magic = cpu_to_be32(xfs_magics[cur->bc_btnum]); |
1185 | new->bb_level = cpu_to_be16(cur->bc_nlevels); | 1043 | new->bb_level = cpu_to_be16(cur->bc_nlevels); |
1186 | new->bb_numrecs = cpu_to_be16(2); | 1044 | new->bb_numrecs = cpu_to_be16(2); |
1187 | new->bb_leftsib = cpu_to_be32(NULLAGBLOCK); | 1045 | new->bb_leftsib = cpu_to_be32(NULLAGBLOCK); |
1188 | new->bb_rightsib = cpu_to_be32(NULLAGBLOCK); | 1046 | new->bb_rightsib = cpu_to_be32(NULLAGBLOCK); |
1189 | xfs_alloc_log_block(cur->bc_tp, nbp, XFS_BB_ALL_BITS); | 1047 | xfs_alloc_log_block(cur->bc_tp, nbp, XFS_BB_ALL_BITS); |
1190 | ASSERT(lbno != NULLAGBLOCK && rbno != NULLAGBLOCK); | 1048 | ASSERT(lbno != NULLAGBLOCK && rbno != NULLAGBLOCK); |
1191 | /* | 1049 | /* |
1192 | * Fill in the key data in the new root. | 1050 | * Fill in the key data in the new root. |
1193 | */ | 1051 | */ |
1194 | { | 1052 | { |
1195 | xfs_alloc_key_t *kp; /* btree key pointer */ | 1053 | xfs_alloc_key_t *kp; /* btree key pointer */ |
1196 | 1054 | ||
1197 | kp = XFS_ALLOC_KEY_ADDR(new, 1, cur); | 1055 | kp = XFS_ALLOC_KEY_ADDR(new, 1, cur); |
1198 | if (be16_to_cpu(left->bb_level) > 0) { | 1056 | if (be16_to_cpu(left->bb_level) > 0) { |
1199 | kp[0] = *XFS_ALLOC_KEY_ADDR(left, 1, cur); | 1057 | kp[0] = *XFS_ALLOC_KEY_ADDR(left, 1, cur); |
1200 | kp[1] = *XFS_ALLOC_KEY_ADDR(right, 1, cur); | 1058 | kp[1] = *XFS_ALLOC_KEY_ADDR(right, 1, cur); |
1201 | } else { | 1059 | } else { |
1202 | xfs_alloc_rec_t *rp; /* btree record pointer */ | 1060 | xfs_alloc_rec_t *rp; /* btree record pointer */ |
1203 | 1061 | ||
1204 | rp = XFS_ALLOC_REC_ADDR(left, 1, cur); | 1062 | rp = XFS_ALLOC_REC_ADDR(left, 1, cur); |
1205 | kp[0].ar_startblock = rp->ar_startblock; | 1063 | kp[0].ar_startblock = rp->ar_startblock; |
1206 | kp[0].ar_blockcount = rp->ar_blockcount; | 1064 | kp[0].ar_blockcount = rp->ar_blockcount; |
1207 | rp = XFS_ALLOC_REC_ADDR(right, 1, cur); | 1065 | rp = XFS_ALLOC_REC_ADDR(right, 1, cur); |
1208 | kp[1].ar_startblock = rp->ar_startblock; | 1066 | kp[1].ar_startblock = rp->ar_startblock; |
1209 | kp[1].ar_blockcount = rp->ar_blockcount; | 1067 | kp[1].ar_blockcount = rp->ar_blockcount; |
1210 | } | 1068 | } |
1211 | } | 1069 | } |
1212 | xfs_alloc_log_keys(cur, nbp, 1, 2); | 1070 | xfs_alloc_log_keys(cur, nbp, 1, 2); |
1213 | /* | 1071 | /* |
1214 | * Fill in the pointer data in the new root. | 1072 | * Fill in the pointer data in the new root. |
1215 | */ | 1073 | */ |
1216 | { | 1074 | { |
1217 | xfs_alloc_ptr_t *pp; /* btree address pointer */ | 1075 | xfs_alloc_ptr_t *pp; /* btree address pointer */ |
1218 | 1076 | ||
1219 | pp = XFS_ALLOC_PTR_ADDR(new, 1, cur); | 1077 | pp = XFS_ALLOC_PTR_ADDR(new, 1, cur); |
1220 | pp[0] = cpu_to_be32(lbno); | 1078 | pp[0] = cpu_to_be32(lbno); |
1221 | pp[1] = cpu_to_be32(rbno); | 1079 | pp[1] = cpu_to_be32(rbno); |
1222 | } | 1080 | } |
1223 | xfs_alloc_log_ptrs(cur, nbp, 1, 2); | 1081 | xfs_alloc_log_ptrs(cur, nbp, 1, 2); |
1224 | /* | 1082 | /* |
1225 | * Fix up the cursor. | 1083 | * Fix up the cursor. |
1226 | */ | 1084 | */ |
1227 | xfs_btree_setbuf(cur, cur->bc_nlevels, nbp); | 1085 | xfs_btree_setbuf(cur, cur->bc_nlevels, nbp); |
1228 | cur->bc_ptrs[cur->bc_nlevels] = nptr; | 1086 | cur->bc_ptrs[cur->bc_nlevels] = nptr; |
1229 | cur->bc_nlevels++; | 1087 | cur->bc_nlevels++; |
1230 | *stat = 1; | 1088 | *stat = 1; |
1231 | return 0; | 1089 | return 0; |
1232 | } | 1090 | } |
1233 | 1091 | ||
1234 | /* | 1092 | /* |
1235 | * Split cur/level block in half. | 1093 | * Split cur/level block in half. |
1236 | * Return new block number and its first record (to be inserted into parent). | 1094 | * Return new block number and its first record (to be inserted into parent). |
1237 | */ | 1095 | */ |
1238 | STATIC int /* error */ | 1096 | STATIC int /* error */ |
1239 | xfs_alloc_split( | 1097 | xfs_alloc_split( |
1240 | xfs_btree_cur_t *cur, /* btree cursor */ | 1098 | xfs_btree_cur_t *cur, /* btree cursor */ |
1241 | int level, /* level to split */ | 1099 | int level, /* level to split */ |
1242 | xfs_agblock_t *bnop, /* output: block number allocated */ | 1100 | xfs_agblock_t *bnop, /* output: block number allocated */ |
1243 | xfs_alloc_key_t *keyp, /* output: first key of new block */ | 1101 | xfs_alloc_key_t *keyp, /* output: first key of new block */ |
1244 | xfs_btree_cur_t **curp, /* output: new cursor */ | 1102 | xfs_btree_cur_t **curp, /* output: new cursor */ |
1245 | int *stat) /* success/failure */ | 1103 | int *stat) /* success/failure */ |
1246 | { | 1104 | { |
1247 | int error; /* error return value */ | 1105 | int error; /* error return value */ |
1248 | int i; /* loop index/record number */ | 1106 | int i; /* loop index/record number */ |
1249 | xfs_agblock_t lbno; /* left (current) block number */ | 1107 | xfs_agblock_t lbno; /* left (current) block number */ |
1250 | xfs_buf_t *lbp; /* buffer for left block */ | 1108 | xfs_buf_t *lbp; /* buffer for left block */ |
1251 | xfs_alloc_block_t *left; /* left (current) btree block */ | 1109 | xfs_alloc_block_t *left; /* left (current) btree block */ |
1252 | xfs_agblock_t rbno; /* right (new) block number */ | 1110 | xfs_agblock_t rbno; /* right (new) block number */ |
1253 | xfs_buf_t *rbp; /* buffer for right block */ | 1111 | xfs_buf_t *rbp; /* buffer for right block */ |
1254 | xfs_alloc_block_t *right; /* right (new) btree block */ | 1112 | xfs_alloc_block_t *right; /* right (new) btree block */ |
1255 | 1113 | ||
1256 | /* | 1114 | /* |
1257 | * Allocate the new block from the freelist. | 1115 | * Allocate the new block from the freelist. |
1258 | * If we can't do it, we're toast. Give up. | 1116 | * If we can't do it, we're toast. Give up. |
1259 | */ | 1117 | */ |
1260 | error = xfs_alloc_get_freelist(cur->bc_tp, | 1118 | error = xfs_alloc_get_freelist(cur->bc_tp, |
1261 | cur->bc_private.a.agbp, &rbno, 1); | 1119 | cur->bc_private.a.agbp, &rbno, 1); |
1262 | if (error) | 1120 | if (error) |
1263 | return error; | 1121 | return error; |
1264 | if (rbno == NULLAGBLOCK) { | 1122 | if (rbno == NULLAGBLOCK) { |
1265 | *stat = 0; | 1123 | *stat = 0; |
1266 | return 0; | 1124 | return 0; |
1267 | } | 1125 | } |
1268 | xfs_trans_agbtree_delta(cur->bc_tp, 1); | 1126 | xfs_trans_agbtree_delta(cur->bc_tp, 1); |
1269 | rbp = xfs_btree_get_bufs(cur->bc_mp, cur->bc_tp, cur->bc_private.a.agno, | 1127 | rbp = xfs_btree_get_bufs(cur->bc_mp, cur->bc_tp, cur->bc_private.a.agno, |
1270 | rbno, 0); | 1128 | rbno, 0); |
1271 | /* | 1129 | /* |
1272 | * Set up the new block as "right". | 1130 | * Set up the new block as "right". |
1273 | */ | 1131 | */ |
1274 | right = XFS_BUF_TO_ALLOC_BLOCK(rbp); | 1132 | right = XFS_BUF_TO_ALLOC_BLOCK(rbp); |
1275 | /* | 1133 | /* |
1276 | * "Left" is the current (according to the cursor) block. | 1134 | * "Left" is the current (according to the cursor) block. |
1277 | */ | 1135 | */ |
1278 | lbp = cur->bc_bufs[level]; | 1136 | lbp = cur->bc_bufs[level]; |
1279 | left = XFS_BUF_TO_ALLOC_BLOCK(lbp); | 1137 | left = XFS_BUF_TO_ALLOC_BLOCK(lbp); |
1280 | #ifdef DEBUG | 1138 | #ifdef DEBUG |
1281 | if ((error = xfs_btree_check_sblock(cur, left, level, lbp))) | 1139 | if ((error = xfs_btree_check_sblock(cur, left, level, lbp))) |
1282 | return error; | 1140 | return error; |
1283 | #endif | 1141 | #endif |
1284 | /* | 1142 | /* |
1285 | * Fill in the btree header for the new block. | 1143 | * Fill in the btree header for the new block. |
1286 | */ | 1144 | */ |
1287 | right->bb_magic = cpu_to_be32(xfs_magics[cur->bc_btnum]); | 1145 | right->bb_magic = cpu_to_be32(xfs_magics[cur->bc_btnum]); |
1288 | right->bb_level = left->bb_level; | 1146 | right->bb_level = left->bb_level; |
1289 | right->bb_numrecs = cpu_to_be16(be16_to_cpu(left->bb_numrecs) / 2); | 1147 | right->bb_numrecs = cpu_to_be16(be16_to_cpu(left->bb_numrecs) / 2); |
1290 | /* | 1148 | /* |
1291 | * Make sure that if there's an odd number of entries now, that | 1149 | * Make sure that if there's an odd number of entries now, that |
1292 | * each new block will have the same number of entries. | 1150 | * each new block will have the same number of entries. |
1293 | */ | 1151 | */ |
1294 | if ((be16_to_cpu(left->bb_numrecs) & 1) && | 1152 | if ((be16_to_cpu(left->bb_numrecs) & 1) && |
1295 | cur->bc_ptrs[level] <= be16_to_cpu(right->bb_numrecs) + 1) | 1153 | cur->bc_ptrs[level] <= be16_to_cpu(right->bb_numrecs) + 1) |
1296 | be16_add_cpu(&right->bb_numrecs, 1); | 1154 | be16_add_cpu(&right->bb_numrecs, 1); |
1297 | i = be16_to_cpu(left->bb_numrecs) - be16_to_cpu(right->bb_numrecs) + 1; | 1155 | i = be16_to_cpu(left->bb_numrecs) - be16_to_cpu(right->bb_numrecs) + 1; |
1298 | /* | 1156 | /* |
1299 | * For non-leaf blocks, copy keys and addresses over to the new block. | 1157 | * For non-leaf blocks, copy keys and addresses over to the new block. |
1300 | */ | 1158 | */ |
1301 | if (level > 0) { | 1159 | if (level > 0) { |
1302 | xfs_alloc_key_t *lkp; /* left btree key pointer */ | 1160 | xfs_alloc_key_t *lkp; /* left btree key pointer */ |
1303 | xfs_alloc_ptr_t *lpp; /* left btree address pointer */ | 1161 | xfs_alloc_ptr_t *lpp; /* left btree address pointer */ |
1304 | xfs_alloc_key_t *rkp; /* right btree key pointer */ | 1162 | xfs_alloc_key_t *rkp; /* right btree key pointer */ |
1305 | xfs_alloc_ptr_t *rpp; /* right btree address pointer */ | 1163 | xfs_alloc_ptr_t *rpp; /* right btree address pointer */ |
1306 | 1164 | ||
1307 | lkp = XFS_ALLOC_KEY_ADDR(left, i, cur); | 1165 | lkp = XFS_ALLOC_KEY_ADDR(left, i, cur); |
1308 | lpp = XFS_ALLOC_PTR_ADDR(left, i, cur); | 1166 | lpp = XFS_ALLOC_PTR_ADDR(left, i, cur); |
1309 | rkp = XFS_ALLOC_KEY_ADDR(right, 1, cur); | 1167 | rkp = XFS_ALLOC_KEY_ADDR(right, 1, cur); |
1310 | rpp = XFS_ALLOC_PTR_ADDR(right, 1, cur); | 1168 | rpp = XFS_ALLOC_PTR_ADDR(right, 1, cur); |
1311 | #ifdef DEBUG | 1169 | #ifdef DEBUG |
1312 | for (i = 0; i < be16_to_cpu(right->bb_numrecs); i++) { | 1170 | for (i = 0; i < be16_to_cpu(right->bb_numrecs); i++) { |
1313 | if ((error = xfs_btree_check_sptr(cur, be32_to_cpu(lpp[i]), level))) | 1171 | if ((error = xfs_btree_check_sptr(cur, be32_to_cpu(lpp[i]), level))) |
1314 | return error; | 1172 | return error; |
1315 | } | 1173 | } |
1316 | #endif | 1174 | #endif |
1317 | memcpy(rkp, lkp, be16_to_cpu(right->bb_numrecs) * sizeof(*rkp)); | 1175 | memcpy(rkp, lkp, be16_to_cpu(right->bb_numrecs) * sizeof(*rkp)); |
1318 | memcpy(rpp, lpp, be16_to_cpu(right->bb_numrecs) * sizeof(*rpp)); | 1176 | memcpy(rpp, lpp, be16_to_cpu(right->bb_numrecs) * sizeof(*rpp)); |
1319 | xfs_alloc_log_keys(cur, rbp, 1, be16_to_cpu(right->bb_numrecs)); | 1177 | xfs_alloc_log_keys(cur, rbp, 1, be16_to_cpu(right->bb_numrecs)); |
1320 | xfs_alloc_log_ptrs(cur, rbp, 1, be16_to_cpu(right->bb_numrecs)); | 1178 | xfs_alloc_log_ptrs(cur, rbp, 1, be16_to_cpu(right->bb_numrecs)); |
1321 | *keyp = *rkp; | 1179 | *keyp = *rkp; |
1322 | } | 1180 | } |
1323 | /* | 1181 | /* |
1324 | * For leaf blocks, copy records over to the new block. | 1182 | * For leaf blocks, copy records over to the new block. |
1325 | */ | 1183 | */ |
1326 | else { | 1184 | else { |
1327 | xfs_alloc_rec_t *lrp; /* left btree record pointer */ | 1185 | xfs_alloc_rec_t *lrp; /* left btree record pointer */ |
1328 | xfs_alloc_rec_t *rrp; /* right btree record pointer */ | 1186 | xfs_alloc_rec_t *rrp; /* right btree record pointer */ |
1329 | 1187 | ||
1330 | lrp = XFS_ALLOC_REC_ADDR(left, i, cur); | 1188 | lrp = XFS_ALLOC_REC_ADDR(left, i, cur); |
1331 | rrp = XFS_ALLOC_REC_ADDR(right, 1, cur); | 1189 | rrp = XFS_ALLOC_REC_ADDR(right, 1, cur); |
1332 | memcpy(rrp, lrp, be16_to_cpu(right->bb_numrecs) * sizeof(*rrp)); | 1190 | memcpy(rrp, lrp, be16_to_cpu(right->bb_numrecs) * sizeof(*rrp)); |
1333 | xfs_alloc_log_recs(cur, rbp, 1, be16_to_cpu(right->bb_numrecs)); | 1191 | xfs_alloc_log_recs(cur, rbp, 1, be16_to_cpu(right->bb_numrecs)); |
1334 | keyp->ar_startblock = rrp->ar_startblock; | 1192 | keyp->ar_startblock = rrp->ar_startblock; |
1335 | keyp->ar_blockcount = rrp->ar_blockcount; | 1193 | keyp->ar_blockcount = rrp->ar_blockcount; |
1336 | } | 1194 | } |
1337 | /* | 1195 | /* |
1338 | * Find the left block number by looking in the buffer. | 1196 | * Find the left block number by looking in the buffer. |
1339 | * Adjust numrecs, sibling pointers. | 1197 | * Adjust numrecs, sibling pointers. |
1340 | */ | 1198 | */ |
1341 | lbno = XFS_DADDR_TO_AGBNO(cur->bc_mp, XFS_BUF_ADDR(lbp)); | 1199 | lbno = XFS_DADDR_TO_AGBNO(cur->bc_mp, XFS_BUF_ADDR(lbp)); |
1342 | be16_add_cpu(&left->bb_numrecs, -(be16_to_cpu(right->bb_numrecs))); | 1200 | be16_add_cpu(&left->bb_numrecs, -(be16_to_cpu(right->bb_numrecs))); |
1343 | right->bb_rightsib = left->bb_rightsib; | 1201 | right->bb_rightsib = left->bb_rightsib; |
1344 | left->bb_rightsib = cpu_to_be32(rbno); | 1202 | left->bb_rightsib = cpu_to_be32(rbno); |
1345 | right->bb_leftsib = cpu_to_be32(lbno); | 1203 | right->bb_leftsib = cpu_to_be32(lbno); |
1346 | xfs_alloc_log_block(cur->bc_tp, rbp, XFS_BB_ALL_BITS); | 1204 | xfs_alloc_log_block(cur->bc_tp, rbp, XFS_BB_ALL_BITS); |
1347 | xfs_alloc_log_block(cur->bc_tp, lbp, XFS_BB_NUMRECS | XFS_BB_RIGHTSIB); | 1205 | xfs_alloc_log_block(cur->bc_tp, lbp, XFS_BB_NUMRECS | XFS_BB_RIGHTSIB); |
1348 | /* | 1206 | /* |
1349 | * If there's a block to the new block's right, make that block | 1207 | * If there's a block to the new block's right, make that block |
1350 | * point back to right instead of to left. | 1208 | * point back to right instead of to left. |
1351 | */ | 1209 | */ |
1352 | if (be32_to_cpu(right->bb_rightsib) != NULLAGBLOCK) { | 1210 | if (be32_to_cpu(right->bb_rightsib) != NULLAGBLOCK) { |
1353 | xfs_alloc_block_t *rrblock; /* rr btree block */ | 1211 | xfs_alloc_block_t *rrblock; /* rr btree block */ |
1354 | xfs_buf_t *rrbp; /* buffer for rrblock */ | 1212 | xfs_buf_t *rrbp; /* buffer for rrblock */ |
1355 | 1213 | ||
1356 | if ((error = xfs_btree_read_bufs(cur->bc_mp, cur->bc_tp, | 1214 | if ((error = xfs_btree_read_bufs(cur->bc_mp, cur->bc_tp, |
1357 | cur->bc_private.a.agno, be32_to_cpu(right->bb_rightsib), 0, | 1215 | cur->bc_private.a.agno, be32_to_cpu(right->bb_rightsib), 0, |
1358 | &rrbp, XFS_ALLOC_BTREE_REF))) | 1216 | &rrbp, XFS_ALLOC_BTREE_REF))) |
1359 | return error; | 1217 | return error; |
1360 | rrblock = XFS_BUF_TO_ALLOC_BLOCK(rrbp); | 1218 | rrblock = XFS_BUF_TO_ALLOC_BLOCK(rrbp); |
1361 | if ((error = xfs_btree_check_sblock(cur, rrblock, level, rrbp))) | 1219 | if ((error = xfs_btree_check_sblock(cur, rrblock, level, rrbp))) |
1362 | return error; | 1220 | return error; |
1363 | rrblock->bb_leftsib = cpu_to_be32(rbno); | 1221 | rrblock->bb_leftsib = cpu_to_be32(rbno); |
1364 | xfs_alloc_log_block(cur->bc_tp, rrbp, XFS_BB_LEFTSIB); | 1222 | xfs_alloc_log_block(cur->bc_tp, rrbp, XFS_BB_LEFTSIB); |
1365 | } | 1223 | } |
1366 | /* | 1224 | /* |
1367 | * If the cursor is really in the right block, move it there. | 1225 | * If the cursor is really in the right block, move it there. |
1368 | * If it's just pointing past the last entry in left, then we'll | 1226 | * If it's just pointing past the last entry in left, then we'll |
1369 | * insert there, so don't change anything in that case. | 1227 | * insert there, so don't change anything in that case. |
1370 | */ | 1228 | */ |
1371 | if (cur->bc_ptrs[level] > be16_to_cpu(left->bb_numrecs) + 1) { | 1229 | if (cur->bc_ptrs[level] > be16_to_cpu(left->bb_numrecs) + 1) { |
1372 | xfs_btree_setbuf(cur, level, rbp); | 1230 | xfs_btree_setbuf(cur, level, rbp); |
1373 | cur->bc_ptrs[level] -= be16_to_cpu(left->bb_numrecs); | 1231 | cur->bc_ptrs[level] -= be16_to_cpu(left->bb_numrecs); |
1374 | } | 1232 | } |
1375 | /* | 1233 | /* |
1376 | * If there are more levels, we'll need another cursor which refers to | 1234 | * If there are more levels, we'll need another cursor which refers to |
1377 | * the right block, no matter where this cursor was. | 1235 | * the right block, no matter where this cursor was. |
1378 | */ | 1236 | */ |
1379 | if (level + 1 < cur->bc_nlevels) { | 1237 | if (level + 1 < cur->bc_nlevels) { |
1380 | if ((error = xfs_btree_dup_cursor(cur, curp))) | 1238 | if ((error = xfs_btree_dup_cursor(cur, curp))) |
1381 | return error; | 1239 | return error; |
1382 | (*curp)->bc_ptrs[level + 1]++; | 1240 | (*curp)->bc_ptrs[level + 1]++; |
1383 | } | 1241 | } |
1384 | *bnop = rbno; | 1242 | *bnop = rbno; |
1385 | *stat = 1; | 1243 | *stat = 1; |
1386 | return 0; | 1244 | return 0; |
1387 | } | 1245 | } |
1388 | 1246 | ||
1389 | /* | 1247 | /* |
1390 | * Externally visible routines. | 1248 | * Externally visible routines. |
1391 | */ | 1249 | */ |
1392 | 1250 | ||
1393 | /* | 1251 | /* |
1394 | * Delete the record pointed to by cur. | 1252 | * Delete the record pointed to by cur. |
1395 | * The cursor refers to the place where the record was (could be inserted) | 1253 | * The cursor refers to the place where the record was (could be inserted) |
1396 | * when the operation returns. | 1254 | * when the operation returns. |
1397 | */ | 1255 | */ |
1398 | int /* error */ | 1256 | int /* error */ |
1399 | xfs_alloc_delete( | 1257 | xfs_alloc_delete( |
1400 | xfs_btree_cur_t *cur, /* btree cursor */ | 1258 | xfs_btree_cur_t *cur, /* btree cursor */ |
1401 | int *stat) /* success/failure */ | 1259 | int *stat) /* success/failure */ |
1402 | { | 1260 | { |
1403 | int error; /* error return value */ | 1261 | int error; /* error return value */ |
1404 | int i; /* result code */ | 1262 | int i; /* result code */ |
1405 | int level; /* btree level */ | 1263 | int level; /* btree level */ |
1406 | 1264 | ||
1407 | /* | 1265 | /* |
1408 | * Go up the tree, starting at leaf level. | 1266 | * Go up the tree, starting at leaf level. |
1409 | * If 2 is returned then a join was done; go to the next level. | 1267 | * If 2 is returned then a join was done; go to the next level. |
1410 | * Otherwise we are done. | 1268 | * Otherwise we are done. |
1411 | */ | 1269 | */ |
1412 | for (level = 0, i = 2; i == 2; level++) { | 1270 | for (level = 0, i = 2; i == 2; level++) { |
1413 | if ((error = xfs_alloc_delrec(cur, level, &i))) | 1271 | if ((error = xfs_alloc_delrec(cur, level, &i))) |
1414 | return error; | 1272 | return error; |
1415 | } | 1273 | } |
1416 | if (i == 0) { | 1274 | if (i == 0) { |
1417 | for (level = 1; level < cur->bc_nlevels; level++) { | 1275 | for (level = 1; level < cur->bc_nlevels; level++) { |
1418 | if (cur->bc_ptrs[level] == 0) { | 1276 | if (cur->bc_ptrs[level] == 0) { |
1419 | if ((error = xfs_btree_decrement(cur, level, &i))) | 1277 | if ((error = xfs_btree_decrement(cur, level, &i))) |
1420 | return error; | 1278 | return error; |
1421 | break; | 1279 | break; |
1422 | } | 1280 | } |
1423 | } | 1281 | } |
1424 | } | 1282 | } |
1425 | *stat = i; | 1283 | *stat = i; |
1426 | return 0; | 1284 | return 0; |
1427 | } | 1285 | } |
1428 | 1286 | ||
1429 | /* | 1287 | /* |
1430 | * Get the data from the pointed-to record. | 1288 | * Get the data from the pointed-to record. |
1431 | */ | 1289 | */ |
1432 | int /* error */ | 1290 | int /* error */ |
1433 | xfs_alloc_get_rec( | 1291 | xfs_alloc_get_rec( |
1434 | xfs_btree_cur_t *cur, /* btree cursor */ | 1292 | xfs_btree_cur_t *cur, /* btree cursor */ |
1435 | xfs_agblock_t *bno, /* output: starting block of extent */ | 1293 | xfs_agblock_t *bno, /* output: starting block of extent */ |
1436 | xfs_extlen_t *len, /* output: length of extent */ | 1294 | xfs_extlen_t *len, /* output: length of extent */ |
1437 | int *stat) /* output: success/failure */ | 1295 | int *stat) /* output: success/failure */ |
1438 | { | 1296 | { |
1439 | xfs_alloc_block_t *block; /* btree block */ | 1297 | xfs_alloc_block_t *block; /* btree block */ |
1440 | #ifdef DEBUG | 1298 | #ifdef DEBUG |
1441 | int error; /* error return value */ | 1299 | int error; /* error return value */ |
1442 | #endif | 1300 | #endif |
1443 | int ptr; /* record number */ | 1301 | int ptr; /* record number */ |
1444 | 1302 | ||
1445 | ptr = cur->bc_ptrs[0]; | 1303 | ptr = cur->bc_ptrs[0]; |
1446 | block = XFS_BUF_TO_ALLOC_BLOCK(cur->bc_bufs[0]); | 1304 | block = XFS_BUF_TO_ALLOC_BLOCK(cur->bc_bufs[0]); |
1447 | #ifdef DEBUG | 1305 | #ifdef DEBUG |
1448 | if ((error = xfs_btree_check_sblock(cur, block, 0, cur->bc_bufs[0]))) | 1306 | if ((error = xfs_btree_check_sblock(cur, block, 0, cur->bc_bufs[0]))) |
1449 | return error; | 1307 | return error; |
1450 | #endif | 1308 | #endif |
1451 | /* | 1309 | /* |
1452 | * Off the right end or left end, return failure. | 1310 | * Off the right end or left end, return failure. |
1453 | */ | 1311 | */ |
1454 | if (ptr > be16_to_cpu(block->bb_numrecs) || ptr <= 0) { | 1312 | if (ptr > be16_to_cpu(block->bb_numrecs) || ptr <= 0) { |
1455 | *stat = 0; | 1313 | *stat = 0; |
1456 | return 0; | 1314 | return 0; |
1457 | } | 1315 | } |
1458 | /* | 1316 | /* |
1459 | * Point to the record and extract its data. | 1317 | * Point to the record and extract its data. |
1460 | */ | 1318 | */ |
1461 | { | 1319 | { |
1462 | xfs_alloc_rec_t *rec; /* record data */ | 1320 | xfs_alloc_rec_t *rec; /* record data */ |
1463 | 1321 | ||
1464 | rec = XFS_ALLOC_REC_ADDR(block, ptr, cur); | 1322 | rec = XFS_ALLOC_REC_ADDR(block, ptr, cur); |
1465 | *bno = be32_to_cpu(rec->ar_startblock); | 1323 | *bno = be32_to_cpu(rec->ar_startblock); |
1466 | *len = be32_to_cpu(rec->ar_blockcount); | 1324 | *len = be32_to_cpu(rec->ar_blockcount); |
1467 | } | 1325 | } |
1468 | *stat = 1; | 1326 | *stat = 1; |
1469 | return 0; | 1327 | return 0; |
1470 | } | 1328 | } |
1471 | 1329 | ||
1472 | /* | 1330 | /* |
1473 | * Insert the current record at the point referenced by cur. | 1331 | * Insert the current record at the point referenced by cur. |
1474 | * The cursor may be inconsistent on return if splits have been done. | 1332 | * The cursor may be inconsistent on return if splits have been done. |
1475 | */ | 1333 | */ |
1476 | int /* error */ | 1334 | int /* error */ |
1477 | xfs_alloc_insert( | 1335 | xfs_alloc_insert( |
1478 | xfs_btree_cur_t *cur, /* btree cursor */ | 1336 | xfs_btree_cur_t *cur, /* btree cursor */ |
1479 | int *stat) /* success/failure */ | 1337 | int *stat) /* success/failure */ |
1480 | { | 1338 | { |
1481 | int error; /* error return value */ | 1339 | int error; /* error return value */ |
1482 | int i; /* result value, 0 for failure */ | 1340 | int i; /* result value, 0 for failure */ |
1483 | int level; /* current level number in btree */ | 1341 | int level; /* current level number in btree */ |
1484 | xfs_agblock_t nbno; /* new block number (split result) */ | 1342 | xfs_agblock_t nbno; /* new block number (split result) */ |
1485 | xfs_btree_cur_t *ncur; /* new cursor (split result) */ | 1343 | xfs_btree_cur_t *ncur; /* new cursor (split result) */ |
1486 | xfs_alloc_rec_t nrec; /* record being inserted this level */ | 1344 | xfs_alloc_rec_t nrec; /* record being inserted this level */ |
1487 | xfs_btree_cur_t *pcur; /* previous level's cursor */ | 1345 | xfs_btree_cur_t *pcur; /* previous level's cursor */ |
1488 | 1346 | ||
1489 | level = 0; | 1347 | level = 0; |
1490 | nbno = NULLAGBLOCK; | 1348 | nbno = NULLAGBLOCK; |
1491 | nrec.ar_startblock = cpu_to_be32(cur->bc_rec.a.ar_startblock); | 1349 | nrec.ar_startblock = cpu_to_be32(cur->bc_rec.a.ar_startblock); |
1492 | nrec.ar_blockcount = cpu_to_be32(cur->bc_rec.a.ar_blockcount); | 1350 | nrec.ar_blockcount = cpu_to_be32(cur->bc_rec.a.ar_blockcount); |
1493 | ncur = NULL; | 1351 | ncur = NULL; |
1494 | pcur = cur; | 1352 | pcur = cur; |
1495 | /* | 1353 | /* |
1496 | * Loop going up the tree, starting at the leaf level. | 1354 | * Loop going up the tree, starting at the leaf level. |
1497 | * Stop when we don't get a split block, that must mean that | 1355 | * Stop when we don't get a split block, that must mean that |
1498 | * the insert is finished with this level. | 1356 | * the insert is finished with this level. |
1499 | */ | 1357 | */ |
1500 | do { | 1358 | do { |
1501 | /* | 1359 | /* |
1502 | * Insert nrec/nbno into this level of the tree. | 1360 | * Insert nrec/nbno into this level of the tree. |
1503 | * Note if we fail, nbno will be null. | 1361 | * Note if we fail, nbno will be null. |
1504 | */ | 1362 | */ |
1505 | if ((error = xfs_alloc_insrec(pcur, level++, &nbno, &nrec, &ncur, | 1363 | if ((error = xfs_alloc_insrec(pcur, level++, &nbno, &nrec, &ncur, |
1506 | &i))) { | 1364 | &i))) { |
1507 | if (pcur != cur) | 1365 | if (pcur != cur) |
1508 | xfs_btree_del_cursor(pcur, XFS_BTREE_ERROR); | 1366 | xfs_btree_del_cursor(pcur, XFS_BTREE_ERROR); |
1509 | return error; | 1367 | return error; |
1510 | } | 1368 | } |
1511 | /* | 1369 | /* |
1512 | * See if the cursor we just used is trash. | 1370 | * See if the cursor we just used is trash. |
1513 | * Can't trash the caller's cursor, but otherwise we should | 1371 | * Can't trash the caller's cursor, but otherwise we should |
1514 | * if ncur is a new cursor or we're about to be done. | 1372 | * if ncur is a new cursor or we're about to be done. |
1515 | */ | 1373 | */ |
1516 | if (pcur != cur && (ncur || nbno == NULLAGBLOCK)) { | 1374 | if (pcur != cur && (ncur || nbno == NULLAGBLOCK)) { |
1517 | cur->bc_nlevels = pcur->bc_nlevels; | 1375 | cur->bc_nlevels = pcur->bc_nlevels; |
1518 | xfs_btree_del_cursor(pcur, XFS_BTREE_NOERROR); | 1376 | xfs_btree_del_cursor(pcur, XFS_BTREE_NOERROR); |
1519 | } | 1377 | } |
1520 | /* | 1378 | /* |
1521 | * If we got a new cursor, switch to it. | 1379 | * If we got a new cursor, switch to it. |
1522 | */ | 1380 | */ |
1523 | if (ncur) { | 1381 | if (ncur) { |
1524 | pcur = ncur; | 1382 | pcur = ncur; |
1525 | ncur = NULL; | 1383 | ncur = NULL; |
1526 | } | 1384 | } |
1527 | } while (nbno != NULLAGBLOCK); | 1385 | } while (nbno != NULLAGBLOCK); |
1528 | *stat = i; | 1386 | *stat = i; |
1529 | return 0; | 1387 | return 0; |
1530 | } | 1388 | } |
1531 | 1389 | ||
1532 | STATIC struct xfs_btree_cur * | 1390 | STATIC struct xfs_btree_cur * |
1533 | xfs_allocbt_dup_cursor( | 1391 | xfs_allocbt_dup_cursor( |
1534 | struct xfs_btree_cur *cur) | 1392 | struct xfs_btree_cur *cur) |
1535 | { | 1393 | { |
1536 | return xfs_allocbt_init_cursor(cur->bc_mp, cur->bc_tp, | 1394 | return xfs_allocbt_init_cursor(cur->bc_mp, cur->bc_tp, |
1537 | cur->bc_private.a.agbp, cur->bc_private.a.agno, | 1395 | cur->bc_private.a.agbp, cur->bc_private.a.agno, |
1538 | cur->bc_btnum); | 1396 | cur->bc_btnum); |
1539 | } | 1397 | } |
1540 | 1398 | ||
1541 | /* | 1399 | /* |
1542 | * Update the longest extent in the AGF | 1400 | * Update the longest extent in the AGF |
1543 | */ | 1401 | */ |
1544 | STATIC void | 1402 | STATIC void |
1545 | xfs_allocbt_update_lastrec( | 1403 | xfs_allocbt_update_lastrec( |
1546 | struct xfs_btree_cur *cur, | 1404 | struct xfs_btree_cur *cur, |
1547 | struct xfs_btree_block *block, | 1405 | struct xfs_btree_block *block, |
1548 | union xfs_btree_rec *rec, | 1406 | union xfs_btree_rec *rec, |
1549 | int ptr, | 1407 | int ptr, |
1550 | int reason) | 1408 | int reason) |
1551 | { | 1409 | { |
1552 | struct xfs_agf *agf = XFS_BUF_TO_AGF(cur->bc_private.a.agbp); | 1410 | struct xfs_agf *agf = XFS_BUF_TO_AGF(cur->bc_private.a.agbp); |
1553 | xfs_agnumber_t seqno = be32_to_cpu(agf->agf_seqno); | 1411 | xfs_agnumber_t seqno = be32_to_cpu(agf->agf_seqno); |
1554 | __be32 len; | 1412 | __be32 len; |
1555 | 1413 | ||
1556 | ASSERT(cur->bc_btnum == XFS_BTNUM_CNT); | 1414 | ASSERT(cur->bc_btnum == XFS_BTNUM_CNT); |
1557 | 1415 | ||
1558 | switch (reason) { | 1416 | switch (reason) { |
1559 | case LASTREC_UPDATE: | 1417 | case LASTREC_UPDATE: |
1560 | /* | 1418 | /* |
1561 | * If this is the last leaf block and it's the last record, | 1419 | * If this is the last leaf block and it's the last record, |
1562 | * then update the size of the longest extent in the AG. | 1420 | * then update the size of the longest extent in the AG. |
1563 | */ | 1421 | */ |
1564 | if (ptr != xfs_btree_get_numrecs(block)) | 1422 | if (ptr != xfs_btree_get_numrecs(block)) |
1565 | return; | 1423 | return; |
1566 | len = rec->alloc.ar_blockcount; | 1424 | len = rec->alloc.ar_blockcount; |
1567 | break; | 1425 | break; |
1568 | default: | 1426 | default: |
1569 | ASSERT(0); | 1427 | ASSERT(0); |
1570 | return; | 1428 | return; |
1571 | } | 1429 | } |
1572 | 1430 | ||
1573 | agf->agf_longest = len; | 1431 | agf->agf_longest = len; |
1574 | cur->bc_mp->m_perag[seqno].pagf_longest = be32_to_cpu(len); | 1432 | cur->bc_mp->m_perag[seqno].pagf_longest = be32_to_cpu(len); |
1575 | xfs_alloc_log_agf(cur->bc_tp, cur->bc_private.a.agbp, XFS_AGF_LONGEST); | 1433 | xfs_alloc_log_agf(cur->bc_tp, cur->bc_private.a.agbp, XFS_AGF_LONGEST); |
1576 | } | 1434 | } |
1577 | 1435 | ||
1578 | STATIC int | 1436 | STATIC int |
1579 | xfs_allocbt_get_maxrecs( | 1437 | xfs_allocbt_get_maxrecs( |
1580 | struct xfs_btree_cur *cur, | 1438 | struct xfs_btree_cur *cur, |
1581 | int level) | 1439 | int level) |
1582 | { | 1440 | { |
1583 | return cur->bc_mp->m_alloc_mxr[level != 0]; | 1441 | return cur->bc_mp->m_alloc_mxr[level != 0]; |
1584 | } | 1442 | } |
1585 | 1443 | ||
1586 | STATIC void | 1444 | STATIC void |
1587 | xfs_allocbt_init_key_from_rec( | 1445 | xfs_allocbt_init_key_from_rec( |
1588 | union xfs_btree_key *key, | 1446 | union xfs_btree_key *key, |
1589 | union xfs_btree_rec *rec) | 1447 | union xfs_btree_rec *rec) |
1590 | { | 1448 | { |
1591 | ASSERT(rec->alloc.ar_startblock != 0); | 1449 | ASSERT(rec->alloc.ar_startblock != 0); |
1592 | 1450 | ||
1593 | key->alloc.ar_startblock = rec->alloc.ar_startblock; | 1451 | key->alloc.ar_startblock = rec->alloc.ar_startblock; |
1594 | key->alloc.ar_blockcount = rec->alloc.ar_blockcount; | 1452 | key->alloc.ar_blockcount = rec->alloc.ar_blockcount; |
1595 | } | 1453 | } |
1596 | 1454 | ||
1597 | STATIC void | 1455 | STATIC void |
1598 | xfs_allocbt_init_ptr_from_cur( | 1456 | xfs_allocbt_init_ptr_from_cur( |
1599 | struct xfs_btree_cur *cur, | 1457 | struct xfs_btree_cur *cur, |
1600 | union xfs_btree_ptr *ptr) | 1458 | union xfs_btree_ptr *ptr) |
1601 | { | 1459 | { |
1602 | struct xfs_agf *agf = XFS_BUF_TO_AGF(cur->bc_private.a.agbp); | 1460 | struct xfs_agf *agf = XFS_BUF_TO_AGF(cur->bc_private.a.agbp); |
1603 | 1461 | ||
1604 | ASSERT(cur->bc_private.a.agno == be32_to_cpu(agf->agf_seqno)); | 1462 | ASSERT(cur->bc_private.a.agno == be32_to_cpu(agf->agf_seqno)); |
1605 | ASSERT(agf->agf_roots[cur->bc_btnum] != 0); | 1463 | ASSERT(agf->agf_roots[cur->bc_btnum] != 0); |
1606 | 1464 | ||
1607 | ptr->s = agf->agf_roots[cur->bc_btnum]; | 1465 | ptr->s = agf->agf_roots[cur->bc_btnum]; |
1608 | } | 1466 | } |
1609 | 1467 | ||
1610 | STATIC __int64_t | 1468 | STATIC __int64_t |
1611 | xfs_allocbt_key_diff( | 1469 | xfs_allocbt_key_diff( |
1612 | struct xfs_btree_cur *cur, | 1470 | struct xfs_btree_cur *cur, |
1613 | union xfs_btree_key *key) | 1471 | union xfs_btree_key *key) |
1614 | { | 1472 | { |
1615 | xfs_alloc_rec_incore_t *rec = &cur->bc_rec.a; | 1473 | xfs_alloc_rec_incore_t *rec = &cur->bc_rec.a; |
1616 | xfs_alloc_key_t *kp = &key->alloc; | 1474 | xfs_alloc_key_t *kp = &key->alloc; |
1617 | __int64_t diff; | 1475 | __int64_t diff; |
1618 | 1476 | ||
1619 | if (cur->bc_btnum == XFS_BTNUM_BNO) { | 1477 | if (cur->bc_btnum == XFS_BTNUM_BNO) { |
1620 | return (__int64_t)be32_to_cpu(kp->ar_startblock) - | 1478 | return (__int64_t)be32_to_cpu(kp->ar_startblock) - |
1621 | rec->ar_startblock; | 1479 | rec->ar_startblock; |
1622 | } | 1480 | } |
1623 | 1481 | ||
1624 | diff = (__int64_t)be32_to_cpu(kp->ar_blockcount) - rec->ar_blockcount; | 1482 | diff = (__int64_t)be32_to_cpu(kp->ar_blockcount) - rec->ar_blockcount; |
1625 | if (diff) | 1483 | if (diff) |
1626 | return diff; | 1484 | return diff; |
1627 | 1485 | ||
1628 | return (__int64_t)be32_to_cpu(kp->ar_startblock) - rec->ar_startblock; | 1486 | return (__int64_t)be32_to_cpu(kp->ar_startblock) - rec->ar_startblock; |
1629 | } | 1487 | } |
1630 | 1488 | ||
1631 | #ifdef XFS_BTREE_TRACE | 1489 | #ifdef XFS_BTREE_TRACE |
1632 | ktrace_t *xfs_allocbt_trace_buf; | 1490 | ktrace_t *xfs_allocbt_trace_buf; |
1633 | 1491 | ||
1634 | STATIC void | 1492 | STATIC void |
1635 | xfs_allocbt_trace_enter( | 1493 | xfs_allocbt_trace_enter( |
1636 | struct xfs_btree_cur *cur, | 1494 | struct xfs_btree_cur *cur, |
1637 | const char *func, | 1495 | const char *func, |
1638 | char *s, | 1496 | char *s, |
1639 | int type, | 1497 | int type, |
1640 | int line, | 1498 | int line, |
1641 | __psunsigned_t a0, | 1499 | __psunsigned_t a0, |
1642 | __psunsigned_t a1, | 1500 | __psunsigned_t a1, |
1643 | __psunsigned_t a2, | 1501 | __psunsigned_t a2, |
1644 | __psunsigned_t a3, | 1502 | __psunsigned_t a3, |
1645 | __psunsigned_t a4, | 1503 | __psunsigned_t a4, |
1646 | __psunsigned_t a5, | 1504 | __psunsigned_t a5, |
1647 | __psunsigned_t a6, | 1505 | __psunsigned_t a6, |
1648 | __psunsigned_t a7, | 1506 | __psunsigned_t a7, |
1649 | __psunsigned_t a8, | 1507 | __psunsigned_t a8, |
1650 | __psunsigned_t a9, | 1508 | __psunsigned_t a9, |
1651 | __psunsigned_t a10) | 1509 | __psunsigned_t a10) |
1652 | { | 1510 | { |
1653 | ktrace_enter(xfs_allocbt_trace_buf, (void *)(__psint_t)type, | 1511 | ktrace_enter(xfs_allocbt_trace_buf, (void *)(__psint_t)type, |
1654 | (void *)func, (void *)s, NULL, (void *)cur, | 1512 | (void *)func, (void *)s, NULL, (void *)cur, |
1655 | (void *)a0, (void *)a1, (void *)a2, (void *)a3, | 1513 | (void *)a0, (void *)a1, (void *)a2, (void *)a3, |
1656 | (void *)a4, (void *)a5, (void *)a6, (void *)a7, | 1514 | (void *)a4, (void *)a5, (void *)a6, (void *)a7, |
1657 | (void *)a8, (void *)a9, (void *)a10); | 1515 | (void *)a8, (void *)a9, (void *)a10); |
1658 | } | 1516 | } |
1659 | 1517 | ||
1660 | STATIC void | 1518 | STATIC void |
1661 | xfs_allocbt_trace_cursor( | 1519 | xfs_allocbt_trace_cursor( |
1662 | struct xfs_btree_cur *cur, | 1520 | struct xfs_btree_cur *cur, |
1663 | __uint32_t *s0, | 1521 | __uint32_t *s0, |
1664 | __uint64_t *l0, | 1522 | __uint64_t *l0, |
1665 | __uint64_t *l1) | 1523 | __uint64_t *l1) |
1666 | { | 1524 | { |
1667 | *s0 = cur->bc_private.a.agno; | 1525 | *s0 = cur->bc_private.a.agno; |
1668 | *l0 = cur->bc_rec.a.ar_startblock; | 1526 | *l0 = cur->bc_rec.a.ar_startblock; |
1669 | *l1 = cur->bc_rec.a.ar_blockcount; | 1527 | *l1 = cur->bc_rec.a.ar_blockcount; |
1670 | } | 1528 | } |
1671 | 1529 | ||
1672 | STATIC void | 1530 | STATIC void |
1673 | xfs_allocbt_trace_key( | 1531 | xfs_allocbt_trace_key( |
1674 | struct xfs_btree_cur *cur, | 1532 | struct xfs_btree_cur *cur, |
1675 | union xfs_btree_key *key, | 1533 | union xfs_btree_key *key, |
1676 | __uint64_t *l0, | 1534 | __uint64_t *l0, |
1677 | __uint64_t *l1) | 1535 | __uint64_t *l1) |
1678 | { | 1536 | { |
1679 | *l0 = be32_to_cpu(key->alloc.ar_startblock); | 1537 | *l0 = be32_to_cpu(key->alloc.ar_startblock); |
1680 | *l1 = be32_to_cpu(key->alloc.ar_blockcount); | 1538 | *l1 = be32_to_cpu(key->alloc.ar_blockcount); |
1681 | } | 1539 | } |
1682 | 1540 | ||
1683 | STATIC void | 1541 | STATIC void |
1684 | xfs_allocbt_trace_record( | 1542 | xfs_allocbt_trace_record( |
1685 | struct xfs_btree_cur *cur, | 1543 | struct xfs_btree_cur *cur, |
1686 | union xfs_btree_rec *rec, | 1544 | union xfs_btree_rec *rec, |
1687 | __uint64_t *l0, | 1545 | __uint64_t *l0, |
1688 | __uint64_t *l1, | 1546 | __uint64_t *l1, |
1689 | __uint64_t *l2) | 1547 | __uint64_t *l2) |
1690 | { | 1548 | { |
1691 | *l0 = be32_to_cpu(rec->alloc.ar_startblock); | 1549 | *l0 = be32_to_cpu(rec->alloc.ar_startblock); |
1692 | *l1 = be32_to_cpu(rec->alloc.ar_blockcount); | 1550 | *l1 = be32_to_cpu(rec->alloc.ar_blockcount); |
1693 | *l2 = 0; | 1551 | *l2 = 0; |
1694 | } | 1552 | } |
1695 | #endif /* XFS_BTREE_TRACE */ | 1553 | #endif /* XFS_BTREE_TRACE */ |
1696 | 1554 | ||
1697 | static const struct xfs_btree_ops xfs_allocbt_ops = { | 1555 | static const struct xfs_btree_ops xfs_allocbt_ops = { |
1698 | .rec_len = sizeof(xfs_alloc_rec_t), | 1556 | .rec_len = sizeof(xfs_alloc_rec_t), |
1699 | .key_len = sizeof(xfs_alloc_key_t), | 1557 | .key_len = sizeof(xfs_alloc_key_t), |
1700 | 1558 | ||
1701 | .dup_cursor = xfs_allocbt_dup_cursor, | 1559 | .dup_cursor = xfs_allocbt_dup_cursor, |
1702 | .update_lastrec = xfs_allocbt_update_lastrec, | 1560 | .update_lastrec = xfs_allocbt_update_lastrec, |
1703 | .get_maxrecs = xfs_allocbt_get_maxrecs, | 1561 | .get_maxrecs = xfs_allocbt_get_maxrecs, |
1704 | .init_key_from_rec = xfs_allocbt_init_key_from_rec, | 1562 | .init_key_from_rec = xfs_allocbt_init_key_from_rec, |
1705 | .init_ptr_from_cur = xfs_allocbt_init_ptr_from_cur, | 1563 | .init_ptr_from_cur = xfs_allocbt_init_ptr_from_cur, |
1706 | .key_diff = xfs_allocbt_key_diff, | 1564 | .key_diff = xfs_allocbt_key_diff, |
1707 | 1565 | ||
1708 | #ifdef XFS_BTREE_TRACE | 1566 | #ifdef XFS_BTREE_TRACE |
1709 | .trace_enter = xfs_allocbt_trace_enter, | 1567 | .trace_enter = xfs_allocbt_trace_enter, |
1710 | .trace_cursor = xfs_allocbt_trace_cursor, | 1568 | .trace_cursor = xfs_allocbt_trace_cursor, |
1711 | .trace_key = xfs_allocbt_trace_key, | 1569 | .trace_key = xfs_allocbt_trace_key, |
1712 | .trace_record = xfs_allocbt_trace_record, | 1570 | .trace_record = xfs_allocbt_trace_record, |
1713 | #endif | 1571 | #endif |
1714 | }; | 1572 | }; |
1715 | 1573 | ||
1716 | /* | 1574 | /* |
1717 | * Allocate a new allocation btree cursor. | 1575 | * Allocate a new allocation btree cursor. |
1718 | */ | 1576 | */ |
1719 | struct xfs_btree_cur * /* new alloc btree cursor */ | 1577 | struct xfs_btree_cur * /* new alloc btree cursor */ |
1720 | xfs_allocbt_init_cursor( | 1578 | xfs_allocbt_init_cursor( |
1721 | struct xfs_mount *mp, /* file system mount point */ | 1579 | struct xfs_mount *mp, /* file system mount point */ |
1722 | struct xfs_trans *tp, /* transaction pointer */ | 1580 | struct xfs_trans *tp, /* transaction pointer */ |
1723 | struct xfs_buf *agbp, /* buffer for agf structure */ | 1581 | struct xfs_buf *agbp, /* buffer for agf structure */ |
1724 | xfs_agnumber_t agno, /* allocation group number */ | 1582 | xfs_agnumber_t agno, /* allocation group number */ |
1725 | xfs_btnum_t btnum) /* btree identifier */ | 1583 | xfs_btnum_t btnum) /* btree identifier */ |
1726 | { | 1584 | { |
1727 | struct xfs_agf *agf = XFS_BUF_TO_AGF(agbp); | 1585 | struct xfs_agf *agf = XFS_BUF_TO_AGF(agbp); |
1728 | struct xfs_btree_cur *cur; | 1586 | struct xfs_btree_cur *cur; |
1729 | 1587 | ||
1730 | ASSERT(btnum == XFS_BTNUM_BNO || btnum == XFS_BTNUM_CNT); | 1588 | ASSERT(btnum == XFS_BTNUM_BNO || btnum == XFS_BTNUM_CNT); |
1731 | 1589 | ||
1732 | cur = kmem_zone_zalloc(xfs_btree_cur_zone, KM_SLEEP); | 1590 | cur = kmem_zone_zalloc(xfs_btree_cur_zone, KM_SLEEP); |
1733 | 1591 | ||
1734 | cur->bc_tp = tp; | 1592 | cur->bc_tp = tp; |
1735 | cur->bc_mp = mp; | 1593 | cur->bc_mp = mp; |
1736 | cur->bc_nlevels = be32_to_cpu(agf->agf_levels[btnum]); | 1594 | cur->bc_nlevels = be32_to_cpu(agf->agf_levels[btnum]); |
1737 | cur->bc_btnum = btnum; | 1595 | cur->bc_btnum = btnum; |
1738 | cur->bc_blocklog = mp->m_sb.sb_blocklog; | 1596 | cur->bc_blocklog = mp->m_sb.sb_blocklog; |
1739 | 1597 | ||
1740 | cur->bc_ops = &xfs_allocbt_ops; | 1598 | cur->bc_ops = &xfs_allocbt_ops; |
1741 | if (btnum == XFS_BTNUM_CNT) | 1599 | if (btnum == XFS_BTNUM_CNT) |
1742 | cur->bc_flags = XFS_BTREE_LASTREC_UPDATE; | 1600 | cur->bc_flags = XFS_BTREE_LASTREC_UPDATE; |
1743 | 1601 | ||
1744 | cur->bc_private.a.agbp = agbp; | 1602 | cur->bc_private.a.agbp = agbp; |
1745 | cur->bc_private.a.agno = agno; | 1603 | cur->bc_private.a.agno = agno; |
1746 | 1604 | ||
1747 | return cur; | 1605 | return cur; |
1748 | } | 1606 | } |
1749 | 1607 |
fs/xfs/xfs_bmap_btree.c
1 | /* | 1 | /* |
2 | * Copyright (c) 2000-2003,2005 Silicon Graphics, Inc. | 2 | * Copyright (c) 2000-2003,2005 Silicon Graphics, Inc. |
3 | * All Rights Reserved. | 3 | * All Rights Reserved. |
4 | * | 4 | * |
5 | * This program is free software; you can redistribute it and/or | 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 | 6 | * modify it under the terms of the GNU General Public License as |
7 | * published by the Free Software Foundation. | 7 | * published by the Free Software Foundation. |
8 | * | 8 | * |
9 | * This program is distributed in the hope that it would be useful, | 9 | * This program is distributed in the hope that it would be useful, |
10 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | 10 | * but WITHOUT ANY WARRANTY; without even the implied warranty of |
11 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | 11 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
12 | * GNU General Public License for more details. | 12 | * GNU General Public License for more details. |
13 | * | 13 | * |
14 | * You should have received a copy of the GNU General Public License | 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, | 15 | * along with this program; if not, write the Free Software Foundation, |
16 | * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA | 16 | * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA |
17 | */ | 17 | */ |
18 | #include "xfs.h" | 18 | #include "xfs.h" |
19 | #include "xfs_fs.h" | 19 | #include "xfs_fs.h" |
20 | #include "xfs_types.h" | 20 | #include "xfs_types.h" |
21 | #include "xfs_bit.h" | 21 | #include "xfs_bit.h" |
22 | #include "xfs_log.h" | 22 | #include "xfs_log.h" |
23 | #include "xfs_inum.h" | 23 | #include "xfs_inum.h" |
24 | #include "xfs_trans.h" | 24 | #include "xfs_trans.h" |
25 | #include "xfs_sb.h" | 25 | #include "xfs_sb.h" |
26 | #include "xfs_ag.h" | 26 | #include "xfs_ag.h" |
27 | #include "xfs_dir2.h" | 27 | #include "xfs_dir2.h" |
28 | #include "xfs_dmapi.h" | 28 | #include "xfs_dmapi.h" |
29 | #include "xfs_mount.h" | 29 | #include "xfs_mount.h" |
30 | #include "xfs_bmap_btree.h" | 30 | #include "xfs_bmap_btree.h" |
31 | #include "xfs_alloc_btree.h" | 31 | #include "xfs_alloc_btree.h" |
32 | #include "xfs_ialloc_btree.h" | 32 | #include "xfs_ialloc_btree.h" |
33 | #include "xfs_dir2_sf.h" | 33 | #include "xfs_dir2_sf.h" |
34 | #include "xfs_attr_sf.h" | 34 | #include "xfs_attr_sf.h" |
35 | #include "xfs_dinode.h" | 35 | #include "xfs_dinode.h" |
36 | #include "xfs_inode.h" | 36 | #include "xfs_inode.h" |
37 | #include "xfs_inode_item.h" | 37 | #include "xfs_inode_item.h" |
38 | #include "xfs_alloc.h" | 38 | #include "xfs_alloc.h" |
39 | #include "xfs_btree.h" | 39 | #include "xfs_btree.h" |
40 | #include "xfs_btree_trace.h" | 40 | #include "xfs_btree_trace.h" |
41 | #include "xfs_ialloc.h" | 41 | #include "xfs_ialloc.h" |
42 | #include "xfs_itable.h" | 42 | #include "xfs_itable.h" |
43 | #include "xfs_bmap.h" | 43 | #include "xfs_bmap.h" |
44 | #include "xfs_error.h" | 44 | #include "xfs_error.h" |
45 | #include "xfs_quota.h" | 45 | #include "xfs_quota.h" |
46 | 46 | ||
47 | /* | 47 | /* |
48 | * Prototypes for internal btree functions. | 48 | * Prototypes for internal btree functions. |
49 | */ | 49 | */ |
50 | 50 | ||
51 | 51 | ||
52 | STATIC int xfs_bmbt_killroot(xfs_btree_cur_t *); | 52 | STATIC int xfs_bmbt_killroot(xfs_btree_cur_t *); |
53 | STATIC void xfs_bmbt_log_keys(xfs_btree_cur_t *, xfs_buf_t *, int, int); | 53 | STATIC void xfs_bmbt_log_keys(xfs_btree_cur_t *, xfs_buf_t *, int, int); |
54 | STATIC void xfs_bmbt_log_ptrs(xfs_btree_cur_t *, xfs_buf_t *, int, int); | 54 | STATIC void xfs_bmbt_log_ptrs(xfs_btree_cur_t *, xfs_buf_t *, int, int); |
55 | STATIC int xfs_bmbt_lshift(xfs_btree_cur_t *, int, int *); | ||
56 | STATIC int xfs_bmbt_split(xfs_btree_cur_t *, int, xfs_fsblock_t *, | 55 | STATIC int xfs_bmbt_split(xfs_btree_cur_t *, int, xfs_fsblock_t *, |
57 | __uint64_t *, xfs_btree_cur_t **, int *); | 56 | __uint64_t *, xfs_btree_cur_t **, int *); |
58 | 57 | ||
59 | #undef EXIT | 58 | #undef EXIT |
60 | 59 | ||
61 | #define ENTRY XBT_ENTRY | 60 | #define ENTRY XBT_ENTRY |
62 | #define ERROR XBT_ERROR | 61 | #define ERROR XBT_ERROR |
63 | #define EXIT XBT_EXIT | 62 | #define EXIT XBT_EXIT |
64 | 63 | ||
65 | /* | 64 | /* |
66 | * Keep the XFS_BMBT_TRACE_ names around for now until all code using them | 65 | * Keep the XFS_BMBT_TRACE_ names around for now until all code using them |
67 | * is converted to be generic and thus switches to the XFS_BTREE_TRACE_ names. | 66 | * is converted to be generic and thus switches to the XFS_BTREE_TRACE_ names. |
68 | */ | 67 | */ |
69 | #define XFS_BMBT_TRACE_ARGBI(c,b,i) \ | 68 | #define XFS_BMBT_TRACE_ARGBI(c,b,i) \ |
70 | XFS_BTREE_TRACE_ARGBI(c,b,i) | 69 | XFS_BTREE_TRACE_ARGBI(c,b,i) |
71 | #define XFS_BMBT_TRACE_ARGBII(c,b,i,j) \ | 70 | #define XFS_BMBT_TRACE_ARGBII(c,b,i,j) \ |
72 | XFS_BTREE_TRACE_ARGBII(c,b,i,j) | 71 | XFS_BTREE_TRACE_ARGBII(c,b,i,j) |
73 | #define XFS_BMBT_TRACE_ARGFFFI(c,o,b,i,j) \ | 72 | #define XFS_BMBT_TRACE_ARGFFFI(c,o,b,i,j) \ |
74 | XFS_BTREE_TRACE_ARGFFFI(c,o,b,i,j) | 73 | XFS_BTREE_TRACE_ARGFFFI(c,o,b,i,j) |
75 | #define XFS_BMBT_TRACE_ARGI(c,i) \ | 74 | #define XFS_BMBT_TRACE_ARGI(c,i) \ |
76 | XFS_BTREE_TRACE_ARGI(c,i) | 75 | XFS_BTREE_TRACE_ARGI(c,i) |
77 | #define XFS_BMBT_TRACE_ARGIFK(c,i,f,s) \ | 76 | #define XFS_BMBT_TRACE_ARGIFK(c,i,f,s) \ |
78 | XFS_BTREE_TRACE_ARGIPK(c,i,(union xfs_btree_ptr)f,s) | 77 | XFS_BTREE_TRACE_ARGIPK(c,i,(union xfs_btree_ptr)f,s) |
79 | #define XFS_BMBT_TRACE_ARGIFR(c,i,f,r) \ | 78 | #define XFS_BMBT_TRACE_ARGIFR(c,i,f,r) \ |
80 | XFS_BTREE_TRACE_ARGIPR(c,i, \ | 79 | XFS_BTREE_TRACE_ARGIPR(c,i, \ |
81 | (union xfs_btree_ptr)f, (union xfs_btree_rec *)r) | 80 | (union xfs_btree_ptr)f, (union xfs_btree_rec *)r) |
82 | #define XFS_BMBT_TRACE_ARGIK(c,i,k) \ | 81 | #define XFS_BMBT_TRACE_ARGIK(c,i,k) \ |
83 | XFS_BTREE_TRACE_ARGIK(c,i,(union xfs_btree_key *)k) | 82 | XFS_BTREE_TRACE_ARGIK(c,i,(union xfs_btree_key *)k) |
84 | #define XFS_BMBT_TRACE_CURSOR(c,s) \ | 83 | #define XFS_BMBT_TRACE_CURSOR(c,s) \ |
85 | XFS_BTREE_TRACE_CURSOR(c,s) | 84 | XFS_BTREE_TRACE_CURSOR(c,s) |
86 | 85 | ||
87 | 86 | ||
88 | /* | 87 | /* |
89 | * Internal functions. | 88 | * Internal functions. |
90 | */ | 89 | */ |
91 | 90 | ||
92 | /* | 91 | /* |
93 | * Delete record pointed to by cur/level. | 92 | * Delete record pointed to by cur/level. |
94 | */ | 93 | */ |
95 | STATIC int /* error */ | 94 | STATIC int /* error */ |
96 | xfs_bmbt_delrec( | 95 | xfs_bmbt_delrec( |
97 | xfs_btree_cur_t *cur, | 96 | xfs_btree_cur_t *cur, |
98 | int level, | 97 | int level, |
99 | int *stat) /* success/failure */ | 98 | int *stat) /* success/failure */ |
100 | { | 99 | { |
101 | xfs_bmbt_block_t *block; /* bmap btree block */ | 100 | xfs_bmbt_block_t *block; /* bmap btree block */ |
102 | xfs_fsblock_t bno; /* fs-relative block number */ | 101 | xfs_fsblock_t bno; /* fs-relative block number */ |
103 | xfs_buf_t *bp; /* buffer for block */ | 102 | xfs_buf_t *bp; /* buffer for block */ |
104 | int error; /* error return value */ | 103 | int error; /* error return value */ |
105 | int i; /* loop counter */ | 104 | int i; /* loop counter */ |
106 | int j; /* temp state */ | 105 | int j; /* temp state */ |
107 | xfs_bmbt_key_t key; /* bmap btree key */ | 106 | xfs_bmbt_key_t key; /* bmap btree key */ |
108 | xfs_bmbt_key_t *kp=NULL; /* pointer to bmap btree key */ | 107 | xfs_bmbt_key_t *kp=NULL; /* pointer to bmap btree key */ |
109 | xfs_fsblock_t lbno; /* left sibling block number */ | 108 | xfs_fsblock_t lbno; /* left sibling block number */ |
110 | xfs_buf_t *lbp; /* left buffer pointer */ | 109 | xfs_buf_t *lbp; /* left buffer pointer */ |
111 | xfs_bmbt_block_t *left; /* left btree block */ | 110 | xfs_bmbt_block_t *left; /* left btree block */ |
112 | xfs_bmbt_key_t *lkp; /* left btree key */ | 111 | xfs_bmbt_key_t *lkp; /* left btree key */ |
113 | xfs_bmbt_ptr_t *lpp; /* left address pointer */ | 112 | xfs_bmbt_ptr_t *lpp; /* left address pointer */ |
114 | int lrecs=0; /* left record count */ | 113 | int lrecs=0; /* left record count */ |
115 | xfs_bmbt_rec_t *lrp; /* left record pointer */ | 114 | xfs_bmbt_rec_t *lrp; /* left record pointer */ |
116 | xfs_mount_t *mp; /* file system mount point */ | 115 | xfs_mount_t *mp; /* file system mount point */ |
117 | xfs_bmbt_ptr_t *pp; /* pointer to bmap block addr */ | 116 | xfs_bmbt_ptr_t *pp; /* pointer to bmap block addr */ |
118 | int ptr; /* key/record index */ | 117 | int ptr; /* key/record index */ |
119 | xfs_fsblock_t rbno; /* right sibling block number */ | 118 | xfs_fsblock_t rbno; /* right sibling block number */ |
120 | xfs_buf_t *rbp; /* right buffer pointer */ | 119 | xfs_buf_t *rbp; /* right buffer pointer */ |
121 | xfs_bmbt_block_t *right; /* right btree block */ | 120 | xfs_bmbt_block_t *right; /* right btree block */ |
122 | xfs_bmbt_key_t *rkp; /* right btree key */ | 121 | xfs_bmbt_key_t *rkp; /* right btree key */ |
123 | xfs_bmbt_rec_t *rp; /* pointer to bmap btree rec */ | 122 | xfs_bmbt_rec_t *rp; /* pointer to bmap btree rec */ |
124 | xfs_bmbt_ptr_t *rpp; /* right address pointer */ | 123 | xfs_bmbt_ptr_t *rpp; /* right address pointer */ |
125 | xfs_bmbt_block_t *rrblock; /* right-right btree block */ | 124 | xfs_bmbt_block_t *rrblock; /* right-right btree block */ |
126 | xfs_buf_t *rrbp; /* right-right buffer pointer */ | 125 | xfs_buf_t *rrbp; /* right-right buffer pointer */ |
127 | int rrecs=0; /* right record count */ | 126 | int rrecs=0; /* right record count */ |
128 | xfs_bmbt_rec_t *rrp; /* right record pointer */ | 127 | xfs_bmbt_rec_t *rrp; /* right record pointer */ |
129 | xfs_btree_cur_t *tcur; /* temporary btree cursor */ | 128 | xfs_btree_cur_t *tcur; /* temporary btree cursor */ |
130 | int numrecs; /* temporary numrec count */ | 129 | int numrecs; /* temporary numrec count */ |
131 | int numlrecs, numrrecs; | 130 | int numlrecs, numrrecs; |
132 | 131 | ||
133 | XFS_BMBT_TRACE_CURSOR(cur, ENTRY); | 132 | XFS_BMBT_TRACE_CURSOR(cur, ENTRY); |
134 | XFS_BMBT_TRACE_ARGI(cur, level); | 133 | XFS_BMBT_TRACE_ARGI(cur, level); |
135 | ptr = cur->bc_ptrs[level]; | 134 | ptr = cur->bc_ptrs[level]; |
136 | tcur = NULL; | 135 | tcur = NULL; |
137 | if (ptr == 0) { | 136 | if (ptr == 0) { |
138 | XFS_BMBT_TRACE_CURSOR(cur, EXIT); | 137 | XFS_BMBT_TRACE_CURSOR(cur, EXIT); |
139 | *stat = 0; | 138 | *stat = 0; |
140 | return 0; | 139 | return 0; |
141 | } | 140 | } |
142 | block = xfs_bmbt_get_block(cur, level, &bp); | 141 | block = xfs_bmbt_get_block(cur, level, &bp); |
143 | numrecs = be16_to_cpu(block->bb_numrecs); | 142 | numrecs = be16_to_cpu(block->bb_numrecs); |
144 | #ifdef DEBUG | 143 | #ifdef DEBUG |
145 | if ((error = xfs_btree_check_lblock(cur, block, level, bp))) { | 144 | if ((error = xfs_btree_check_lblock(cur, block, level, bp))) { |
146 | XFS_BMBT_TRACE_CURSOR(cur, ERROR); | 145 | XFS_BMBT_TRACE_CURSOR(cur, ERROR); |
147 | goto error0; | 146 | goto error0; |
148 | } | 147 | } |
149 | #endif | 148 | #endif |
150 | if (ptr > numrecs) { | 149 | if (ptr > numrecs) { |
151 | XFS_BMBT_TRACE_CURSOR(cur, EXIT); | 150 | XFS_BMBT_TRACE_CURSOR(cur, EXIT); |
152 | *stat = 0; | 151 | *stat = 0; |
153 | return 0; | 152 | return 0; |
154 | } | 153 | } |
155 | XFS_STATS_INC(xs_bmbt_delrec); | 154 | XFS_STATS_INC(xs_bmbt_delrec); |
156 | if (level > 0) { | 155 | if (level > 0) { |
157 | kp = XFS_BMAP_KEY_IADDR(block, 1, cur); | 156 | kp = XFS_BMAP_KEY_IADDR(block, 1, cur); |
158 | pp = XFS_BMAP_PTR_IADDR(block, 1, cur); | 157 | pp = XFS_BMAP_PTR_IADDR(block, 1, cur); |
159 | #ifdef DEBUG | 158 | #ifdef DEBUG |
160 | for (i = ptr; i < numrecs; i++) { | 159 | for (i = ptr; i < numrecs; i++) { |
161 | if ((error = xfs_btree_check_lptr_disk(cur, pp[i], level))) { | 160 | if ((error = xfs_btree_check_lptr_disk(cur, pp[i], level))) { |
162 | XFS_BMBT_TRACE_CURSOR(cur, ERROR); | 161 | XFS_BMBT_TRACE_CURSOR(cur, ERROR); |
163 | goto error0; | 162 | goto error0; |
164 | } | 163 | } |
165 | } | 164 | } |
166 | #endif | 165 | #endif |
167 | if (ptr < numrecs) { | 166 | if (ptr < numrecs) { |
168 | memmove(&kp[ptr - 1], &kp[ptr], | 167 | memmove(&kp[ptr - 1], &kp[ptr], |
169 | (numrecs - ptr) * sizeof(*kp)); | 168 | (numrecs - ptr) * sizeof(*kp)); |
170 | memmove(&pp[ptr - 1], &pp[ptr], | 169 | memmove(&pp[ptr - 1], &pp[ptr], |
171 | (numrecs - ptr) * sizeof(*pp)); | 170 | (numrecs - ptr) * sizeof(*pp)); |
172 | xfs_bmbt_log_ptrs(cur, bp, ptr, numrecs - 1); | 171 | xfs_bmbt_log_ptrs(cur, bp, ptr, numrecs - 1); |
173 | xfs_bmbt_log_keys(cur, bp, ptr, numrecs - 1); | 172 | xfs_bmbt_log_keys(cur, bp, ptr, numrecs - 1); |
174 | } | 173 | } |
175 | } else { | 174 | } else { |
176 | rp = XFS_BMAP_REC_IADDR(block, 1, cur); | 175 | rp = XFS_BMAP_REC_IADDR(block, 1, cur); |
177 | if (ptr < numrecs) { | 176 | if (ptr < numrecs) { |
178 | memmove(&rp[ptr - 1], &rp[ptr], | 177 | memmove(&rp[ptr - 1], &rp[ptr], |
179 | (numrecs - ptr) * sizeof(*rp)); | 178 | (numrecs - ptr) * sizeof(*rp)); |
180 | xfs_bmbt_log_recs(cur, bp, ptr, numrecs - 1); | 179 | xfs_bmbt_log_recs(cur, bp, ptr, numrecs - 1); |
181 | } | 180 | } |
182 | if (ptr == 1) { | 181 | if (ptr == 1) { |
183 | key.br_startoff = | 182 | key.br_startoff = |
184 | cpu_to_be64(xfs_bmbt_disk_get_startoff(rp)); | 183 | cpu_to_be64(xfs_bmbt_disk_get_startoff(rp)); |
185 | kp = &key; | 184 | kp = &key; |
186 | } | 185 | } |
187 | } | 186 | } |
188 | numrecs--; | 187 | numrecs--; |
189 | block->bb_numrecs = cpu_to_be16(numrecs); | 188 | block->bb_numrecs = cpu_to_be16(numrecs); |
190 | xfs_bmbt_log_block(cur, bp, XFS_BB_NUMRECS); | 189 | xfs_bmbt_log_block(cur, bp, XFS_BB_NUMRECS); |
191 | /* | 190 | /* |
192 | * We're at the root level. | 191 | * We're at the root level. |
193 | * First, shrink the root block in-memory. | 192 | * First, shrink the root block in-memory. |
194 | * Try to get rid of the next level down. | 193 | * Try to get rid of the next level down. |
195 | * If we can't then there's nothing left to do. | 194 | * If we can't then there's nothing left to do. |
196 | */ | 195 | */ |
197 | if (level == cur->bc_nlevels - 1) { | 196 | if (level == cur->bc_nlevels - 1) { |
198 | xfs_iroot_realloc(cur->bc_private.b.ip, -1, | 197 | xfs_iroot_realloc(cur->bc_private.b.ip, -1, |
199 | cur->bc_private.b.whichfork); | 198 | cur->bc_private.b.whichfork); |
200 | if ((error = xfs_bmbt_killroot(cur))) { | 199 | if ((error = xfs_bmbt_killroot(cur))) { |
201 | XFS_BMBT_TRACE_CURSOR(cur, ERROR); | 200 | XFS_BMBT_TRACE_CURSOR(cur, ERROR); |
202 | goto error0; | 201 | goto error0; |
203 | } | 202 | } |
204 | if (level > 0 && (error = xfs_btree_decrement(cur, level, &j))) { | 203 | if (level > 0 && (error = xfs_btree_decrement(cur, level, &j))) { |
205 | XFS_BMBT_TRACE_CURSOR(cur, ERROR); | 204 | XFS_BMBT_TRACE_CURSOR(cur, ERROR); |
206 | goto error0; | 205 | goto error0; |
207 | } | 206 | } |
208 | XFS_BMBT_TRACE_CURSOR(cur, EXIT); | 207 | XFS_BMBT_TRACE_CURSOR(cur, EXIT); |
209 | *stat = 1; | 208 | *stat = 1; |
210 | return 0; | 209 | return 0; |
211 | } | 210 | } |
212 | if (ptr == 1 && (error = xfs_btree_updkey(cur, (union xfs_btree_key *)kp, level + 1))) { | 211 | if (ptr == 1 && (error = xfs_btree_updkey(cur, (union xfs_btree_key *)kp, level + 1))) { |
213 | XFS_BMBT_TRACE_CURSOR(cur, ERROR); | 212 | XFS_BMBT_TRACE_CURSOR(cur, ERROR); |
214 | goto error0; | 213 | goto error0; |
215 | } | 214 | } |
216 | if (numrecs >= XFS_BMAP_BLOCK_IMINRECS(level, cur)) { | 215 | if (numrecs >= XFS_BMAP_BLOCK_IMINRECS(level, cur)) { |
217 | if (level > 0 && (error = xfs_btree_decrement(cur, level, &j))) { | 216 | if (level > 0 && (error = xfs_btree_decrement(cur, level, &j))) { |
218 | XFS_BMBT_TRACE_CURSOR(cur, ERROR); | 217 | XFS_BMBT_TRACE_CURSOR(cur, ERROR); |
219 | goto error0; | 218 | goto error0; |
220 | } | 219 | } |
221 | XFS_BMBT_TRACE_CURSOR(cur, EXIT); | 220 | XFS_BMBT_TRACE_CURSOR(cur, EXIT); |
222 | *stat = 1; | 221 | *stat = 1; |
223 | return 0; | 222 | return 0; |
224 | } | 223 | } |
225 | rbno = be64_to_cpu(block->bb_rightsib); | 224 | rbno = be64_to_cpu(block->bb_rightsib); |
226 | lbno = be64_to_cpu(block->bb_leftsib); | 225 | lbno = be64_to_cpu(block->bb_leftsib); |
227 | /* | 226 | /* |
228 | * One child of root, need to get a chance to copy its contents | 227 | * One child of root, need to get a chance to copy its contents |
229 | * into the root and delete it. Can't go up to next level, | 228 | * into the root and delete it. Can't go up to next level, |
230 | * there's nothing to delete there. | 229 | * there's nothing to delete there. |
231 | */ | 230 | */ |
232 | if (lbno == NULLFSBLOCK && rbno == NULLFSBLOCK && | 231 | if (lbno == NULLFSBLOCK && rbno == NULLFSBLOCK && |
233 | level == cur->bc_nlevels - 2) { | 232 | level == cur->bc_nlevels - 2) { |
234 | if ((error = xfs_bmbt_killroot(cur))) { | 233 | if ((error = xfs_bmbt_killroot(cur))) { |
235 | XFS_BMBT_TRACE_CURSOR(cur, ERROR); | 234 | XFS_BMBT_TRACE_CURSOR(cur, ERROR); |
236 | goto error0; | 235 | goto error0; |
237 | } | 236 | } |
238 | if (level > 0 && (error = xfs_btree_decrement(cur, level, &i))) { | 237 | if (level > 0 && (error = xfs_btree_decrement(cur, level, &i))) { |
239 | XFS_BMBT_TRACE_CURSOR(cur, ERROR); | 238 | XFS_BMBT_TRACE_CURSOR(cur, ERROR); |
240 | goto error0; | 239 | goto error0; |
241 | } | 240 | } |
242 | XFS_BMBT_TRACE_CURSOR(cur, EXIT); | 241 | XFS_BMBT_TRACE_CURSOR(cur, EXIT); |
243 | *stat = 1; | 242 | *stat = 1; |
244 | return 0; | 243 | return 0; |
245 | } | 244 | } |
246 | ASSERT(rbno != NULLFSBLOCK || lbno != NULLFSBLOCK); | 245 | ASSERT(rbno != NULLFSBLOCK || lbno != NULLFSBLOCK); |
247 | if ((error = xfs_btree_dup_cursor(cur, &tcur))) { | 246 | if ((error = xfs_btree_dup_cursor(cur, &tcur))) { |
248 | XFS_BMBT_TRACE_CURSOR(cur, ERROR); | 247 | XFS_BMBT_TRACE_CURSOR(cur, ERROR); |
249 | goto error0; | 248 | goto error0; |
250 | } | 249 | } |
251 | bno = NULLFSBLOCK; | 250 | bno = NULLFSBLOCK; |
252 | if (rbno != NULLFSBLOCK) { | 251 | if (rbno != NULLFSBLOCK) { |
253 | i = xfs_btree_lastrec(tcur, level); | 252 | i = xfs_btree_lastrec(tcur, level); |
254 | XFS_WANT_CORRUPTED_GOTO(i == 1, error0); | 253 | XFS_WANT_CORRUPTED_GOTO(i == 1, error0); |
255 | if ((error = xfs_btree_increment(tcur, level, &i))) { | 254 | if ((error = xfs_btree_increment(tcur, level, &i))) { |
256 | XFS_BMBT_TRACE_CURSOR(cur, ERROR); | 255 | XFS_BMBT_TRACE_CURSOR(cur, ERROR); |
257 | goto error0; | 256 | goto error0; |
258 | } | 257 | } |
259 | XFS_WANT_CORRUPTED_GOTO(i == 1, error0); | 258 | XFS_WANT_CORRUPTED_GOTO(i == 1, error0); |
260 | i = xfs_btree_lastrec(tcur, level); | 259 | i = xfs_btree_lastrec(tcur, level); |
261 | XFS_WANT_CORRUPTED_GOTO(i == 1, error0); | 260 | XFS_WANT_CORRUPTED_GOTO(i == 1, error0); |
262 | rbp = tcur->bc_bufs[level]; | 261 | rbp = tcur->bc_bufs[level]; |
263 | right = XFS_BUF_TO_BMBT_BLOCK(rbp); | 262 | right = XFS_BUF_TO_BMBT_BLOCK(rbp); |
264 | #ifdef DEBUG | 263 | #ifdef DEBUG |
265 | if ((error = xfs_btree_check_lblock(cur, right, level, rbp))) { | 264 | if ((error = xfs_btree_check_lblock(cur, right, level, rbp))) { |
266 | XFS_BMBT_TRACE_CURSOR(cur, ERROR); | 265 | XFS_BMBT_TRACE_CURSOR(cur, ERROR); |
267 | goto error0; | 266 | goto error0; |
268 | } | 267 | } |
269 | #endif | 268 | #endif |
270 | bno = be64_to_cpu(right->bb_leftsib); | 269 | bno = be64_to_cpu(right->bb_leftsib); |
271 | if (be16_to_cpu(right->bb_numrecs) - 1 >= | 270 | if (be16_to_cpu(right->bb_numrecs) - 1 >= |
272 | XFS_BMAP_BLOCK_IMINRECS(level, cur)) { | 271 | XFS_BMAP_BLOCK_IMINRECS(level, cur)) { |
273 | if ((error = xfs_bmbt_lshift(tcur, level, &i))) { | 272 | if ((error = xfs_btree_lshift(tcur, level, &i))) { |
274 | XFS_BMBT_TRACE_CURSOR(cur, ERROR); | 273 | XFS_BMBT_TRACE_CURSOR(cur, ERROR); |
275 | goto error0; | 274 | goto error0; |
276 | } | 275 | } |
277 | if (i) { | 276 | if (i) { |
278 | ASSERT(be16_to_cpu(block->bb_numrecs) >= | 277 | ASSERT(be16_to_cpu(block->bb_numrecs) >= |
279 | XFS_BMAP_BLOCK_IMINRECS(level, tcur)); | 278 | XFS_BMAP_BLOCK_IMINRECS(level, tcur)); |
280 | xfs_btree_del_cursor(tcur, XFS_BTREE_NOERROR); | 279 | xfs_btree_del_cursor(tcur, XFS_BTREE_NOERROR); |
281 | tcur = NULL; | 280 | tcur = NULL; |
282 | if (level > 0) { | 281 | if (level > 0) { |
283 | if ((error = xfs_btree_decrement(cur, | 282 | if ((error = xfs_btree_decrement(cur, |
284 | level, &i))) { | 283 | level, &i))) { |
285 | XFS_BMBT_TRACE_CURSOR(cur, | 284 | XFS_BMBT_TRACE_CURSOR(cur, |
286 | ERROR); | 285 | ERROR); |
287 | goto error0; | 286 | goto error0; |
288 | } | 287 | } |
289 | } | 288 | } |
290 | XFS_BMBT_TRACE_CURSOR(cur, EXIT); | 289 | XFS_BMBT_TRACE_CURSOR(cur, EXIT); |
291 | *stat = 1; | 290 | *stat = 1; |
292 | return 0; | 291 | return 0; |
293 | } | 292 | } |
294 | } | 293 | } |
295 | rrecs = be16_to_cpu(right->bb_numrecs); | 294 | rrecs = be16_to_cpu(right->bb_numrecs); |
296 | if (lbno != NULLFSBLOCK) { | 295 | if (lbno != NULLFSBLOCK) { |
297 | i = xfs_btree_firstrec(tcur, level); | 296 | i = xfs_btree_firstrec(tcur, level); |
298 | XFS_WANT_CORRUPTED_GOTO(i == 1, error0); | 297 | XFS_WANT_CORRUPTED_GOTO(i == 1, error0); |
299 | if ((error = xfs_btree_decrement(tcur, level, &i))) { | 298 | if ((error = xfs_btree_decrement(tcur, level, &i))) { |
300 | XFS_BMBT_TRACE_CURSOR(cur, ERROR); | 299 | XFS_BMBT_TRACE_CURSOR(cur, ERROR); |
301 | goto error0; | 300 | goto error0; |
302 | } | 301 | } |
303 | XFS_WANT_CORRUPTED_GOTO(i == 1, error0); | 302 | XFS_WANT_CORRUPTED_GOTO(i == 1, error0); |
304 | } | 303 | } |
305 | } | 304 | } |
306 | if (lbno != NULLFSBLOCK) { | 305 | if (lbno != NULLFSBLOCK) { |
307 | i = xfs_btree_firstrec(tcur, level); | 306 | i = xfs_btree_firstrec(tcur, level); |
308 | XFS_WANT_CORRUPTED_GOTO(i == 1, error0); | 307 | XFS_WANT_CORRUPTED_GOTO(i == 1, error0); |
309 | /* | 308 | /* |
310 | * decrement to last in block | 309 | * decrement to last in block |
311 | */ | 310 | */ |
312 | if ((error = xfs_btree_decrement(tcur, level, &i))) { | 311 | if ((error = xfs_btree_decrement(tcur, level, &i))) { |
313 | XFS_BMBT_TRACE_CURSOR(cur, ERROR); | 312 | XFS_BMBT_TRACE_CURSOR(cur, ERROR); |
314 | goto error0; | 313 | goto error0; |
315 | } | 314 | } |
316 | i = xfs_btree_firstrec(tcur, level); | 315 | i = xfs_btree_firstrec(tcur, level); |
317 | XFS_WANT_CORRUPTED_GOTO(i == 1, error0); | 316 | XFS_WANT_CORRUPTED_GOTO(i == 1, error0); |
318 | lbp = tcur->bc_bufs[level]; | 317 | lbp = tcur->bc_bufs[level]; |
319 | left = XFS_BUF_TO_BMBT_BLOCK(lbp); | 318 | left = XFS_BUF_TO_BMBT_BLOCK(lbp); |
320 | #ifdef DEBUG | 319 | #ifdef DEBUG |
321 | if ((error = xfs_btree_check_lblock(cur, left, level, lbp))) { | 320 | if ((error = xfs_btree_check_lblock(cur, left, level, lbp))) { |
322 | XFS_BMBT_TRACE_CURSOR(cur, ERROR); | 321 | XFS_BMBT_TRACE_CURSOR(cur, ERROR); |
323 | goto error0; | 322 | goto error0; |
324 | } | 323 | } |
325 | #endif | 324 | #endif |
326 | bno = be64_to_cpu(left->bb_rightsib); | 325 | bno = be64_to_cpu(left->bb_rightsib); |
327 | if (be16_to_cpu(left->bb_numrecs) - 1 >= | 326 | if (be16_to_cpu(left->bb_numrecs) - 1 >= |
328 | XFS_BMAP_BLOCK_IMINRECS(level, cur)) { | 327 | XFS_BMAP_BLOCK_IMINRECS(level, cur)) { |
329 | if ((error = xfs_btree_rshift(tcur, level, &i))) { | 328 | if ((error = xfs_btree_rshift(tcur, level, &i))) { |
330 | XFS_BMBT_TRACE_CURSOR(cur, ERROR); | 329 | XFS_BMBT_TRACE_CURSOR(cur, ERROR); |
331 | goto error0; | 330 | goto error0; |
332 | } | 331 | } |
333 | if (i) { | 332 | if (i) { |
334 | ASSERT(be16_to_cpu(block->bb_numrecs) >= | 333 | ASSERT(be16_to_cpu(block->bb_numrecs) >= |
335 | XFS_BMAP_BLOCK_IMINRECS(level, tcur)); | 334 | XFS_BMAP_BLOCK_IMINRECS(level, tcur)); |
336 | xfs_btree_del_cursor(tcur, XFS_BTREE_NOERROR); | 335 | xfs_btree_del_cursor(tcur, XFS_BTREE_NOERROR); |
337 | tcur = NULL; | 336 | tcur = NULL; |
338 | if (level == 0) | 337 | if (level == 0) |
339 | cur->bc_ptrs[0]++; | 338 | cur->bc_ptrs[0]++; |
340 | XFS_BMBT_TRACE_CURSOR(cur, EXIT); | 339 | XFS_BMBT_TRACE_CURSOR(cur, EXIT); |
341 | *stat = 1; | 340 | *stat = 1; |
342 | return 0; | 341 | return 0; |
343 | } | 342 | } |
344 | } | 343 | } |
345 | lrecs = be16_to_cpu(left->bb_numrecs); | 344 | lrecs = be16_to_cpu(left->bb_numrecs); |
346 | } | 345 | } |
347 | xfs_btree_del_cursor(tcur, XFS_BTREE_NOERROR); | 346 | xfs_btree_del_cursor(tcur, XFS_BTREE_NOERROR); |
348 | tcur = NULL; | 347 | tcur = NULL; |
349 | mp = cur->bc_mp; | 348 | mp = cur->bc_mp; |
350 | ASSERT(bno != NULLFSBLOCK); | 349 | ASSERT(bno != NULLFSBLOCK); |
351 | if (lbno != NULLFSBLOCK && | 350 | if (lbno != NULLFSBLOCK && |
352 | lrecs + be16_to_cpu(block->bb_numrecs) <= XFS_BMAP_BLOCK_IMAXRECS(level, cur)) { | 351 | lrecs + be16_to_cpu(block->bb_numrecs) <= XFS_BMAP_BLOCK_IMAXRECS(level, cur)) { |
353 | rbno = bno; | 352 | rbno = bno; |
354 | right = block; | 353 | right = block; |
355 | rbp = bp; | 354 | rbp = bp; |
356 | if ((error = xfs_btree_read_bufl(mp, cur->bc_tp, lbno, 0, &lbp, | 355 | if ((error = xfs_btree_read_bufl(mp, cur->bc_tp, lbno, 0, &lbp, |
357 | XFS_BMAP_BTREE_REF))) { | 356 | XFS_BMAP_BTREE_REF))) { |
358 | XFS_BMBT_TRACE_CURSOR(cur, ERROR); | 357 | XFS_BMBT_TRACE_CURSOR(cur, ERROR); |
359 | goto error0; | 358 | goto error0; |
360 | } | 359 | } |
361 | left = XFS_BUF_TO_BMBT_BLOCK(lbp); | 360 | left = XFS_BUF_TO_BMBT_BLOCK(lbp); |
362 | if ((error = xfs_btree_check_lblock(cur, left, level, lbp))) { | 361 | if ((error = xfs_btree_check_lblock(cur, left, level, lbp))) { |
363 | XFS_BMBT_TRACE_CURSOR(cur, ERROR); | 362 | XFS_BMBT_TRACE_CURSOR(cur, ERROR); |
364 | goto error0; | 363 | goto error0; |
365 | } | 364 | } |
366 | } else if (rbno != NULLFSBLOCK && | 365 | } else if (rbno != NULLFSBLOCK && |
367 | rrecs + be16_to_cpu(block->bb_numrecs) <= | 366 | rrecs + be16_to_cpu(block->bb_numrecs) <= |
368 | XFS_BMAP_BLOCK_IMAXRECS(level, cur)) { | 367 | XFS_BMAP_BLOCK_IMAXRECS(level, cur)) { |
369 | lbno = bno; | 368 | lbno = bno; |
370 | left = block; | 369 | left = block; |
371 | lbp = bp; | 370 | lbp = bp; |
372 | if ((error = xfs_btree_read_bufl(mp, cur->bc_tp, rbno, 0, &rbp, | 371 | if ((error = xfs_btree_read_bufl(mp, cur->bc_tp, rbno, 0, &rbp, |
373 | XFS_BMAP_BTREE_REF))) { | 372 | XFS_BMAP_BTREE_REF))) { |
374 | XFS_BMBT_TRACE_CURSOR(cur, ERROR); | 373 | XFS_BMBT_TRACE_CURSOR(cur, ERROR); |
375 | goto error0; | 374 | goto error0; |
376 | } | 375 | } |
377 | right = XFS_BUF_TO_BMBT_BLOCK(rbp); | 376 | right = XFS_BUF_TO_BMBT_BLOCK(rbp); |
378 | if ((error = xfs_btree_check_lblock(cur, right, level, rbp))) { | 377 | if ((error = xfs_btree_check_lblock(cur, right, level, rbp))) { |
379 | XFS_BMBT_TRACE_CURSOR(cur, ERROR); | 378 | XFS_BMBT_TRACE_CURSOR(cur, ERROR); |
380 | goto error0; | 379 | goto error0; |
381 | } | 380 | } |
382 | lrecs = be16_to_cpu(left->bb_numrecs); | 381 | lrecs = be16_to_cpu(left->bb_numrecs); |
383 | } else { | 382 | } else { |
384 | if (level > 0 && (error = xfs_btree_decrement(cur, level, &i))) { | 383 | if (level > 0 && (error = xfs_btree_decrement(cur, level, &i))) { |
385 | XFS_BMBT_TRACE_CURSOR(cur, ERROR); | 384 | XFS_BMBT_TRACE_CURSOR(cur, ERROR); |
386 | goto error0; | 385 | goto error0; |
387 | } | 386 | } |
388 | XFS_BMBT_TRACE_CURSOR(cur, EXIT); | 387 | XFS_BMBT_TRACE_CURSOR(cur, EXIT); |
389 | *stat = 1; | 388 | *stat = 1; |
390 | return 0; | 389 | return 0; |
391 | } | 390 | } |
392 | numlrecs = be16_to_cpu(left->bb_numrecs); | 391 | numlrecs = be16_to_cpu(left->bb_numrecs); |
393 | numrrecs = be16_to_cpu(right->bb_numrecs); | 392 | numrrecs = be16_to_cpu(right->bb_numrecs); |
394 | if (level > 0) { | 393 | if (level > 0) { |
395 | lkp = XFS_BMAP_KEY_IADDR(left, numlrecs + 1, cur); | 394 | lkp = XFS_BMAP_KEY_IADDR(left, numlrecs + 1, cur); |
396 | lpp = XFS_BMAP_PTR_IADDR(left, numlrecs + 1, cur); | 395 | lpp = XFS_BMAP_PTR_IADDR(left, numlrecs + 1, cur); |
397 | rkp = XFS_BMAP_KEY_IADDR(right, 1, cur); | 396 | rkp = XFS_BMAP_KEY_IADDR(right, 1, cur); |
398 | rpp = XFS_BMAP_PTR_IADDR(right, 1, cur); | 397 | rpp = XFS_BMAP_PTR_IADDR(right, 1, cur); |
399 | #ifdef DEBUG | 398 | #ifdef DEBUG |
400 | for (i = 0; i < numrrecs; i++) { | 399 | for (i = 0; i < numrrecs; i++) { |
401 | if ((error = xfs_btree_check_lptr_disk(cur, rpp[i], level))) { | 400 | if ((error = xfs_btree_check_lptr_disk(cur, rpp[i], level))) { |
402 | XFS_BMBT_TRACE_CURSOR(cur, ERROR); | 401 | XFS_BMBT_TRACE_CURSOR(cur, ERROR); |
403 | goto error0; | 402 | goto error0; |
404 | } | 403 | } |
405 | } | 404 | } |
406 | #endif | 405 | #endif |
407 | memcpy(lkp, rkp, numrrecs * sizeof(*lkp)); | 406 | memcpy(lkp, rkp, numrrecs * sizeof(*lkp)); |
408 | memcpy(lpp, rpp, numrrecs * sizeof(*lpp)); | 407 | memcpy(lpp, rpp, numrrecs * sizeof(*lpp)); |
409 | xfs_bmbt_log_keys(cur, lbp, numlrecs + 1, numlrecs + numrrecs); | 408 | xfs_bmbt_log_keys(cur, lbp, numlrecs + 1, numlrecs + numrrecs); |
410 | xfs_bmbt_log_ptrs(cur, lbp, numlrecs + 1, numlrecs + numrrecs); | 409 | xfs_bmbt_log_ptrs(cur, lbp, numlrecs + 1, numlrecs + numrrecs); |
411 | } else { | 410 | } else { |
412 | lrp = XFS_BMAP_REC_IADDR(left, numlrecs + 1, cur); | 411 | lrp = XFS_BMAP_REC_IADDR(left, numlrecs + 1, cur); |
413 | rrp = XFS_BMAP_REC_IADDR(right, 1, cur); | 412 | rrp = XFS_BMAP_REC_IADDR(right, 1, cur); |
414 | memcpy(lrp, rrp, numrrecs * sizeof(*lrp)); | 413 | memcpy(lrp, rrp, numrrecs * sizeof(*lrp)); |
415 | xfs_bmbt_log_recs(cur, lbp, numlrecs + 1, numlrecs + numrrecs); | 414 | xfs_bmbt_log_recs(cur, lbp, numlrecs + 1, numlrecs + numrrecs); |
416 | } | 415 | } |
417 | be16_add_cpu(&left->bb_numrecs, numrrecs); | 416 | be16_add_cpu(&left->bb_numrecs, numrrecs); |
418 | left->bb_rightsib = right->bb_rightsib; | 417 | left->bb_rightsib = right->bb_rightsib; |
419 | xfs_bmbt_log_block(cur, lbp, XFS_BB_RIGHTSIB | XFS_BB_NUMRECS); | 418 | xfs_bmbt_log_block(cur, lbp, XFS_BB_RIGHTSIB | XFS_BB_NUMRECS); |
420 | if (be64_to_cpu(left->bb_rightsib) != NULLDFSBNO) { | 419 | if (be64_to_cpu(left->bb_rightsib) != NULLDFSBNO) { |
421 | if ((error = xfs_btree_read_bufl(mp, cur->bc_tp, | 420 | if ((error = xfs_btree_read_bufl(mp, cur->bc_tp, |
422 | be64_to_cpu(left->bb_rightsib), | 421 | be64_to_cpu(left->bb_rightsib), |
423 | 0, &rrbp, XFS_BMAP_BTREE_REF))) { | 422 | 0, &rrbp, XFS_BMAP_BTREE_REF))) { |
424 | XFS_BMBT_TRACE_CURSOR(cur, ERROR); | 423 | XFS_BMBT_TRACE_CURSOR(cur, ERROR); |
425 | goto error0; | 424 | goto error0; |
426 | } | 425 | } |
427 | rrblock = XFS_BUF_TO_BMBT_BLOCK(rrbp); | 426 | rrblock = XFS_BUF_TO_BMBT_BLOCK(rrbp); |
428 | if ((error = xfs_btree_check_lblock(cur, rrblock, level, rrbp))) { | 427 | if ((error = xfs_btree_check_lblock(cur, rrblock, level, rrbp))) { |
429 | XFS_BMBT_TRACE_CURSOR(cur, ERROR); | 428 | XFS_BMBT_TRACE_CURSOR(cur, ERROR); |
430 | goto error0; | 429 | goto error0; |
431 | } | 430 | } |
432 | rrblock->bb_leftsib = cpu_to_be64(lbno); | 431 | rrblock->bb_leftsib = cpu_to_be64(lbno); |
433 | xfs_bmbt_log_block(cur, rrbp, XFS_BB_LEFTSIB); | 432 | xfs_bmbt_log_block(cur, rrbp, XFS_BB_LEFTSIB); |
434 | } | 433 | } |
435 | xfs_bmap_add_free(XFS_DADDR_TO_FSB(mp, XFS_BUF_ADDR(rbp)), 1, | 434 | xfs_bmap_add_free(XFS_DADDR_TO_FSB(mp, XFS_BUF_ADDR(rbp)), 1, |
436 | cur->bc_private.b.flist, mp); | 435 | cur->bc_private.b.flist, mp); |
437 | cur->bc_private.b.ip->i_d.di_nblocks--; | 436 | cur->bc_private.b.ip->i_d.di_nblocks--; |
438 | xfs_trans_log_inode(cur->bc_tp, cur->bc_private.b.ip, XFS_ILOG_CORE); | 437 | xfs_trans_log_inode(cur->bc_tp, cur->bc_private.b.ip, XFS_ILOG_CORE); |
439 | XFS_TRANS_MOD_DQUOT_BYINO(mp, cur->bc_tp, cur->bc_private.b.ip, | 438 | XFS_TRANS_MOD_DQUOT_BYINO(mp, cur->bc_tp, cur->bc_private.b.ip, |
440 | XFS_TRANS_DQ_BCOUNT, -1L); | 439 | XFS_TRANS_DQ_BCOUNT, -1L); |
441 | xfs_trans_binval(cur->bc_tp, rbp); | 440 | xfs_trans_binval(cur->bc_tp, rbp); |
442 | if (bp != lbp) { | 441 | if (bp != lbp) { |
443 | cur->bc_bufs[level] = lbp; | 442 | cur->bc_bufs[level] = lbp; |
444 | cur->bc_ptrs[level] += lrecs; | 443 | cur->bc_ptrs[level] += lrecs; |
445 | cur->bc_ra[level] = 0; | 444 | cur->bc_ra[level] = 0; |
446 | } else if ((error = xfs_btree_increment(cur, level + 1, &i))) { | 445 | } else if ((error = xfs_btree_increment(cur, level + 1, &i))) { |
447 | XFS_BMBT_TRACE_CURSOR(cur, ERROR); | 446 | XFS_BMBT_TRACE_CURSOR(cur, ERROR); |
448 | goto error0; | 447 | goto error0; |
449 | } | 448 | } |
450 | if (level > 0) | 449 | if (level > 0) |
451 | cur->bc_ptrs[level]--; | 450 | cur->bc_ptrs[level]--; |
452 | XFS_BMBT_TRACE_CURSOR(cur, EXIT); | 451 | XFS_BMBT_TRACE_CURSOR(cur, EXIT); |
453 | *stat = 2; | 452 | *stat = 2; |
454 | return 0; | 453 | return 0; |
455 | 454 | ||
456 | error0: | 455 | error0: |
457 | if (tcur) | 456 | if (tcur) |
458 | xfs_btree_del_cursor(tcur, XFS_BTREE_ERROR); | 457 | xfs_btree_del_cursor(tcur, XFS_BTREE_ERROR); |
459 | return error; | 458 | return error; |
460 | } | 459 | } |
461 | 460 | ||
462 | /* | 461 | /* |
463 | * Insert one record/level. Return information to the caller | 462 | * Insert one record/level. Return information to the caller |
464 | * allowing the next level up to proceed if necessary. | 463 | * allowing the next level up to proceed if necessary. |
465 | */ | 464 | */ |
466 | STATIC int /* error */ | 465 | STATIC int /* error */ |
467 | xfs_bmbt_insrec( | 466 | xfs_bmbt_insrec( |
468 | xfs_btree_cur_t *cur, | 467 | xfs_btree_cur_t *cur, |
469 | int level, | 468 | int level, |
470 | xfs_fsblock_t *bnop, | 469 | xfs_fsblock_t *bnop, |
471 | xfs_bmbt_rec_t *recp, | 470 | xfs_bmbt_rec_t *recp, |
472 | xfs_btree_cur_t **curp, | 471 | xfs_btree_cur_t **curp, |
473 | int *stat) /* no-go/done/continue */ | 472 | int *stat) /* no-go/done/continue */ |
474 | { | 473 | { |
475 | xfs_bmbt_block_t *block; /* bmap btree block */ | 474 | xfs_bmbt_block_t *block; /* bmap btree block */ |
476 | xfs_buf_t *bp; /* buffer for block */ | 475 | xfs_buf_t *bp; /* buffer for block */ |
477 | int error; /* error return value */ | 476 | int error; /* error return value */ |
478 | int i; /* loop index */ | 477 | int i; /* loop index */ |
479 | xfs_bmbt_key_t key; /* bmap btree key */ | 478 | xfs_bmbt_key_t key; /* bmap btree key */ |
480 | xfs_bmbt_key_t *kp=NULL; /* pointer to bmap btree key */ | 479 | xfs_bmbt_key_t *kp=NULL; /* pointer to bmap btree key */ |
481 | int logflags; /* inode logging flags */ | 480 | int logflags; /* inode logging flags */ |
482 | xfs_fsblock_t nbno; /* new block number */ | 481 | xfs_fsblock_t nbno; /* new block number */ |
483 | struct xfs_btree_cur *ncur; /* new btree cursor */ | 482 | struct xfs_btree_cur *ncur; /* new btree cursor */ |
484 | __uint64_t startoff; /* new btree key value */ | 483 | __uint64_t startoff; /* new btree key value */ |
485 | xfs_bmbt_rec_t nrec; /* new record count */ | 484 | xfs_bmbt_rec_t nrec; /* new record count */ |
486 | int optr; /* old key/record index */ | 485 | int optr; /* old key/record index */ |
487 | xfs_bmbt_ptr_t *pp; /* pointer to bmap block addr */ | 486 | xfs_bmbt_ptr_t *pp; /* pointer to bmap block addr */ |
488 | int ptr; /* key/record index */ | 487 | int ptr; /* key/record index */ |
489 | xfs_bmbt_rec_t *rp=NULL; /* pointer to bmap btree rec */ | 488 | xfs_bmbt_rec_t *rp=NULL; /* pointer to bmap btree rec */ |
490 | int numrecs; | 489 | int numrecs; |
491 | 490 | ||
492 | ASSERT(level < cur->bc_nlevels); | 491 | ASSERT(level < cur->bc_nlevels); |
493 | XFS_BMBT_TRACE_CURSOR(cur, ENTRY); | 492 | XFS_BMBT_TRACE_CURSOR(cur, ENTRY); |
494 | XFS_BMBT_TRACE_ARGIFR(cur, level, *bnop, recp); | 493 | XFS_BMBT_TRACE_ARGIFR(cur, level, *bnop, recp); |
495 | ncur = NULL; | 494 | ncur = NULL; |
496 | key.br_startoff = cpu_to_be64(xfs_bmbt_disk_get_startoff(recp)); | 495 | key.br_startoff = cpu_to_be64(xfs_bmbt_disk_get_startoff(recp)); |
497 | optr = ptr = cur->bc_ptrs[level]; | 496 | optr = ptr = cur->bc_ptrs[level]; |
498 | if (ptr == 0) { | 497 | if (ptr == 0) { |
499 | XFS_BMBT_TRACE_CURSOR(cur, EXIT); | 498 | XFS_BMBT_TRACE_CURSOR(cur, EXIT); |
500 | *stat = 0; | 499 | *stat = 0; |
501 | return 0; | 500 | return 0; |
502 | } | 501 | } |
503 | XFS_STATS_INC(xs_bmbt_insrec); | 502 | XFS_STATS_INC(xs_bmbt_insrec); |
504 | block = xfs_bmbt_get_block(cur, level, &bp); | 503 | block = xfs_bmbt_get_block(cur, level, &bp); |
505 | numrecs = be16_to_cpu(block->bb_numrecs); | 504 | numrecs = be16_to_cpu(block->bb_numrecs); |
506 | #ifdef DEBUG | 505 | #ifdef DEBUG |
507 | if ((error = xfs_btree_check_lblock(cur, block, level, bp))) { | 506 | if ((error = xfs_btree_check_lblock(cur, block, level, bp))) { |
508 | XFS_BMBT_TRACE_CURSOR(cur, ERROR); | 507 | XFS_BMBT_TRACE_CURSOR(cur, ERROR); |
509 | return error; | 508 | return error; |
510 | } | 509 | } |
511 | if (ptr <= numrecs) { | 510 | if (ptr <= numrecs) { |
512 | if (level == 0) { | 511 | if (level == 0) { |
513 | rp = XFS_BMAP_REC_IADDR(block, ptr, cur); | 512 | rp = XFS_BMAP_REC_IADDR(block, ptr, cur); |
514 | xfs_btree_check_rec(XFS_BTNUM_BMAP, recp, rp); | 513 | xfs_btree_check_rec(XFS_BTNUM_BMAP, recp, rp); |
515 | } else { | 514 | } else { |
516 | kp = XFS_BMAP_KEY_IADDR(block, ptr, cur); | 515 | kp = XFS_BMAP_KEY_IADDR(block, ptr, cur); |
517 | xfs_btree_check_key(XFS_BTNUM_BMAP, &key, kp); | 516 | xfs_btree_check_key(XFS_BTNUM_BMAP, &key, kp); |
518 | } | 517 | } |
519 | } | 518 | } |
520 | #endif | 519 | #endif |
521 | nbno = NULLFSBLOCK; | 520 | nbno = NULLFSBLOCK; |
522 | if (numrecs == XFS_BMAP_BLOCK_IMAXRECS(level, cur)) { | 521 | if (numrecs == XFS_BMAP_BLOCK_IMAXRECS(level, cur)) { |
523 | if (numrecs < XFS_BMAP_BLOCK_DMAXRECS(level, cur)) { | 522 | if (numrecs < XFS_BMAP_BLOCK_DMAXRECS(level, cur)) { |
524 | /* | 523 | /* |
525 | * A root block, that can be made bigger. | 524 | * A root block, that can be made bigger. |
526 | */ | 525 | */ |
527 | xfs_iroot_realloc(cur->bc_private.b.ip, 1, | 526 | xfs_iroot_realloc(cur->bc_private.b.ip, 1, |
528 | cur->bc_private.b.whichfork); | 527 | cur->bc_private.b.whichfork); |
529 | block = xfs_bmbt_get_block(cur, level, &bp); | 528 | block = xfs_bmbt_get_block(cur, level, &bp); |
530 | } else if (level == cur->bc_nlevels - 1) { | 529 | } else if (level == cur->bc_nlevels - 1) { |
531 | if ((error = xfs_bmbt_newroot(cur, &logflags, stat)) || | 530 | if ((error = xfs_bmbt_newroot(cur, &logflags, stat)) || |
532 | *stat == 0) { | 531 | *stat == 0) { |
533 | XFS_BMBT_TRACE_CURSOR(cur, ERROR); | 532 | XFS_BMBT_TRACE_CURSOR(cur, ERROR); |
534 | return error; | 533 | return error; |
535 | } | 534 | } |
536 | xfs_trans_log_inode(cur->bc_tp, cur->bc_private.b.ip, | 535 | xfs_trans_log_inode(cur->bc_tp, cur->bc_private.b.ip, |
537 | logflags); | 536 | logflags); |
538 | block = xfs_bmbt_get_block(cur, level, &bp); | 537 | block = xfs_bmbt_get_block(cur, level, &bp); |
539 | } else { | 538 | } else { |
540 | if ((error = xfs_btree_rshift(cur, level, &i))) { | 539 | if ((error = xfs_btree_rshift(cur, level, &i))) { |
541 | XFS_BMBT_TRACE_CURSOR(cur, ERROR); | 540 | XFS_BMBT_TRACE_CURSOR(cur, ERROR); |
542 | return error; | 541 | return error; |
543 | } | 542 | } |
544 | if (i) { | 543 | if (i) { |
545 | /* nothing */ | 544 | /* nothing */ |
546 | } else { | 545 | } else { |
547 | if ((error = xfs_bmbt_lshift(cur, level, &i))) { | 546 | if ((error = xfs_btree_lshift(cur, level, &i))) { |
548 | XFS_BMBT_TRACE_CURSOR(cur, ERROR); | 547 | XFS_BMBT_TRACE_CURSOR(cur, ERROR); |
549 | return error; | 548 | return error; |
550 | } | 549 | } |
551 | if (i) { | 550 | if (i) { |
552 | optr = ptr = cur->bc_ptrs[level]; | 551 | optr = ptr = cur->bc_ptrs[level]; |
553 | } else { | 552 | } else { |
554 | if ((error = xfs_bmbt_split(cur, level, | 553 | if ((error = xfs_bmbt_split(cur, level, |
555 | &nbno, &startoff, &ncur, | 554 | &nbno, &startoff, &ncur, |
556 | &i))) { | 555 | &i))) { |
557 | XFS_BMBT_TRACE_CURSOR(cur, | 556 | XFS_BMBT_TRACE_CURSOR(cur, |
558 | ERROR); | 557 | ERROR); |
559 | return error; | 558 | return error; |
560 | } | 559 | } |
561 | if (i) { | 560 | if (i) { |
562 | block = xfs_bmbt_get_block( | 561 | block = xfs_bmbt_get_block( |
563 | cur, level, &bp); | 562 | cur, level, &bp); |
564 | #ifdef DEBUG | 563 | #ifdef DEBUG |
565 | if ((error = | 564 | if ((error = |
566 | xfs_btree_check_lblock(cur, | 565 | xfs_btree_check_lblock(cur, |
567 | block, level, bp))) { | 566 | block, level, bp))) { |
568 | XFS_BMBT_TRACE_CURSOR( | 567 | XFS_BMBT_TRACE_CURSOR( |
569 | cur, ERROR); | 568 | cur, ERROR); |
570 | return error; | 569 | return error; |
571 | } | 570 | } |
572 | #endif | 571 | #endif |
573 | ptr = cur->bc_ptrs[level]; | 572 | ptr = cur->bc_ptrs[level]; |
574 | xfs_bmbt_disk_set_allf(&nrec, | 573 | xfs_bmbt_disk_set_allf(&nrec, |
575 | startoff, 0, 0, | 574 | startoff, 0, 0, |
576 | XFS_EXT_NORM); | 575 | XFS_EXT_NORM); |
577 | } else { | 576 | } else { |
578 | XFS_BMBT_TRACE_CURSOR(cur, | 577 | XFS_BMBT_TRACE_CURSOR(cur, |
579 | EXIT); | 578 | EXIT); |
580 | *stat = 0; | 579 | *stat = 0; |
581 | return 0; | 580 | return 0; |
582 | } | 581 | } |
583 | } | 582 | } |
584 | } | 583 | } |
585 | } | 584 | } |
586 | } | 585 | } |
587 | numrecs = be16_to_cpu(block->bb_numrecs); | 586 | numrecs = be16_to_cpu(block->bb_numrecs); |
588 | if (level > 0) { | 587 | if (level > 0) { |
589 | kp = XFS_BMAP_KEY_IADDR(block, 1, cur); | 588 | kp = XFS_BMAP_KEY_IADDR(block, 1, cur); |
590 | pp = XFS_BMAP_PTR_IADDR(block, 1, cur); | 589 | pp = XFS_BMAP_PTR_IADDR(block, 1, cur); |
591 | #ifdef DEBUG | 590 | #ifdef DEBUG |
592 | for (i = numrecs; i >= ptr; i--) { | 591 | for (i = numrecs; i >= ptr; i--) { |
593 | if ((error = xfs_btree_check_lptr_disk(cur, pp[i - 1], | 592 | if ((error = xfs_btree_check_lptr_disk(cur, pp[i - 1], |
594 | level))) { | 593 | level))) { |
595 | XFS_BMBT_TRACE_CURSOR(cur, ERROR); | 594 | XFS_BMBT_TRACE_CURSOR(cur, ERROR); |
596 | return error; | 595 | return error; |
597 | } | 596 | } |
598 | } | 597 | } |
599 | #endif | 598 | #endif |
600 | memmove(&kp[ptr], &kp[ptr - 1], | 599 | memmove(&kp[ptr], &kp[ptr - 1], |
601 | (numrecs - ptr + 1) * sizeof(*kp)); | 600 | (numrecs - ptr + 1) * sizeof(*kp)); |
602 | memmove(&pp[ptr], &pp[ptr - 1], | 601 | memmove(&pp[ptr], &pp[ptr - 1], |
603 | (numrecs - ptr + 1) * sizeof(*pp)); | 602 | (numrecs - ptr + 1) * sizeof(*pp)); |
604 | #ifdef DEBUG | 603 | #ifdef DEBUG |
605 | if ((error = xfs_btree_check_lptr(cur, *bnop, level))) { | 604 | if ((error = xfs_btree_check_lptr(cur, *bnop, level))) { |
606 | XFS_BMBT_TRACE_CURSOR(cur, ERROR); | 605 | XFS_BMBT_TRACE_CURSOR(cur, ERROR); |
607 | return error; | 606 | return error; |
608 | } | 607 | } |
609 | #endif | 608 | #endif |
610 | kp[ptr - 1] = key; | 609 | kp[ptr - 1] = key; |
611 | pp[ptr - 1] = cpu_to_be64(*bnop); | 610 | pp[ptr - 1] = cpu_to_be64(*bnop); |
612 | numrecs++; | 611 | numrecs++; |
613 | block->bb_numrecs = cpu_to_be16(numrecs); | 612 | block->bb_numrecs = cpu_to_be16(numrecs); |
614 | xfs_bmbt_log_keys(cur, bp, ptr, numrecs); | 613 | xfs_bmbt_log_keys(cur, bp, ptr, numrecs); |
615 | xfs_bmbt_log_ptrs(cur, bp, ptr, numrecs); | 614 | xfs_bmbt_log_ptrs(cur, bp, ptr, numrecs); |
616 | } else { | 615 | } else { |
617 | rp = XFS_BMAP_REC_IADDR(block, 1, cur); | 616 | rp = XFS_BMAP_REC_IADDR(block, 1, cur); |
618 | memmove(&rp[ptr], &rp[ptr - 1], | 617 | memmove(&rp[ptr], &rp[ptr - 1], |
619 | (numrecs - ptr + 1) * sizeof(*rp)); | 618 | (numrecs - ptr + 1) * sizeof(*rp)); |
620 | rp[ptr - 1] = *recp; | 619 | rp[ptr - 1] = *recp; |
621 | numrecs++; | 620 | numrecs++; |
622 | block->bb_numrecs = cpu_to_be16(numrecs); | 621 | block->bb_numrecs = cpu_to_be16(numrecs); |
623 | xfs_bmbt_log_recs(cur, bp, ptr, numrecs); | 622 | xfs_bmbt_log_recs(cur, bp, ptr, numrecs); |
624 | } | 623 | } |
625 | xfs_bmbt_log_block(cur, bp, XFS_BB_NUMRECS); | 624 | xfs_bmbt_log_block(cur, bp, XFS_BB_NUMRECS); |
626 | #ifdef DEBUG | 625 | #ifdef DEBUG |
627 | if (ptr < numrecs) { | 626 | if (ptr < numrecs) { |
628 | if (level == 0) | 627 | if (level == 0) |
629 | xfs_btree_check_rec(XFS_BTNUM_BMAP, rp + ptr - 1, | 628 | xfs_btree_check_rec(XFS_BTNUM_BMAP, rp + ptr - 1, |
630 | rp + ptr); | 629 | rp + ptr); |
631 | else | 630 | else |
632 | xfs_btree_check_key(XFS_BTNUM_BMAP, kp + ptr - 1, | 631 | xfs_btree_check_key(XFS_BTNUM_BMAP, kp + ptr - 1, |
633 | kp + ptr); | 632 | kp + ptr); |
634 | } | 633 | } |
635 | #endif | 634 | #endif |
636 | if (optr == 1 && (error = xfs_btree_updkey(cur, (union xfs_btree_key *)&key, level + 1))) { | 635 | if (optr == 1 && (error = xfs_btree_updkey(cur, (union xfs_btree_key *)&key, level + 1))) { |
637 | XFS_BMBT_TRACE_CURSOR(cur, ERROR); | 636 | XFS_BMBT_TRACE_CURSOR(cur, ERROR); |
638 | return error; | 637 | return error; |
639 | } | 638 | } |
640 | *bnop = nbno; | 639 | *bnop = nbno; |
641 | if (nbno != NULLFSBLOCK) { | 640 | if (nbno != NULLFSBLOCK) { |
642 | *recp = nrec; | 641 | *recp = nrec; |
643 | *curp = ncur; | 642 | *curp = ncur; |
644 | } | 643 | } |
645 | XFS_BMBT_TRACE_CURSOR(cur, EXIT); | 644 | XFS_BMBT_TRACE_CURSOR(cur, EXIT); |
646 | *stat = 1; | 645 | *stat = 1; |
647 | return 0; | 646 | return 0; |
648 | } | 647 | } |
649 | 648 | ||
650 | STATIC int | 649 | STATIC int |
651 | xfs_bmbt_killroot( | 650 | xfs_bmbt_killroot( |
652 | xfs_btree_cur_t *cur) | 651 | xfs_btree_cur_t *cur) |
653 | { | 652 | { |
654 | xfs_bmbt_block_t *block; | 653 | xfs_bmbt_block_t *block; |
655 | xfs_bmbt_block_t *cblock; | 654 | xfs_bmbt_block_t *cblock; |
656 | xfs_buf_t *cbp; | 655 | xfs_buf_t *cbp; |
657 | xfs_bmbt_key_t *ckp; | 656 | xfs_bmbt_key_t *ckp; |
658 | xfs_bmbt_ptr_t *cpp; | 657 | xfs_bmbt_ptr_t *cpp; |
659 | #ifdef DEBUG | 658 | #ifdef DEBUG |
660 | int error; | 659 | int error; |
661 | #endif | 660 | #endif |
662 | int i; | 661 | int i; |
663 | xfs_bmbt_key_t *kp; | 662 | xfs_bmbt_key_t *kp; |
664 | xfs_inode_t *ip; | 663 | xfs_inode_t *ip; |
665 | xfs_ifork_t *ifp; | 664 | xfs_ifork_t *ifp; |
666 | int level; | 665 | int level; |
667 | xfs_bmbt_ptr_t *pp; | 666 | xfs_bmbt_ptr_t *pp; |
668 | 667 | ||
669 | XFS_BMBT_TRACE_CURSOR(cur, ENTRY); | 668 | XFS_BMBT_TRACE_CURSOR(cur, ENTRY); |
670 | level = cur->bc_nlevels - 1; | 669 | level = cur->bc_nlevels - 1; |
671 | ASSERT(level >= 1); | 670 | ASSERT(level >= 1); |
672 | /* | 671 | /* |
673 | * Don't deal with the root block needs to be a leaf case. | 672 | * Don't deal with the root block needs to be a leaf case. |
674 | * We're just going to turn the thing back into extents anyway. | 673 | * We're just going to turn the thing back into extents anyway. |
675 | */ | 674 | */ |
676 | if (level == 1) { | 675 | if (level == 1) { |
677 | XFS_BMBT_TRACE_CURSOR(cur, EXIT); | 676 | XFS_BMBT_TRACE_CURSOR(cur, EXIT); |
678 | return 0; | 677 | return 0; |
679 | } | 678 | } |
680 | block = xfs_bmbt_get_block(cur, level, &cbp); | 679 | block = xfs_bmbt_get_block(cur, level, &cbp); |
681 | /* | 680 | /* |
682 | * Give up if the root has multiple children. | 681 | * Give up if the root has multiple children. |
683 | */ | 682 | */ |
684 | if (be16_to_cpu(block->bb_numrecs) != 1) { | 683 | if (be16_to_cpu(block->bb_numrecs) != 1) { |
685 | XFS_BMBT_TRACE_CURSOR(cur, EXIT); | 684 | XFS_BMBT_TRACE_CURSOR(cur, EXIT); |
686 | return 0; | 685 | return 0; |
687 | } | 686 | } |
688 | /* | 687 | /* |
689 | * Only do this if the next level will fit. | 688 | * Only do this if the next level will fit. |
690 | * Then the data must be copied up to the inode, | 689 | * Then the data must be copied up to the inode, |
691 | * instead of freeing the root you free the next level. | 690 | * instead of freeing the root you free the next level. |
692 | */ | 691 | */ |
693 | cbp = cur->bc_bufs[level - 1]; | 692 | cbp = cur->bc_bufs[level - 1]; |
694 | cblock = XFS_BUF_TO_BMBT_BLOCK(cbp); | 693 | cblock = XFS_BUF_TO_BMBT_BLOCK(cbp); |
695 | if (be16_to_cpu(cblock->bb_numrecs) > XFS_BMAP_BLOCK_DMAXRECS(level, cur)) { | 694 | if (be16_to_cpu(cblock->bb_numrecs) > XFS_BMAP_BLOCK_DMAXRECS(level, cur)) { |
696 | XFS_BMBT_TRACE_CURSOR(cur, EXIT); | 695 | XFS_BMBT_TRACE_CURSOR(cur, EXIT); |
697 | return 0; | 696 | return 0; |
698 | } | 697 | } |
699 | ASSERT(be64_to_cpu(cblock->bb_leftsib) == NULLDFSBNO); | 698 | ASSERT(be64_to_cpu(cblock->bb_leftsib) == NULLDFSBNO); |
700 | ASSERT(be64_to_cpu(cblock->bb_rightsib) == NULLDFSBNO); | 699 | ASSERT(be64_to_cpu(cblock->bb_rightsib) == NULLDFSBNO); |
701 | ip = cur->bc_private.b.ip; | 700 | ip = cur->bc_private.b.ip; |
702 | ifp = XFS_IFORK_PTR(ip, cur->bc_private.b.whichfork); | 701 | ifp = XFS_IFORK_PTR(ip, cur->bc_private.b.whichfork); |
703 | ASSERT(XFS_BMAP_BLOCK_IMAXRECS(level, cur) == | 702 | ASSERT(XFS_BMAP_BLOCK_IMAXRECS(level, cur) == |
704 | XFS_BMAP_BROOT_MAXRECS(ifp->if_broot_bytes)); | 703 | XFS_BMAP_BROOT_MAXRECS(ifp->if_broot_bytes)); |
705 | i = (int)(be16_to_cpu(cblock->bb_numrecs) - XFS_BMAP_BLOCK_IMAXRECS(level, cur)); | 704 | i = (int)(be16_to_cpu(cblock->bb_numrecs) - XFS_BMAP_BLOCK_IMAXRECS(level, cur)); |
706 | if (i) { | 705 | if (i) { |
707 | xfs_iroot_realloc(ip, i, cur->bc_private.b.whichfork); | 706 | xfs_iroot_realloc(ip, i, cur->bc_private.b.whichfork); |
708 | block = ifp->if_broot; | 707 | block = ifp->if_broot; |
709 | } | 708 | } |
710 | be16_add_cpu(&block->bb_numrecs, i); | 709 | be16_add_cpu(&block->bb_numrecs, i); |
711 | ASSERT(block->bb_numrecs == cblock->bb_numrecs); | 710 | ASSERT(block->bb_numrecs == cblock->bb_numrecs); |
712 | kp = XFS_BMAP_KEY_IADDR(block, 1, cur); | 711 | kp = XFS_BMAP_KEY_IADDR(block, 1, cur); |
713 | ckp = XFS_BMAP_KEY_IADDR(cblock, 1, cur); | 712 | ckp = XFS_BMAP_KEY_IADDR(cblock, 1, cur); |
714 | memcpy(kp, ckp, be16_to_cpu(block->bb_numrecs) * sizeof(*kp)); | 713 | memcpy(kp, ckp, be16_to_cpu(block->bb_numrecs) * sizeof(*kp)); |
715 | pp = XFS_BMAP_PTR_IADDR(block, 1, cur); | 714 | pp = XFS_BMAP_PTR_IADDR(block, 1, cur); |
716 | cpp = XFS_BMAP_PTR_IADDR(cblock, 1, cur); | 715 | cpp = XFS_BMAP_PTR_IADDR(cblock, 1, cur); |
717 | #ifdef DEBUG | 716 | #ifdef DEBUG |
718 | for (i = 0; i < be16_to_cpu(cblock->bb_numrecs); i++) { | 717 | for (i = 0; i < be16_to_cpu(cblock->bb_numrecs); i++) { |
719 | if ((error = xfs_btree_check_lptr_disk(cur, cpp[i], level - 1))) { | 718 | if ((error = xfs_btree_check_lptr_disk(cur, cpp[i], level - 1))) { |
720 | XFS_BMBT_TRACE_CURSOR(cur, ERROR); | 719 | XFS_BMBT_TRACE_CURSOR(cur, ERROR); |
721 | return error; | 720 | return error; |
722 | } | 721 | } |
723 | } | 722 | } |
724 | #endif | 723 | #endif |
725 | memcpy(pp, cpp, be16_to_cpu(block->bb_numrecs) * sizeof(*pp)); | 724 | memcpy(pp, cpp, be16_to_cpu(block->bb_numrecs) * sizeof(*pp)); |
726 | xfs_bmap_add_free(XFS_DADDR_TO_FSB(cur->bc_mp, XFS_BUF_ADDR(cbp)), 1, | 725 | xfs_bmap_add_free(XFS_DADDR_TO_FSB(cur->bc_mp, XFS_BUF_ADDR(cbp)), 1, |
727 | cur->bc_private.b.flist, cur->bc_mp); | 726 | cur->bc_private.b.flist, cur->bc_mp); |
728 | ip->i_d.di_nblocks--; | 727 | ip->i_d.di_nblocks--; |
729 | XFS_TRANS_MOD_DQUOT_BYINO(cur->bc_mp, cur->bc_tp, ip, | 728 | XFS_TRANS_MOD_DQUOT_BYINO(cur->bc_mp, cur->bc_tp, ip, |
730 | XFS_TRANS_DQ_BCOUNT, -1L); | 729 | XFS_TRANS_DQ_BCOUNT, -1L); |
731 | xfs_trans_binval(cur->bc_tp, cbp); | 730 | xfs_trans_binval(cur->bc_tp, cbp); |
732 | cur->bc_bufs[level - 1] = NULL; | 731 | cur->bc_bufs[level - 1] = NULL; |
733 | be16_add_cpu(&block->bb_level, -1); | 732 | be16_add_cpu(&block->bb_level, -1); |
734 | xfs_trans_log_inode(cur->bc_tp, ip, | 733 | xfs_trans_log_inode(cur->bc_tp, ip, |
735 | XFS_ILOG_CORE | XFS_ILOG_FBROOT(cur->bc_private.b.whichfork)); | 734 | XFS_ILOG_CORE | XFS_ILOG_FBROOT(cur->bc_private.b.whichfork)); |
736 | cur->bc_nlevels--; | 735 | cur->bc_nlevels--; |
737 | XFS_BMBT_TRACE_CURSOR(cur, EXIT); | 736 | XFS_BMBT_TRACE_CURSOR(cur, EXIT); |
738 | return 0; | 737 | return 0; |
739 | } | 738 | } |
740 | 739 | ||
741 | /* | 740 | /* |
742 | * Log key values from the btree block. | 741 | * Log key values from the btree block. |
743 | */ | 742 | */ |
744 | STATIC void | 743 | STATIC void |
745 | xfs_bmbt_log_keys( | 744 | xfs_bmbt_log_keys( |
746 | xfs_btree_cur_t *cur, | 745 | xfs_btree_cur_t *cur, |
747 | xfs_buf_t *bp, | 746 | xfs_buf_t *bp, |
748 | int kfirst, | 747 | int kfirst, |
749 | int klast) | 748 | int klast) |
750 | { | 749 | { |
751 | xfs_trans_t *tp; | 750 | xfs_trans_t *tp; |
752 | 751 | ||
753 | XFS_BMBT_TRACE_CURSOR(cur, ENTRY); | 752 | XFS_BMBT_TRACE_CURSOR(cur, ENTRY); |
754 | XFS_BMBT_TRACE_ARGBII(cur, bp, kfirst, klast); | 753 | XFS_BMBT_TRACE_ARGBII(cur, bp, kfirst, klast); |
755 | tp = cur->bc_tp; | 754 | tp = cur->bc_tp; |
756 | if (bp) { | 755 | if (bp) { |
757 | xfs_bmbt_block_t *block; | 756 | xfs_bmbt_block_t *block; |
758 | int first; | 757 | int first; |
759 | xfs_bmbt_key_t *kp; | 758 | xfs_bmbt_key_t *kp; |
760 | int last; | 759 | int last; |
761 | 760 | ||
762 | block = XFS_BUF_TO_BMBT_BLOCK(bp); | 761 | block = XFS_BUF_TO_BMBT_BLOCK(bp); |
763 | kp = XFS_BMAP_KEY_DADDR(block, 1, cur); | 762 | kp = XFS_BMAP_KEY_DADDR(block, 1, cur); |
764 | first = (int)((xfs_caddr_t)&kp[kfirst - 1] - (xfs_caddr_t)block); | 763 | first = (int)((xfs_caddr_t)&kp[kfirst - 1] - (xfs_caddr_t)block); |
765 | last = (int)(((xfs_caddr_t)&kp[klast] - 1) - (xfs_caddr_t)block); | 764 | last = (int)(((xfs_caddr_t)&kp[klast] - 1) - (xfs_caddr_t)block); |
766 | xfs_trans_log_buf(tp, bp, first, last); | 765 | xfs_trans_log_buf(tp, bp, first, last); |
767 | } else { | 766 | } else { |
768 | xfs_inode_t *ip; | 767 | xfs_inode_t *ip; |
769 | 768 | ||
770 | ip = cur->bc_private.b.ip; | 769 | ip = cur->bc_private.b.ip; |
771 | xfs_trans_log_inode(tp, ip, | 770 | xfs_trans_log_inode(tp, ip, |
772 | XFS_ILOG_FBROOT(cur->bc_private.b.whichfork)); | 771 | XFS_ILOG_FBROOT(cur->bc_private.b.whichfork)); |
773 | } | 772 | } |
774 | XFS_BMBT_TRACE_CURSOR(cur, EXIT); | 773 | XFS_BMBT_TRACE_CURSOR(cur, EXIT); |
775 | } | 774 | } |
776 | 775 | ||
777 | /* | 776 | /* |
778 | * Log pointer values from the btree block. | 777 | * Log pointer values from the btree block. |
779 | */ | 778 | */ |
780 | STATIC void | 779 | STATIC void |
781 | xfs_bmbt_log_ptrs( | 780 | xfs_bmbt_log_ptrs( |
782 | xfs_btree_cur_t *cur, | 781 | xfs_btree_cur_t *cur, |
783 | xfs_buf_t *bp, | 782 | xfs_buf_t *bp, |
784 | int pfirst, | 783 | int pfirst, |
785 | int plast) | 784 | int plast) |
786 | { | 785 | { |
787 | xfs_trans_t *tp; | 786 | xfs_trans_t *tp; |
788 | 787 | ||
789 | XFS_BMBT_TRACE_CURSOR(cur, ENTRY); | 788 | XFS_BMBT_TRACE_CURSOR(cur, ENTRY); |
790 | XFS_BMBT_TRACE_ARGBII(cur, bp, pfirst, plast); | 789 | XFS_BMBT_TRACE_ARGBII(cur, bp, pfirst, plast); |
791 | tp = cur->bc_tp; | 790 | tp = cur->bc_tp; |
792 | if (bp) { | 791 | if (bp) { |
793 | xfs_bmbt_block_t *block; | 792 | xfs_bmbt_block_t *block; |
794 | int first; | 793 | int first; |
795 | int last; | 794 | int last; |
796 | xfs_bmbt_ptr_t *pp; | 795 | xfs_bmbt_ptr_t *pp; |
797 | 796 | ||
798 | block = XFS_BUF_TO_BMBT_BLOCK(bp); | 797 | block = XFS_BUF_TO_BMBT_BLOCK(bp); |
799 | pp = XFS_BMAP_PTR_DADDR(block, 1, cur); | 798 | pp = XFS_BMAP_PTR_DADDR(block, 1, cur); |
800 | first = (int)((xfs_caddr_t)&pp[pfirst - 1] - (xfs_caddr_t)block); | 799 | first = (int)((xfs_caddr_t)&pp[pfirst - 1] - (xfs_caddr_t)block); |
801 | last = (int)(((xfs_caddr_t)&pp[plast] - 1) - (xfs_caddr_t)block); | 800 | last = (int)(((xfs_caddr_t)&pp[plast] - 1) - (xfs_caddr_t)block); |
802 | xfs_trans_log_buf(tp, bp, first, last); | 801 | xfs_trans_log_buf(tp, bp, first, last); |
803 | } else { | 802 | } else { |
804 | xfs_inode_t *ip; | 803 | xfs_inode_t *ip; |
805 | 804 | ||
806 | ip = cur->bc_private.b.ip; | 805 | ip = cur->bc_private.b.ip; |
807 | xfs_trans_log_inode(tp, ip, | 806 | xfs_trans_log_inode(tp, ip, |
808 | XFS_ILOG_FBROOT(cur->bc_private.b.whichfork)); | 807 | XFS_ILOG_FBROOT(cur->bc_private.b.whichfork)); |
809 | } | 808 | } |
810 | XFS_BMBT_TRACE_CURSOR(cur, EXIT); | 809 | XFS_BMBT_TRACE_CURSOR(cur, EXIT); |
811 | } | ||
812 | |||
813 | /* | ||
814 | * Move 1 record left from cur/level if possible. | ||
815 | * Update cur to reflect the new path. | ||
816 | */ | ||
817 | STATIC int /* error */ | ||
818 | xfs_bmbt_lshift( | ||
819 | xfs_btree_cur_t *cur, | ||
820 | int level, | ||
821 | int *stat) /* success/failure */ | ||
822 | { | ||
823 | int error; /* error return value */ | ||
824 | #ifdef DEBUG | ||
825 | int i; /* loop counter */ | ||
826 | #endif | ||
827 | xfs_bmbt_key_t key; /* bmap btree key */ | ||
828 | xfs_buf_t *lbp; /* left buffer pointer */ | ||
829 | xfs_bmbt_block_t *left; /* left btree block */ | ||
830 | xfs_bmbt_key_t *lkp=NULL; /* left btree key */ | ||
831 | xfs_bmbt_ptr_t *lpp; /* left address pointer */ | ||
832 | int lrecs; /* left record count */ | ||
833 | xfs_bmbt_rec_t *lrp=NULL; /* left record pointer */ | ||
834 | xfs_mount_t *mp; /* file system mount point */ | ||
835 | xfs_buf_t *rbp; /* right buffer pointer */ | ||
836 | xfs_bmbt_block_t *right; /* right btree block */ | ||
837 | xfs_bmbt_key_t *rkp=NULL; /* right btree key */ | ||
838 | xfs_bmbt_ptr_t *rpp=NULL; /* right address pointer */ | ||
839 | xfs_bmbt_rec_t *rrp=NULL; /* right record pointer */ | ||
840 | int rrecs; /* right record count */ | ||
841 | |||
842 | XFS_BMBT_TRACE_CURSOR(cur, ENTRY); | ||
843 | XFS_BMBT_TRACE_ARGI(cur, level); | ||
844 | if (level == cur->bc_nlevels - 1) { | ||
845 | XFS_BMBT_TRACE_CURSOR(cur, EXIT); | ||
846 | *stat = 0; | ||
847 | return 0; | ||
848 | } | ||
849 | rbp = cur->bc_bufs[level]; | ||
850 | right = XFS_BUF_TO_BMBT_BLOCK(rbp); | ||
851 | #ifdef DEBUG | ||
852 | if ((error = xfs_btree_check_lblock(cur, right, level, rbp))) { | ||
853 | XFS_BMBT_TRACE_CURSOR(cur, ERROR); | ||
854 | return error; | ||
855 | } | ||
856 | #endif | ||
857 | if (be64_to_cpu(right->bb_leftsib) == NULLDFSBNO) { | ||
858 | XFS_BMBT_TRACE_CURSOR(cur, EXIT); | ||
859 | *stat = 0; | ||
860 | return 0; | ||
861 | } | ||
862 | if (cur->bc_ptrs[level] <= 1) { | ||
863 | XFS_BMBT_TRACE_CURSOR(cur, EXIT); | ||
864 | *stat = 0; | ||
865 | return 0; | ||
866 | } | ||
867 | mp = cur->bc_mp; | ||
868 | if ((error = xfs_btree_read_bufl(mp, cur->bc_tp, be64_to_cpu(right->bb_leftsib), 0, | ||
869 | &lbp, XFS_BMAP_BTREE_REF))) { | ||
870 | XFS_BMBT_TRACE_CURSOR(cur, ERROR); | ||
871 | return error; | ||
872 | } | ||
873 | left = XFS_BUF_TO_BMBT_BLOCK(lbp); | ||
874 | if ((error = xfs_btree_check_lblock(cur, left, level, lbp))) { | ||
875 | XFS_BMBT_TRACE_CURSOR(cur, ERROR); | ||
876 | return error; | ||
877 | } | ||
878 | if (be16_to_cpu(left->bb_numrecs) == XFS_BMAP_BLOCK_IMAXRECS(level, cur)) { | ||
879 | XFS_BMBT_TRACE_CURSOR(cur, EXIT); | ||
880 | *stat = 0; | ||
881 | return 0; | ||
882 | } | ||
883 | lrecs = be16_to_cpu(left->bb_numrecs) + 1; | ||
884 | if (level > 0) { | ||
885 | lkp = XFS_BMAP_KEY_IADDR(left, lrecs, cur); | ||
886 | rkp = XFS_BMAP_KEY_IADDR(right, 1, cur); | ||
887 | *lkp = *rkp; | ||
888 | xfs_bmbt_log_keys(cur, lbp, lrecs, lrecs); | ||
889 | lpp = XFS_BMAP_PTR_IADDR(left, lrecs, cur); | ||
890 | rpp = XFS_BMAP_PTR_IADDR(right, 1, cur); | ||
891 | #ifdef DEBUG | ||
892 | if ((error = xfs_btree_check_lptr_disk(cur, *rpp, level))) { | ||
893 | XFS_BMBT_TRACE_CURSOR(cur, ERROR); | ||
894 | return error; | ||
895 | } | ||
896 | #endif | ||
897 | *lpp = *rpp; | ||
898 | xfs_bmbt_log_ptrs(cur, lbp, lrecs, lrecs); | ||
899 | } else { | ||
900 | lrp = XFS_BMAP_REC_IADDR(left, lrecs, cur); | ||
901 | rrp = XFS_BMAP_REC_IADDR(right, 1, cur); | ||
902 | *lrp = *rrp; | ||
903 | xfs_bmbt_log_recs(cur, lbp, lrecs, lrecs); | ||
904 | } | ||
905 | left->bb_numrecs = cpu_to_be16(lrecs); | ||
906 | xfs_bmbt_log_block(cur, lbp, XFS_BB_NUMRECS); | ||
907 | #ifdef DEBUG | ||
908 | if (level > 0) | ||
909 | xfs_btree_check_key(XFS_BTNUM_BMAP, lkp - 1, lkp); | ||
910 | else | ||
911 | xfs_btree_check_rec(XFS_BTNUM_BMAP, lrp - 1, lrp); | ||
912 | #endif | ||
913 | rrecs = be16_to_cpu(right->bb_numrecs) - 1; | ||
914 | right->bb_numrecs = cpu_to_be16(rrecs); | ||
915 | xfs_bmbt_log_block(cur, rbp, XFS_BB_NUMRECS); | ||
916 | if (level > 0) { | ||
917 | #ifdef DEBUG | ||
918 | for (i = 0; i < rrecs; i++) { | ||
919 | if ((error = xfs_btree_check_lptr_disk(cur, rpp[i + 1], | ||
920 | level))) { | ||
921 | XFS_BMBT_TRACE_CURSOR(cur, ERROR); | ||
922 | return error; | ||
923 | } | ||
924 | } | ||
925 | #endif | ||
926 | memmove(rkp, rkp + 1, rrecs * sizeof(*rkp)); | ||
927 | memmove(rpp, rpp + 1, rrecs * sizeof(*rpp)); | ||
928 | xfs_bmbt_log_keys(cur, rbp, 1, rrecs); | ||
929 | xfs_bmbt_log_ptrs(cur, rbp, 1, rrecs); | ||
930 | } else { | ||
931 | memmove(rrp, rrp + 1, rrecs * sizeof(*rrp)); | ||
932 | xfs_bmbt_log_recs(cur, rbp, 1, rrecs); | ||
933 | key.br_startoff = cpu_to_be64(xfs_bmbt_disk_get_startoff(rrp)); | ||
934 | rkp = &key; | ||
935 | } | ||
936 | if ((error = xfs_btree_updkey(cur, (union xfs_btree_key *)rkp, level + 1))) { | ||
937 | XFS_BMBT_TRACE_CURSOR(cur, ERROR); | ||
938 | return error; | ||
939 | } | ||
940 | cur->bc_ptrs[level]--; | ||
941 | XFS_BMBT_TRACE_CURSOR(cur, EXIT); | ||
942 | *stat = 1; | ||
943 | return 0; | ||
944 | } | 810 | } |
945 | 811 | ||
946 | /* | 812 | /* |
947 | * Determine the extent state. | 813 | * Determine the extent state. |
948 | */ | 814 | */ |
949 | /* ARGSUSED */ | 815 | /* ARGSUSED */ |
950 | STATIC xfs_exntst_t | 816 | STATIC xfs_exntst_t |
951 | xfs_extent_state( | 817 | xfs_extent_state( |
952 | xfs_filblks_t blks, | 818 | xfs_filblks_t blks, |
953 | int extent_flag) | 819 | int extent_flag) |
954 | { | 820 | { |
955 | if (extent_flag) { | 821 | if (extent_flag) { |
956 | ASSERT(blks != 0); /* saved for DMIG */ | 822 | ASSERT(blks != 0); /* saved for DMIG */ |
957 | return XFS_EXT_UNWRITTEN; | 823 | return XFS_EXT_UNWRITTEN; |
958 | } | 824 | } |
959 | return XFS_EXT_NORM; | 825 | return XFS_EXT_NORM; |
960 | } | 826 | } |
961 | 827 | ||
962 | 828 | ||
963 | /* | 829 | /* |
964 | * Split cur/level block in half. | 830 | * Split cur/level block in half. |
965 | * Return new block number and its first record (to be inserted into parent). | 831 | * Return new block number and its first record (to be inserted into parent). |
966 | */ | 832 | */ |
967 | STATIC int /* error */ | 833 | STATIC int /* error */ |
968 | xfs_bmbt_split( | 834 | xfs_bmbt_split( |
969 | xfs_btree_cur_t *cur, | 835 | xfs_btree_cur_t *cur, |
970 | int level, | 836 | int level, |
971 | xfs_fsblock_t *bnop, | 837 | xfs_fsblock_t *bnop, |
972 | __uint64_t *startoff, | 838 | __uint64_t *startoff, |
973 | xfs_btree_cur_t **curp, | 839 | xfs_btree_cur_t **curp, |
974 | int *stat) /* success/failure */ | 840 | int *stat) /* success/failure */ |
975 | { | 841 | { |
976 | xfs_alloc_arg_t args; /* block allocation args */ | 842 | xfs_alloc_arg_t args; /* block allocation args */ |
977 | int error; /* error return value */ | 843 | int error; /* error return value */ |
978 | int i; /* loop counter */ | 844 | int i; /* loop counter */ |
979 | xfs_fsblock_t lbno; /* left sibling block number */ | 845 | xfs_fsblock_t lbno; /* left sibling block number */ |
980 | xfs_buf_t *lbp; /* left buffer pointer */ | 846 | xfs_buf_t *lbp; /* left buffer pointer */ |
981 | xfs_bmbt_block_t *left; /* left btree block */ | 847 | xfs_bmbt_block_t *left; /* left btree block */ |
982 | xfs_bmbt_key_t *lkp; /* left btree key */ | 848 | xfs_bmbt_key_t *lkp; /* left btree key */ |
983 | xfs_bmbt_ptr_t *lpp; /* left address pointer */ | 849 | xfs_bmbt_ptr_t *lpp; /* left address pointer */ |
984 | xfs_bmbt_rec_t *lrp; /* left record pointer */ | 850 | xfs_bmbt_rec_t *lrp; /* left record pointer */ |
985 | xfs_buf_t *rbp; /* right buffer pointer */ | 851 | xfs_buf_t *rbp; /* right buffer pointer */ |
986 | xfs_bmbt_block_t *right; /* right btree block */ | 852 | xfs_bmbt_block_t *right; /* right btree block */ |
987 | xfs_bmbt_key_t *rkp; /* right btree key */ | 853 | xfs_bmbt_key_t *rkp; /* right btree key */ |
988 | xfs_bmbt_ptr_t *rpp; /* right address pointer */ | 854 | xfs_bmbt_ptr_t *rpp; /* right address pointer */ |
989 | xfs_bmbt_block_t *rrblock; /* right-right btree block */ | 855 | xfs_bmbt_block_t *rrblock; /* right-right btree block */ |
990 | xfs_buf_t *rrbp; /* right-right buffer pointer */ | 856 | xfs_buf_t *rrbp; /* right-right buffer pointer */ |
991 | xfs_bmbt_rec_t *rrp; /* right record pointer */ | 857 | xfs_bmbt_rec_t *rrp; /* right record pointer */ |
992 | 858 | ||
993 | XFS_BMBT_TRACE_CURSOR(cur, ENTRY); | 859 | XFS_BMBT_TRACE_CURSOR(cur, ENTRY); |
994 | // disable until merged into common code | 860 | // disable until merged into common code |
995 | // XFS_BMBT_TRACE_ARGIFK(cur, level, *bnop, *startoff); | 861 | // XFS_BMBT_TRACE_ARGIFK(cur, level, *bnop, *startoff); |
996 | args.tp = cur->bc_tp; | 862 | args.tp = cur->bc_tp; |
997 | args.mp = cur->bc_mp; | 863 | args.mp = cur->bc_mp; |
998 | lbp = cur->bc_bufs[level]; | 864 | lbp = cur->bc_bufs[level]; |
999 | lbno = XFS_DADDR_TO_FSB(args.mp, XFS_BUF_ADDR(lbp)); | 865 | lbno = XFS_DADDR_TO_FSB(args.mp, XFS_BUF_ADDR(lbp)); |
1000 | left = XFS_BUF_TO_BMBT_BLOCK(lbp); | 866 | left = XFS_BUF_TO_BMBT_BLOCK(lbp); |
1001 | args.fsbno = cur->bc_private.b.firstblock; | 867 | args.fsbno = cur->bc_private.b.firstblock; |
1002 | args.firstblock = args.fsbno; | 868 | args.firstblock = args.fsbno; |
1003 | args.minleft = 0; | 869 | args.minleft = 0; |
1004 | if (args.fsbno == NULLFSBLOCK) { | 870 | if (args.fsbno == NULLFSBLOCK) { |
1005 | args.fsbno = lbno; | 871 | args.fsbno = lbno; |
1006 | args.type = XFS_ALLOCTYPE_START_BNO; | 872 | args.type = XFS_ALLOCTYPE_START_BNO; |
1007 | /* | 873 | /* |
1008 | * Make sure there is sufficient room left in the AG to | 874 | * Make sure there is sufficient room left in the AG to |
1009 | * complete a full tree split for an extent insert. If | 875 | * complete a full tree split for an extent insert. If |
1010 | * we are converting the middle part of an extent then | 876 | * we are converting the middle part of an extent then |
1011 | * we may need space for two tree splits. | 877 | * we may need space for two tree splits. |
1012 | * | 878 | * |
1013 | * We are relying on the caller to make the correct block | 879 | * We are relying on the caller to make the correct block |
1014 | * reservation for this operation to succeed. If the | 880 | * reservation for this operation to succeed. If the |
1015 | * reservation amount is insufficient then we may fail a | 881 | * reservation amount is insufficient then we may fail a |
1016 | * block allocation here and corrupt the filesystem. | 882 | * block allocation here and corrupt the filesystem. |
1017 | */ | 883 | */ |
1018 | args.minleft = xfs_trans_get_block_res(args.tp); | 884 | args.minleft = xfs_trans_get_block_res(args.tp); |
1019 | } else if (cur->bc_private.b.flist->xbf_low) | 885 | } else if (cur->bc_private.b.flist->xbf_low) |
1020 | args.type = XFS_ALLOCTYPE_START_BNO; | 886 | args.type = XFS_ALLOCTYPE_START_BNO; |
1021 | else | 887 | else |
1022 | args.type = XFS_ALLOCTYPE_NEAR_BNO; | 888 | args.type = XFS_ALLOCTYPE_NEAR_BNO; |
1023 | args.mod = args.alignment = args.total = args.isfl = | 889 | args.mod = args.alignment = args.total = args.isfl = |
1024 | args.userdata = args.minalignslop = 0; | 890 | args.userdata = args.minalignslop = 0; |
1025 | args.minlen = args.maxlen = args.prod = 1; | 891 | args.minlen = args.maxlen = args.prod = 1; |
1026 | args.wasdel = cur->bc_private.b.flags & XFS_BTCUR_BPRV_WASDEL; | 892 | args.wasdel = cur->bc_private.b.flags & XFS_BTCUR_BPRV_WASDEL; |
1027 | if (!args.wasdel && xfs_trans_get_block_res(args.tp) == 0) { | 893 | if (!args.wasdel && xfs_trans_get_block_res(args.tp) == 0) { |
1028 | XFS_BMBT_TRACE_CURSOR(cur, ERROR); | 894 | XFS_BMBT_TRACE_CURSOR(cur, ERROR); |
1029 | return XFS_ERROR(ENOSPC); | 895 | return XFS_ERROR(ENOSPC); |
1030 | } | 896 | } |
1031 | if ((error = xfs_alloc_vextent(&args))) { | 897 | if ((error = xfs_alloc_vextent(&args))) { |
1032 | XFS_BMBT_TRACE_CURSOR(cur, ERROR); | 898 | XFS_BMBT_TRACE_CURSOR(cur, ERROR); |
1033 | return error; | 899 | return error; |
1034 | } | 900 | } |
1035 | if (args.fsbno == NULLFSBLOCK && args.minleft) { | 901 | if (args.fsbno == NULLFSBLOCK && args.minleft) { |
1036 | /* | 902 | /* |
1037 | * Could not find an AG with enough free space to satisfy | 903 | * Could not find an AG with enough free space to satisfy |
1038 | * a full btree split. Try again without minleft and if | 904 | * a full btree split. Try again without minleft and if |
1039 | * successful activate the lowspace algorithm. | 905 | * successful activate the lowspace algorithm. |
1040 | */ | 906 | */ |
1041 | args.fsbno = 0; | 907 | args.fsbno = 0; |
1042 | args.type = XFS_ALLOCTYPE_FIRST_AG; | 908 | args.type = XFS_ALLOCTYPE_FIRST_AG; |
1043 | args.minleft = 0; | 909 | args.minleft = 0; |
1044 | if ((error = xfs_alloc_vextent(&args))) { | 910 | if ((error = xfs_alloc_vextent(&args))) { |
1045 | XFS_BMBT_TRACE_CURSOR(cur, ERROR); | 911 | XFS_BMBT_TRACE_CURSOR(cur, ERROR); |
1046 | return error; | 912 | return error; |
1047 | } | 913 | } |
1048 | cur->bc_private.b.flist->xbf_low = 1; | 914 | cur->bc_private.b.flist->xbf_low = 1; |
1049 | } | 915 | } |
1050 | if (args.fsbno == NULLFSBLOCK) { | 916 | if (args.fsbno == NULLFSBLOCK) { |
1051 | XFS_BMBT_TRACE_CURSOR(cur, EXIT); | 917 | XFS_BMBT_TRACE_CURSOR(cur, EXIT); |
1052 | *stat = 0; | 918 | *stat = 0; |
1053 | return 0; | 919 | return 0; |
1054 | } | 920 | } |
1055 | ASSERT(args.len == 1); | 921 | ASSERT(args.len == 1); |
1056 | cur->bc_private.b.firstblock = args.fsbno; | 922 | cur->bc_private.b.firstblock = args.fsbno; |
1057 | cur->bc_private.b.allocated++; | 923 | cur->bc_private.b.allocated++; |
1058 | cur->bc_private.b.ip->i_d.di_nblocks++; | 924 | cur->bc_private.b.ip->i_d.di_nblocks++; |
1059 | xfs_trans_log_inode(args.tp, cur->bc_private.b.ip, XFS_ILOG_CORE); | 925 | xfs_trans_log_inode(args.tp, cur->bc_private.b.ip, XFS_ILOG_CORE); |
1060 | XFS_TRANS_MOD_DQUOT_BYINO(args.mp, args.tp, cur->bc_private.b.ip, | 926 | XFS_TRANS_MOD_DQUOT_BYINO(args.mp, args.tp, cur->bc_private.b.ip, |
1061 | XFS_TRANS_DQ_BCOUNT, 1L); | 927 | XFS_TRANS_DQ_BCOUNT, 1L); |
1062 | rbp = xfs_btree_get_bufl(args.mp, args.tp, args.fsbno, 0); | 928 | rbp = xfs_btree_get_bufl(args.mp, args.tp, args.fsbno, 0); |
1063 | right = XFS_BUF_TO_BMBT_BLOCK(rbp); | 929 | right = XFS_BUF_TO_BMBT_BLOCK(rbp); |
1064 | #ifdef DEBUG | 930 | #ifdef DEBUG |
1065 | if ((error = xfs_btree_check_lblock(cur, left, level, rbp))) { | 931 | if ((error = xfs_btree_check_lblock(cur, left, level, rbp))) { |
1066 | XFS_BMBT_TRACE_CURSOR(cur, ERROR); | 932 | XFS_BMBT_TRACE_CURSOR(cur, ERROR); |
1067 | return error; | 933 | return error; |
1068 | } | 934 | } |
1069 | #endif | 935 | #endif |
1070 | right->bb_magic = cpu_to_be32(XFS_BMAP_MAGIC); | 936 | right->bb_magic = cpu_to_be32(XFS_BMAP_MAGIC); |
1071 | right->bb_level = left->bb_level; | 937 | right->bb_level = left->bb_level; |
1072 | right->bb_numrecs = cpu_to_be16(be16_to_cpu(left->bb_numrecs) / 2); | 938 | right->bb_numrecs = cpu_to_be16(be16_to_cpu(left->bb_numrecs) / 2); |
1073 | if ((be16_to_cpu(left->bb_numrecs) & 1) && | 939 | if ((be16_to_cpu(left->bb_numrecs) & 1) && |
1074 | cur->bc_ptrs[level] <= be16_to_cpu(right->bb_numrecs) + 1) | 940 | cur->bc_ptrs[level] <= be16_to_cpu(right->bb_numrecs) + 1) |
1075 | be16_add_cpu(&right->bb_numrecs, 1); | 941 | be16_add_cpu(&right->bb_numrecs, 1); |
1076 | i = be16_to_cpu(left->bb_numrecs) - be16_to_cpu(right->bb_numrecs) + 1; | 942 | i = be16_to_cpu(left->bb_numrecs) - be16_to_cpu(right->bb_numrecs) + 1; |
1077 | if (level > 0) { | 943 | if (level > 0) { |
1078 | lkp = XFS_BMAP_KEY_IADDR(left, i, cur); | 944 | lkp = XFS_BMAP_KEY_IADDR(left, i, cur); |
1079 | lpp = XFS_BMAP_PTR_IADDR(left, i, cur); | 945 | lpp = XFS_BMAP_PTR_IADDR(left, i, cur); |
1080 | rkp = XFS_BMAP_KEY_IADDR(right, 1, cur); | 946 | rkp = XFS_BMAP_KEY_IADDR(right, 1, cur); |
1081 | rpp = XFS_BMAP_PTR_IADDR(right, 1, cur); | 947 | rpp = XFS_BMAP_PTR_IADDR(right, 1, cur); |
1082 | #ifdef DEBUG | 948 | #ifdef DEBUG |
1083 | for (i = 0; i < be16_to_cpu(right->bb_numrecs); i++) { | 949 | for (i = 0; i < be16_to_cpu(right->bb_numrecs); i++) { |
1084 | if ((error = xfs_btree_check_lptr_disk(cur, lpp[i], level))) { | 950 | if ((error = xfs_btree_check_lptr_disk(cur, lpp[i], level))) { |
1085 | XFS_BMBT_TRACE_CURSOR(cur, ERROR); | 951 | XFS_BMBT_TRACE_CURSOR(cur, ERROR); |
1086 | return error; | 952 | return error; |
1087 | } | 953 | } |
1088 | } | 954 | } |
1089 | #endif | 955 | #endif |
1090 | memcpy(rkp, lkp, be16_to_cpu(right->bb_numrecs) * sizeof(*rkp)); | 956 | memcpy(rkp, lkp, be16_to_cpu(right->bb_numrecs) * sizeof(*rkp)); |
1091 | memcpy(rpp, lpp, be16_to_cpu(right->bb_numrecs) * sizeof(*rpp)); | 957 | memcpy(rpp, lpp, be16_to_cpu(right->bb_numrecs) * sizeof(*rpp)); |
1092 | xfs_bmbt_log_keys(cur, rbp, 1, be16_to_cpu(right->bb_numrecs)); | 958 | xfs_bmbt_log_keys(cur, rbp, 1, be16_to_cpu(right->bb_numrecs)); |
1093 | xfs_bmbt_log_ptrs(cur, rbp, 1, be16_to_cpu(right->bb_numrecs)); | 959 | xfs_bmbt_log_ptrs(cur, rbp, 1, be16_to_cpu(right->bb_numrecs)); |
1094 | *startoff = be64_to_cpu(rkp->br_startoff); | 960 | *startoff = be64_to_cpu(rkp->br_startoff); |
1095 | } else { | 961 | } else { |
1096 | lrp = XFS_BMAP_REC_IADDR(left, i, cur); | 962 | lrp = XFS_BMAP_REC_IADDR(left, i, cur); |
1097 | rrp = XFS_BMAP_REC_IADDR(right, 1, cur); | 963 | rrp = XFS_BMAP_REC_IADDR(right, 1, cur); |
1098 | memcpy(rrp, lrp, be16_to_cpu(right->bb_numrecs) * sizeof(*rrp)); | 964 | memcpy(rrp, lrp, be16_to_cpu(right->bb_numrecs) * sizeof(*rrp)); |
1099 | xfs_bmbt_log_recs(cur, rbp, 1, be16_to_cpu(right->bb_numrecs)); | 965 | xfs_bmbt_log_recs(cur, rbp, 1, be16_to_cpu(right->bb_numrecs)); |
1100 | *startoff = xfs_bmbt_disk_get_startoff(rrp); | 966 | *startoff = xfs_bmbt_disk_get_startoff(rrp); |
1101 | } | 967 | } |
1102 | be16_add_cpu(&left->bb_numrecs, -(be16_to_cpu(right->bb_numrecs))); | 968 | be16_add_cpu(&left->bb_numrecs, -(be16_to_cpu(right->bb_numrecs))); |
1103 | right->bb_rightsib = left->bb_rightsib; | 969 | right->bb_rightsib = left->bb_rightsib; |
1104 | left->bb_rightsib = cpu_to_be64(args.fsbno); | 970 | left->bb_rightsib = cpu_to_be64(args.fsbno); |
1105 | right->bb_leftsib = cpu_to_be64(lbno); | 971 | right->bb_leftsib = cpu_to_be64(lbno); |
1106 | xfs_bmbt_log_block(cur, rbp, XFS_BB_ALL_BITS); | 972 | xfs_bmbt_log_block(cur, rbp, XFS_BB_ALL_BITS); |
1107 | xfs_bmbt_log_block(cur, lbp, XFS_BB_NUMRECS | XFS_BB_RIGHTSIB); | 973 | xfs_bmbt_log_block(cur, lbp, XFS_BB_NUMRECS | XFS_BB_RIGHTSIB); |
1108 | if (be64_to_cpu(right->bb_rightsib) != NULLDFSBNO) { | 974 | if (be64_to_cpu(right->bb_rightsib) != NULLDFSBNO) { |
1109 | if ((error = xfs_btree_read_bufl(args.mp, args.tp, | 975 | if ((error = xfs_btree_read_bufl(args.mp, args.tp, |
1110 | be64_to_cpu(right->bb_rightsib), 0, &rrbp, | 976 | be64_to_cpu(right->bb_rightsib), 0, &rrbp, |
1111 | XFS_BMAP_BTREE_REF))) { | 977 | XFS_BMAP_BTREE_REF))) { |
1112 | XFS_BMBT_TRACE_CURSOR(cur, ERROR); | 978 | XFS_BMBT_TRACE_CURSOR(cur, ERROR); |
1113 | return error; | 979 | return error; |
1114 | } | 980 | } |
1115 | rrblock = XFS_BUF_TO_BMBT_BLOCK(rrbp); | 981 | rrblock = XFS_BUF_TO_BMBT_BLOCK(rrbp); |
1116 | if ((error = xfs_btree_check_lblock(cur, rrblock, level, rrbp))) { | 982 | if ((error = xfs_btree_check_lblock(cur, rrblock, level, rrbp))) { |
1117 | XFS_BMBT_TRACE_CURSOR(cur, ERROR); | 983 | XFS_BMBT_TRACE_CURSOR(cur, ERROR); |
1118 | return error; | 984 | return error; |
1119 | } | 985 | } |
1120 | rrblock->bb_leftsib = cpu_to_be64(args.fsbno); | 986 | rrblock->bb_leftsib = cpu_to_be64(args.fsbno); |
1121 | xfs_bmbt_log_block(cur, rrbp, XFS_BB_LEFTSIB); | 987 | xfs_bmbt_log_block(cur, rrbp, XFS_BB_LEFTSIB); |
1122 | } | 988 | } |
1123 | if (cur->bc_ptrs[level] > be16_to_cpu(left->bb_numrecs) + 1) { | 989 | if (cur->bc_ptrs[level] > be16_to_cpu(left->bb_numrecs) + 1) { |
1124 | xfs_btree_setbuf(cur, level, rbp); | 990 | xfs_btree_setbuf(cur, level, rbp); |
1125 | cur->bc_ptrs[level] -= be16_to_cpu(left->bb_numrecs); | 991 | cur->bc_ptrs[level] -= be16_to_cpu(left->bb_numrecs); |
1126 | } | 992 | } |
1127 | if (level + 1 < cur->bc_nlevels) { | 993 | if (level + 1 < cur->bc_nlevels) { |
1128 | if ((error = xfs_btree_dup_cursor(cur, curp))) { | 994 | if ((error = xfs_btree_dup_cursor(cur, curp))) { |
1129 | XFS_BMBT_TRACE_CURSOR(cur, ERROR); | 995 | XFS_BMBT_TRACE_CURSOR(cur, ERROR); |
1130 | return error; | 996 | return error; |
1131 | } | 997 | } |
1132 | (*curp)->bc_ptrs[level + 1]++; | 998 | (*curp)->bc_ptrs[level + 1]++; |
1133 | } | 999 | } |
1134 | *bnop = args.fsbno; | 1000 | *bnop = args.fsbno; |
1135 | XFS_BMBT_TRACE_CURSOR(cur, EXIT); | 1001 | XFS_BMBT_TRACE_CURSOR(cur, EXIT); |
1136 | *stat = 1; | 1002 | *stat = 1; |
1137 | return 0; | 1003 | return 0; |
1138 | } | 1004 | } |
1139 | 1005 | ||
1140 | /* | 1006 | /* |
1141 | * Convert on-disk form of btree root to in-memory form. | 1007 | * Convert on-disk form of btree root to in-memory form. |
1142 | */ | 1008 | */ |
1143 | void | 1009 | void |
1144 | xfs_bmdr_to_bmbt( | 1010 | xfs_bmdr_to_bmbt( |
1145 | xfs_bmdr_block_t *dblock, | 1011 | xfs_bmdr_block_t *dblock, |
1146 | int dblocklen, | 1012 | int dblocklen, |
1147 | xfs_bmbt_block_t *rblock, | 1013 | xfs_bmbt_block_t *rblock, |
1148 | int rblocklen) | 1014 | int rblocklen) |
1149 | { | 1015 | { |
1150 | int dmxr; | 1016 | int dmxr; |
1151 | xfs_bmbt_key_t *fkp; | 1017 | xfs_bmbt_key_t *fkp; |
1152 | __be64 *fpp; | 1018 | __be64 *fpp; |
1153 | xfs_bmbt_key_t *tkp; | 1019 | xfs_bmbt_key_t *tkp; |
1154 | __be64 *tpp; | 1020 | __be64 *tpp; |
1155 | 1021 | ||
1156 | rblock->bb_magic = cpu_to_be32(XFS_BMAP_MAGIC); | 1022 | rblock->bb_magic = cpu_to_be32(XFS_BMAP_MAGIC); |
1157 | rblock->bb_level = dblock->bb_level; | 1023 | rblock->bb_level = dblock->bb_level; |
1158 | ASSERT(be16_to_cpu(rblock->bb_level) > 0); | 1024 | ASSERT(be16_to_cpu(rblock->bb_level) > 0); |
1159 | rblock->bb_numrecs = dblock->bb_numrecs; | 1025 | rblock->bb_numrecs = dblock->bb_numrecs; |
1160 | rblock->bb_leftsib = cpu_to_be64(NULLDFSBNO); | 1026 | rblock->bb_leftsib = cpu_to_be64(NULLDFSBNO); |
1161 | rblock->bb_rightsib = cpu_to_be64(NULLDFSBNO); | 1027 | rblock->bb_rightsib = cpu_to_be64(NULLDFSBNO); |
1162 | dmxr = (int)XFS_BTREE_BLOCK_MAXRECS(dblocklen, xfs_bmdr, 0); | 1028 | dmxr = (int)XFS_BTREE_BLOCK_MAXRECS(dblocklen, xfs_bmdr, 0); |
1163 | fkp = XFS_BTREE_KEY_ADDR(xfs_bmdr, dblock, 1); | 1029 | fkp = XFS_BTREE_KEY_ADDR(xfs_bmdr, dblock, 1); |
1164 | tkp = XFS_BMAP_BROOT_KEY_ADDR(rblock, 1, rblocklen); | 1030 | tkp = XFS_BMAP_BROOT_KEY_ADDR(rblock, 1, rblocklen); |
1165 | fpp = XFS_BTREE_PTR_ADDR(xfs_bmdr, dblock, 1, dmxr); | 1031 | fpp = XFS_BTREE_PTR_ADDR(xfs_bmdr, dblock, 1, dmxr); |
1166 | tpp = XFS_BMAP_BROOT_PTR_ADDR(rblock, 1, rblocklen); | 1032 | tpp = XFS_BMAP_BROOT_PTR_ADDR(rblock, 1, rblocklen); |
1167 | dmxr = be16_to_cpu(dblock->bb_numrecs); | 1033 | dmxr = be16_to_cpu(dblock->bb_numrecs); |
1168 | memcpy(tkp, fkp, sizeof(*fkp) * dmxr); | 1034 | memcpy(tkp, fkp, sizeof(*fkp) * dmxr); |
1169 | memcpy(tpp, fpp, sizeof(*fpp) * dmxr); | 1035 | memcpy(tpp, fpp, sizeof(*fpp) * dmxr); |
1170 | } | 1036 | } |
1171 | 1037 | ||
1172 | /* | 1038 | /* |
1173 | * Delete the record pointed to by cur. | 1039 | * Delete the record pointed to by cur. |
1174 | */ | 1040 | */ |
1175 | int /* error */ | 1041 | int /* error */ |
1176 | xfs_bmbt_delete( | 1042 | xfs_bmbt_delete( |
1177 | xfs_btree_cur_t *cur, | 1043 | xfs_btree_cur_t *cur, |
1178 | int *stat) /* success/failure */ | 1044 | int *stat) /* success/failure */ |
1179 | { | 1045 | { |
1180 | int error; /* error return value */ | 1046 | int error; /* error return value */ |
1181 | int i; | 1047 | int i; |
1182 | int level; | 1048 | int level; |
1183 | 1049 | ||
1184 | XFS_BMBT_TRACE_CURSOR(cur, ENTRY); | 1050 | XFS_BMBT_TRACE_CURSOR(cur, ENTRY); |
1185 | for (level = 0, i = 2; i == 2; level++) { | 1051 | for (level = 0, i = 2; i == 2; level++) { |
1186 | if ((error = xfs_bmbt_delrec(cur, level, &i))) { | 1052 | if ((error = xfs_bmbt_delrec(cur, level, &i))) { |
1187 | XFS_BMBT_TRACE_CURSOR(cur, ERROR); | 1053 | XFS_BMBT_TRACE_CURSOR(cur, ERROR); |
1188 | return error; | 1054 | return error; |
1189 | } | 1055 | } |
1190 | } | 1056 | } |
1191 | if (i == 0) { | 1057 | if (i == 0) { |
1192 | for (level = 1; level < cur->bc_nlevels; level++) { | 1058 | for (level = 1; level < cur->bc_nlevels; level++) { |
1193 | if (cur->bc_ptrs[level] == 0) { | 1059 | if (cur->bc_ptrs[level] == 0) { |
1194 | if ((error = xfs_btree_decrement(cur, level, | 1060 | if ((error = xfs_btree_decrement(cur, level, |
1195 | &i))) { | 1061 | &i))) { |
1196 | XFS_BMBT_TRACE_CURSOR(cur, ERROR); | 1062 | XFS_BMBT_TRACE_CURSOR(cur, ERROR); |
1197 | return error; | 1063 | return error; |
1198 | } | 1064 | } |
1199 | break; | 1065 | break; |
1200 | } | 1066 | } |
1201 | } | 1067 | } |
1202 | } | 1068 | } |
1203 | XFS_BMBT_TRACE_CURSOR(cur, EXIT); | 1069 | XFS_BMBT_TRACE_CURSOR(cur, EXIT); |
1204 | *stat = i; | 1070 | *stat = i; |
1205 | return 0; | 1071 | return 0; |
1206 | } | 1072 | } |
1207 | 1073 | ||
1208 | /* | 1074 | /* |
1209 | * Convert a compressed bmap extent record to an uncompressed form. | 1075 | * Convert a compressed bmap extent record to an uncompressed form. |
1210 | * This code must be in sync with the routines xfs_bmbt_get_startoff, | 1076 | * This code must be in sync with the routines xfs_bmbt_get_startoff, |
1211 | * xfs_bmbt_get_startblock, xfs_bmbt_get_blockcount and xfs_bmbt_get_state. | 1077 | * xfs_bmbt_get_startblock, xfs_bmbt_get_blockcount and xfs_bmbt_get_state. |
1212 | */ | 1078 | */ |
1213 | 1079 | ||
1214 | STATIC_INLINE void | 1080 | STATIC_INLINE void |
1215 | __xfs_bmbt_get_all( | 1081 | __xfs_bmbt_get_all( |
1216 | __uint64_t l0, | 1082 | __uint64_t l0, |
1217 | __uint64_t l1, | 1083 | __uint64_t l1, |
1218 | xfs_bmbt_irec_t *s) | 1084 | xfs_bmbt_irec_t *s) |
1219 | { | 1085 | { |
1220 | int ext_flag; | 1086 | int ext_flag; |
1221 | xfs_exntst_t st; | 1087 | xfs_exntst_t st; |
1222 | 1088 | ||
1223 | ext_flag = (int)(l0 >> (64 - BMBT_EXNTFLAG_BITLEN)); | 1089 | ext_flag = (int)(l0 >> (64 - BMBT_EXNTFLAG_BITLEN)); |
1224 | s->br_startoff = ((xfs_fileoff_t)l0 & | 1090 | s->br_startoff = ((xfs_fileoff_t)l0 & |
1225 | XFS_MASK64LO(64 - BMBT_EXNTFLAG_BITLEN)) >> 9; | 1091 | XFS_MASK64LO(64 - BMBT_EXNTFLAG_BITLEN)) >> 9; |
1226 | #if XFS_BIG_BLKNOS | 1092 | #if XFS_BIG_BLKNOS |
1227 | s->br_startblock = (((xfs_fsblock_t)l0 & XFS_MASK64LO(9)) << 43) | | 1093 | s->br_startblock = (((xfs_fsblock_t)l0 & XFS_MASK64LO(9)) << 43) | |
1228 | (((xfs_fsblock_t)l1) >> 21); | 1094 | (((xfs_fsblock_t)l1) >> 21); |
1229 | #else | 1095 | #else |
1230 | #ifdef DEBUG | 1096 | #ifdef DEBUG |
1231 | { | 1097 | { |
1232 | xfs_dfsbno_t b; | 1098 | xfs_dfsbno_t b; |
1233 | 1099 | ||
1234 | b = (((xfs_dfsbno_t)l0 & XFS_MASK64LO(9)) << 43) | | 1100 | b = (((xfs_dfsbno_t)l0 & XFS_MASK64LO(9)) << 43) | |
1235 | (((xfs_dfsbno_t)l1) >> 21); | 1101 | (((xfs_dfsbno_t)l1) >> 21); |
1236 | ASSERT((b >> 32) == 0 || ISNULLDSTARTBLOCK(b)); | 1102 | ASSERT((b >> 32) == 0 || ISNULLDSTARTBLOCK(b)); |
1237 | s->br_startblock = (xfs_fsblock_t)b; | 1103 | s->br_startblock = (xfs_fsblock_t)b; |
1238 | } | 1104 | } |
1239 | #else /* !DEBUG */ | 1105 | #else /* !DEBUG */ |
1240 | s->br_startblock = (xfs_fsblock_t)(((xfs_dfsbno_t)l1) >> 21); | 1106 | s->br_startblock = (xfs_fsblock_t)(((xfs_dfsbno_t)l1) >> 21); |
1241 | #endif /* DEBUG */ | 1107 | #endif /* DEBUG */ |
1242 | #endif /* XFS_BIG_BLKNOS */ | 1108 | #endif /* XFS_BIG_BLKNOS */ |
1243 | s->br_blockcount = (xfs_filblks_t)(l1 & XFS_MASK64LO(21)); | 1109 | s->br_blockcount = (xfs_filblks_t)(l1 & XFS_MASK64LO(21)); |
1244 | /* This is xfs_extent_state() in-line */ | 1110 | /* This is xfs_extent_state() in-line */ |
1245 | if (ext_flag) { | 1111 | if (ext_flag) { |
1246 | ASSERT(s->br_blockcount != 0); /* saved for DMIG */ | 1112 | ASSERT(s->br_blockcount != 0); /* saved for DMIG */ |
1247 | st = XFS_EXT_UNWRITTEN; | 1113 | st = XFS_EXT_UNWRITTEN; |
1248 | } else | 1114 | } else |
1249 | st = XFS_EXT_NORM; | 1115 | st = XFS_EXT_NORM; |
1250 | s->br_state = st; | 1116 | s->br_state = st; |
1251 | } | 1117 | } |
1252 | 1118 | ||
1253 | void | 1119 | void |
1254 | xfs_bmbt_get_all( | 1120 | xfs_bmbt_get_all( |
1255 | xfs_bmbt_rec_host_t *r, | 1121 | xfs_bmbt_rec_host_t *r, |
1256 | xfs_bmbt_irec_t *s) | 1122 | xfs_bmbt_irec_t *s) |
1257 | { | 1123 | { |
1258 | __xfs_bmbt_get_all(r->l0, r->l1, s); | 1124 | __xfs_bmbt_get_all(r->l0, r->l1, s); |
1259 | } | 1125 | } |
1260 | 1126 | ||
1261 | /* | 1127 | /* |
1262 | * Get the block pointer for the given level of the cursor. | 1128 | * Get the block pointer for the given level of the cursor. |
1263 | * Fill in the buffer pointer, if applicable. | 1129 | * Fill in the buffer pointer, if applicable. |
1264 | */ | 1130 | */ |
1265 | xfs_bmbt_block_t * | 1131 | xfs_bmbt_block_t * |
1266 | xfs_bmbt_get_block( | 1132 | xfs_bmbt_get_block( |
1267 | xfs_btree_cur_t *cur, | 1133 | xfs_btree_cur_t *cur, |
1268 | int level, | 1134 | int level, |
1269 | xfs_buf_t **bpp) | 1135 | xfs_buf_t **bpp) |
1270 | { | 1136 | { |
1271 | xfs_ifork_t *ifp; | 1137 | xfs_ifork_t *ifp; |
1272 | xfs_bmbt_block_t *rval; | 1138 | xfs_bmbt_block_t *rval; |
1273 | 1139 | ||
1274 | if (level < cur->bc_nlevels - 1) { | 1140 | if (level < cur->bc_nlevels - 1) { |
1275 | *bpp = cur->bc_bufs[level]; | 1141 | *bpp = cur->bc_bufs[level]; |
1276 | rval = XFS_BUF_TO_BMBT_BLOCK(*bpp); | 1142 | rval = XFS_BUF_TO_BMBT_BLOCK(*bpp); |
1277 | } else { | 1143 | } else { |
1278 | *bpp = NULL; | 1144 | *bpp = NULL; |
1279 | ifp = XFS_IFORK_PTR(cur->bc_private.b.ip, | 1145 | ifp = XFS_IFORK_PTR(cur->bc_private.b.ip, |
1280 | cur->bc_private.b.whichfork); | 1146 | cur->bc_private.b.whichfork); |
1281 | rval = ifp->if_broot; | 1147 | rval = ifp->if_broot; |
1282 | } | 1148 | } |
1283 | return rval; | 1149 | return rval; |
1284 | } | 1150 | } |
1285 | 1151 | ||
1286 | /* | 1152 | /* |
1287 | * Extract the blockcount field from an in memory bmap extent record. | 1153 | * Extract the blockcount field from an in memory bmap extent record. |
1288 | */ | 1154 | */ |
1289 | xfs_filblks_t | 1155 | xfs_filblks_t |
1290 | xfs_bmbt_get_blockcount( | 1156 | xfs_bmbt_get_blockcount( |
1291 | xfs_bmbt_rec_host_t *r) | 1157 | xfs_bmbt_rec_host_t *r) |
1292 | { | 1158 | { |
1293 | return (xfs_filblks_t)(r->l1 & XFS_MASK64LO(21)); | 1159 | return (xfs_filblks_t)(r->l1 & XFS_MASK64LO(21)); |
1294 | } | 1160 | } |
1295 | 1161 | ||
1296 | /* | 1162 | /* |
1297 | * Extract the startblock field from an in memory bmap extent record. | 1163 | * Extract the startblock field from an in memory bmap extent record. |
1298 | */ | 1164 | */ |
1299 | xfs_fsblock_t | 1165 | xfs_fsblock_t |
1300 | xfs_bmbt_get_startblock( | 1166 | xfs_bmbt_get_startblock( |
1301 | xfs_bmbt_rec_host_t *r) | 1167 | xfs_bmbt_rec_host_t *r) |
1302 | { | 1168 | { |
1303 | #if XFS_BIG_BLKNOS | 1169 | #if XFS_BIG_BLKNOS |
1304 | return (((xfs_fsblock_t)r->l0 & XFS_MASK64LO(9)) << 43) | | 1170 | return (((xfs_fsblock_t)r->l0 & XFS_MASK64LO(9)) << 43) | |
1305 | (((xfs_fsblock_t)r->l1) >> 21); | 1171 | (((xfs_fsblock_t)r->l1) >> 21); |
1306 | #else | 1172 | #else |
1307 | #ifdef DEBUG | 1173 | #ifdef DEBUG |
1308 | xfs_dfsbno_t b; | 1174 | xfs_dfsbno_t b; |
1309 | 1175 | ||
1310 | b = (((xfs_dfsbno_t)r->l0 & XFS_MASK64LO(9)) << 43) | | 1176 | b = (((xfs_dfsbno_t)r->l0 & XFS_MASK64LO(9)) << 43) | |
1311 | (((xfs_dfsbno_t)r->l1) >> 21); | 1177 | (((xfs_dfsbno_t)r->l1) >> 21); |
1312 | ASSERT((b >> 32) == 0 || ISNULLDSTARTBLOCK(b)); | 1178 | ASSERT((b >> 32) == 0 || ISNULLDSTARTBLOCK(b)); |
1313 | return (xfs_fsblock_t)b; | 1179 | return (xfs_fsblock_t)b; |
1314 | #else /* !DEBUG */ | 1180 | #else /* !DEBUG */ |
1315 | return (xfs_fsblock_t)(((xfs_dfsbno_t)r->l1) >> 21); | 1181 | return (xfs_fsblock_t)(((xfs_dfsbno_t)r->l1) >> 21); |
1316 | #endif /* DEBUG */ | 1182 | #endif /* DEBUG */ |
1317 | #endif /* XFS_BIG_BLKNOS */ | 1183 | #endif /* XFS_BIG_BLKNOS */ |
1318 | } | 1184 | } |
1319 | 1185 | ||
1320 | /* | 1186 | /* |
1321 | * Extract the startoff field from an in memory bmap extent record. | 1187 | * Extract the startoff field from an in memory bmap extent record. |
1322 | */ | 1188 | */ |
1323 | xfs_fileoff_t | 1189 | xfs_fileoff_t |
1324 | xfs_bmbt_get_startoff( | 1190 | xfs_bmbt_get_startoff( |
1325 | xfs_bmbt_rec_host_t *r) | 1191 | xfs_bmbt_rec_host_t *r) |
1326 | { | 1192 | { |
1327 | return ((xfs_fileoff_t)r->l0 & | 1193 | return ((xfs_fileoff_t)r->l0 & |
1328 | XFS_MASK64LO(64 - BMBT_EXNTFLAG_BITLEN)) >> 9; | 1194 | XFS_MASK64LO(64 - BMBT_EXNTFLAG_BITLEN)) >> 9; |
1329 | } | 1195 | } |
1330 | 1196 | ||
1331 | xfs_exntst_t | 1197 | xfs_exntst_t |
1332 | xfs_bmbt_get_state( | 1198 | xfs_bmbt_get_state( |
1333 | xfs_bmbt_rec_host_t *r) | 1199 | xfs_bmbt_rec_host_t *r) |
1334 | { | 1200 | { |
1335 | int ext_flag; | 1201 | int ext_flag; |
1336 | 1202 | ||
1337 | ext_flag = (int)((r->l0) >> (64 - BMBT_EXNTFLAG_BITLEN)); | 1203 | ext_flag = (int)((r->l0) >> (64 - BMBT_EXNTFLAG_BITLEN)); |
1338 | return xfs_extent_state(xfs_bmbt_get_blockcount(r), | 1204 | return xfs_extent_state(xfs_bmbt_get_blockcount(r), |
1339 | ext_flag); | 1205 | ext_flag); |
1340 | } | 1206 | } |
1341 | 1207 | ||
1342 | /* Endian flipping versions of the bmbt extraction functions */ | 1208 | /* Endian flipping versions of the bmbt extraction functions */ |
1343 | void | 1209 | void |
1344 | xfs_bmbt_disk_get_all( | 1210 | xfs_bmbt_disk_get_all( |
1345 | xfs_bmbt_rec_t *r, | 1211 | xfs_bmbt_rec_t *r, |
1346 | xfs_bmbt_irec_t *s) | 1212 | xfs_bmbt_irec_t *s) |
1347 | { | 1213 | { |
1348 | __xfs_bmbt_get_all(be64_to_cpu(r->l0), be64_to_cpu(r->l1), s); | 1214 | __xfs_bmbt_get_all(be64_to_cpu(r->l0), be64_to_cpu(r->l1), s); |
1349 | } | 1215 | } |
1350 | 1216 | ||
1351 | /* | 1217 | /* |
1352 | * Extract the blockcount field from an on disk bmap extent record. | 1218 | * Extract the blockcount field from an on disk bmap extent record. |
1353 | */ | 1219 | */ |
1354 | xfs_filblks_t | 1220 | xfs_filblks_t |
1355 | xfs_bmbt_disk_get_blockcount( | 1221 | xfs_bmbt_disk_get_blockcount( |
1356 | xfs_bmbt_rec_t *r) | 1222 | xfs_bmbt_rec_t *r) |
1357 | { | 1223 | { |
1358 | return (xfs_filblks_t)(be64_to_cpu(r->l1) & XFS_MASK64LO(21)); | 1224 | return (xfs_filblks_t)(be64_to_cpu(r->l1) & XFS_MASK64LO(21)); |
1359 | } | 1225 | } |
1360 | 1226 | ||
1361 | /* | 1227 | /* |
1362 | * Extract the startoff field from a disk format bmap extent record. | 1228 | * Extract the startoff field from a disk format bmap extent record. |
1363 | */ | 1229 | */ |
1364 | xfs_fileoff_t | 1230 | xfs_fileoff_t |
1365 | xfs_bmbt_disk_get_startoff( | 1231 | xfs_bmbt_disk_get_startoff( |
1366 | xfs_bmbt_rec_t *r) | 1232 | xfs_bmbt_rec_t *r) |
1367 | { | 1233 | { |
1368 | return ((xfs_fileoff_t)be64_to_cpu(r->l0) & | 1234 | return ((xfs_fileoff_t)be64_to_cpu(r->l0) & |
1369 | XFS_MASK64LO(64 - BMBT_EXNTFLAG_BITLEN)) >> 9; | 1235 | XFS_MASK64LO(64 - BMBT_EXNTFLAG_BITLEN)) >> 9; |
1370 | } | 1236 | } |
1371 | 1237 | ||
1372 | /* | 1238 | /* |
1373 | * Insert the current record at the point referenced by cur. | 1239 | * Insert the current record at the point referenced by cur. |
1374 | * | 1240 | * |
1375 | * A multi-level split of the tree on insert will invalidate the original | 1241 | * A multi-level split of the tree on insert will invalidate the original |
1376 | * cursor. All callers of this function should assume that the cursor is | 1242 | * cursor. All callers of this function should assume that the cursor is |
1377 | * no longer valid and revalidate it. | 1243 | * no longer valid and revalidate it. |
1378 | */ | 1244 | */ |
1379 | int /* error */ | 1245 | int /* error */ |
1380 | xfs_bmbt_insert( | 1246 | xfs_bmbt_insert( |
1381 | xfs_btree_cur_t *cur, | 1247 | xfs_btree_cur_t *cur, |
1382 | int *stat) /* success/failure */ | 1248 | int *stat) /* success/failure */ |
1383 | { | 1249 | { |
1384 | int error; /* error return value */ | 1250 | int error; /* error return value */ |
1385 | int i; | 1251 | int i; |
1386 | int level; | 1252 | int level; |
1387 | xfs_fsblock_t nbno; | 1253 | xfs_fsblock_t nbno; |
1388 | xfs_btree_cur_t *ncur; | 1254 | xfs_btree_cur_t *ncur; |
1389 | xfs_bmbt_rec_t nrec; | 1255 | xfs_bmbt_rec_t nrec; |
1390 | xfs_btree_cur_t *pcur; | 1256 | xfs_btree_cur_t *pcur; |
1391 | 1257 | ||
1392 | XFS_BMBT_TRACE_CURSOR(cur, ENTRY); | 1258 | XFS_BMBT_TRACE_CURSOR(cur, ENTRY); |
1393 | level = 0; | 1259 | level = 0; |
1394 | nbno = NULLFSBLOCK; | 1260 | nbno = NULLFSBLOCK; |
1395 | xfs_bmbt_disk_set_all(&nrec, &cur->bc_rec.b); | 1261 | xfs_bmbt_disk_set_all(&nrec, &cur->bc_rec.b); |
1396 | ncur = NULL; | 1262 | ncur = NULL; |
1397 | pcur = cur; | 1263 | pcur = cur; |
1398 | do { | 1264 | do { |
1399 | if ((error = xfs_bmbt_insrec(pcur, level++, &nbno, &nrec, &ncur, | 1265 | if ((error = xfs_bmbt_insrec(pcur, level++, &nbno, &nrec, &ncur, |
1400 | &i))) { | 1266 | &i))) { |
1401 | if (pcur != cur) | 1267 | if (pcur != cur) |
1402 | xfs_btree_del_cursor(pcur, XFS_BTREE_ERROR); | 1268 | xfs_btree_del_cursor(pcur, XFS_BTREE_ERROR); |
1403 | XFS_BMBT_TRACE_CURSOR(cur, ERROR); | 1269 | XFS_BMBT_TRACE_CURSOR(cur, ERROR); |
1404 | return error; | 1270 | return error; |
1405 | } | 1271 | } |
1406 | XFS_WANT_CORRUPTED_GOTO(i == 1, error0); | 1272 | XFS_WANT_CORRUPTED_GOTO(i == 1, error0); |
1407 | if (pcur != cur && (ncur || nbno == NULLFSBLOCK)) { | 1273 | if (pcur != cur && (ncur || nbno == NULLFSBLOCK)) { |
1408 | cur->bc_nlevels = pcur->bc_nlevels; | 1274 | cur->bc_nlevels = pcur->bc_nlevels; |
1409 | cur->bc_private.b.allocated += | 1275 | cur->bc_private.b.allocated += |
1410 | pcur->bc_private.b.allocated; | 1276 | pcur->bc_private.b.allocated; |
1411 | pcur->bc_private.b.allocated = 0; | 1277 | pcur->bc_private.b.allocated = 0; |
1412 | ASSERT((cur->bc_private.b.firstblock != NULLFSBLOCK) || | 1278 | ASSERT((cur->bc_private.b.firstblock != NULLFSBLOCK) || |
1413 | XFS_IS_REALTIME_INODE(cur->bc_private.b.ip)); | 1279 | XFS_IS_REALTIME_INODE(cur->bc_private.b.ip)); |
1414 | cur->bc_private.b.firstblock = | 1280 | cur->bc_private.b.firstblock = |
1415 | pcur->bc_private.b.firstblock; | 1281 | pcur->bc_private.b.firstblock; |
1416 | ASSERT(cur->bc_private.b.flist == | 1282 | ASSERT(cur->bc_private.b.flist == |
1417 | pcur->bc_private.b.flist); | 1283 | pcur->bc_private.b.flist); |
1418 | xfs_btree_del_cursor(pcur, XFS_BTREE_NOERROR); | 1284 | xfs_btree_del_cursor(pcur, XFS_BTREE_NOERROR); |
1419 | } | 1285 | } |
1420 | if (ncur) { | 1286 | if (ncur) { |
1421 | pcur = ncur; | 1287 | pcur = ncur; |
1422 | ncur = NULL; | 1288 | ncur = NULL; |
1423 | } | 1289 | } |
1424 | } while (nbno != NULLFSBLOCK); | 1290 | } while (nbno != NULLFSBLOCK); |
1425 | XFS_BMBT_TRACE_CURSOR(cur, EXIT); | 1291 | XFS_BMBT_TRACE_CURSOR(cur, EXIT); |
1426 | *stat = i; | 1292 | *stat = i; |
1427 | return 0; | 1293 | return 0; |
1428 | error0: | 1294 | error0: |
1429 | XFS_BMBT_TRACE_CURSOR(cur, ERROR); | 1295 | XFS_BMBT_TRACE_CURSOR(cur, ERROR); |
1430 | return error; | 1296 | return error; |
1431 | } | 1297 | } |
1432 | 1298 | ||
1433 | /* | 1299 | /* |
1434 | * Log fields from the btree block header. | 1300 | * Log fields from the btree block header. |
1435 | */ | 1301 | */ |
1436 | void | 1302 | void |
1437 | xfs_bmbt_log_block( | 1303 | xfs_bmbt_log_block( |
1438 | xfs_btree_cur_t *cur, | 1304 | xfs_btree_cur_t *cur, |
1439 | xfs_buf_t *bp, | 1305 | xfs_buf_t *bp, |
1440 | int fields) | 1306 | int fields) |
1441 | { | 1307 | { |
1442 | int first; | 1308 | int first; |
1443 | int last; | 1309 | int last; |
1444 | xfs_trans_t *tp; | 1310 | xfs_trans_t *tp; |
1445 | static const short offsets[] = { | 1311 | static const short offsets[] = { |
1446 | offsetof(xfs_bmbt_block_t, bb_magic), | 1312 | offsetof(xfs_bmbt_block_t, bb_magic), |
1447 | offsetof(xfs_bmbt_block_t, bb_level), | 1313 | offsetof(xfs_bmbt_block_t, bb_level), |
1448 | offsetof(xfs_bmbt_block_t, bb_numrecs), | 1314 | offsetof(xfs_bmbt_block_t, bb_numrecs), |
1449 | offsetof(xfs_bmbt_block_t, bb_leftsib), | 1315 | offsetof(xfs_bmbt_block_t, bb_leftsib), |
1450 | offsetof(xfs_bmbt_block_t, bb_rightsib), | 1316 | offsetof(xfs_bmbt_block_t, bb_rightsib), |
1451 | sizeof(xfs_bmbt_block_t) | 1317 | sizeof(xfs_bmbt_block_t) |
1452 | }; | 1318 | }; |
1453 | 1319 | ||
1454 | XFS_BMBT_TRACE_CURSOR(cur, ENTRY); | 1320 | XFS_BMBT_TRACE_CURSOR(cur, ENTRY); |
1455 | XFS_BMBT_TRACE_ARGBI(cur, bp, fields); | 1321 | XFS_BMBT_TRACE_ARGBI(cur, bp, fields); |
1456 | tp = cur->bc_tp; | 1322 | tp = cur->bc_tp; |
1457 | if (bp) { | 1323 | if (bp) { |
1458 | xfs_btree_offsets(fields, offsets, XFS_BB_NUM_BITS, &first, | 1324 | xfs_btree_offsets(fields, offsets, XFS_BB_NUM_BITS, &first, |
1459 | &last); | 1325 | &last); |
1460 | xfs_trans_log_buf(tp, bp, first, last); | 1326 | xfs_trans_log_buf(tp, bp, first, last); |
1461 | } else | 1327 | } else |
1462 | xfs_trans_log_inode(tp, cur->bc_private.b.ip, | 1328 | xfs_trans_log_inode(tp, cur->bc_private.b.ip, |
1463 | XFS_ILOG_FBROOT(cur->bc_private.b.whichfork)); | 1329 | XFS_ILOG_FBROOT(cur->bc_private.b.whichfork)); |
1464 | XFS_BMBT_TRACE_CURSOR(cur, EXIT); | 1330 | XFS_BMBT_TRACE_CURSOR(cur, EXIT); |
1465 | } | 1331 | } |
1466 | 1332 | ||
1467 | /* | 1333 | /* |
1468 | * Log record values from the btree block. | 1334 | * Log record values from the btree block. |
1469 | */ | 1335 | */ |
1470 | void | 1336 | void |
1471 | xfs_bmbt_log_recs( | 1337 | xfs_bmbt_log_recs( |
1472 | xfs_btree_cur_t *cur, | 1338 | xfs_btree_cur_t *cur, |
1473 | xfs_buf_t *bp, | 1339 | xfs_buf_t *bp, |
1474 | int rfirst, | 1340 | int rfirst, |
1475 | int rlast) | 1341 | int rlast) |
1476 | { | 1342 | { |
1477 | xfs_bmbt_block_t *block; | 1343 | xfs_bmbt_block_t *block; |
1478 | int first; | 1344 | int first; |
1479 | int last; | 1345 | int last; |
1480 | xfs_bmbt_rec_t *rp; | 1346 | xfs_bmbt_rec_t *rp; |
1481 | xfs_trans_t *tp; | 1347 | xfs_trans_t *tp; |
1482 | 1348 | ||
1483 | XFS_BMBT_TRACE_CURSOR(cur, ENTRY); | 1349 | XFS_BMBT_TRACE_CURSOR(cur, ENTRY); |
1484 | XFS_BMBT_TRACE_ARGBII(cur, bp, rfirst, rlast); | 1350 | XFS_BMBT_TRACE_ARGBII(cur, bp, rfirst, rlast); |
1485 | ASSERT(bp); | 1351 | ASSERT(bp); |
1486 | tp = cur->bc_tp; | 1352 | tp = cur->bc_tp; |
1487 | block = XFS_BUF_TO_BMBT_BLOCK(bp); | 1353 | block = XFS_BUF_TO_BMBT_BLOCK(bp); |
1488 | rp = XFS_BMAP_REC_DADDR(block, 1, cur); | 1354 | rp = XFS_BMAP_REC_DADDR(block, 1, cur); |
1489 | first = (int)((xfs_caddr_t)&rp[rfirst - 1] - (xfs_caddr_t)block); | 1355 | first = (int)((xfs_caddr_t)&rp[rfirst - 1] - (xfs_caddr_t)block); |
1490 | last = (int)(((xfs_caddr_t)&rp[rlast] - 1) - (xfs_caddr_t)block); | 1356 | last = (int)(((xfs_caddr_t)&rp[rlast] - 1) - (xfs_caddr_t)block); |
1491 | xfs_trans_log_buf(tp, bp, first, last); | 1357 | xfs_trans_log_buf(tp, bp, first, last); |
1492 | XFS_BMBT_TRACE_CURSOR(cur, EXIT); | 1358 | XFS_BMBT_TRACE_CURSOR(cur, EXIT); |
1493 | } | 1359 | } |
1494 | 1360 | ||
1495 | /* | 1361 | /* |
1496 | * Give the bmap btree a new root block. Copy the old broot contents | 1362 | * Give the bmap btree a new root block. Copy the old broot contents |
1497 | * down into a real block and make the broot point to it. | 1363 | * down into a real block and make the broot point to it. |
1498 | */ | 1364 | */ |
1499 | int /* error */ | 1365 | int /* error */ |
1500 | xfs_bmbt_newroot( | 1366 | xfs_bmbt_newroot( |
1501 | xfs_btree_cur_t *cur, /* btree cursor */ | 1367 | xfs_btree_cur_t *cur, /* btree cursor */ |
1502 | int *logflags, /* logging flags for inode */ | 1368 | int *logflags, /* logging flags for inode */ |
1503 | int *stat) /* return status - 0 fail */ | 1369 | int *stat) /* return status - 0 fail */ |
1504 | { | 1370 | { |
1505 | xfs_alloc_arg_t args; /* allocation arguments */ | 1371 | xfs_alloc_arg_t args; /* allocation arguments */ |
1506 | xfs_bmbt_block_t *block; /* bmap btree block */ | 1372 | xfs_bmbt_block_t *block; /* bmap btree block */ |
1507 | xfs_buf_t *bp; /* buffer for block */ | 1373 | xfs_buf_t *bp; /* buffer for block */ |
1508 | xfs_bmbt_block_t *cblock; /* child btree block */ | 1374 | xfs_bmbt_block_t *cblock; /* child btree block */ |
1509 | xfs_bmbt_key_t *ckp; /* child key pointer */ | 1375 | xfs_bmbt_key_t *ckp; /* child key pointer */ |
1510 | xfs_bmbt_ptr_t *cpp; /* child ptr pointer */ | 1376 | xfs_bmbt_ptr_t *cpp; /* child ptr pointer */ |
1511 | int error; /* error return code */ | 1377 | int error; /* error return code */ |
1512 | #ifdef DEBUG | 1378 | #ifdef DEBUG |
1513 | int i; /* loop counter */ | 1379 | int i; /* loop counter */ |
1514 | #endif | 1380 | #endif |
1515 | xfs_bmbt_key_t *kp; /* pointer to bmap btree key */ | 1381 | xfs_bmbt_key_t *kp; /* pointer to bmap btree key */ |
1516 | int level; /* btree level */ | 1382 | int level; /* btree level */ |
1517 | xfs_bmbt_ptr_t *pp; /* pointer to bmap block addr */ | 1383 | xfs_bmbt_ptr_t *pp; /* pointer to bmap block addr */ |
1518 | 1384 | ||
1519 | XFS_BMBT_TRACE_CURSOR(cur, ENTRY); | 1385 | XFS_BMBT_TRACE_CURSOR(cur, ENTRY); |
1520 | level = cur->bc_nlevels - 1; | 1386 | level = cur->bc_nlevels - 1; |
1521 | block = xfs_bmbt_get_block(cur, level, &bp); | 1387 | block = xfs_bmbt_get_block(cur, level, &bp); |
1522 | /* | 1388 | /* |
1523 | * Copy the root into a real block. | 1389 | * Copy the root into a real block. |
1524 | */ | 1390 | */ |
1525 | args.mp = cur->bc_mp; | 1391 | args.mp = cur->bc_mp; |
1526 | pp = XFS_BMAP_PTR_IADDR(block, 1, cur); | 1392 | pp = XFS_BMAP_PTR_IADDR(block, 1, cur); |
1527 | args.tp = cur->bc_tp; | 1393 | args.tp = cur->bc_tp; |
1528 | args.fsbno = cur->bc_private.b.firstblock; | 1394 | args.fsbno = cur->bc_private.b.firstblock; |
1529 | args.mod = args.minleft = args.alignment = args.total = args.isfl = | 1395 | args.mod = args.minleft = args.alignment = args.total = args.isfl = |
1530 | args.userdata = args.minalignslop = 0; | 1396 | args.userdata = args.minalignslop = 0; |
1531 | args.minlen = args.maxlen = args.prod = 1; | 1397 | args.minlen = args.maxlen = args.prod = 1; |
1532 | args.wasdel = cur->bc_private.b.flags & XFS_BTCUR_BPRV_WASDEL; | 1398 | args.wasdel = cur->bc_private.b.flags & XFS_BTCUR_BPRV_WASDEL; |
1533 | args.firstblock = args.fsbno; | 1399 | args.firstblock = args.fsbno; |
1534 | if (args.fsbno == NULLFSBLOCK) { | 1400 | if (args.fsbno == NULLFSBLOCK) { |
1535 | #ifdef DEBUG | 1401 | #ifdef DEBUG |
1536 | if ((error = xfs_btree_check_lptr_disk(cur, *pp, level))) { | 1402 | if ((error = xfs_btree_check_lptr_disk(cur, *pp, level))) { |
1537 | XFS_BMBT_TRACE_CURSOR(cur, ERROR); | 1403 | XFS_BMBT_TRACE_CURSOR(cur, ERROR); |
1538 | return error; | 1404 | return error; |
1539 | } | 1405 | } |
1540 | #endif | 1406 | #endif |
1541 | args.fsbno = be64_to_cpu(*pp); | 1407 | args.fsbno = be64_to_cpu(*pp); |
1542 | args.type = XFS_ALLOCTYPE_START_BNO; | 1408 | args.type = XFS_ALLOCTYPE_START_BNO; |
1543 | } else if (cur->bc_private.b.flist->xbf_low) | 1409 | } else if (cur->bc_private.b.flist->xbf_low) |
1544 | args.type = XFS_ALLOCTYPE_START_BNO; | 1410 | args.type = XFS_ALLOCTYPE_START_BNO; |
1545 | else | 1411 | else |
1546 | args.type = XFS_ALLOCTYPE_NEAR_BNO; | 1412 | args.type = XFS_ALLOCTYPE_NEAR_BNO; |
1547 | if ((error = xfs_alloc_vextent(&args))) { | 1413 | if ((error = xfs_alloc_vextent(&args))) { |
1548 | XFS_BMBT_TRACE_CURSOR(cur, ERROR); | 1414 | XFS_BMBT_TRACE_CURSOR(cur, ERROR); |
1549 | return error; | 1415 | return error; |
1550 | } | 1416 | } |
1551 | if (args.fsbno == NULLFSBLOCK) { | 1417 | if (args.fsbno == NULLFSBLOCK) { |
1552 | XFS_BMBT_TRACE_CURSOR(cur, EXIT); | 1418 | XFS_BMBT_TRACE_CURSOR(cur, EXIT); |
1553 | *stat = 0; | 1419 | *stat = 0; |
1554 | return 0; | 1420 | return 0; |
1555 | } | 1421 | } |
1556 | ASSERT(args.len == 1); | 1422 | ASSERT(args.len == 1); |
1557 | cur->bc_private.b.firstblock = args.fsbno; | 1423 | cur->bc_private.b.firstblock = args.fsbno; |
1558 | cur->bc_private.b.allocated++; | 1424 | cur->bc_private.b.allocated++; |
1559 | cur->bc_private.b.ip->i_d.di_nblocks++; | 1425 | cur->bc_private.b.ip->i_d.di_nblocks++; |
1560 | XFS_TRANS_MOD_DQUOT_BYINO(args.mp, args.tp, cur->bc_private.b.ip, | 1426 | XFS_TRANS_MOD_DQUOT_BYINO(args.mp, args.tp, cur->bc_private.b.ip, |
1561 | XFS_TRANS_DQ_BCOUNT, 1L); | 1427 | XFS_TRANS_DQ_BCOUNT, 1L); |
1562 | bp = xfs_btree_get_bufl(args.mp, cur->bc_tp, args.fsbno, 0); | 1428 | bp = xfs_btree_get_bufl(args.mp, cur->bc_tp, args.fsbno, 0); |
1563 | cblock = XFS_BUF_TO_BMBT_BLOCK(bp); | 1429 | cblock = XFS_BUF_TO_BMBT_BLOCK(bp); |
1564 | *cblock = *block; | 1430 | *cblock = *block; |
1565 | be16_add_cpu(&block->bb_level, 1); | 1431 | be16_add_cpu(&block->bb_level, 1); |
1566 | block->bb_numrecs = cpu_to_be16(1); | 1432 | block->bb_numrecs = cpu_to_be16(1); |
1567 | cur->bc_nlevels++; | 1433 | cur->bc_nlevels++; |
1568 | cur->bc_ptrs[level + 1] = 1; | 1434 | cur->bc_ptrs[level + 1] = 1; |
1569 | kp = XFS_BMAP_KEY_IADDR(block, 1, cur); | 1435 | kp = XFS_BMAP_KEY_IADDR(block, 1, cur); |
1570 | ckp = XFS_BMAP_KEY_IADDR(cblock, 1, cur); | 1436 | ckp = XFS_BMAP_KEY_IADDR(cblock, 1, cur); |
1571 | memcpy(ckp, kp, be16_to_cpu(cblock->bb_numrecs) * sizeof(*kp)); | 1437 | memcpy(ckp, kp, be16_to_cpu(cblock->bb_numrecs) * sizeof(*kp)); |
1572 | cpp = XFS_BMAP_PTR_IADDR(cblock, 1, cur); | 1438 | cpp = XFS_BMAP_PTR_IADDR(cblock, 1, cur); |
1573 | #ifdef DEBUG | 1439 | #ifdef DEBUG |
1574 | for (i = 0; i < be16_to_cpu(cblock->bb_numrecs); i++) { | 1440 | for (i = 0; i < be16_to_cpu(cblock->bb_numrecs); i++) { |
1575 | if ((error = xfs_btree_check_lptr_disk(cur, pp[i], level))) { | 1441 | if ((error = xfs_btree_check_lptr_disk(cur, pp[i], level))) { |
1576 | XFS_BMBT_TRACE_CURSOR(cur, ERROR); | 1442 | XFS_BMBT_TRACE_CURSOR(cur, ERROR); |
1577 | return error; | 1443 | return error; |
1578 | } | 1444 | } |
1579 | } | 1445 | } |
1580 | #endif | 1446 | #endif |
1581 | memcpy(cpp, pp, be16_to_cpu(cblock->bb_numrecs) * sizeof(*pp)); | 1447 | memcpy(cpp, pp, be16_to_cpu(cblock->bb_numrecs) * sizeof(*pp)); |
1582 | #ifdef DEBUG | 1448 | #ifdef DEBUG |
1583 | if ((error = xfs_btree_check_lptr(cur, args.fsbno, level))) { | 1449 | if ((error = xfs_btree_check_lptr(cur, args.fsbno, level))) { |
1584 | XFS_BMBT_TRACE_CURSOR(cur, ERROR); | 1450 | XFS_BMBT_TRACE_CURSOR(cur, ERROR); |
1585 | return error; | 1451 | return error; |
1586 | } | 1452 | } |
1587 | #endif | 1453 | #endif |
1588 | *pp = cpu_to_be64(args.fsbno); | 1454 | *pp = cpu_to_be64(args.fsbno); |
1589 | xfs_iroot_realloc(cur->bc_private.b.ip, 1 - be16_to_cpu(cblock->bb_numrecs), | 1455 | xfs_iroot_realloc(cur->bc_private.b.ip, 1 - be16_to_cpu(cblock->bb_numrecs), |
1590 | cur->bc_private.b.whichfork); | 1456 | cur->bc_private.b.whichfork); |
1591 | xfs_btree_setbuf(cur, level, bp); | 1457 | xfs_btree_setbuf(cur, level, bp); |
1592 | /* | 1458 | /* |
1593 | * Do all this logging at the end so that | 1459 | * Do all this logging at the end so that |
1594 | * the root is at the right level. | 1460 | * the root is at the right level. |
1595 | */ | 1461 | */ |
1596 | xfs_bmbt_log_block(cur, bp, XFS_BB_ALL_BITS); | 1462 | xfs_bmbt_log_block(cur, bp, XFS_BB_ALL_BITS); |
1597 | xfs_bmbt_log_keys(cur, bp, 1, be16_to_cpu(cblock->bb_numrecs)); | 1463 | xfs_bmbt_log_keys(cur, bp, 1, be16_to_cpu(cblock->bb_numrecs)); |
1598 | xfs_bmbt_log_ptrs(cur, bp, 1, be16_to_cpu(cblock->bb_numrecs)); | 1464 | xfs_bmbt_log_ptrs(cur, bp, 1, be16_to_cpu(cblock->bb_numrecs)); |
1599 | XFS_BMBT_TRACE_CURSOR(cur, EXIT); | 1465 | XFS_BMBT_TRACE_CURSOR(cur, EXIT); |
1600 | *logflags |= | 1466 | *logflags |= |
1601 | XFS_ILOG_CORE | XFS_ILOG_FBROOT(cur->bc_private.b.whichfork); | 1467 | XFS_ILOG_CORE | XFS_ILOG_FBROOT(cur->bc_private.b.whichfork); |
1602 | *stat = 1; | 1468 | *stat = 1; |
1603 | return 0; | 1469 | return 0; |
1604 | } | 1470 | } |
1605 | 1471 | ||
1606 | /* | 1472 | /* |
1607 | * Set all the fields in a bmap extent record from the arguments. | 1473 | * Set all the fields in a bmap extent record from the arguments. |
1608 | */ | 1474 | */ |
1609 | void | 1475 | void |
1610 | xfs_bmbt_set_allf( | 1476 | xfs_bmbt_set_allf( |
1611 | xfs_bmbt_rec_host_t *r, | 1477 | xfs_bmbt_rec_host_t *r, |
1612 | xfs_fileoff_t startoff, | 1478 | xfs_fileoff_t startoff, |
1613 | xfs_fsblock_t startblock, | 1479 | xfs_fsblock_t startblock, |
1614 | xfs_filblks_t blockcount, | 1480 | xfs_filblks_t blockcount, |
1615 | xfs_exntst_t state) | 1481 | xfs_exntst_t state) |
1616 | { | 1482 | { |
1617 | int extent_flag = (state == XFS_EXT_NORM) ? 0 : 1; | 1483 | int extent_flag = (state == XFS_EXT_NORM) ? 0 : 1; |
1618 | 1484 | ||
1619 | ASSERT(state == XFS_EXT_NORM || state == XFS_EXT_UNWRITTEN); | 1485 | ASSERT(state == XFS_EXT_NORM || state == XFS_EXT_UNWRITTEN); |
1620 | ASSERT((startoff & XFS_MASK64HI(64-BMBT_STARTOFF_BITLEN)) == 0); | 1486 | ASSERT((startoff & XFS_MASK64HI(64-BMBT_STARTOFF_BITLEN)) == 0); |
1621 | ASSERT((blockcount & XFS_MASK64HI(64-BMBT_BLOCKCOUNT_BITLEN)) == 0); | 1487 | ASSERT((blockcount & XFS_MASK64HI(64-BMBT_BLOCKCOUNT_BITLEN)) == 0); |
1622 | 1488 | ||
1623 | #if XFS_BIG_BLKNOS | 1489 | #if XFS_BIG_BLKNOS |
1624 | ASSERT((startblock & XFS_MASK64HI(64-BMBT_STARTBLOCK_BITLEN)) == 0); | 1490 | ASSERT((startblock & XFS_MASK64HI(64-BMBT_STARTBLOCK_BITLEN)) == 0); |
1625 | 1491 | ||
1626 | r->l0 = ((xfs_bmbt_rec_base_t)extent_flag << 63) | | 1492 | r->l0 = ((xfs_bmbt_rec_base_t)extent_flag << 63) | |
1627 | ((xfs_bmbt_rec_base_t)startoff << 9) | | 1493 | ((xfs_bmbt_rec_base_t)startoff << 9) | |
1628 | ((xfs_bmbt_rec_base_t)startblock >> 43); | 1494 | ((xfs_bmbt_rec_base_t)startblock >> 43); |
1629 | r->l1 = ((xfs_bmbt_rec_base_t)startblock << 21) | | 1495 | r->l1 = ((xfs_bmbt_rec_base_t)startblock << 21) | |
1630 | ((xfs_bmbt_rec_base_t)blockcount & | 1496 | ((xfs_bmbt_rec_base_t)blockcount & |
1631 | (xfs_bmbt_rec_base_t)XFS_MASK64LO(21)); | 1497 | (xfs_bmbt_rec_base_t)XFS_MASK64LO(21)); |
1632 | #else /* !XFS_BIG_BLKNOS */ | 1498 | #else /* !XFS_BIG_BLKNOS */ |
1633 | if (ISNULLSTARTBLOCK(startblock)) { | 1499 | if (ISNULLSTARTBLOCK(startblock)) { |
1634 | r->l0 = ((xfs_bmbt_rec_base_t)extent_flag << 63) | | 1500 | r->l0 = ((xfs_bmbt_rec_base_t)extent_flag << 63) | |
1635 | ((xfs_bmbt_rec_base_t)startoff << 9) | | 1501 | ((xfs_bmbt_rec_base_t)startoff << 9) | |
1636 | (xfs_bmbt_rec_base_t)XFS_MASK64LO(9); | 1502 | (xfs_bmbt_rec_base_t)XFS_MASK64LO(9); |
1637 | r->l1 = XFS_MASK64HI(11) | | 1503 | r->l1 = XFS_MASK64HI(11) | |
1638 | ((xfs_bmbt_rec_base_t)startblock << 21) | | 1504 | ((xfs_bmbt_rec_base_t)startblock << 21) | |
1639 | ((xfs_bmbt_rec_base_t)blockcount & | 1505 | ((xfs_bmbt_rec_base_t)blockcount & |
1640 | (xfs_bmbt_rec_base_t)XFS_MASK64LO(21)); | 1506 | (xfs_bmbt_rec_base_t)XFS_MASK64LO(21)); |
1641 | } else { | 1507 | } else { |
1642 | r->l0 = ((xfs_bmbt_rec_base_t)extent_flag << 63) | | 1508 | r->l0 = ((xfs_bmbt_rec_base_t)extent_flag << 63) | |
1643 | ((xfs_bmbt_rec_base_t)startoff << 9); | 1509 | ((xfs_bmbt_rec_base_t)startoff << 9); |
1644 | r->l1 = ((xfs_bmbt_rec_base_t)startblock << 21) | | 1510 | r->l1 = ((xfs_bmbt_rec_base_t)startblock << 21) | |
1645 | ((xfs_bmbt_rec_base_t)blockcount & | 1511 | ((xfs_bmbt_rec_base_t)blockcount & |
1646 | (xfs_bmbt_rec_base_t)XFS_MASK64LO(21)); | 1512 | (xfs_bmbt_rec_base_t)XFS_MASK64LO(21)); |
1647 | } | 1513 | } |
1648 | #endif /* XFS_BIG_BLKNOS */ | 1514 | #endif /* XFS_BIG_BLKNOS */ |
1649 | } | 1515 | } |
1650 | 1516 | ||
1651 | /* | 1517 | /* |
1652 | * Set all the fields in a bmap extent record from the uncompressed form. | 1518 | * Set all the fields in a bmap extent record from the uncompressed form. |
1653 | */ | 1519 | */ |
1654 | void | 1520 | void |
1655 | xfs_bmbt_set_all( | 1521 | xfs_bmbt_set_all( |
1656 | xfs_bmbt_rec_host_t *r, | 1522 | xfs_bmbt_rec_host_t *r, |
1657 | xfs_bmbt_irec_t *s) | 1523 | xfs_bmbt_irec_t *s) |
1658 | { | 1524 | { |
1659 | xfs_bmbt_set_allf(r, s->br_startoff, s->br_startblock, | 1525 | xfs_bmbt_set_allf(r, s->br_startoff, s->br_startblock, |
1660 | s->br_blockcount, s->br_state); | 1526 | s->br_blockcount, s->br_state); |
1661 | } | 1527 | } |
1662 | 1528 | ||
1663 | 1529 | ||
1664 | /* | 1530 | /* |
1665 | * Set all the fields in a disk format bmap extent record from the arguments. | 1531 | * Set all the fields in a disk format bmap extent record from the arguments. |
1666 | */ | 1532 | */ |
1667 | void | 1533 | void |
1668 | xfs_bmbt_disk_set_allf( | 1534 | xfs_bmbt_disk_set_allf( |
1669 | xfs_bmbt_rec_t *r, | 1535 | xfs_bmbt_rec_t *r, |
1670 | xfs_fileoff_t startoff, | 1536 | xfs_fileoff_t startoff, |
1671 | xfs_fsblock_t startblock, | 1537 | xfs_fsblock_t startblock, |
1672 | xfs_filblks_t blockcount, | 1538 | xfs_filblks_t blockcount, |
1673 | xfs_exntst_t state) | 1539 | xfs_exntst_t state) |
1674 | { | 1540 | { |
1675 | int extent_flag = (state == XFS_EXT_NORM) ? 0 : 1; | 1541 | int extent_flag = (state == XFS_EXT_NORM) ? 0 : 1; |
1676 | 1542 | ||
1677 | ASSERT(state == XFS_EXT_NORM || state == XFS_EXT_UNWRITTEN); | 1543 | ASSERT(state == XFS_EXT_NORM || state == XFS_EXT_UNWRITTEN); |
1678 | ASSERT((startoff & XFS_MASK64HI(64-BMBT_STARTOFF_BITLEN)) == 0); | 1544 | ASSERT((startoff & XFS_MASK64HI(64-BMBT_STARTOFF_BITLEN)) == 0); |
1679 | ASSERT((blockcount & XFS_MASK64HI(64-BMBT_BLOCKCOUNT_BITLEN)) == 0); | 1545 | ASSERT((blockcount & XFS_MASK64HI(64-BMBT_BLOCKCOUNT_BITLEN)) == 0); |
1680 | 1546 | ||
1681 | #if XFS_BIG_BLKNOS | 1547 | #if XFS_BIG_BLKNOS |
1682 | ASSERT((startblock & XFS_MASK64HI(64-BMBT_STARTBLOCK_BITLEN)) == 0); | 1548 | ASSERT((startblock & XFS_MASK64HI(64-BMBT_STARTBLOCK_BITLEN)) == 0); |
1683 | 1549 | ||
1684 | r->l0 = cpu_to_be64( | 1550 | r->l0 = cpu_to_be64( |
1685 | ((xfs_bmbt_rec_base_t)extent_flag << 63) | | 1551 | ((xfs_bmbt_rec_base_t)extent_flag << 63) | |
1686 | ((xfs_bmbt_rec_base_t)startoff << 9) | | 1552 | ((xfs_bmbt_rec_base_t)startoff << 9) | |
1687 | ((xfs_bmbt_rec_base_t)startblock >> 43)); | 1553 | ((xfs_bmbt_rec_base_t)startblock >> 43)); |
1688 | r->l1 = cpu_to_be64( | 1554 | r->l1 = cpu_to_be64( |
1689 | ((xfs_bmbt_rec_base_t)startblock << 21) | | 1555 | ((xfs_bmbt_rec_base_t)startblock << 21) | |
1690 | ((xfs_bmbt_rec_base_t)blockcount & | 1556 | ((xfs_bmbt_rec_base_t)blockcount & |
1691 | (xfs_bmbt_rec_base_t)XFS_MASK64LO(21))); | 1557 | (xfs_bmbt_rec_base_t)XFS_MASK64LO(21))); |
1692 | #else /* !XFS_BIG_BLKNOS */ | 1558 | #else /* !XFS_BIG_BLKNOS */ |
1693 | if (ISNULLSTARTBLOCK(startblock)) { | 1559 | if (ISNULLSTARTBLOCK(startblock)) { |
1694 | r->l0 = cpu_to_be64( | 1560 | r->l0 = cpu_to_be64( |
1695 | ((xfs_bmbt_rec_base_t)extent_flag << 63) | | 1561 | ((xfs_bmbt_rec_base_t)extent_flag << 63) | |
1696 | ((xfs_bmbt_rec_base_t)startoff << 9) | | 1562 | ((xfs_bmbt_rec_base_t)startoff << 9) | |
1697 | (xfs_bmbt_rec_base_t)XFS_MASK64LO(9)); | 1563 | (xfs_bmbt_rec_base_t)XFS_MASK64LO(9)); |
1698 | r->l1 = cpu_to_be64(XFS_MASK64HI(11) | | 1564 | r->l1 = cpu_to_be64(XFS_MASK64HI(11) | |
1699 | ((xfs_bmbt_rec_base_t)startblock << 21) | | 1565 | ((xfs_bmbt_rec_base_t)startblock << 21) | |
1700 | ((xfs_bmbt_rec_base_t)blockcount & | 1566 | ((xfs_bmbt_rec_base_t)blockcount & |
1701 | (xfs_bmbt_rec_base_t)XFS_MASK64LO(21))); | 1567 | (xfs_bmbt_rec_base_t)XFS_MASK64LO(21))); |
1702 | } else { | 1568 | } else { |
1703 | r->l0 = cpu_to_be64( | 1569 | r->l0 = cpu_to_be64( |
1704 | ((xfs_bmbt_rec_base_t)extent_flag << 63) | | 1570 | ((xfs_bmbt_rec_base_t)extent_flag << 63) | |
1705 | ((xfs_bmbt_rec_base_t)startoff << 9)); | 1571 | ((xfs_bmbt_rec_base_t)startoff << 9)); |
1706 | r->l1 = cpu_to_be64( | 1572 | r->l1 = cpu_to_be64( |
1707 | ((xfs_bmbt_rec_base_t)startblock << 21) | | 1573 | ((xfs_bmbt_rec_base_t)startblock << 21) | |
1708 | ((xfs_bmbt_rec_base_t)blockcount & | 1574 | ((xfs_bmbt_rec_base_t)blockcount & |
1709 | (xfs_bmbt_rec_base_t)XFS_MASK64LO(21))); | 1575 | (xfs_bmbt_rec_base_t)XFS_MASK64LO(21))); |
1710 | } | 1576 | } |
1711 | #endif /* XFS_BIG_BLKNOS */ | 1577 | #endif /* XFS_BIG_BLKNOS */ |
1712 | } | 1578 | } |
1713 | 1579 | ||
1714 | /* | 1580 | /* |
1715 | * Set all the fields in a bmap extent record from the uncompressed form. | 1581 | * Set all the fields in a bmap extent record from the uncompressed form. |
1716 | */ | 1582 | */ |
1717 | void | 1583 | void |
1718 | xfs_bmbt_disk_set_all( | 1584 | xfs_bmbt_disk_set_all( |
1719 | xfs_bmbt_rec_t *r, | 1585 | xfs_bmbt_rec_t *r, |
1720 | xfs_bmbt_irec_t *s) | 1586 | xfs_bmbt_irec_t *s) |
1721 | { | 1587 | { |
1722 | xfs_bmbt_disk_set_allf(r, s->br_startoff, s->br_startblock, | 1588 | xfs_bmbt_disk_set_allf(r, s->br_startoff, s->br_startblock, |
1723 | s->br_blockcount, s->br_state); | 1589 | s->br_blockcount, s->br_state); |
1724 | } | 1590 | } |
1725 | 1591 | ||
1726 | /* | 1592 | /* |
1727 | * Set the blockcount field in a bmap extent record. | 1593 | * Set the blockcount field in a bmap extent record. |
1728 | */ | 1594 | */ |
1729 | void | 1595 | void |
1730 | xfs_bmbt_set_blockcount( | 1596 | xfs_bmbt_set_blockcount( |
1731 | xfs_bmbt_rec_host_t *r, | 1597 | xfs_bmbt_rec_host_t *r, |
1732 | xfs_filblks_t v) | 1598 | xfs_filblks_t v) |
1733 | { | 1599 | { |
1734 | ASSERT((v & XFS_MASK64HI(43)) == 0); | 1600 | ASSERT((v & XFS_MASK64HI(43)) == 0); |
1735 | r->l1 = (r->l1 & (xfs_bmbt_rec_base_t)XFS_MASK64HI(43)) | | 1601 | r->l1 = (r->l1 & (xfs_bmbt_rec_base_t)XFS_MASK64HI(43)) | |
1736 | (xfs_bmbt_rec_base_t)(v & XFS_MASK64LO(21)); | 1602 | (xfs_bmbt_rec_base_t)(v & XFS_MASK64LO(21)); |
1737 | } | 1603 | } |
1738 | 1604 | ||
1739 | /* | 1605 | /* |
1740 | * Set the startblock field in a bmap extent record. | 1606 | * Set the startblock field in a bmap extent record. |
1741 | */ | 1607 | */ |
1742 | void | 1608 | void |
1743 | xfs_bmbt_set_startblock( | 1609 | xfs_bmbt_set_startblock( |
1744 | xfs_bmbt_rec_host_t *r, | 1610 | xfs_bmbt_rec_host_t *r, |
1745 | xfs_fsblock_t v) | 1611 | xfs_fsblock_t v) |
1746 | { | 1612 | { |
1747 | #if XFS_BIG_BLKNOS | 1613 | #if XFS_BIG_BLKNOS |
1748 | ASSERT((v & XFS_MASK64HI(12)) == 0); | 1614 | ASSERT((v & XFS_MASK64HI(12)) == 0); |
1749 | r->l0 = (r->l0 & (xfs_bmbt_rec_base_t)XFS_MASK64HI(55)) | | 1615 | r->l0 = (r->l0 & (xfs_bmbt_rec_base_t)XFS_MASK64HI(55)) | |
1750 | (xfs_bmbt_rec_base_t)(v >> 43); | 1616 | (xfs_bmbt_rec_base_t)(v >> 43); |
1751 | r->l1 = (r->l1 & (xfs_bmbt_rec_base_t)XFS_MASK64LO(21)) | | 1617 | r->l1 = (r->l1 & (xfs_bmbt_rec_base_t)XFS_MASK64LO(21)) | |
1752 | (xfs_bmbt_rec_base_t)(v << 21); | 1618 | (xfs_bmbt_rec_base_t)(v << 21); |
1753 | #else /* !XFS_BIG_BLKNOS */ | 1619 | #else /* !XFS_BIG_BLKNOS */ |
1754 | if (ISNULLSTARTBLOCK(v)) { | 1620 | if (ISNULLSTARTBLOCK(v)) { |
1755 | r->l0 |= (xfs_bmbt_rec_base_t)XFS_MASK64LO(9); | 1621 | r->l0 |= (xfs_bmbt_rec_base_t)XFS_MASK64LO(9); |
1756 | r->l1 = (xfs_bmbt_rec_base_t)XFS_MASK64HI(11) | | 1622 | r->l1 = (xfs_bmbt_rec_base_t)XFS_MASK64HI(11) | |
1757 | ((xfs_bmbt_rec_base_t)v << 21) | | 1623 | ((xfs_bmbt_rec_base_t)v << 21) | |
1758 | (r->l1 & (xfs_bmbt_rec_base_t)XFS_MASK64LO(21)); | 1624 | (r->l1 & (xfs_bmbt_rec_base_t)XFS_MASK64LO(21)); |
1759 | } else { | 1625 | } else { |
1760 | r->l0 &= ~(xfs_bmbt_rec_base_t)XFS_MASK64LO(9); | 1626 | r->l0 &= ~(xfs_bmbt_rec_base_t)XFS_MASK64LO(9); |
1761 | r->l1 = ((xfs_bmbt_rec_base_t)v << 21) | | 1627 | r->l1 = ((xfs_bmbt_rec_base_t)v << 21) | |
1762 | (r->l1 & (xfs_bmbt_rec_base_t)XFS_MASK64LO(21)); | 1628 | (r->l1 & (xfs_bmbt_rec_base_t)XFS_MASK64LO(21)); |
1763 | } | 1629 | } |
1764 | #endif /* XFS_BIG_BLKNOS */ | 1630 | #endif /* XFS_BIG_BLKNOS */ |
1765 | } | 1631 | } |
1766 | 1632 | ||
1767 | /* | 1633 | /* |
1768 | * Set the startoff field in a bmap extent record. | 1634 | * Set the startoff field in a bmap extent record. |
1769 | */ | 1635 | */ |
1770 | void | 1636 | void |
1771 | xfs_bmbt_set_startoff( | 1637 | xfs_bmbt_set_startoff( |
1772 | xfs_bmbt_rec_host_t *r, | 1638 | xfs_bmbt_rec_host_t *r, |
1773 | xfs_fileoff_t v) | 1639 | xfs_fileoff_t v) |
1774 | { | 1640 | { |
1775 | ASSERT((v & XFS_MASK64HI(9)) == 0); | 1641 | ASSERT((v & XFS_MASK64HI(9)) == 0); |
1776 | r->l0 = (r->l0 & (xfs_bmbt_rec_base_t) XFS_MASK64HI(1)) | | 1642 | r->l0 = (r->l0 & (xfs_bmbt_rec_base_t) XFS_MASK64HI(1)) | |
1777 | ((xfs_bmbt_rec_base_t)v << 9) | | 1643 | ((xfs_bmbt_rec_base_t)v << 9) | |
1778 | (r->l0 & (xfs_bmbt_rec_base_t)XFS_MASK64LO(9)); | 1644 | (r->l0 & (xfs_bmbt_rec_base_t)XFS_MASK64LO(9)); |
1779 | } | 1645 | } |
1780 | 1646 | ||
1781 | /* | 1647 | /* |
1782 | * Set the extent state field in a bmap extent record. | 1648 | * Set the extent state field in a bmap extent record. |
1783 | */ | 1649 | */ |
1784 | void | 1650 | void |
1785 | xfs_bmbt_set_state( | 1651 | xfs_bmbt_set_state( |
1786 | xfs_bmbt_rec_host_t *r, | 1652 | xfs_bmbt_rec_host_t *r, |
1787 | xfs_exntst_t v) | 1653 | xfs_exntst_t v) |
1788 | { | 1654 | { |
1789 | ASSERT(v == XFS_EXT_NORM || v == XFS_EXT_UNWRITTEN); | 1655 | ASSERT(v == XFS_EXT_NORM || v == XFS_EXT_UNWRITTEN); |
1790 | if (v == XFS_EXT_NORM) | 1656 | if (v == XFS_EXT_NORM) |
1791 | r->l0 &= XFS_MASK64LO(64 - BMBT_EXNTFLAG_BITLEN); | 1657 | r->l0 &= XFS_MASK64LO(64 - BMBT_EXNTFLAG_BITLEN); |
1792 | else | 1658 | else |
1793 | r->l0 |= XFS_MASK64HI(BMBT_EXNTFLAG_BITLEN); | 1659 | r->l0 |= XFS_MASK64HI(BMBT_EXNTFLAG_BITLEN); |
1794 | } | 1660 | } |
1795 | 1661 | ||
1796 | /* | 1662 | /* |
1797 | * Convert in-memory form of btree root to on-disk form. | 1663 | * Convert in-memory form of btree root to on-disk form. |
1798 | */ | 1664 | */ |
1799 | void | 1665 | void |
1800 | xfs_bmbt_to_bmdr( | 1666 | xfs_bmbt_to_bmdr( |
1801 | xfs_bmbt_block_t *rblock, | 1667 | xfs_bmbt_block_t *rblock, |
1802 | int rblocklen, | 1668 | int rblocklen, |
1803 | xfs_bmdr_block_t *dblock, | 1669 | xfs_bmdr_block_t *dblock, |
1804 | int dblocklen) | 1670 | int dblocklen) |
1805 | { | 1671 | { |
1806 | int dmxr; | 1672 | int dmxr; |
1807 | xfs_bmbt_key_t *fkp; | 1673 | xfs_bmbt_key_t *fkp; |
1808 | __be64 *fpp; | 1674 | __be64 *fpp; |
1809 | xfs_bmbt_key_t *tkp; | 1675 | xfs_bmbt_key_t *tkp; |
1810 | __be64 *tpp; | 1676 | __be64 *tpp; |
1811 | 1677 | ||
1812 | ASSERT(be32_to_cpu(rblock->bb_magic) == XFS_BMAP_MAGIC); | 1678 | ASSERT(be32_to_cpu(rblock->bb_magic) == XFS_BMAP_MAGIC); |
1813 | ASSERT(be64_to_cpu(rblock->bb_leftsib) == NULLDFSBNO); | 1679 | ASSERT(be64_to_cpu(rblock->bb_leftsib) == NULLDFSBNO); |
1814 | ASSERT(be64_to_cpu(rblock->bb_rightsib) == NULLDFSBNO); | 1680 | ASSERT(be64_to_cpu(rblock->bb_rightsib) == NULLDFSBNO); |
1815 | ASSERT(be16_to_cpu(rblock->bb_level) > 0); | 1681 | ASSERT(be16_to_cpu(rblock->bb_level) > 0); |
1816 | dblock->bb_level = rblock->bb_level; | 1682 | dblock->bb_level = rblock->bb_level; |
1817 | dblock->bb_numrecs = rblock->bb_numrecs; | 1683 | dblock->bb_numrecs = rblock->bb_numrecs; |
1818 | dmxr = (int)XFS_BTREE_BLOCK_MAXRECS(dblocklen, xfs_bmdr, 0); | 1684 | dmxr = (int)XFS_BTREE_BLOCK_MAXRECS(dblocklen, xfs_bmdr, 0); |
1819 | fkp = XFS_BMAP_BROOT_KEY_ADDR(rblock, 1, rblocklen); | 1685 | fkp = XFS_BMAP_BROOT_KEY_ADDR(rblock, 1, rblocklen); |
1820 | tkp = XFS_BTREE_KEY_ADDR(xfs_bmdr, dblock, 1); | 1686 | tkp = XFS_BTREE_KEY_ADDR(xfs_bmdr, dblock, 1); |
1821 | fpp = XFS_BMAP_BROOT_PTR_ADDR(rblock, 1, rblocklen); | 1687 | fpp = XFS_BMAP_BROOT_PTR_ADDR(rblock, 1, rblocklen); |
1822 | tpp = XFS_BTREE_PTR_ADDR(xfs_bmdr, dblock, 1, dmxr); | 1688 | tpp = XFS_BTREE_PTR_ADDR(xfs_bmdr, dblock, 1, dmxr); |
1823 | dmxr = be16_to_cpu(dblock->bb_numrecs); | 1689 | dmxr = be16_to_cpu(dblock->bb_numrecs); |
1824 | memcpy(tkp, fkp, sizeof(*fkp) * dmxr); | 1690 | memcpy(tkp, fkp, sizeof(*fkp) * dmxr); |
1825 | memcpy(tpp, fpp, sizeof(*fpp) * dmxr); | 1691 | memcpy(tpp, fpp, sizeof(*fpp) * dmxr); |
1826 | } | 1692 | } |
1827 | 1693 | ||
1828 | /* | 1694 | /* |
1829 | * Check extent records, which have just been read, for | 1695 | * Check extent records, which have just been read, for |
1830 | * any bit in the extent flag field. ASSERT on debug | 1696 | * any bit in the extent flag field. ASSERT on debug |
1831 | * kernels, as this condition should not occur. | 1697 | * kernels, as this condition should not occur. |
1832 | * Return an error condition (1) if any flags found, | 1698 | * Return an error condition (1) if any flags found, |
1833 | * otherwise return 0. | 1699 | * otherwise return 0. |
1834 | */ | 1700 | */ |
1835 | 1701 | ||
1836 | int | 1702 | int |
1837 | xfs_check_nostate_extents( | 1703 | xfs_check_nostate_extents( |
1838 | xfs_ifork_t *ifp, | 1704 | xfs_ifork_t *ifp, |
1839 | xfs_extnum_t idx, | 1705 | xfs_extnum_t idx, |
1840 | xfs_extnum_t num) | 1706 | xfs_extnum_t num) |
1841 | { | 1707 | { |
1842 | for (; num > 0; num--, idx++) { | 1708 | for (; num > 0; num--, idx++) { |
1843 | xfs_bmbt_rec_host_t *ep = xfs_iext_get_ext(ifp, idx); | 1709 | xfs_bmbt_rec_host_t *ep = xfs_iext_get_ext(ifp, idx); |
1844 | if ((ep->l0 >> | 1710 | if ((ep->l0 >> |
1845 | (64 - BMBT_EXNTFLAG_BITLEN)) != 0) { | 1711 | (64 - BMBT_EXNTFLAG_BITLEN)) != 0) { |
1846 | ASSERT(0); | 1712 | ASSERT(0); |
1847 | return 1; | 1713 | return 1; |
1848 | } | 1714 | } |
1849 | } | 1715 | } |
1850 | return 0; | 1716 | return 0; |
1851 | } | 1717 | } |
1852 | 1718 | ||
1853 | 1719 | ||
1854 | STATIC struct xfs_btree_cur * | 1720 | STATIC struct xfs_btree_cur * |
1855 | xfs_bmbt_dup_cursor( | 1721 | xfs_bmbt_dup_cursor( |
1856 | struct xfs_btree_cur *cur) | 1722 | struct xfs_btree_cur *cur) |
1857 | { | 1723 | { |
1858 | struct xfs_btree_cur *new; | 1724 | struct xfs_btree_cur *new; |
1859 | 1725 | ||
1860 | new = xfs_bmbt_init_cursor(cur->bc_mp, cur->bc_tp, | 1726 | new = xfs_bmbt_init_cursor(cur->bc_mp, cur->bc_tp, |
1861 | cur->bc_private.b.ip, cur->bc_private.b.whichfork); | 1727 | cur->bc_private.b.ip, cur->bc_private.b.whichfork); |
1862 | 1728 | ||
1863 | /* | 1729 | /* |
1864 | * Copy the firstblock, flist, and flags values, | 1730 | * Copy the firstblock, flist, and flags values, |
1865 | * since init cursor doesn't get them. | 1731 | * since init cursor doesn't get them. |
1866 | */ | 1732 | */ |
1867 | new->bc_private.b.firstblock = cur->bc_private.b.firstblock; | 1733 | new->bc_private.b.firstblock = cur->bc_private.b.firstblock; |
1868 | new->bc_private.b.flist = cur->bc_private.b.flist; | 1734 | new->bc_private.b.flist = cur->bc_private.b.flist; |
1869 | new->bc_private.b.flags = cur->bc_private.b.flags; | 1735 | new->bc_private.b.flags = cur->bc_private.b.flags; |
1870 | 1736 | ||
1871 | return new; | 1737 | return new; |
1872 | } | 1738 | } |
1873 | 1739 | ||
1874 | STATIC int | 1740 | STATIC int |
1875 | xfs_bmbt_get_maxrecs( | 1741 | xfs_bmbt_get_maxrecs( |
1876 | struct xfs_btree_cur *cur, | 1742 | struct xfs_btree_cur *cur, |
1877 | int level) | 1743 | int level) |
1878 | { | 1744 | { |
1879 | return XFS_BMAP_BLOCK_IMAXRECS(level, cur); | 1745 | return XFS_BMAP_BLOCK_IMAXRECS(level, cur); |
1880 | } | 1746 | } |
1881 | 1747 | ||
1882 | STATIC void | 1748 | STATIC void |
1883 | xfs_bmbt_init_key_from_rec( | 1749 | xfs_bmbt_init_key_from_rec( |
1884 | union xfs_btree_key *key, | 1750 | union xfs_btree_key *key, |
1885 | union xfs_btree_rec *rec) | 1751 | union xfs_btree_rec *rec) |
1886 | { | 1752 | { |
1887 | key->bmbt.br_startoff = | 1753 | key->bmbt.br_startoff = |
1888 | cpu_to_be64(xfs_bmbt_disk_get_startoff(&rec->bmbt)); | 1754 | cpu_to_be64(xfs_bmbt_disk_get_startoff(&rec->bmbt)); |
1889 | } | 1755 | } |
1890 | 1756 | ||
1891 | STATIC void | 1757 | STATIC void |
1892 | xfs_bmbt_init_ptr_from_cur( | 1758 | xfs_bmbt_init_ptr_from_cur( |
1893 | struct xfs_btree_cur *cur, | 1759 | struct xfs_btree_cur *cur, |
1894 | union xfs_btree_ptr *ptr) | 1760 | union xfs_btree_ptr *ptr) |
1895 | { | 1761 | { |
1896 | ptr->l = 0; | 1762 | ptr->l = 0; |
1897 | } | 1763 | } |
1898 | 1764 | ||
1899 | STATIC __int64_t | 1765 | STATIC __int64_t |
1900 | xfs_bmbt_key_diff( | 1766 | xfs_bmbt_key_diff( |
1901 | struct xfs_btree_cur *cur, | 1767 | struct xfs_btree_cur *cur, |
1902 | union xfs_btree_key *key) | 1768 | union xfs_btree_key *key) |
1903 | { | 1769 | { |
1904 | return (__int64_t)be64_to_cpu(key->bmbt.br_startoff) - | 1770 | return (__int64_t)be64_to_cpu(key->bmbt.br_startoff) - |
1905 | cur->bc_rec.b.br_startoff; | 1771 | cur->bc_rec.b.br_startoff; |
1906 | } | 1772 | } |
1907 | 1773 | ||
1908 | #ifdef XFS_BTREE_TRACE | 1774 | #ifdef XFS_BTREE_TRACE |
1909 | ktrace_t *xfs_bmbt_trace_buf; | 1775 | ktrace_t *xfs_bmbt_trace_buf; |
1910 | 1776 | ||
1911 | STATIC void | 1777 | STATIC void |
1912 | xfs_bmbt_trace_enter( | 1778 | xfs_bmbt_trace_enter( |
1913 | struct xfs_btree_cur *cur, | 1779 | struct xfs_btree_cur *cur, |
1914 | const char *func, | 1780 | const char *func, |
1915 | char *s, | 1781 | char *s, |
1916 | int type, | 1782 | int type, |
1917 | int line, | 1783 | int line, |
1918 | __psunsigned_t a0, | 1784 | __psunsigned_t a0, |
1919 | __psunsigned_t a1, | 1785 | __psunsigned_t a1, |
1920 | __psunsigned_t a2, | 1786 | __psunsigned_t a2, |
1921 | __psunsigned_t a3, | 1787 | __psunsigned_t a3, |
1922 | __psunsigned_t a4, | 1788 | __psunsigned_t a4, |
1923 | __psunsigned_t a5, | 1789 | __psunsigned_t a5, |
1924 | __psunsigned_t a6, | 1790 | __psunsigned_t a6, |
1925 | __psunsigned_t a7, | 1791 | __psunsigned_t a7, |
1926 | __psunsigned_t a8, | 1792 | __psunsigned_t a8, |
1927 | __psunsigned_t a9, | 1793 | __psunsigned_t a9, |
1928 | __psunsigned_t a10) | 1794 | __psunsigned_t a10) |
1929 | { | 1795 | { |
1930 | struct xfs_inode *ip = cur->bc_private.b.ip; | 1796 | struct xfs_inode *ip = cur->bc_private.b.ip; |
1931 | int whichfork = cur->bc_private.b.whichfork; | 1797 | int whichfork = cur->bc_private.b.whichfork; |
1932 | 1798 | ||
1933 | ktrace_enter(xfs_bmbt_trace_buf, | 1799 | ktrace_enter(xfs_bmbt_trace_buf, |
1934 | (void *)((__psint_t)type | (whichfork << 8) | (line << 16)), | 1800 | (void *)((__psint_t)type | (whichfork << 8) | (line << 16)), |
1935 | (void *)func, (void *)s, (void *)ip, (void *)cur, | 1801 | (void *)func, (void *)s, (void *)ip, (void *)cur, |
1936 | (void *)a0, (void *)a1, (void *)a2, (void *)a3, | 1802 | (void *)a0, (void *)a1, (void *)a2, (void *)a3, |
1937 | (void *)a4, (void *)a5, (void *)a6, (void *)a7, | 1803 | (void *)a4, (void *)a5, (void *)a6, (void *)a7, |
1938 | (void *)a8, (void *)a9, (void *)a10); | 1804 | (void *)a8, (void *)a9, (void *)a10); |
1939 | ktrace_enter(ip->i_btrace, | 1805 | ktrace_enter(ip->i_btrace, |
1940 | (void *)((__psint_t)type | (whichfork << 8) | (line << 16)), | 1806 | (void *)((__psint_t)type | (whichfork << 8) | (line << 16)), |
1941 | (void *)func, (void *)s, (void *)ip, (void *)cur, | 1807 | (void *)func, (void *)s, (void *)ip, (void *)cur, |
1942 | (void *)a0, (void *)a1, (void *)a2, (void *)a3, | 1808 | (void *)a0, (void *)a1, (void *)a2, (void *)a3, |
1943 | (void *)a4, (void *)a5, (void *)a6, (void *)a7, | 1809 | (void *)a4, (void *)a5, (void *)a6, (void *)a7, |
1944 | (void *)a8, (void *)a9, (void *)a10); | 1810 | (void *)a8, (void *)a9, (void *)a10); |
1945 | } | 1811 | } |
1946 | 1812 | ||
1947 | STATIC void | 1813 | STATIC void |
1948 | xfs_bmbt_trace_cursor( | 1814 | xfs_bmbt_trace_cursor( |
1949 | struct xfs_btree_cur *cur, | 1815 | struct xfs_btree_cur *cur, |
1950 | __uint32_t *s0, | 1816 | __uint32_t *s0, |
1951 | __uint64_t *l0, | 1817 | __uint64_t *l0, |
1952 | __uint64_t *l1) | 1818 | __uint64_t *l1) |
1953 | { | 1819 | { |
1954 | struct xfs_bmbt_rec_host r; | 1820 | struct xfs_bmbt_rec_host r; |
1955 | 1821 | ||
1956 | xfs_bmbt_set_all(&r, &cur->bc_rec.b); | 1822 | xfs_bmbt_set_all(&r, &cur->bc_rec.b); |
1957 | 1823 | ||
1958 | *s0 = (cur->bc_nlevels << 24) | | 1824 | *s0 = (cur->bc_nlevels << 24) | |
1959 | (cur->bc_private.b.flags << 16) | | 1825 | (cur->bc_private.b.flags << 16) | |
1960 | cur->bc_private.b.allocated; | 1826 | cur->bc_private.b.allocated; |
1961 | *l0 = r.l0; | 1827 | *l0 = r.l0; |
1962 | *l1 = r.l1; | 1828 | *l1 = r.l1; |
1963 | } | 1829 | } |
1964 | 1830 | ||
1965 | STATIC void | 1831 | STATIC void |
1966 | xfs_bmbt_trace_key( | 1832 | xfs_bmbt_trace_key( |
1967 | struct xfs_btree_cur *cur, | 1833 | struct xfs_btree_cur *cur, |
1968 | union xfs_btree_key *key, | 1834 | union xfs_btree_key *key, |
1969 | __uint64_t *l0, | 1835 | __uint64_t *l0, |
1970 | __uint64_t *l1) | 1836 | __uint64_t *l1) |
1971 | { | 1837 | { |
1972 | *l0 = be64_to_cpu(key->bmbt.br_startoff); | 1838 | *l0 = be64_to_cpu(key->bmbt.br_startoff); |
1973 | *l1 = 0; | 1839 | *l1 = 0; |
1974 | } | 1840 | } |
1975 | 1841 | ||
1976 | STATIC void | 1842 | STATIC void |
1977 | xfs_bmbt_trace_record( | 1843 | xfs_bmbt_trace_record( |
1978 | struct xfs_btree_cur *cur, | 1844 | struct xfs_btree_cur *cur, |
1979 | union xfs_btree_rec *rec, | 1845 | union xfs_btree_rec *rec, |
1980 | __uint64_t *l0, | 1846 | __uint64_t *l0, |
1981 | __uint64_t *l1, | 1847 | __uint64_t *l1, |
1982 | __uint64_t *l2) | 1848 | __uint64_t *l2) |
1983 | { | 1849 | { |
1984 | struct xfs_bmbt_irec irec; | 1850 | struct xfs_bmbt_irec irec; |
1985 | 1851 | ||
1986 | xfs_bmbt_disk_get_all(&rec->bmbt, &irec); | 1852 | xfs_bmbt_disk_get_all(&rec->bmbt, &irec); |
1987 | *l0 = irec.br_startoff; | 1853 | *l0 = irec.br_startoff; |
1988 | *l1 = irec.br_startblock; | 1854 | *l1 = irec.br_startblock; |
1989 | *l2 = irec.br_blockcount; | 1855 | *l2 = irec.br_blockcount; |
1990 | } | 1856 | } |
1991 | #endif /* XFS_BTREE_TRACE */ | 1857 | #endif /* XFS_BTREE_TRACE */ |
1992 | 1858 | ||
1993 | static const struct xfs_btree_ops xfs_bmbt_ops = { | 1859 | static const struct xfs_btree_ops xfs_bmbt_ops = { |
1994 | .rec_len = sizeof(xfs_bmbt_rec_t), | 1860 | .rec_len = sizeof(xfs_bmbt_rec_t), |
1995 | .key_len = sizeof(xfs_bmbt_key_t), | 1861 | .key_len = sizeof(xfs_bmbt_key_t), |
1996 | 1862 | ||
1997 | .dup_cursor = xfs_bmbt_dup_cursor, | 1863 | .dup_cursor = xfs_bmbt_dup_cursor, |
1998 | .get_maxrecs = xfs_bmbt_get_maxrecs, | 1864 | .get_maxrecs = xfs_bmbt_get_maxrecs, |
1999 | .init_key_from_rec = xfs_bmbt_init_key_from_rec, | 1865 | .init_key_from_rec = xfs_bmbt_init_key_from_rec, |
2000 | .init_ptr_from_cur = xfs_bmbt_init_ptr_from_cur, | 1866 | .init_ptr_from_cur = xfs_bmbt_init_ptr_from_cur, |
2001 | .key_diff = xfs_bmbt_key_diff, | 1867 | .key_diff = xfs_bmbt_key_diff, |
2002 | 1868 | ||
2003 | #ifdef XFS_BTREE_TRACE | 1869 | #ifdef XFS_BTREE_TRACE |
2004 | .trace_enter = xfs_bmbt_trace_enter, | 1870 | .trace_enter = xfs_bmbt_trace_enter, |
2005 | .trace_cursor = xfs_bmbt_trace_cursor, | 1871 | .trace_cursor = xfs_bmbt_trace_cursor, |
2006 | .trace_key = xfs_bmbt_trace_key, | 1872 | .trace_key = xfs_bmbt_trace_key, |
2007 | .trace_record = xfs_bmbt_trace_record, | 1873 | .trace_record = xfs_bmbt_trace_record, |
2008 | #endif | 1874 | #endif |
2009 | }; | 1875 | }; |
2010 | 1876 | ||
2011 | /* | 1877 | /* |
2012 | * Allocate a new bmap btree cursor. | 1878 | * Allocate a new bmap btree cursor. |
2013 | */ | 1879 | */ |
2014 | struct xfs_btree_cur * /* new bmap btree cursor */ | 1880 | struct xfs_btree_cur * /* new bmap btree cursor */ |
2015 | xfs_bmbt_init_cursor( | 1881 | xfs_bmbt_init_cursor( |
2016 | struct xfs_mount *mp, /* file system mount point */ | 1882 | struct xfs_mount *mp, /* file system mount point */ |
2017 | struct xfs_trans *tp, /* transaction pointer */ | 1883 | struct xfs_trans *tp, /* transaction pointer */ |
2018 | struct xfs_inode *ip, /* inode owning the btree */ | 1884 | struct xfs_inode *ip, /* inode owning the btree */ |
2019 | int whichfork) /* data or attr fork */ | 1885 | int whichfork) /* data or attr fork */ |
2020 | { | 1886 | { |
2021 | struct xfs_ifork *ifp = XFS_IFORK_PTR(ip, whichfork); | 1887 | struct xfs_ifork *ifp = XFS_IFORK_PTR(ip, whichfork); |
2022 | struct xfs_btree_cur *cur; | 1888 | struct xfs_btree_cur *cur; |
2023 | 1889 | ||
2024 | cur = kmem_zone_zalloc(xfs_btree_cur_zone, KM_SLEEP); | 1890 | cur = kmem_zone_zalloc(xfs_btree_cur_zone, KM_SLEEP); |
2025 | 1891 | ||
2026 | cur->bc_tp = tp; | 1892 | cur->bc_tp = tp; |
2027 | cur->bc_mp = mp; | 1893 | cur->bc_mp = mp; |
2028 | cur->bc_nlevels = be16_to_cpu(ifp->if_broot->bb_level) + 1; | 1894 | cur->bc_nlevels = be16_to_cpu(ifp->if_broot->bb_level) + 1; |
2029 | cur->bc_btnum = XFS_BTNUM_BMAP; | 1895 | cur->bc_btnum = XFS_BTNUM_BMAP; |
2030 | cur->bc_blocklog = mp->m_sb.sb_blocklog; | 1896 | cur->bc_blocklog = mp->m_sb.sb_blocklog; |
2031 | 1897 | ||
2032 | cur->bc_ops = &xfs_bmbt_ops; | 1898 | cur->bc_ops = &xfs_bmbt_ops; |
2033 | cur->bc_flags = XFS_BTREE_LONG_PTRS | XFS_BTREE_ROOT_IN_INODE; | 1899 | cur->bc_flags = XFS_BTREE_LONG_PTRS | XFS_BTREE_ROOT_IN_INODE; |
2034 | 1900 | ||
2035 | cur->bc_private.b.forksize = XFS_IFORK_SIZE(ip, whichfork); | 1901 | cur->bc_private.b.forksize = XFS_IFORK_SIZE(ip, whichfork); |
2036 | cur->bc_private.b.ip = ip; | 1902 | cur->bc_private.b.ip = ip; |
2037 | cur->bc_private.b.firstblock = NULLFSBLOCK; | 1903 | cur->bc_private.b.firstblock = NULLFSBLOCK; |
2038 | cur->bc_private.b.flist = NULL; | 1904 | cur->bc_private.b.flist = NULL; |
2039 | cur->bc_private.b.allocated = 0; | 1905 | cur->bc_private.b.allocated = 0; |
2040 | cur->bc_private.b.flags = 0; | 1906 | cur->bc_private.b.flags = 0; |
2041 | cur->bc_private.b.whichfork = whichfork; | 1907 | cur->bc_private.b.whichfork = whichfork; |
2042 | 1908 | ||
2043 | return cur; | 1909 | return cur; |
2044 | } | 1910 | } |
2045 | 1911 |
fs/xfs/xfs_btree.c
1 | /* | 1 | /* |
2 | * Copyright (c) 2000-2002,2005 Silicon Graphics, Inc. | 2 | * Copyright (c) 2000-2002,2005 Silicon Graphics, Inc. |
3 | * All Rights Reserved. | 3 | * All Rights Reserved. |
4 | * | 4 | * |
5 | * This program is free software; you can redistribute it and/or | 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 | 6 | * modify it under the terms of the GNU General Public License as |
7 | * published by the Free Software Foundation. | 7 | * published by the Free Software Foundation. |
8 | * | 8 | * |
9 | * This program is distributed in the hope that it would be useful, | 9 | * This program is distributed in the hope that it would be useful, |
10 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | 10 | * but WITHOUT ANY WARRANTY; without even the implied warranty of |
11 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | 11 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
12 | * GNU General Public License for more details. | 12 | * GNU General Public License for more details. |
13 | * | 13 | * |
14 | * You should have received a copy of the GNU General Public License | 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, | 15 | * along with this program; if not, write the Free Software Foundation, |
16 | * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA | 16 | * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA |
17 | */ | 17 | */ |
18 | #include "xfs.h" | 18 | #include "xfs.h" |
19 | #include "xfs_fs.h" | 19 | #include "xfs_fs.h" |
20 | #include "xfs_types.h" | 20 | #include "xfs_types.h" |
21 | #include "xfs_bit.h" | 21 | #include "xfs_bit.h" |
22 | #include "xfs_log.h" | 22 | #include "xfs_log.h" |
23 | #include "xfs_inum.h" | 23 | #include "xfs_inum.h" |
24 | #include "xfs_trans.h" | 24 | #include "xfs_trans.h" |
25 | #include "xfs_sb.h" | 25 | #include "xfs_sb.h" |
26 | #include "xfs_ag.h" | 26 | #include "xfs_ag.h" |
27 | #include "xfs_dir2.h" | 27 | #include "xfs_dir2.h" |
28 | #include "xfs_dmapi.h" | 28 | #include "xfs_dmapi.h" |
29 | #include "xfs_mount.h" | 29 | #include "xfs_mount.h" |
30 | #include "xfs_bmap_btree.h" | 30 | #include "xfs_bmap_btree.h" |
31 | #include "xfs_alloc_btree.h" | 31 | #include "xfs_alloc_btree.h" |
32 | #include "xfs_ialloc_btree.h" | 32 | #include "xfs_ialloc_btree.h" |
33 | #include "xfs_dir2_sf.h" | 33 | #include "xfs_dir2_sf.h" |
34 | #include "xfs_attr_sf.h" | 34 | #include "xfs_attr_sf.h" |
35 | #include "xfs_dinode.h" | 35 | #include "xfs_dinode.h" |
36 | #include "xfs_inode.h" | 36 | #include "xfs_inode.h" |
37 | #include "xfs_inode_item.h" | 37 | #include "xfs_inode_item.h" |
38 | #include "xfs_btree.h" | 38 | #include "xfs_btree.h" |
39 | #include "xfs_btree_trace.h" | 39 | #include "xfs_btree_trace.h" |
40 | #include "xfs_ialloc.h" | 40 | #include "xfs_ialloc.h" |
41 | #include "xfs_error.h" | 41 | #include "xfs_error.h" |
42 | 42 | ||
43 | /* | 43 | /* |
44 | * Cursor allocation zone. | 44 | * Cursor allocation zone. |
45 | */ | 45 | */ |
46 | kmem_zone_t *xfs_btree_cur_zone; | 46 | kmem_zone_t *xfs_btree_cur_zone; |
47 | 47 | ||
48 | /* | 48 | /* |
49 | * Btree magic numbers. | 49 | * Btree magic numbers. |
50 | */ | 50 | */ |
51 | const __uint32_t xfs_magics[XFS_BTNUM_MAX] = { | 51 | const __uint32_t xfs_magics[XFS_BTNUM_MAX] = { |
52 | XFS_ABTB_MAGIC, XFS_ABTC_MAGIC, XFS_BMAP_MAGIC, XFS_IBT_MAGIC | 52 | XFS_ABTB_MAGIC, XFS_ABTC_MAGIC, XFS_BMAP_MAGIC, XFS_IBT_MAGIC |
53 | }; | 53 | }; |
54 | 54 | ||
55 | /* | 55 | /* |
56 | * External routines. | 56 | * External routines. |
57 | */ | 57 | */ |
58 | 58 | ||
59 | #ifdef DEBUG | 59 | #ifdef DEBUG |
60 | /* | 60 | /* |
61 | * Debug routine: check that keys are in the right order. | 61 | * Debug routine: check that keys are in the right order. |
62 | */ | 62 | */ |
63 | void | 63 | void |
64 | xfs_btree_check_key( | 64 | xfs_btree_check_key( |
65 | xfs_btnum_t btnum, /* btree identifier */ | 65 | xfs_btnum_t btnum, /* btree identifier */ |
66 | void *ak1, /* pointer to left (lower) key */ | 66 | void *ak1, /* pointer to left (lower) key */ |
67 | void *ak2) /* pointer to right (higher) key */ | 67 | void *ak2) /* pointer to right (higher) key */ |
68 | { | 68 | { |
69 | switch (btnum) { | 69 | switch (btnum) { |
70 | case XFS_BTNUM_BNO: { | 70 | case XFS_BTNUM_BNO: { |
71 | xfs_alloc_key_t *k1; | 71 | xfs_alloc_key_t *k1; |
72 | xfs_alloc_key_t *k2; | 72 | xfs_alloc_key_t *k2; |
73 | 73 | ||
74 | k1 = ak1; | 74 | k1 = ak1; |
75 | k2 = ak2; | 75 | k2 = ak2; |
76 | ASSERT(be32_to_cpu(k1->ar_startblock) < be32_to_cpu(k2->ar_startblock)); | 76 | ASSERT(be32_to_cpu(k1->ar_startblock) < be32_to_cpu(k2->ar_startblock)); |
77 | break; | 77 | break; |
78 | } | 78 | } |
79 | case XFS_BTNUM_CNT: { | 79 | case XFS_BTNUM_CNT: { |
80 | xfs_alloc_key_t *k1; | 80 | xfs_alloc_key_t *k1; |
81 | xfs_alloc_key_t *k2; | 81 | xfs_alloc_key_t *k2; |
82 | 82 | ||
83 | k1 = ak1; | 83 | k1 = ak1; |
84 | k2 = ak2; | 84 | k2 = ak2; |
85 | ASSERT(be32_to_cpu(k1->ar_blockcount) < be32_to_cpu(k2->ar_blockcount) || | 85 | ASSERT(be32_to_cpu(k1->ar_blockcount) < be32_to_cpu(k2->ar_blockcount) || |
86 | (k1->ar_blockcount == k2->ar_blockcount && | 86 | (k1->ar_blockcount == k2->ar_blockcount && |
87 | be32_to_cpu(k1->ar_startblock) < be32_to_cpu(k2->ar_startblock))); | 87 | be32_to_cpu(k1->ar_startblock) < be32_to_cpu(k2->ar_startblock))); |
88 | break; | 88 | break; |
89 | } | 89 | } |
90 | case XFS_BTNUM_BMAP: { | 90 | case XFS_BTNUM_BMAP: { |
91 | xfs_bmbt_key_t *k1; | 91 | xfs_bmbt_key_t *k1; |
92 | xfs_bmbt_key_t *k2; | 92 | xfs_bmbt_key_t *k2; |
93 | 93 | ||
94 | k1 = ak1; | 94 | k1 = ak1; |
95 | k2 = ak2; | 95 | k2 = ak2; |
96 | ASSERT(be64_to_cpu(k1->br_startoff) < be64_to_cpu(k2->br_startoff)); | 96 | ASSERT(be64_to_cpu(k1->br_startoff) < be64_to_cpu(k2->br_startoff)); |
97 | break; | 97 | break; |
98 | } | 98 | } |
99 | case XFS_BTNUM_INO: { | 99 | case XFS_BTNUM_INO: { |
100 | xfs_inobt_key_t *k1; | 100 | xfs_inobt_key_t *k1; |
101 | xfs_inobt_key_t *k2; | 101 | xfs_inobt_key_t *k2; |
102 | 102 | ||
103 | k1 = ak1; | 103 | k1 = ak1; |
104 | k2 = ak2; | 104 | k2 = ak2; |
105 | ASSERT(be32_to_cpu(k1->ir_startino) < be32_to_cpu(k2->ir_startino)); | 105 | ASSERT(be32_to_cpu(k1->ir_startino) < be32_to_cpu(k2->ir_startino)); |
106 | break; | 106 | break; |
107 | } | 107 | } |
108 | default: | 108 | default: |
109 | ASSERT(0); | 109 | ASSERT(0); |
110 | } | 110 | } |
111 | } | 111 | } |
112 | 112 | ||
113 | /* | 113 | /* |
114 | * Debug routine: check that records are in the right order. | 114 | * Debug routine: check that records are in the right order. |
115 | */ | 115 | */ |
116 | void | 116 | void |
117 | xfs_btree_check_rec( | 117 | xfs_btree_check_rec( |
118 | xfs_btnum_t btnum, /* btree identifier */ | 118 | xfs_btnum_t btnum, /* btree identifier */ |
119 | void *ar1, /* pointer to left (lower) record */ | 119 | void *ar1, /* pointer to left (lower) record */ |
120 | void *ar2) /* pointer to right (higher) record */ | 120 | void *ar2) /* pointer to right (higher) record */ |
121 | { | 121 | { |
122 | switch (btnum) { | 122 | switch (btnum) { |
123 | case XFS_BTNUM_BNO: { | 123 | case XFS_BTNUM_BNO: { |
124 | xfs_alloc_rec_t *r1; | 124 | xfs_alloc_rec_t *r1; |
125 | xfs_alloc_rec_t *r2; | 125 | xfs_alloc_rec_t *r2; |
126 | 126 | ||
127 | r1 = ar1; | 127 | r1 = ar1; |
128 | r2 = ar2; | 128 | r2 = ar2; |
129 | ASSERT(be32_to_cpu(r1->ar_startblock) + | 129 | ASSERT(be32_to_cpu(r1->ar_startblock) + |
130 | be32_to_cpu(r1->ar_blockcount) <= | 130 | be32_to_cpu(r1->ar_blockcount) <= |
131 | be32_to_cpu(r2->ar_startblock)); | 131 | be32_to_cpu(r2->ar_startblock)); |
132 | break; | 132 | break; |
133 | } | 133 | } |
134 | case XFS_BTNUM_CNT: { | 134 | case XFS_BTNUM_CNT: { |
135 | xfs_alloc_rec_t *r1; | 135 | xfs_alloc_rec_t *r1; |
136 | xfs_alloc_rec_t *r2; | 136 | xfs_alloc_rec_t *r2; |
137 | 137 | ||
138 | r1 = ar1; | 138 | r1 = ar1; |
139 | r2 = ar2; | 139 | r2 = ar2; |
140 | ASSERT(be32_to_cpu(r1->ar_blockcount) < be32_to_cpu(r2->ar_blockcount) || | 140 | ASSERT(be32_to_cpu(r1->ar_blockcount) < be32_to_cpu(r2->ar_blockcount) || |
141 | (r1->ar_blockcount == r2->ar_blockcount && | 141 | (r1->ar_blockcount == r2->ar_blockcount && |
142 | be32_to_cpu(r1->ar_startblock) < be32_to_cpu(r2->ar_startblock))); | 142 | be32_to_cpu(r1->ar_startblock) < be32_to_cpu(r2->ar_startblock))); |
143 | break; | 143 | break; |
144 | } | 144 | } |
145 | case XFS_BTNUM_BMAP: { | 145 | case XFS_BTNUM_BMAP: { |
146 | xfs_bmbt_rec_t *r1; | 146 | xfs_bmbt_rec_t *r1; |
147 | xfs_bmbt_rec_t *r2; | 147 | xfs_bmbt_rec_t *r2; |
148 | 148 | ||
149 | r1 = ar1; | 149 | r1 = ar1; |
150 | r2 = ar2; | 150 | r2 = ar2; |
151 | ASSERT(xfs_bmbt_disk_get_startoff(r1) + | 151 | ASSERT(xfs_bmbt_disk_get_startoff(r1) + |
152 | xfs_bmbt_disk_get_blockcount(r1) <= | 152 | xfs_bmbt_disk_get_blockcount(r1) <= |
153 | xfs_bmbt_disk_get_startoff(r2)); | 153 | xfs_bmbt_disk_get_startoff(r2)); |
154 | break; | 154 | break; |
155 | } | 155 | } |
156 | case XFS_BTNUM_INO: { | 156 | case XFS_BTNUM_INO: { |
157 | xfs_inobt_rec_t *r1; | 157 | xfs_inobt_rec_t *r1; |
158 | xfs_inobt_rec_t *r2; | 158 | xfs_inobt_rec_t *r2; |
159 | 159 | ||
160 | r1 = ar1; | 160 | r1 = ar1; |
161 | r2 = ar2; | 161 | r2 = ar2; |
162 | ASSERT(be32_to_cpu(r1->ir_startino) + XFS_INODES_PER_CHUNK <= | 162 | ASSERT(be32_to_cpu(r1->ir_startino) + XFS_INODES_PER_CHUNK <= |
163 | be32_to_cpu(r2->ir_startino)); | 163 | be32_to_cpu(r2->ir_startino)); |
164 | break; | 164 | break; |
165 | } | 165 | } |
166 | default: | 166 | default: |
167 | ASSERT(0); | 167 | ASSERT(0); |
168 | } | 168 | } |
169 | } | 169 | } |
170 | #endif /* DEBUG */ | 170 | #endif /* DEBUG */ |
171 | 171 | ||
172 | int /* error (0 or EFSCORRUPTED) */ | 172 | int /* error (0 or EFSCORRUPTED) */ |
173 | xfs_btree_check_lblock( | 173 | xfs_btree_check_lblock( |
174 | struct xfs_btree_cur *cur, /* btree cursor */ | 174 | struct xfs_btree_cur *cur, /* btree cursor */ |
175 | struct xfs_btree_lblock *block, /* btree long form block pointer */ | 175 | struct xfs_btree_lblock *block, /* btree long form block pointer */ |
176 | int level, /* level of the btree block */ | 176 | int level, /* level of the btree block */ |
177 | struct xfs_buf *bp) /* buffer for block, if any */ | 177 | struct xfs_buf *bp) /* buffer for block, if any */ |
178 | { | 178 | { |
179 | int lblock_ok; /* block passes checks */ | 179 | int lblock_ok; /* block passes checks */ |
180 | struct xfs_mount *mp; /* file system mount point */ | 180 | struct xfs_mount *mp; /* file system mount point */ |
181 | 181 | ||
182 | mp = cur->bc_mp; | 182 | mp = cur->bc_mp; |
183 | lblock_ok = | 183 | lblock_ok = |
184 | be32_to_cpu(block->bb_magic) == xfs_magics[cur->bc_btnum] && | 184 | be32_to_cpu(block->bb_magic) == xfs_magics[cur->bc_btnum] && |
185 | be16_to_cpu(block->bb_level) == level && | 185 | be16_to_cpu(block->bb_level) == level && |
186 | be16_to_cpu(block->bb_numrecs) <= | 186 | be16_to_cpu(block->bb_numrecs) <= |
187 | cur->bc_ops->get_maxrecs(cur, level) && | 187 | cur->bc_ops->get_maxrecs(cur, level) && |
188 | block->bb_leftsib && | 188 | block->bb_leftsib && |
189 | (be64_to_cpu(block->bb_leftsib) == NULLDFSBNO || | 189 | (be64_to_cpu(block->bb_leftsib) == NULLDFSBNO || |
190 | XFS_FSB_SANITY_CHECK(mp, be64_to_cpu(block->bb_leftsib))) && | 190 | XFS_FSB_SANITY_CHECK(mp, be64_to_cpu(block->bb_leftsib))) && |
191 | block->bb_rightsib && | 191 | block->bb_rightsib && |
192 | (be64_to_cpu(block->bb_rightsib) == NULLDFSBNO || | 192 | (be64_to_cpu(block->bb_rightsib) == NULLDFSBNO || |
193 | XFS_FSB_SANITY_CHECK(mp, be64_to_cpu(block->bb_rightsib))); | 193 | XFS_FSB_SANITY_CHECK(mp, be64_to_cpu(block->bb_rightsib))); |
194 | if (unlikely(XFS_TEST_ERROR(!lblock_ok, mp, | 194 | if (unlikely(XFS_TEST_ERROR(!lblock_ok, mp, |
195 | XFS_ERRTAG_BTREE_CHECK_LBLOCK, | 195 | XFS_ERRTAG_BTREE_CHECK_LBLOCK, |
196 | XFS_RANDOM_BTREE_CHECK_LBLOCK))) { | 196 | XFS_RANDOM_BTREE_CHECK_LBLOCK))) { |
197 | if (bp) | 197 | if (bp) |
198 | xfs_buftrace("LBTREE ERROR", bp); | 198 | xfs_buftrace("LBTREE ERROR", bp); |
199 | XFS_ERROR_REPORT("xfs_btree_check_lblock", XFS_ERRLEVEL_LOW, | 199 | XFS_ERROR_REPORT("xfs_btree_check_lblock", XFS_ERRLEVEL_LOW, |
200 | mp); | 200 | mp); |
201 | return XFS_ERROR(EFSCORRUPTED); | 201 | return XFS_ERROR(EFSCORRUPTED); |
202 | } | 202 | } |
203 | return 0; | 203 | return 0; |
204 | } | 204 | } |
205 | 205 | ||
206 | int /* error (0 or EFSCORRUPTED) */ | 206 | int /* error (0 or EFSCORRUPTED) */ |
207 | xfs_btree_check_sblock( | 207 | xfs_btree_check_sblock( |
208 | struct xfs_btree_cur *cur, /* btree cursor */ | 208 | struct xfs_btree_cur *cur, /* btree cursor */ |
209 | struct xfs_btree_sblock *block, /* btree short form block pointer */ | 209 | struct xfs_btree_sblock *block, /* btree short form block pointer */ |
210 | int level, /* level of the btree block */ | 210 | int level, /* level of the btree block */ |
211 | struct xfs_buf *bp) /* buffer containing block */ | 211 | struct xfs_buf *bp) /* buffer containing block */ |
212 | { | 212 | { |
213 | struct xfs_buf *agbp; /* buffer for ag. freespace struct */ | 213 | struct xfs_buf *agbp; /* buffer for ag. freespace struct */ |
214 | struct xfs_agf *agf; /* ag. freespace structure */ | 214 | struct xfs_agf *agf; /* ag. freespace structure */ |
215 | xfs_agblock_t agflen; /* native ag. freespace length */ | 215 | xfs_agblock_t agflen; /* native ag. freespace length */ |
216 | int sblock_ok; /* block passes checks */ | 216 | int sblock_ok; /* block passes checks */ |
217 | 217 | ||
218 | agbp = cur->bc_private.a.agbp; | 218 | agbp = cur->bc_private.a.agbp; |
219 | agf = XFS_BUF_TO_AGF(agbp); | 219 | agf = XFS_BUF_TO_AGF(agbp); |
220 | agflen = be32_to_cpu(agf->agf_length); | 220 | agflen = be32_to_cpu(agf->agf_length); |
221 | sblock_ok = | 221 | sblock_ok = |
222 | be32_to_cpu(block->bb_magic) == xfs_magics[cur->bc_btnum] && | 222 | be32_to_cpu(block->bb_magic) == xfs_magics[cur->bc_btnum] && |
223 | be16_to_cpu(block->bb_level) == level && | 223 | be16_to_cpu(block->bb_level) == level && |
224 | be16_to_cpu(block->bb_numrecs) <= | 224 | be16_to_cpu(block->bb_numrecs) <= |
225 | cur->bc_ops->get_maxrecs(cur, level) && | 225 | cur->bc_ops->get_maxrecs(cur, level) && |
226 | (be32_to_cpu(block->bb_leftsib) == NULLAGBLOCK || | 226 | (be32_to_cpu(block->bb_leftsib) == NULLAGBLOCK || |
227 | be32_to_cpu(block->bb_leftsib) < agflen) && | 227 | be32_to_cpu(block->bb_leftsib) < agflen) && |
228 | block->bb_leftsib && | 228 | block->bb_leftsib && |
229 | (be32_to_cpu(block->bb_rightsib) == NULLAGBLOCK || | 229 | (be32_to_cpu(block->bb_rightsib) == NULLAGBLOCK || |
230 | be32_to_cpu(block->bb_rightsib) < agflen) && | 230 | be32_to_cpu(block->bb_rightsib) < agflen) && |
231 | block->bb_rightsib; | 231 | block->bb_rightsib; |
232 | if (unlikely(XFS_TEST_ERROR(!sblock_ok, cur->bc_mp, | 232 | if (unlikely(XFS_TEST_ERROR(!sblock_ok, cur->bc_mp, |
233 | XFS_ERRTAG_BTREE_CHECK_SBLOCK, | 233 | XFS_ERRTAG_BTREE_CHECK_SBLOCK, |
234 | XFS_RANDOM_BTREE_CHECK_SBLOCK))) { | 234 | XFS_RANDOM_BTREE_CHECK_SBLOCK))) { |
235 | if (bp) | 235 | if (bp) |
236 | xfs_buftrace("SBTREE ERROR", bp); | 236 | xfs_buftrace("SBTREE ERROR", bp); |
237 | XFS_ERROR_REPORT("xfs_btree_check_sblock", XFS_ERRLEVEL_LOW, | 237 | XFS_ERROR_REPORT("xfs_btree_check_sblock", XFS_ERRLEVEL_LOW, |
238 | cur->bc_mp); | 238 | cur->bc_mp); |
239 | return XFS_ERROR(EFSCORRUPTED); | 239 | return XFS_ERROR(EFSCORRUPTED); |
240 | } | 240 | } |
241 | return 0; | 241 | return 0; |
242 | } | 242 | } |
243 | 243 | ||
244 | /* | 244 | /* |
245 | * Debug routine: check that block header is ok. | 245 | * Debug routine: check that block header is ok. |
246 | */ | 246 | */ |
247 | int | 247 | int |
248 | xfs_btree_check_block( | 248 | xfs_btree_check_block( |
249 | struct xfs_btree_cur *cur, /* btree cursor */ | 249 | struct xfs_btree_cur *cur, /* btree cursor */ |
250 | struct xfs_btree_block *block, /* generic btree block pointer */ | 250 | struct xfs_btree_block *block, /* generic btree block pointer */ |
251 | int level, /* level of the btree block */ | 251 | int level, /* level of the btree block */ |
252 | struct xfs_buf *bp) /* buffer containing block, if any */ | 252 | struct xfs_buf *bp) /* buffer containing block, if any */ |
253 | { | 253 | { |
254 | if (cur->bc_flags & XFS_BTREE_LONG_PTRS) { | 254 | if (cur->bc_flags & XFS_BTREE_LONG_PTRS) { |
255 | return xfs_btree_check_lblock(cur, | 255 | return xfs_btree_check_lblock(cur, |
256 | (struct xfs_btree_lblock *)block, level, bp); | 256 | (struct xfs_btree_lblock *)block, level, bp); |
257 | } else { | 257 | } else { |
258 | return xfs_btree_check_sblock(cur, | 258 | return xfs_btree_check_sblock(cur, |
259 | (struct xfs_btree_sblock *)block, level, bp); | 259 | (struct xfs_btree_sblock *)block, level, bp); |
260 | } | 260 | } |
261 | } | 261 | } |
262 | 262 | ||
263 | /* | 263 | /* |
264 | * Check that (long) pointer is ok. | 264 | * Check that (long) pointer is ok. |
265 | */ | 265 | */ |
266 | int /* error (0 or EFSCORRUPTED) */ | 266 | int /* error (0 or EFSCORRUPTED) */ |
267 | xfs_btree_check_lptr( | 267 | xfs_btree_check_lptr( |
268 | struct xfs_btree_cur *cur, /* btree cursor */ | 268 | struct xfs_btree_cur *cur, /* btree cursor */ |
269 | xfs_dfsbno_t bno, /* btree block disk address */ | 269 | xfs_dfsbno_t bno, /* btree block disk address */ |
270 | int level) /* btree block level */ | 270 | int level) /* btree block level */ |
271 | { | 271 | { |
272 | XFS_WANT_CORRUPTED_RETURN( | 272 | XFS_WANT_CORRUPTED_RETURN( |
273 | level > 0 && | 273 | level > 0 && |
274 | bno != NULLDFSBNO && | 274 | bno != NULLDFSBNO && |
275 | XFS_FSB_SANITY_CHECK(cur->bc_mp, bno)); | 275 | XFS_FSB_SANITY_CHECK(cur->bc_mp, bno)); |
276 | return 0; | 276 | return 0; |
277 | } | 277 | } |
278 | 278 | ||
279 | /* | 279 | /* |
280 | * Check that (short) pointer is ok. | 280 | * Check that (short) pointer is ok. |
281 | */ | 281 | */ |
282 | int /* error (0 or EFSCORRUPTED) */ | 282 | int /* error (0 or EFSCORRUPTED) */ |
283 | xfs_btree_check_sptr( | 283 | xfs_btree_check_sptr( |
284 | struct xfs_btree_cur *cur, /* btree cursor */ | 284 | struct xfs_btree_cur *cur, /* btree cursor */ |
285 | xfs_agblock_t bno, /* btree block disk address */ | 285 | xfs_agblock_t bno, /* btree block disk address */ |
286 | int level) /* btree block level */ | 286 | int level) /* btree block level */ |
287 | { | 287 | { |
288 | xfs_agblock_t agblocks = cur->bc_mp->m_sb.sb_agblocks; | 288 | xfs_agblock_t agblocks = cur->bc_mp->m_sb.sb_agblocks; |
289 | 289 | ||
290 | XFS_WANT_CORRUPTED_RETURN( | 290 | XFS_WANT_CORRUPTED_RETURN( |
291 | level > 0 && | 291 | level > 0 && |
292 | bno != NULLAGBLOCK && | 292 | bno != NULLAGBLOCK && |
293 | bno != 0 && | 293 | bno != 0 && |
294 | bno < agblocks); | 294 | bno < agblocks); |
295 | return 0; | 295 | return 0; |
296 | } | 296 | } |
297 | 297 | ||
298 | /* | 298 | /* |
299 | * Check that block ptr is ok. | 299 | * Check that block ptr is ok. |
300 | */ | 300 | */ |
301 | int /* error (0 or EFSCORRUPTED) */ | 301 | int /* error (0 or EFSCORRUPTED) */ |
302 | xfs_btree_check_ptr( | 302 | xfs_btree_check_ptr( |
303 | struct xfs_btree_cur *cur, /* btree cursor */ | 303 | struct xfs_btree_cur *cur, /* btree cursor */ |
304 | union xfs_btree_ptr *ptr, /* btree block disk address */ | 304 | union xfs_btree_ptr *ptr, /* btree block disk address */ |
305 | int index, /* offset from ptr to check */ | 305 | int index, /* offset from ptr to check */ |
306 | int level) /* btree block level */ | 306 | int level) /* btree block level */ |
307 | { | 307 | { |
308 | if (cur->bc_flags & XFS_BTREE_LONG_PTRS) { | 308 | if (cur->bc_flags & XFS_BTREE_LONG_PTRS) { |
309 | return xfs_btree_check_lptr(cur, | 309 | return xfs_btree_check_lptr(cur, |
310 | be64_to_cpu((&ptr->l)[index]), level); | 310 | be64_to_cpu((&ptr->l)[index]), level); |
311 | } else { | 311 | } else { |
312 | return xfs_btree_check_sptr(cur, | 312 | return xfs_btree_check_sptr(cur, |
313 | be32_to_cpu((&ptr->s)[index]), level); | 313 | be32_to_cpu((&ptr->s)[index]), level); |
314 | } | 314 | } |
315 | } | 315 | } |
316 | 316 | ||
317 | /* | 317 | /* |
318 | * Delete the btree cursor. | 318 | * Delete the btree cursor. |
319 | */ | 319 | */ |
320 | void | 320 | void |
321 | xfs_btree_del_cursor( | 321 | xfs_btree_del_cursor( |
322 | xfs_btree_cur_t *cur, /* btree cursor */ | 322 | xfs_btree_cur_t *cur, /* btree cursor */ |
323 | int error) /* del because of error */ | 323 | int error) /* del because of error */ |
324 | { | 324 | { |
325 | int i; /* btree level */ | 325 | int i; /* btree level */ |
326 | 326 | ||
327 | /* | 327 | /* |
328 | * Clear the buffer pointers, and release the buffers. | 328 | * Clear the buffer pointers, and release the buffers. |
329 | * If we're doing this in the face of an error, we | 329 | * If we're doing this in the face of an error, we |
330 | * need to make sure to inspect all of the entries | 330 | * need to make sure to inspect all of the entries |
331 | * in the bc_bufs array for buffers to be unlocked. | 331 | * in the bc_bufs array for buffers to be unlocked. |
332 | * This is because some of the btree code works from | 332 | * This is because some of the btree code works from |
333 | * level n down to 0, and if we get an error along | 333 | * level n down to 0, and if we get an error along |
334 | * the way we won't have initialized all the entries | 334 | * the way we won't have initialized all the entries |
335 | * down to 0. | 335 | * down to 0. |
336 | */ | 336 | */ |
337 | for (i = 0; i < cur->bc_nlevels; i++) { | 337 | for (i = 0; i < cur->bc_nlevels; i++) { |
338 | if (cur->bc_bufs[i]) | 338 | if (cur->bc_bufs[i]) |
339 | xfs_btree_setbuf(cur, i, NULL); | 339 | xfs_btree_setbuf(cur, i, NULL); |
340 | else if (!error) | 340 | else if (!error) |
341 | break; | 341 | break; |
342 | } | 342 | } |
343 | /* | 343 | /* |
344 | * Can't free a bmap cursor without having dealt with the | 344 | * Can't free a bmap cursor without having dealt with the |
345 | * allocated indirect blocks' accounting. | 345 | * allocated indirect blocks' accounting. |
346 | */ | 346 | */ |
347 | ASSERT(cur->bc_btnum != XFS_BTNUM_BMAP || | 347 | ASSERT(cur->bc_btnum != XFS_BTNUM_BMAP || |
348 | cur->bc_private.b.allocated == 0); | 348 | cur->bc_private.b.allocated == 0); |
349 | /* | 349 | /* |
350 | * Free the cursor. | 350 | * Free the cursor. |
351 | */ | 351 | */ |
352 | kmem_zone_free(xfs_btree_cur_zone, cur); | 352 | kmem_zone_free(xfs_btree_cur_zone, cur); |
353 | } | 353 | } |
354 | 354 | ||
355 | /* | 355 | /* |
356 | * Duplicate the btree cursor. | 356 | * Duplicate the btree cursor. |
357 | * Allocate a new one, copy the record, re-get the buffers. | 357 | * Allocate a new one, copy the record, re-get the buffers. |
358 | */ | 358 | */ |
359 | int /* error */ | 359 | int /* error */ |
360 | xfs_btree_dup_cursor( | 360 | xfs_btree_dup_cursor( |
361 | xfs_btree_cur_t *cur, /* input cursor */ | 361 | xfs_btree_cur_t *cur, /* input cursor */ |
362 | xfs_btree_cur_t **ncur) /* output cursor */ | 362 | xfs_btree_cur_t **ncur) /* output cursor */ |
363 | { | 363 | { |
364 | xfs_buf_t *bp; /* btree block's buffer pointer */ | 364 | xfs_buf_t *bp; /* btree block's buffer pointer */ |
365 | int error; /* error return value */ | 365 | int error; /* error return value */ |
366 | int i; /* level number of btree block */ | 366 | int i; /* level number of btree block */ |
367 | xfs_mount_t *mp; /* mount structure for filesystem */ | 367 | xfs_mount_t *mp; /* mount structure for filesystem */ |
368 | xfs_btree_cur_t *new; /* new cursor value */ | 368 | xfs_btree_cur_t *new; /* new cursor value */ |
369 | xfs_trans_t *tp; /* transaction pointer, can be NULL */ | 369 | xfs_trans_t *tp; /* transaction pointer, can be NULL */ |
370 | 370 | ||
371 | tp = cur->bc_tp; | 371 | tp = cur->bc_tp; |
372 | mp = cur->bc_mp; | 372 | mp = cur->bc_mp; |
373 | 373 | ||
374 | /* | 374 | /* |
375 | * Allocate a new cursor like the old one. | 375 | * Allocate a new cursor like the old one. |
376 | */ | 376 | */ |
377 | new = cur->bc_ops->dup_cursor(cur); | 377 | new = cur->bc_ops->dup_cursor(cur); |
378 | 378 | ||
379 | /* | 379 | /* |
380 | * Copy the record currently in the cursor. | 380 | * Copy the record currently in the cursor. |
381 | */ | 381 | */ |
382 | new->bc_rec = cur->bc_rec; | 382 | new->bc_rec = cur->bc_rec; |
383 | 383 | ||
384 | /* | 384 | /* |
385 | * For each level current, re-get the buffer and copy the ptr value. | 385 | * For each level current, re-get the buffer and copy the ptr value. |
386 | */ | 386 | */ |
387 | for (i = 0; i < new->bc_nlevels; i++) { | 387 | for (i = 0; i < new->bc_nlevels; i++) { |
388 | new->bc_ptrs[i] = cur->bc_ptrs[i]; | 388 | new->bc_ptrs[i] = cur->bc_ptrs[i]; |
389 | new->bc_ra[i] = cur->bc_ra[i]; | 389 | new->bc_ra[i] = cur->bc_ra[i]; |
390 | if ((bp = cur->bc_bufs[i])) { | 390 | if ((bp = cur->bc_bufs[i])) { |
391 | if ((error = xfs_trans_read_buf(mp, tp, mp->m_ddev_targp, | 391 | if ((error = xfs_trans_read_buf(mp, tp, mp->m_ddev_targp, |
392 | XFS_BUF_ADDR(bp), mp->m_bsize, 0, &bp))) { | 392 | XFS_BUF_ADDR(bp), mp->m_bsize, 0, &bp))) { |
393 | xfs_btree_del_cursor(new, error); | 393 | xfs_btree_del_cursor(new, error); |
394 | *ncur = NULL; | 394 | *ncur = NULL; |
395 | return error; | 395 | return error; |
396 | } | 396 | } |
397 | new->bc_bufs[i] = bp; | 397 | new->bc_bufs[i] = bp; |
398 | ASSERT(bp); | 398 | ASSERT(bp); |
399 | ASSERT(!XFS_BUF_GETERROR(bp)); | 399 | ASSERT(!XFS_BUF_GETERROR(bp)); |
400 | } else | 400 | } else |
401 | new->bc_bufs[i] = NULL; | 401 | new->bc_bufs[i] = NULL; |
402 | } | 402 | } |
403 | *ncur = new; | 403 | *ncur = new; |
404 | return 0; | 404 | return 0; |
405 | } | 405 | } |
406 | 406 | ||
407 | /* | 407 | /* |
408 | * XFS btree block layout and addressing: | 408 | * XFS btree block layout and addressing: |
409 | * | 409 | * |
410 | * There are two types of blocks in the btree: leaf and non-leaf blocks. | 410 | * There are two types of blocks in the btree: leaf and non-leaf blocks. |
411 | * | 411 | * |
412 | * The leaf record start with a header then followed by records containing | 412 | * The leaf record start with a header then followed by records containing |
413 | * the values. A non-leaf block also starts with the same header, and | 413 | * the values. A non-leaf block also starts with the same header, and |
414 | * then first contains lookup keys followed by an equal number of pointers | 414 | * then first contains lookup keys followed by an equal number of pointers |
415 | * to the btree blocks at the previous level. | 415 | * to the btree blocks at the previous level. |
416 | * | 416 | * |
417 | * +--------+-------+-------+-------+-------+-------+-------+ | 417 | * +--------+-------+-------+-------+-------+-------+-------+ |
418 | * Leaf: | header | rec 1 | rec 2 | rec 3 | rec 4 | rec 5 | rec N | | 418 | * Leaf: | header | rec 1 | rec 2 | rec 3 | rec 4 | rec 5 | rec N | |
419 | * +--------+-------+-------+-------+-------+-------+-------+ | 419 | * +--------+-------+-------+-------+-------+-------+-------+ |
420 | * | 420 | * |
421 | * +--------+-------+-------+-------+-------+-------+-------+ | 421 | * +--------+-------+-------+-------+-------+-------+-------+ |
422 | * Non-Leaf: | header | key 1 | key 2 | key N | ptr 1 | ptr 2 | ptr N | | 422 | * Non-Leaf: | header | key 1 | key 2 | key N | ptr 1 | ptr 2 | ptr N | |
423 | * +--------+-------+-------+-------+-------+-------+-------+ | 423 | * +--------+-------+-------+-------+-------+-------+-------+ |
424 | * | 424 | * |
425 | * The header is called struct xfs_btree_block for reasons better left unknown | 425 | * The header is called struct xfs_btree_block for reasons better left unknown |
426 | * and comes in different versions for short (32bit) and long (64bit) block | 426 | * and comes in different versions for short (32bit) and long (64bit) block |
427 | * pointers. The record and key structures are defined by the btree instances | 427 | * pointers. The record and key structures are defined by the btree instances |
428 | * and opaque to the btree core. The block pointers are simple disk endian | 428 | * and opaque to the btree core. The block pointers are simple disk endian |
429 | * integers, available in a short (32bit) and long (64bit) variant. | 429 | * integers, available in a short (32bit) and long (64bit) variant. |
430 | * | 430 | * |
431 | * The helpers below calculate the offset of a given record, key or pointer | 431 | * The helpers below calculate the offset of a given record, key or pointer |
432 | * into a btree block (xfs_btree_*_offset) or return a pointer to the given | 432 | * into a btree block (xfs_btree_*_offset) or return a pointer to the given |
433 | * record, key or pointer (xfs_btree_*_addr). Note that all addressing | 433 | * record, key or pointer (xfs_btree_*_addr). Note that all addressing |
434 | * inside the btree block is done using indices starting at one, not zero! | 434 | * inside the btree block is done using indices starting at one, not zero! |
435 | */ | 435 | */ |
436 | 436 | ||
437 | /* | 437 | /* |
438 | * Return size of the btree block header for this btree instance. | 438 | * Return size of the btree block header for this btree instance. |
439 | */ | 439 | */ |
440 | static inline size_t xfs_btree_block_len(struct xfs_btree_cur *cur) | 440 | static inline size_t xfs_btree_block_len(struct xfs_btree_cur *cur) |
441 | { | 441 | { |
442 | return (cur->bc_flags & XFS_BTREE_LONG_PTRS) ? | 442 | return (cur->bc_flags & XFS_BTREE_LONG_PTRS) ? |
443 | sizeof(struct xfs_btree_lblock) : | 443 | sizeof(struct xfs_btree_lblock) : |
444 | sizeof(struct xfs_btree_sblock); | 444 | sizeof(struct xfs_btree_sblock); |
445 | } | 445 | } |
446 | 446 | ||
447 | /* | 447 | /* |
448 | * Return size of btree block pointers for this btree instance. | 448 | * Return size of btree block pointers for this btree instance. |
449 | */ | 449 | */ |
450 | static inline size_t xfs_btree_ptr_len(struct xfs_btree_cur *cur) | 450 | static inline size_t xfs_btree_ptr_len(struct xfs_btree_cur *cur) |
451 | { | 451 | { |
452 | return (cur->bc_flags & XFS_BTREE_LONG_PTRS) ? | 452 | return (cur->bc_flags & XFS_BTREE_LONG_PTRS) ? |
453 | sizeof(__be64) : sizeof(__be32); | 453 | sizeof(__be64) : sizeof(__be32); |
454 | } | 454 | } |
455 | 455 | ||
456 | /* | 456 | /* |
457 | * Calculate offset of the n-th record in a btree block. | 457 | * Calculate offset of the n-th record in a btree block. |
458 | */ | 458 | */ |
459 | STATIC size_t | 459 | STATIC size_t |
460 | xfs_btree_rec_offset( | 460 | xfs_btree_rec_offset( |
461 | struct xfs_btree_cur *cur, | 461 | struct xfs_btree_cur *cur, |
462 | int n) | 462 | int n) |
463 | { | 463 | { |
464 | return xfs_btree_block_len(cur) + | 464 | return xfs_btree_block_len(cur) + |
465 | (n - 1) * cur->bc_ops->rec_len; | 465 | (n - 1) * cur->bc_ops->rec_len; |
466 | } | 466 | } |
467 | 467 | ||
468 | /* | 468 | /* |
469 | * Calculate offset of the n-th key in a btree block. | 469 | * Calculate offset of the n-th key in a btree block. |
470 | */ | 470 | */ |
471 | STATIC size_t | 471 | STATIC size_t |
472 | xfs_btree_key_offset( | 472 | xfs_btree_key_offset( |
473 | struct xfs_btree_cur *cur, | 473 | struct xfs_btree_cur *cur, |
474 | int n) | 474 | int n) |
475 | { | 475 | { |
476 | return xfs_btree_block_len(cur) + | 476 | return xfs_btree_block_len(cur) + |
477 | (n - 1) * cur->bc_ops->key_len; | 477 | (n - 1) * cur->bc_ops->key_len; |
478 | } | 478 | } |
479 | 479 | ||
480 | /* | 480 | /* |
481 | * Calculate offset of the n-th block pointer in a btree block. | 481 | * Calculate offset of the n-th block pointer in a btree block. |
482 | */ | 482 | */ |
483 | STATIC size_t | 483 | STATIC size_t |
484 | xfs_btree_ptr_offset( | 484 | xfs_btree_ptr_offset( |
485 | struct xfs_btree_cur *cur, | 485 | struct xfs_btree_cur *cur, |
486 | int n, | 486 | int n, |
487 | int level) | 487 | int level) |
488 | { | 488 | { |
489 | return xfs_btree_block_len(cur) + | 489 | return xfs_btree_block_len(cur) + |
490 | cur->bc_ops->get_maxrecs(cur, level) * cur->bc_ops->key_len + | 490 | cur->bc_ops->get_maxrecs(cur, level) * cur->bc_ops->key_len + |
491 | (n - 1) * xfs_btree_ptr_len(cur); | 491 | (n - 1) * xfs_btree_ptr_len(cur); |
492 | } | 492 | } |
493 | 493 | ||
494 | /* | 494 | /* |
495 | * Return a pointer to the n-th record in the btree block. | 495 | * Return a pointer to the n-th record in the btree block. |
496 | */ | 496 | */ |
497 | STATIC union xfs_btree_rec * | 497 | STATIC union xfs_btree_rec * |
498 | xfs_btree_rec_addr( | 498 | xfs_btree_rec_addr( |
499 | struct xfs_btree_cur *cur, | 499 | struct xfs_btree_cur *cur, |
500 | int n, | 500 | int n, |
501 | struct xfs_btree_block *block) | 501 | struct xfs_btree_block *block) |
502 | { | 502 | { |
503 | return (union xfs_btree_rec *) | 503 | return (union xfs_btree_rec *) |
504 | ((char *)block + xfs_btree_rec_offset(cur, n)); | 504 | ((char *)block + xfs_btree_rec_offset(cur, n)); |
505 | } | 505 | } |
506 | 506 | ||
507 | /* | 507 | /* |
508 | * Return a pointer to the n-th key in the btree block. | 508 | * Return a pointer to the n-th key in the btree block. |
509 | */ | 509 | */ |
510 | STATIC union xfs_btree_key * | 510 | STATIC union xfs_btree_key * |
511 | xfs_btree_key_addr( | 511 | xfs_btree_key_addr( |
512 | struct xfs_btree_cur *cur, | 512 | struct xfs_btree_cur *cur, |
513 | int n, | 513 | int n, |
514 | struct xfs_btree_block *block) | 514 | struct xfs_btree_block *block) |
515 | { | 515 | { |
516 | return (union xfs_btree_key *) | 516 | return (union xfs_btree_key *) |
517 | ((char *)block + xfs_btree_key_offset(cur, n)); | 517 | ((char *)block + xfs_btree_key_offset(cur, n)); |
518 | } | 518 | } |
519 | 519 | ||
520 | /* | 520 | /* |
521 | * Return a pointer to the n-th block pointer in the btree block. | 521 | * Return a pointer to the n-th block pointer in the btree block. |
522 | */ | 522 | */ |
523 | STATIC union xfs_btree_ptr * | 523 | STATIC union xfs_btree_ptr * |
524 | xfs_btree_ptr_addr( | 524 | xfs_btree_ptr_addr( |
525 | struct xfs_btree_cur *cur, | 525 | struct xfs_btree_cur *cur, |
526 | int n, | 526 | int n, |
527 | struct xfs_btree_block *block) | 527 | struct xfs_btree_block *block) |
528 | { | 528 | { |
529 | int level = xfs_btree_get_level(block); | 529 | int level = xfs_btree_get_level(block); |
530 | 530 | ||
531 | ASSERT(block->bb_level != 0); | 531 | ASSERT(block->bb_level != 0); |
532 | 532 | ||
533 | return (union xfs_btree_ptr *) | 533 | return (union xfs_btree_ptr *) |
534 | ((char *)block + xfs_btree_ptr_offset(cur, n, level)); | 534 | ((char *)block + xfs_btree_ptr_offset(cur, n, level)); |
535 | } | 535 | } |
536 | 536 | ||
537 | /* | 537 | /* |
538 | * Get a the root block which is stored in the inode. | 538 | * Get a the root block which is stored in the inode. |
539 | * | 539 | * |
540 | * For now this btree implementation assumes the btree root is always | 540 | * For now this btree implementation assumes the btree root is always |
541 | * stored in the if_broot field of an inode fork. | 541 | * stored in the if_broot field of an inode fork. |
542 | */ | 542 | */ |
543 | STATIC struct xfs_btree_block * | 543 | STATIC struct xfs_btree_block * |
544 | xfs_btree_get_iroot( | 544 | xfs_btree_get_iroot( |
545 | struct xfs_btree_cur *cur) | 545 | struct xfs_btree_cur *cur) |
546 | { | 546 | { |
547 | struct xfs_ifork *ifp; | 547 | struct xfs_ifork *ifp; |
548 | 548 | ||
549 | ifp = XFS_IFORK_PTR(cur->bc_private.b.ip, cur->bc_private.b.whichfork); | 549 | ifp = XFS_IFORK_PTR(cur->bc_private.b.ip, cur->bc_private.b.whichfork); |
550 | return (struct xfs_btree_block *)ifp->if_broot; | 550 | return (struct xfs_btree_block *)ifp->if_broot; |
551 | } | 551 | } |
552 | 552 | ||
553 | /* | 553 | /* |
554 | * Retrieve the block pointer from the cursor at the given level. | 554 | * Retrieve the block pointer from the cursor at the given level. |
555 | * This may be an inode btree root or from a buffer. | 555 | * This may be an inode btree root or from a buffer. |
556 | */ | 556 | */ |
557 | STATIC struct xfs_btree_block * /* generic btree block pointer */ | 557 | STATIC struct xfs_btree_block * /* generic btree block pointer */ |
558 | xfs_btree_get_block( | 558 | xfs_btree_get_block( |
559 | struct xfs_btree_cur *cur, /* btree cursor */ | 559 | struct xfs_btree_cur *cur, /* btree cursor */ |
560 | int level, /* level in btree */ | 560 | int level, /* level in btree */ |
561 | struct xfs_buf **bpp) /* buffer containing the block */ | 561 | struct xfs_buf **bpp) /* buffer containing the block */ |
562 | { | 562 | { |
563 | if ((cur->bc_flags & XFS_BTREE_ROOT_IN_INODE) && | 563 | if ((cur->bc_flags & XFS_BTREE_ROOT_IN_INODE) && |
564 | (level == cur->bc_nlevels - 1)) { | 564 | (level == cur->bc_nlevels - 1)) { |
565 | *bpp = NULL; | 565 | *bpp = NULL; |
566 | return xfs_btree_get_iroot(cur); | 566 | return xfs_btree_get_iroot(cur); |
567 | } | 567 | } |
568 | 568 | ||
569 | *bpp = cur->bc_bufs[level]; | 569 | *bpp = cur->bc_bufs[level]; |
570 | return XFS_BUF_TO_BLOCK(*bpp); | 570 | return XFS_BUF_TO_BLOCK(*bpp); |
571 | } | 571 | } |
572 | 572 | ||
573 | /* | 573 | /* |
574 | * Get a buffer for the block, return it with no data read. | 574 | * Get a buffer for the block, return it with no data read. |
575 | * Long-form addressing. | 575 | * Long-form addressing. |
576 | */ | 576 | */ |
577 | xfs_buf_t * /* buffer for fsbno */ | 577 | xfs_buf_t * /* buffer for fsbno */ |
578 | xfs_btree_get_bufl( | 578 | xfs_btree_get_bufl( |
579 | xfs_mount_t *mp, /* file system mount point */ | 579 | xfs_mount_t *mp, /* file system mount point */ |
580 | xfs_trans_t *tp, /* transaction pointer */ | 580 | xfs_trans_t *tp, /* transaction pointer */ |
581 | xfs_fsblock_t fsbno, /* file system block number */ | 581 | xfs_fsblock_t fsbno, /* file system block number */ |
582 | uint lock) /* lock flags for get_buf */ | 582 | uint lock) /* lock flags for get_buf */ |
583 | { | 583 | { |
584 | xfs_buf_t *bp; /* buffer pointer (return value) */ | 584 | xfs_buf_t *bp; /* buffer pointer (return value) */ |
585 | xfs_daddr_t d; /* real disk block address */ | 585 | xfs_daddr_t d; /* real disk block address */ |
586 | 586 | ||
587 | ASSERT(fsbno != NULLFSBLOCK); | 587 | ASSERT(fsbno != NULLFSBLOCK); |
588 | d = XFS_FSB_TO_DADDR(mp, fsbno); | 588 | d = XFS_FSB_TO_DADDR(mp, fsbno); |
589 | bp = xfs_trans_get_buf(tp, mp->m_ddev_targp, d, mp->m_bsize, lock); | 589 | bp = xfs_trans_get_buf(tp, mp->m_ddev_targp, d, mp->m_bsize, lock); |
590 | ASSERT(bp); | 590 | ASSERT(bp); |
591 | ASSERT(!XFS_BUF_GETERROR(bp)); | 591 | ASSERT(!XFS_BUF_GETERROR(bp)); |
592 | return bp; | 592 | return bp; |
593 | } | 593 | } |
594 | 594 | ||
595 | /* | 595 | /* |
596 | * Get a buffer for the block, return it with no data read. | 596 | * Get a buffer for the block, return it with no data read. |
597 | * Short-form addressing. | 597 | * Short-form addressing. |
598 | */ | 598 | */ |
599 | xfs_buf_t * /* buffer for agno/agbno */ | 599 | xfs_buf_t * /* buffer for agno/agbno */ |
600 | xfs_btree_get_bufs( | 600 | xfs_btree_get_bufs( |
601 | xfs_mount_t *mp, /* file system mount point */ | 601 | xfs_mount_t *mp, /* file system mount point */ |
602 | xfs_trans_t *tp, /* transaction pointer */ | 602 | xfs_trans_t *tp, /* transaction pointer */ |
603 | xfs_agnumber_t agno, /* allocation group number */ | 603 | xfs_agnumber_t agno, /* allocation group number */ |
604 | xfs_agblock_t agbno, /* allocation group block number */ | 604 | xfs_agblock_t agbno, /* allocation group block number */ |
605 | uint lock) /* lock flags for get_buf */ | 605 | uint lock) /* lock flags for get_buf */ |
606 | { | 606 | { |
607 | xfs_buf_t *bp; /* buffer pointer (return value) */ | 607 | xfs_buf_t *bp; /* buffer pointer (return value) */ |
608 | xfs_daddr_t d; /* real disk block address */ | 608 | xfs_daddr_t d; /* real disk block address */ |
609 | 609 | ||
610 | ASSERT(agno != NULLAGNUMBER); | 610 | ASSERT(agno != NULLAGNUMBER); |
611 | ASSERT(agbno != NULLAGBLOCK); | 611 | ASSERT(agbno != NULLAGBLOCK); |
612 | d = XFS_AGB_TO_DADDR(mp, agno, agbno); | 612 | d = XFS_AGB_TO_DADDR(mp, agno, agbno); |
613 | bp = xfs_trans_get_buf(tp, mp->m_ddev_targp, d, mp->m_bsize, lock); | 613 | bp = xfs_trans_get_buf(tp, mp->m_ddev_targp, d, mp->m_bsize, lock); |
614 | ASSERT(bp); | 614 | ASSERT(bp); |
615 | ASSERT(!XFS_BUF_GETERROR(bp)); | 615 | ASSERT(!XFS_BUF_GETERROR(bp)); |
616 | return bp; | 616 | return bp; |
617 | } | 617 | } |
618 | 618 | ||
619 | /* | 619 | /* |
620 | * Check for the cursor referring to the last block at the given level. | 620 | * Check for the cursor referring to the last block at the given level. |
621 | */ | 621 | */ |
622 | int /* 1=is last block, 0=not last block */ | 622 | int /* 1=is last block, 0=not last block */ |
623 | xfs_btree_islastblock( | 623 | xfs_btree_islastblock( |
624 | xfs_btree_cur_t *cur, /* btree cursor */ | 624 | xfs_btree_cur_t *cur, /* btree cursor */ |
625 | int level) /* level to check */ | 625 | int level) /* level to check */ |
626 | { | 626 | { |
627 | xfs_btree_block_t *block; /* generic btree block pointer */ | 627 | xfs_btree_block_t *block; /* generic btree block pointer */ |
628 | xfs_buf_t *bp; /* buffer containing block */ | 628 | xfs_buf_t *bp; /* buffer containing block */ |
629 | 629 | ||
630 | block = xfs_btree_get_block(cur, level, &bp); | 630 | block = xfs_btree_get_block(cur, level, &bp); |
631 | xfs_btree_check_block(cur, block, level, bp); | 631 | xfs_btree_check_block(cur, block, level, bp); |
632 | if (cur->bc_flags & XFS_BTREE_LONG_PTRS) | 632 | if (cur->bc_flags & XFS_BTREE_LONG_PTRS) |
633 | return be64_to_cpu(block->bb_u.l.bb_rightsib) == NULLDFSBNO; | 633 | return be64_to_cpu(block->bb_u.l.bb_rightsib) == NULLDFSBNO; |
634 | else | 634 | else |
635 | return be32_to_cpu(block->bb_u.s.bb_rightsib) == NULLAGBLOCK; | 635 | return be32_to_cpu(block->bb_u.s.bb_rightsib) == NULLAGBLOCK; |
636 | } | 636 | } |
637 | 637 | ||
638 | /* | 638 | /* |
639 | * Change the cursor to point to the first record at the given level. | 639 | * Change the cursor to point to the first record at the given level. |
640 | * Other levels are unaffected. | 640 | * Other levels are unaffected. |
641 | */ | 641 | */ |
642 | int /* success=1, failure=0 */ | 642 | int /* success=1, failure=0 */ |
643 | xfs_btree_firstrec( | 643 | xfs_btree_firstrec( |
644 | xfs_btree_cur_t *cur, /* btree cursor */ | 644 | xfs_btree_cur_t *cur, /* btree cursor */ |
645 | int level) /* level to change */ | 645 | int level) /* level to change */ |
646 | { | 646 | { |
647 | xfs_btree_block_t *block; /* generic btree block pointer */ | 647 | xfs_btree_block_t *block; /* generic btree block pointer */ |
648 | xfs_buf_t *bp; /* buffer containing block */ | 648 | xfs_buf_t *bp; /* buffer containing block */ |
649 | 649 | ||
650 | /* | 650 | /* |
651 | * Get the block pointer for this level. | 651 | * Get the block pointer for this level. |
652 | */ | 652 | */ |
653 | block = xfs_btree_get_block(cur, level, &bp); | 653 | block = xfs_btree_get_block(cur, level, &bp); |
654 | xfs_btree_check_block(cur, block, level, bp); | 654 | xfs_btree_check_block(cur, block, level, bp); |
655 | /* | 655 | /* |
656 | * It's empty, there is no such record. | 656 | * It's empty, there is no such record. |
657 | */ | 657 | */ |
658 | if (!block->bb_numrecs) | 658 | if (!block->bb_numrecs) |
659 | return 0; | 659 | return 0; |
660 | /* | 660 | /* |
661 | * Set the ptr value to 1, that's the first record/key. | 661 | * Set the ptr value to 1, that's the first record/key. |
662 | */ | 662 | */ |
663 | cur->bc_ptrs[level] = 1; | 663 | cur->bc_ptrs[level] = 1; |
664 | return 1; | 664 | return 1; |
665 | } | 665 | } |
666 | 666 | ||
667 | /* | 667 | /* |
668 | * Change the cursor to point to the last record in the current block | 668 | * Change the cursor to point to the last record in the current block |
669 | * at the given level. Other levels are unaffected. | 669 | * at the given level. Other levels are unaffected. |
670 | */ | 670 | */ |
671 | int /* success=1, failure=0 */ | 671 | int /* success=1, failure=0 */ |
672 | xfs_btree_lastrec( | 672 | xfs_btree_lastrec( |
673 | xfs_btree_cur_t *cur, /* btree cursor */ | 673 | xfs_btree_cur_t *cur, /* btree cursor */ |
674 | int level) /* level to change */ | 674 | int level) /* level to change */ |
675 | { | 675 | { |
676 | xfs_btree_block_t *block; /* generic btree block pointer */ | 676 | xfs_btree_block_t *block; /* generic btree block pointer */ |
677 | xfs_buf_t *bp; /* buffer containing block */ | 677 | xfs_buf_t *bp; /* buffer containing block */ |
678 | 678 | ||
679 | /* | 679 | /* |
680 | * Get the block pointer for this level. | 680 | * Get the block pointer for this level. |
681 | */ | 681 | */ |
682 | block = xfs_btree_get_block(cur, level, &bp); | 682 | block = xfs_btree_get_block(cur, level, &bp); |
683 | xfs_btree_check_block(cur, block, level, bp); | 683 | xfs_btree_check_block(cur, block, level, bp); |
684 | /* | 684 | /* |
685 | * It's empty, there is no such record. | 685 | * It's empty, there is no such record. |
686 | */ | 686 | */ |
687 | if (!block->bb_numrecs) | 687 | if (!block->bb_numrecs) |
688 | return 0; | 688 | return 0; |
689 | /* | 689 | /* |
690 | * Set the ptr value to numrecs, that's the last record/key. | 690 | * Set the ptr value to numrecs, that's the last record/key. |
691 | */ | 691 | */ |
692 | cur->bc_ptrs[level] = be16_to_cpu(block->bb_numrecs); | 692 | cur->bc_ptrs[level] = be16_to_cpu(block->bb_numrecs); |
693 | return 1; | 693 | return 1; |
694 | } | 694 | } |
695 | 695 | ||
696 | /* | 696 | /* |
697 | * Compute first and last byte offsets for the fields given. | 697 | * Compute first and last byte offsets for the fields given. |
698 | * Interprets the offsets table, which contains struct field offsets. | 698 | * Interprets the offsets table, which contains struct field offsets. |
699 | */ | 699 | */ |
700 | void | 700 | void |
701 | xfs_btree_offsets( | 701 | xfs_btree_offsets( |
702 | __int64_t fields, /* bitmask of fields */ | 702 | __int64_t fields, /* bitmask of fields */ |
703 | const short *offsets, /* table of field offsets */ | 703 | const short *offsets, /* table of field offsets */ |
704 | int nbits, /* number of bits to inspect */ | 704 | int nbits, /* number of bits to inspect */ |
705 | int *first, /* output: first byte offset */ | 705 | int *first, /* output: first byte offset */ |
706 | int *last) /* output: last byte offset */ | 706 | int *last) /* output: last byte offset */ |
707 | { | 707 | { |
708 | int i; /* current bit number */ | 708 | int i; /* current bit number */ |
709 | __int64_t imask; /* mask for current bit number */ | 709 | __int64_t imask; /* mask for current bit number */ |
710 | 710 | ||
711 | ASSERT(fields != 0); | 711 | ASSERT(fields != 0); |
712 | /* | 712 | /* |
713 | * Find the lowest bit, so the first byte offset. | 713 | * Find the lowest bit, so the first byte offset. |
714 | */ | 714 | */ |
715 | for (i = 0, imask = 1LL; ; i++, imask <<= 1) { | 715 | for (i = 0, imask = 1LL; ; i++, imask <<= 1) { |
716 | if (imask & fields) { | 716 | if (imask & fields) { |
717 | *first = offsets[i]; | 717 | *first = offsets[i]; |
718 | break; | 718 | break; |
719 | } | 719 | } |
720 | } | 720 | } |
721 | /* | 721 | /* |
722 | * Find the highest bit, so the last byte offset. | 722 | * Find the highest bit, so the last byte offset. |
723 | */ | 723 | */ |
724 | for (i = nbits - 1, imask = 1LL << i; ; i--, imask >>= 1) { | 724 | for (i = nbits - 1, imask = 1LL << i; ; i--, imask >>= 1) { |
725 | if (imask & fields) { | 725 | if (imask & fields) { |
726 | *last = offsets[i + 1] - 1; | 726 | *last = offsets[i + 1] - 1; |
727 | break; | 727 | break; |
728 | } | 728 | } |
729 | } | 729 | } |
730 | } | 730 | } |
731 | 731 | ||
732 | /* | 732 | /* |
733 | * Get a buffer for the block, return it read in. | 733 | * Get a buffer for the block, return it read in. |
734 | * Long-form addressing. | 734 | * Long-form addressing. |
735 | */ | 735 | */ |
736 | int /* error */ | 736 | int /* error */ |
737 | xfs_btree_read_bufl( | 737 | xfs_btree_read_bufl( |
738 | xfs_mount_t *mp, /* file system mount point */ | 738 | xfs_mount_t *mp, /* file system mount point */ |
739 | xfs_trans_t *tp, /* transaction pointer */ | 739 | xfs_trans_t *tp, /* transaction pointer */ |
740 | xfs_fsblock_t fsbno, /* file system block number */ | 740 | xfs_fsblock_t fsbno, /* file system block number */ |
741 | uint lock, /* lock flags for read_buf */ | 741 | uint lock, /* lock flags for read_buf */ |
742 | xfs_buf_t **bpp, /* buffer for fsbno */ | 742 | xfs_buf_t **bpp, /* buffer for fsbno */ |
743 | int refval) /* ref count value for buffer */ | 743 | int refval) /* ref count value for buffer */ |
744 | { | 744 | { |
745 | xfs_buf_t *bp; /* return value */ | 745 | xfs_buf_t *bp; /* return value */ |
746 | xfs_daddr_t d; /* real disk block address */ | 746 | xfs_daddr_t d; /* real disk block address */ |
747 | int error; | 747 | int error; |
748 | 748 | ||
749 | ASSERT(fsbno != NULLFSBLOCK); | 749 | ASSERT(fsbno != NULLFSBLOCK); |
750 | d = XFS_FSB_TO_DADDR(mp, fsbno); | 750 | d = XFS_FSB_TO_DADDR(mp, fsbno); |
751 | if ((error = xfs_trans_read_buf(mp, tp, mp->m_ddev_targp, d, | 751 | if ((error = xfs_trans_read_buf(mp, tp, mp->m_ddev_targp, d, |
752 | mp->m_bsize, lock, &bp))) { | 752 | mp->m_bsize, lock, &bp))) { |
753 | return error; | 753 | return error; |
754 | } | 754 | } |
755 | ASSERT(!bp || !XFS_BUF_GETERROR(bp)); | 755 | ASSERT(!bp || !XFS_BUF_GETERROR(bp)); |
756 | if (bp != NULL) { | 756 | if (bp != NULL) { |
757 | XFS_BUF_SET_VTYPE_REF(bp, B_FS_MAP, refval); | 757 | XFS_BUF_SET_VTYPE_REF(bp, B_FS_MAP, refval); |
758 | } | 758 | } |
759 | *bpp = bp; | 759 | *bpp = bp; |
760 | return 0; | 760 | return 0; |
761 | } | 761 | } |
762 | 762 | ||
763 | /* | 763 | /* |
764 | * Get a buffer for the block, return it read in. | 764 | * Get a buffer for the block, return it read in. |
765 | * Short-form addressing. | 765 | * Short-form addressing. |
766 | */ | 766 | */ |
767 | int /* error */ | 767 | int /* error */ |
768 | xfs_btree_read_bufs( | 768 | xfs_btree_read_bufs( |
769 | xfs_mount_t *mp, /* file system mount point */ | 769 | xfs_mount_t *mp, /* file system mount point */ |
770 | xfs_trans_t *tp, /* transaction pointer */ | 770 | xfs_trans_t *tp, /* transaction pointer */ |
771 | xfs_agnumber_t agno, /* allocation group number */ | 771 | xfs_agnumber_t agno, /* allocation group number */ |
772 | xfs_agblock_t agbno, /* allocation group block number */ | 772 | xfs_agblock_t agbno, /* allocation group block number */ |
773 | uint lock, /* lock flags for read_buf */ | 773 | uint lock, /* lock flags for read_buf */ |
774 | xfs_buf_t **bpp, /* buffer for agno/agbno */ | 774 | xfs_buf_t **bpp, /* buffer for agno/agbno */ |
775 | int refval) /* ref count value for buffer */ | 775 | int refval) /* ref count value for buffer */ |
776 | { | 776 | { |
777 | xfs_buf_t *bp; /* return value */ | 777 | xfs_buf_t *bp; /* return value */ |
778 | xfs_daddr_t d; /* real disk block address */ | 778 | xfs_daddr_t d; /* real disk block address */ |
779 | int error; | 779 | int error; |
780 | 780 | ||
781 | ASSERT(agno != NULLAGNUMBER); | 781 | ASSERT(agno != NULLAGNUMBER); |
782 | ASSERT(agbno != NULLAGBLOCK); | 782 | ASSERT(agbno != NULLAGBLOCK); |
783 | d = XFS_AGB_TO_DADDR(mp, agno, agbno); | 783 | d = XFS_AGB_TO_DADDR(mp, agno, agbno); |
784 | if ((error = xfs_trans_read_buf(mp, tp, mp->m_ddev_targp, d, | 784 | if ((error = xfs_trans_read_buf(mp, tp, mp->m_ddev_targp, d, |
785 | mp->m_bsize, lock, &bp))) { | 785 | mp->m_bsize, lock, &bp))) { |
786 | return error; | 786 | return error; |
787 | } | 787 | } |
788 | ASSERT(!bp || !XFS_BUF_GETERROR(bp)); | 788 | ASSERT(!bp || !XFS_BUF_GETERROR(bp)); |
789 | if (bp != NULL) { | 789 | if (bp != NULL) { |
790 | switch (refval) { | 790 | switch (refval) { |
791 | case XFS_ALLOC_BTREE_REF: | 791 | case XFS_ALLOC_BTREE_REF: |
792 | XFS_BUF_SET_VTYPE_REF(bp, B_FS_MAP, refval); | 792 | XFS_BUF_SET_VTYPE_REF(bp, B_FS_MAP, refval); |
793 | break; | 793 | break; |
794 | case XFS_INO_BTREE_REF: | 794 | case XFS_INO_BTREE_REF: |
795 | XFS_BUF_SET_VTYPE_REF(bp, B_FS_INOMAP, refval); | 795 | XFS_BUF_SET_VTYPE_REF(bp, B_FS_INOMAP, refval); |
796 | break; | 796 | break; |
797 | } | 797 | } |
798 | } | 798 | } |
799 | *bpp = bp; | 799 | *bpp = bp; |
800 | return 0; | 800 | return 0; |
801 | } | 801 | } |
802 | 802 | ||
803 | /* | 803 | /* |
804 | * Read-ahead the block, don't wait for it, don't return a buffer. | 804 | * Read-ahead the block, don't wait for it, don't return a buffer. |
805 | * Long-form addressing. | 805 | * Long-form addressing. |
806 | */ | 806 | */ |
807 | /* ARGSUSED */ | 807 | /* ARGSUSED */ |
808 | void | 808 | void |
809 | xfs_btree_reada_bufl( | 809 | xfs_btree_reada_bufl( |
810 | xfs_mount_t *mp, /* file system mount point */ | 810 | xfs_mount_t *mp, /* file system mount point */ |
811 | xfs_fsblock_t fsbno, /* file system block number */ | 811 | xfs_fsblock_t fsbno, /* file system block number */ |
812 | xfs_extlen_t count) /* count of filesystem blocks */ | 812 | xfs_extlen_t count) /* count of filesystem blocks */ |
813 | { | 813 | { |
814 | xfs_daddr_t d; | 814 | xfs_daddr_t d; |
815 | 815 | ||
816 | ASSERT(fsbno != NULLFSBLOCK); | 816 | ASSERT(fsbno != NULLFSBLOCK); |
817 | d = XFS_FSB_TO_DADDR(mp, fsbno); | 817 | d = XFS_FSB_TO_DADDR(mp, fsbno); |
818 | xfs_baread(mp->m_ddev_targp, d, mp->m_bsize * count); | 818 | xfs_baread(mp->m_ddev_targp, d, mp->m_bsize * count); |
819 | } | 819 | } |
820 | 820 | ||
821 | /* | 821 | /* |
822 | * Read-ahead the block, don't wait for it, don't return a buffer. | 822 | * Read-ahead the block, don't wait for it, don't return a buffer. |
823 | * Short-form addressing. | 823 | * Short-form addressing. |
824 | */ | 824 | */ |
825 | /* ARGSUSED */ | 825 | /* ARGSUSED */ |
826 | void | 826 | void |
827 | xfs_btree_reada_bufs( | 827 | xfs_btree_reada_bufs( |
828 | xfs_mount_t *mp, /* file system mount point */ | 828 | xfs_mount_t *mp, /* file system mount point */ |
829 | xfs_agnumber_t agno, /* allocation group number */ | 829 | xfs_agnumber_t agno, /* allocation group number */ |
830 | xfs_agblock_t agbno, /* allocation group block number */ | 830 | xfs_agblock_t agbno, /* allocation group block number */ |
831 | xfs_extlen_t count) /* count of filesystem blocks */ | 831 | xfs_extlen_t count) /* count of filesystem blocks */ |
832 | { | 832 | { |
833 | xfs_daddr_t d; | 833 | xfs_daddr_t d; |
834 | 834 | ||
835 | ASSERT(agno != NULLAGNUMBER); | 835 | ASSERT(agno != NULLAGNUMBER); |
836 | ASSERT(agbno != NULLAGBLOCK); | 836 | ASSERT(agbno != NULLAGBLOCK); |
837 | d = XFS_AGB_TO_DADDR(mp, agno, agbno); | 837 | d = XFS_AGB_TO_DADDR(mp, agno, agbno); |
838 | xfs_baread(mp->m_ddev_targp, d, mp->m_bsize * count); | 838 | xfs_baread(mp->m_ddev_targp, d, mp->m_bsize * count); |
839 | } | 839 | } |
840 | 840 | ||
841 | STATIC int | 841 | STATIC int |
842 | xfs_btree_readahead_lblock( | 842 | xfs_btree_readahead_lblock( |
843 | struct xfs_btree_cur *cur, | 843 | struct xfs_btree_cur *cur, |
844 | int lr, | 844 | int lr, |
845 | struct xfs_btree_block *block) | 845 | struct xfs_btree_block *block) |
846 | { | 846 | { |
847 | int rval = 0; | 847 | int rval = 0; |
848 | xfs_fsblock_t left = be64_to_cpu(block->bb_u.l.bb_leftsib); | 848 | xfs_fsblock_t left = be64_to_cpu(block->bb_u.l.bb_leftsib); |
849 | xfs_fsblock_t right = be64_to_cpu(block->bb_u.l.bb_rightsib); | 849 | xfs_fsblock_t right = be64_to_cpu(block->bb_u.l.bb_rightsib); |
850 | 850 | ||
851 | if ((lr & XFS_BTCUR_LEFTRA) && left != NULLDFSBNO) { | 851 | if ((lr & XFS_BTCUR_LEFTRA) && left != NULLDFSBNO) { |
852 | xfs_btree_reada_bufl(cur->bc_mp, left, 1); | 852 | xfs_btree_reada_bufl(cur->bc_mp, left, 1); |
853 | rval++; | 853 | rval++; |
854 | } | 854 | } |
855 | 855 | ||
856 | if ((lr & XFS_BTCUR_RIGHTRA) && right != NULLDFSBNO) { | 856 | if ((lr & XFS_BTCUR_RIGHTRA) && right != NULLDFSBNO) { |
857 | xfs_btree_reada_bufl(cur->bc_mp, right, 1); | 857 | xfs_btree_reada_bufl(cur->bc_mp, right, 1); |
858 | rval++; | 858 | rval++; |
859 | } | 859 | } |
860 | 860 | ||
861 | return rval; | 861 | return rval; |
862 | } | 862 | } |
863 | 863 | ||
864 | STATIC int | 864 | STATIC int |
865 | xfs_btree_readahead_sblock( | 865 | xfs_btree_readahead_sblock( |
866 | struct xfs_btree_cur *cur, | 866 | struct xfs_btree_cur *cur, |
867 | int lr, | 867 | int lr, |
868 | struct xfs_btree_block *block) | 868 | struct xfs_btree_block *block) |
869 | { | 869 | { |
870 | int rval = 0; | 870 | int rval = 0; |
871 | xfs_agblock_t left = be32_to_cpu(block->bb_u.s.bb_leftsib); | 871 | xfs_agblock_t left = be32_to_cpu(block->bb_u.s.bb_leftsib); |
872 | xfs_agblock_t right = be32_to_cpu(block->bb_u.s.bb_rightsib); | 872 | xfs_agblock_t right = be32_to_cpu(block->bb_u.s.bb_rightsib); |
873 | 873 | ||
874 | 874 | ||
875 | if ((lr & XFS_BTCUR_LEFTRA) && left != NULLAGBLOCK) { | 875 | if ((lr & XFS_BTCUR_LEFTRA) && left != NULLAGBLOCK) { |
876 | xfs_btree_reada_bufs(cur->bc_mp, cur->bc_private.a.agno, | 876 | xfs_btree_reada_bufs(cur->bc_mp, cur->bc_private.a.agno, |
877 | left, 1); | 877 | left, 1); |
878 | rval++; | 878 | rval++; |
879 | } | 879 | } |
880 | 880 | ||
881 | if ((lr & XFS_BTCUR_RIGHTRA) && right != NULLAGBLOCK) { | 881 | if ((lr & XFS_BTCUR_RIGHTRA) && right != NULLAGBLOCK) { |
882 | xfs_btree_reada_bufs(cur->bc_mp, cur->bc_private.a.agno, | 882 | xfs_btree_reada_bufs(cur->bc_mp, cur->bc_private.a.agno, |
883 | right, 1); | 883 | right, 1); |
884 | rval++; | 884 | rval++; |
885 | } | 885 | } |
886 | 886 | ||
887 | return rval; | 887 | return rval; |
888 | } | 888 | } |
889 | 889 | ||
890 | /* | 890 | /* |
891 | * Read-ahead btree blocks, at the given level. | 891 | * Read-ahead btree blocks, at the given level. |
892 | * Bits in lr are set from XFS_BTCUR_{LEFT,RIGHT}RA. | 892 | * Bits in lr are set from XFS_BTCUR_{LEFT,RIGHT}RA. |
893 | */ | 893 | */ |
894 | int | 894 | int |
895 | xfs_btree_readahead( | 895 | xfs_btree_readahead( |
896 | struct xfs_btree_cur *cur, /* btree cursor */ | 896 | struct xfs_btree_cur *cur, /* btree cursor */ |
897 | int lev, /* level in btree */ | 897 | int lev, /* level in btree */ |
898 | int lr) /* left/right bits */ | 898 | int lr) /* left/right bits */ |
899 | { | 899 | { |
900 | struct xfs_btree_block *block; | 900 | struct xfs_btree_block *block; |
901 | 901 | ||
902 | /* | 902 | /* |
903 | * No readahead needed if we are at the root level and the | 903 | * No readahead needed if we are at the root level and the |
904 | * btree root is stored in the inode. | 904 | * btree root is stored in the inode. |
905 | */ | 905 | */ |
906 | if ((cur->bc_flags & XFS_BTREE_ROOT_IN_INODE) && | 906 | if ((cur->bc_flags & XFS_BTREE_ROOT_IN_INODE) && |
907 | (lev == cur->bc_nlevels - 1)) | 907 | (lev == cur->bc_nlevels - 1)) |
908 | return 0; | 908 | return 0; |
909 | 909 | ||
910 | if ((cur->bc_ra[lev] | lr) == cur->bc_ra[lev]) | 910 | if ((cur->bc_ra[lev] | lr) == cur->bc_ra[lev]) |
911 | return 0; | 911 | return 0; |
912 | 912 | ||
913 | cur->bc_ra[lev] |= lr; | 913 | cur->bc_ra[lev] |= lr; |
914 | block = XFS_BUF_TO_BLOCK(cur->bc_bufs[lev]); | 914 | block = XFS_BUF_TO_BLOCK(cur->bc_bufs[lev]); |
915 | 915 | ||
916 | if (cur->bc_flags & XFS_BTREE_LONG_PTRS) | 916 | if (cur->bc_flags & XFS_BTREE_LONG_PTRS) |
917 | return xfs_btree_readahead_lblock(cur, lr, block); | 917 | return xfs_btree_readahead_lblock(cur, lr, block); |
918 | return xfs_btree_readahead_sblock(cur, lr, block); | 918 | return xfs_btree_readahead_sblock(cur, lr, block); |
919 | } | 919 | } |
920 | 920 | ||
921 | /* | 921 | /* |
922 | * Set the buffer for level "lev" in the cursor to bp, releasing | 922 | * Set the buffer for level "lev" in the cursor to bp, releasing |
923 | * any previous buffer. | 923 | * any previous buffer. |
924 | */ | 924 | */ |
925 | void | 925 | void |
926 | xfs_btree_setbuf( | 926 | xfs_btree_setbuf( |
927 | xfs_btree_cur_t *cur, /* btree cursor */ | 927 | xfs_btree_cur_t *cur, /* btree cursor */ |
928 | int lev, /* level in btree */ | 928 | int lev, /* level in btree */ |
929 | xfs_buf_t *bp) /* new buffer to set */ | 929 | xfs_buf_t *bp) /* new buffer to set */ |
930 | { | 930 | { |
931 | xfs_btree_block_t *b; /* btree block */ | 931 | xfs_btree_block_t *b; /* btree block */ |
932 | xfs_buf_t *obp; /* old buffer pointer */ | 932 | xfs_buf_t *obp; /* old buffer pointer */ |
933 | 933 | ||
934 | obp = cur->bc_bufs[lev]; | 934 | obp = cur->bc_bufs[lev]; |
935 | if (obp) | 935 | if (obp) |
936 | xfs_trans_brelse(cur->bc_tp, obp); | 936 | xfs_trans_brelse(cur->bc_tp, obp); |
937 | cur->bc_bufs[lev] = bp; | 937 | cur->bc_bufs[lev] = bp; |
938 | cur->bc_ra[lev] = 0; | 938 | cur->bc_ra[lev] = 0; |
939 | if (!bp) | 939 | if (!bp) |
940 | return; | 940 | return; |
941 | b = XFS_BUF_TO_BLOCK(bp); | 941 | b = XFS_BUF_TO_BLOCK(bp); |
942 | if (cur->bc_flags & XFS_BTREE_LONG_PTRS) { | 942 | if (cur->bc_flags & XFS_BTREE_LONG_PTRS) { |
943 | if (be64_to_cpu(b->bb_u.l.bb_leftsib) == NULLDFSBNO) | 943 | if (be64_to_cpu(b->bb_u.l.bb_leftsib) == NULLDFSBNO) |
944 | cur->bc_ra[lev] |= XFS_BTCUR_LEFTRA; | 944 | cur->bc_ra[lev] |= XFS_BTCUR_LEFTRA; |
945 | if (be64_to_cpu(b->bb_u.l.bb_rightsib) == NULLDFSBNO) | 945 | if (be64_to_cpu(b->bb_u.l.bb_rightsib) == NULLDFSBNO) |
946 | cur->bc_ra[lev] |= XFS_BTCUR_RIGHTRA; | 946 | cur->bc_ra[lev] |= XFS_BTCUR_RIGHTRA; |
947 | } else { | 947 | } else { |
948 | if (be32_to_cpu(b->bb_u.s.bb_leftsib) == NULLAGBLOCK) | 948 | if (be32_to_cpu(b->bb_u.s.bb_leftsib) == NULLAGBLOCK) |
949 | cur->bc_ra[lev] |= XFS_BTCUR_LEFTRA; | 949 | cur->bc_ra[lev] |= XFS_BTCUR_LEFTRA; |
950 | if (be32_to_cpu(b->bb_u.s.bb_rightsib) == NULLAGBLOCK) | 950 | if (be32_to_cpu(b->bb_u.s.bb_rightsib) == NULLAGBLOCK) |
951 | cur->bc_ra[lev] |= XFS_BTCUR_RIGHTRA; | 951 | cur->bc_ra[lev] |= XFS_BTCUR_RIGHTRA; |
952 | } | 952 | } |
953 | } | 953 | } |
954 | 954 | ||
955 | STATIC int | 955 | STATIC int |
956 | xfs_btree_ptr_is_null( | 956 | xfs_btree_ptr_is_null( |
957 | struct xfs_btree_cur *cur, | 957 | struct xfs_btree_cur *cur, |
958 | union xfs_btree_ptr *ptr) | 958 | union xfs_btree_ptr *ptr) |
959 | { | 959 | { |
960 | if (cur->bc_flags & XFS_BTREE_LONG_PTRS) | 960 | if (cur->bc_flags & XFS_BTREE_LONG_PTRS) |
961 | return be64_to_cpu(ptr->l) == NULLFSBLOCK; | 961 | return be64_to_cpu(ptr->l) == NULLFSBLOCK; |
962 | else | 962 | else |
963 | return be32_to_cpu(ptr->s) == NULLAGBLOCK; | 963 | return be32_to_cpu(ptr->s) == NULLAGBLOCK; |
964 | } | 964 | } |
965 | 965 | ||
966 | /* | 966 | /* |
967 | * Get/set/init sibling pointers | 967 | * Get/set/init sibling pointers |
968 | */ | 968 | */ |
969 | STATIC void | 969 | STATIC void |
970 | xfs_btree_get_sibling( | 970 | xfs_btree_get_sibling( |
971 | struct xfs_btree_cur *cur, | 971 | struct xfs_btree_cur *cur, |
972 | struct xfs_btree_block *block, | 972 | struct xfs_btree_block *block, |
973 | union xfs_btree_ptr *ptr, | 973 | union xfs_btree_ptr *ptr, |
974 | int lr) | 974 | int lr) |
975 | { | 975 | { |
976 | ASSERT(lr == XFS_BB_LEFTSIB || lr == XFS_BB_RIGHTSIB); | 976 | ASSERT(lr == XFS_BB_LEFTSIB || lr == XFS_BB_RIGHTSIB); |
977 | 977 | ||
978 | if (cur->bc_flags & XFS_BTREE_LONG_PTRS) { | 978 | if (cur->bc_flags & XFS_BTREE_LONG_PTRS) { |
979 | if (lr == XFS_BB_RIGHTSIB) | 979 | if (lr == XFS_BB_RIGHTSIB) |
980 | ptr->l = block->bb_u.l.bb_rightsib; | 980 | ptr->l = block->bb_u.l.bb_rightsib; |
981 | else | 981 | else |
982 | ptr->l = block->bb_u.l.bb_leftsib; | 982 | ptr->l = block->bb_u.l.bb_leftsib; |
983 | } else { | 983 | } else { |
984 | if (lr == XFS_BB_RIGHTSIB) | 984 | if (lr == XFS_BB_RIGHTSIB) |
985 | ptr->s = block->bb_u.s.bb_rightsib; | 985 | ptr->s = block->bb_u.s.bb_rightsib; |
986 | else | 986 | else |
987 | ptr->s = block->bb_u.s.bb_leftsib; | 987 | ptr->s = block->bb_u.s.bb_leftsib; |
988 | } | 988 | } |
989 | } | 989 | } |
990 | 990 | ||
991 | /* | 991 | /* |
992 | * Return true if ptr is the last record in the btree and | 992 | * Return true if ptr is the last record in the btree and |
993 | * we need to track updateั to this record. The decision | 993 | * we need to track updateั to this record. The decision |
994 | * will be further refined in the update_lastrec method. | 994 | * will be further refined in the update_lastrec method. |
995 | */ | 995 | */ |
996 | STATIC int | 996 | STATIC int |
997 | xfs_btree_is_lastrec( | 997 | xfs_btree_is_lastrec( |
998 | struct xfs_btree_cur *cur, | 998 | struct xfs_btree_cur *cur, |
999 | struct xfs_btree_block *block, | 999 | struct xfs_btree_block *block, |
1000 | int level) | 1000 | int level) |
1001 | { | 1001 | { |
1002 | union xfs_btree_ptr ptr; | 1002 | union xfs_btree_ptr ptr; |
1003 | 1003 | ||
1004 | if (level > 0) | 1004 | if (level > 0) |
1005 | return 0; | 1005 | return 0; |
1006 | if (!(cur->bc_flags & XFS_BTREE_LASTREC_UPDATE)) | 1006 | if (!(cur->bc_flags & XFS_BTREE_LASTREC_UPDATE)) |
1007 | return 0; | 1007 | return 0; |
1008 | 1008 | ||
1009 | xfs_btree_get_sibling(cur, block, &ptr, XFS_BB_RIGHTSIB); | 1009 | xfs_btree_get_sibling(cur, block, &ptr, XFS_BB_RIGHTSIB); |
1010 | if (!xfs_btree_ptr_is_null(cur, &ptr)) | 1010 | if (!xfs_btree_ptr_is_null(cur, &ptr)) |
1011 | return 0; | 1011 | return 0; |
1012 | return 1; | 1012 | return 1; |
1013 | } | 1013 | } |
1014 | 1014 | ||
1015 | STATIC xfs_daddr_t | 1015 | STATIC xfs_daddr_t |
1016 | xfs_btree_ptr_to_daddr( | 1016 | xfs_btree_ptr_to_daddr( |
1017 | struct xfs_btree_cur *cur, | 1017 | struct xfs_btree_cur *cur, |
1018 | union xfs_btree_ptr *ptr) | 1018 | union xfs_btree_ptr *ptr) |
1019 | { | 1019 | { |
1020 | if (cur->bc_flags & XFS_BTREE_LONG_PTRS) { | 1020 | if (cur->bc_flags & XFS_BTREE_LONG_PTRS) { |
1021 | ASSERT(be64_to_cpu(ptr->l) != NULLFSBLOCK); | 1021 | ASSERT(be64_to_cpu(ptr->l) != NULLFSBLOCK); |
1022 | 1022 | ||
1023 | return XFS_FSB_TO_DADDR(cur->bc_mp, be64_to_cpu(ptr->l)); | 1023 | return XFS_FSB_TO_DADDR(cur->bc_mp, be64_to_cpu(ptr->l)); |
1024 | } else { | 1024 | } else { |
1025 | ASSERT(cur->bc_private.a.agno != NULLAGNUMBER); | 1025 | ASSERT(cur->bc_private.a.agno != NULLAGNUMBER); |
1026 | ASSERT(be32_to_cpu(ptr->s) != NULLAGBLOCK); | 1026 | ASSERT(be32_to_cpu(ptr->s) != NULLAGBLOCK); |
1027 | 1027 | ||
1028 | return XFS_AGB_TO_DADDR(cur->bc_mp, cur->bc_private.a.agno, | 1028 | return XFS_AGB_TO_DADDR(cur->bc_mp, cur->bc_private.a.agno, |
1029 | be32_to_cpu(ptr->s)); | 1029 | be32_to_cpu(ptr->s)); |
1030 | } | 1030 | } |
1031 | } | 1031 | } |
1032 | 1032 | ||
1033 | STATIC void | 1033 | STATIC void |
1034 | xfs_btree_set_refs( | 1034 | xfs_btree_set_refs( |
1035 | struct xfs_btree_cur *cur, | 1035 | struct xfs_btree_cur *cur, |
1036 | struct xfs_buf *bp) | 1036 | struct xfs_buf *bp) |
1037 | { | 1037 | { |
1038 | switch (cur->bc_btnum) { | 1038 | switch (cur->bc_btnum) { |
1039 | case XFS_BTNUM_BNO: | 1039 | case XFS_BTNUM_BNO: |
1040 | case XFS_BTNUM_CNT: | 1040 | case XFS_BTNUM_CNT: |
1041 | XFS_BUF_SET_VTYPE_REF(*bpp, B_FS_MAP, XFS_ALLOC_BTREE_REF); | 1041 | XFS_BUF_SET_VTYPE_REF(*bpp, B_FS_MAP, XFS_ALLOC_BTREE_REF); |
1042 | break; | 1042 | break; |
1043 | case XFS_BTNUM_INO: | 1043 | case XFS_BTNUM_INO: |
1044 | XFS_BUF_SET_VTYPE_REF(*bpp, B_FS_INOMAP, XFS_INO_BTREE_REF); | 1044 | XFS_BUF_SET_VTYPE_REF(*bpp, B_FS_INOMAP, XFS_INO_BTREE_REF); |
1045 | break; | 1045 | break; |
1046 | case XFS_BTNUM_BMAP: | 1046 | case XFS_BTNUM_BMAP: |
1047 | XFS_BUF_SET_VTYPE_REF(*bpp, B_FS_MAP, XFS_BMAP_BTREE_REF); | 1047 | XFS_BUF_SET_VTYPE_REF(*bpp, B_FS_MAP, XFS_BMAP_BTREE_REF); |
1048 | break; | 1048 | break; |
1049 | default: | 1049 | default: |
1050 | ASSERT(0); | 1050 | ASSERT(0); |
1051 | } | 1051 | } |
1052 | } | 1052 | } |
1053 | 1053 | ||
1054 | /* | 1054 | /* |
1055 | * Read in the buffer at the given ptr and return the buffer and | 1055 | * Read in the buffer at the given ptr and return the buffer and |
1056 | * the block pointer within the buffer. | 1056 | * the block pointer within the buffer. |
1057 | */ | 1057 | */ |
1058 | STATIC int | 1058 | STATIC int |
1059 | xfs_btree_read_buf_block( | 1059 | xfs_btree_read_buf_block( |
1060 | struct xfs_btree_cur *cur, | 1060 | struct xfs_btree_cur *cur, |
1061 | union xfs_btree_ptr *ptr, | 1061 | union xfs_btree_ptr *ptr, |
1062 | int level, | 1062 | int level, |
1063 | int flags, | 1063 | int flags, |
1064 | struct xfs_btree_block **block, | 1064 | struct xfs_btree_block **block, |
1065 | struct xfs_buf **bpp) | 1065 | struct xfs_buf **bpp) |
1066 | { | 1066 | { |
1067 | struct xfs_mount *mp = cur->bc_mp; | 1067 | struct xfs_mount *mp = cur->bc_mp; |
1068 | xfs_daddr_t d; | 1068 | xfs_daddr_t d; |
1069 | int error; | 1069 | int error; |
1070 | 1070 | ||
1071 | /* need to sort out how callers deal with failures first */ | 1071 | /* need to sort out how callers deal with failures first */ |
1072 | ASSERT(!(flags & XFS_BUF_TRYLOCK)); | 1072 | ASSERT(!(flags & XFS_BUF_TRYLOCK)); |
1073 | 1073 | ||
1074 | d = xfs_btree_ptr_to_daddr(cur, ptr); | 1074 | d = xfs_btree_ptr_to_daddr(cur, ptr); |
1075 | error = xfs_trans_read_buf(mp, cur->bc_tp, mp->m_ddev_targp, d, | 1075 | error = xfs_trans_read_buf(mp, cur->bc_tp, mp->m_ddev_targp, d, |
1076 | mp->m_bsize, flags, bpp); | 1076 | mp->m_bsize, flags, bpp); |
1077 | if (error) | 1077 | if (error) |
1078 | return error; | 1078 | return error; |
1079 | 1079 | ||
1080 | ASSERT(*bpp != NULL); | 1080 | ASSERT(*bpp != NULL); |
1081 | ASSERT(!XFS_BUF_GETERROR(*bpp)); | 1081 | ASSERT(!XFS_BUF_GETERROR(*bpp)); |
1082 | 1082 | ||
1083 | xfs_btree_set_refs(cur, *bpp); | 1083 | xfs_btree_set_refs(cur, *bpp); |
1084 | *block = XFS_BUF_TO_BLOCK(*bpp); | 1084 | *block = XFS_BUF_TO_BLOCK(*bpp); |
1085 | 1085 | ||
1086 | error = xfs_btree_check_block(cur, *block, level, *bpp); | 1086 | error = xfs_btree_check_block(cur, *block, level, *bpp); |
1087 | if (error) | 1087 | if (error) |
1088 | xfs_trans_brelse(cur->bc_tp, *bpp); | 1088 | xfs_trans_brelse(cur->bc_tp, *bpp); |
1089 | return error; | 1089 | return error; |
1090 | } | 1090 | } |
1091 | 1091 | ||
1092 | /* | 1092 | /* |
1093 | * Copy keys from one btree block to another. | 1093 | * Copy keys from one btree block to another. |
1094 | */ | 1094 | */ |
1095 | STATIC void | 1095 | STATIC void |
1096 | xfs_btree_copy_keys( | 1096 | xfs_btree_copy_keys( |
1097 | struct xfs_btree_cur *cur, | 1097 | struct xfs_btree_cur *cur, |
1098 | union xfs_btree_key *dst_key, | 1098 | union xfs_btree_key *dst_key, |
1099 | union xfs_btree_key *src_key, | 1099 | union xfs_btree_key *src_key, |
1100 | int numkeys) | 1100 | int numkeys) |
1101 | { | 1101 | { |
1102 | ASSERT(numkeys >= 0); | 1102 | ASSERT(numkeys >= 0); |
1103 | memcpy(dst_key, src_key, numkeys * cur->bc_ops->key_len); | 1103 | memcpy(dst_key, src_key, numkeys * cur->bc_ops->key_len); |
1104 | } | 1104 | } |
1105 | 1105 | ||
1106 | /* | 1106 | /* |
1107 | * Copy records from one btree block to another. | 1107 | * Copy records from one btree block to another. |
1108 | */ | 1108 | */ |
1109 | STATIC void | 1109 | STATIC void |
1110 | xfs_btree_copy_recs( | 1110 | xfs_btree_copy_recs( |
1111 | struct xfs_btree_cur *cur, | 1111 | struct xfs_btree_cur *cur, |
1112 | union xfs_btree_rec *dst_rec, | 1112 | union xfs_btree_rec *dst_rec, |
1113 | union xfs_btree_rec *src_rec, | 1113 | union xfs_btree_rec *src_rec, |
1114 | int numrecs) | 1114 | int numrecs) |
1115 | { | 1115 | { |
1116 | ASSERT(numrecs >= 0); | 1116 | ASSERT(numrecs >= 0); |
1117 | memcpy(dst_rec, src_rec, numrecs * cur->bc_ops->rec_len); | 1117 | memcpy(dst_rec, src_rec, numrecs * cur->bc_ops->rec_len); |
1118 | } | 1118 | } |
1119 | 1119 | ||
1120 | /* | 1120 | /* |
1121 | * Copy block pointers from one btree block to another. | 1121 | * Copy block pointers from one btree block to another. |
1122 | */ | 1122 | */ |
1123 | STATIC void | 1123 | STATIC void |
1124 | xfs_btree_copy_ptrs( | 1124 | xfs_btree_copy_ptrs( |
1125 | struct xfs_btree_cur *cur, | 1125 | struct xfs_btree_cur *cur, |
1126 | union xfs_btree_ptr *dst_ptr, | 1126 | union xfs_btree_ptr *dst_ptr, |
1127 | union xfs_btree_ptr *src_ptr, | 1127 | union xfs_btree_ptr *src_ptr, |
1128 | int numptrs) | 1128 | int numptrs) |
1129 | { | 1129 | { |
1130 | ASSERT(numptrs >= 0); | 1130 | ASSERT(numptrs >= 0); |
1131 | memcpy(dst_ptr, src_ptr, numptrs * xfs_btree_ptr_len(cur)); | 1131 | memcpy(dst_ptr, src_ptr, numptrs * xfs_btree_ptr_len(cur)); |
1132 | } | 1132 | } |
1133 | 1133 | ||
1134 | /* | 1134 | /* |
1135 | * Shift keys one index left/right inside a single btree block. | 1135 | * Shift keys one index left/right inside a single btree block. |
1136 | */ | 1136 | */ |
1137 | STATIC void | 1137 | STATIC void |
1138 | xfs_btree_shift_keys( | 1138 | xfs_btree_shift_keys( |
1139 | struct xfs_btree_cur *cur, | 1139 | struct xfs_btree_cur *cur, |
1140 | union xfs_btree_key *key, | 1140 | union xfs_btree_key *key, |
1141 | int dir, | 1141 | int dir, |
1142 | int numkeys) | 1142 | int numkeys) |
1143 | { | 1143 | { |
1144 | char *dst_key; | 1144 | char *dst_key; |
1145 | 1145 | ||
1146 | ASSERT(numkeys >= 0); | 1146 | ASSERT(numkeys >= 0); |
1147 | ASSERT(dir == 1 || dir == -1); | 1147 | ASSERT(dir == 1 || dir == -1); |
1148 | 1148 | ||
1149 | dst_key = (char *)key + (dir * cur->bc_ops->key_len); | 1149 | dst_key = (char *)key + (dir * cur->bc_ops->key_len); |
1150 | memmove(dst_key, key, numkeys * cur->bc_ops->key_len); | 1150 | memmove(dst_key, key, numkeys * cur->bc_ops->key_len); |
1151 | } | 1151 | } |
1152 | 1152 | ||
1153 | /* | 1153 | /* |
1154 | * Shift records one index left/right inside a single btree block. | 1154 | * Shift records one index left/right inside a single btree block. |
1155 | */ | 1155 | */ |
1156 | STATIC void | 1156 | STATIC void |
1157 | xfs_btree_shift_recs( | 1157 | xfs_btree_shift_recs( |
1158 | struct xfs_btree_cur *cur, | 1158 | struct xfs_btree_cur *cur, |
1159 | union xfs_btree_rec *rec, | 1159 | union xfs_btree_rec *rec, |
1160 | int dir, | 1160 | int dir, |
1161 | int numrecs) | 1161 | int numrecs) |
1162 | { | 1162 | { |
1163 | char *dst_rec; | 1163 | char *dst_rec; |
1164 | 1164 | ||
1165 | ASSERT(numrecs >= 0); | 1165 | ASSERT(numrecs >= 0); |
1166 | ASSERT(dir == 1 || dir == -1); | 1166 | ASSERT(dir == 1 || dir == -1); |
1167 | 1167 | ||
1168 | dst_rec = (char *)rec + (dir * cur->bc_ops->rec_len); | 1168 | dst_rec = (char *)rec + (dir * cur->bc_ops->rec_len); |
1169 | memmove(dst_rec, rec, numrecs * cur->bc_ops->rec_len); | 1169 | memmove(dst_rec, rec, numrecs * cur->bc_ops->rec_len); |
1170 | } | 1170 | } |
1171 | 1171 | ||
1172 | /* | 1172 | /* |
1173 | * Shift block pointers one index left/right inside a single btree block. | 1173 | * Shift block pointers one index left/right inside a single btree block. |
1174 | */ | 1174 | */ |
1175 | STATIC void | 1175 | STATIC void |
1176 | xfs_btree_shift_ptrs( | 1176 | xfs_btree_shift_ptrs( |
1177 | struct xfs_btree_cur *cur, | 1177 | struct xfs_btree_cur *cur, |
1178 | union xfs_btree_ptr *ptr, | 1178 | union xfs_btree_ptr *ptr, |
1179 | int dir, | 1179 | int dir, |
1180 | int numptrs) | 1180 | int numptrs) |
1181 | { | 1181 | { |
1182 | char *dst_ptr; | 1182 | char *dst_ptr; |
1183 | 1183 | ||
1184 | ASSERT(numptrs >= 0); | 1184 | ASSERT(numptrs >= 0); |
1185 | ASSERT(dir == 1 || dir == -1); | 1185 | ASSERT(dir == 1 || dir == -1); |
1186 | 1186 | ||
1187 | dst_ptr = (char *)ptr + (dir * xfs_btree_ptr_len(cur)); | 1187 | dst_ptr = (char *)ptr + (dir * xfs_btree_ptr_len(cur)); |
1188 | memmove(dst_ptr, ptr, numptrs * xfs_btree_ptr_len(cur)); | 1188 | memmove(dst_ptr, ptr, numptrs * xfs_btree_ptr_len(cur)); |
1189 | } | 1189 | } |
1190 | 1190 | ||
1191 | /* | 1191 | /* |
1192 | * Log key values from the btree block. | 1192 | * Log key values from the btree block. |
1193 | */ | 1193 | */ |
1194 | STATIC void | 1194 | STATIC void |
1195 | xfs_btree_log_keys( | 1195 | xfs_btree_log_keys( |
1196 | struct xfs_btree_cur *cur, | 1196 | struct xfs_btree_cur *cur, |
1197 | struct xfs_buf *bp, | 1197 | struct xfs_buf *bp, |
1198 | int first, | 1198 | int first, |
1199 | int last) | 1199 | int last) |
1200 | { | 1200 | { |
1201 | XFS_BTREE_TRACE_CURSOR(cur, XBT_ENTRY); | 1201 | XFS_BTREE_TRACE_CURSOR(cur, XBT_ENTRY); |
1202 | XFS_BTREE_TRACE_ARGBII(cur, bp, first, last); | 1202 | XFS_BTREE_TRACE_ARGBII(cur, bp, first, last); |
1203 | 1203 | ||
1204 | if (bp) { | 1204 | if (bp) { |
1205 | xfs_trans_log_buf(cur->bc_tp, bp, | 1205 | xfs_trans_log_buf(cur->bc_tp, bp, |
1206 | xfs_btree_key_offset(cur, first), | 1206 | xfs_btree_key_offset(cur, first), |
1207 | xfs_btree_key_offset(cur, last + 1) - 1); | 1207 | xfs_btree_key_offset(cur, last + 1) - 1); |
1208 | } else { | 1208 | } else { |
1209 | xfs_trans_log_inode(cur->bc_tp, cur->bc_private.b.ip, | 1209 | xfs_trans_log_inode(cur->bc_tp, cur->bc_private.b.ip, |
1210 | xfs_ilog_fbroot(cur->bc_private.b.whichfork)); | 1210 | xfs_ilog_fbroot(cur->bc_private.b.whichfork)); |
1211 | } | 1211 | } |
1212 | 1212 | ||
1213 | XFS_BTREE_TRACE_CURSOR(cur, XBT_EXIT); | 1213 | XFS_BTREE_TRACE_CURSOR(cur, XBT_EXIT); |
1214 | } | 1214 | } |
1215 | 1215 | ||
1216 | /* | 1216 | /* |
1217 | * Log record values from the btree block. | 1217 | * Log record values from the btree block. |
1218 | */ | 1218 | */ |
1219 | STATIC void | 1219 | STATIC void |
1220 | xfs_btree_log_recs( | 1220 | xfs_btree_log_recs( |
1221 | struct xfs_btree_cur *cur, | 1221 | struct xfs_btree_cur *cur, |
1222 | struct xfs_buf *bp, | 1222 | struct xfs_buf *bp, |
1223 | int first, | 1223 | int first, |
1224 | int last) | 1224 | int last) |
1225 | { | 1225 | { |
1226 | XFS_BTREE_TRACE_CURSOR(cur, XBT_ENTRY); | 1226 | XFS_BTREE_TRACE_CURSOR(cur, XBT_ENTRY); |
1227 | XFS_BTREE_TRACE_ARGBII(cur, bp, first, last); | 1227 | XFS_BTREE_TRACE_ARGBII(cur, bp, first, last); |
1228 | 1228 | ||
1229 | xfs_trans_log_buf(cur->bc_tp, bp, | 1229 | xfs_trans_log_buf(cur->bc_tp, bp, |
1230 | xfs_btree_rec_offset(cur, first), | 1230 | xfs_btree_rec_offset(cur, first), |
1231 | xfs_btree_rec_offset(cur, last + 1) - 1); | 1231 | xfs_btree_rec_offset(cur, last + 1) - 1); |
1232 | 1232 | ||
1233 | XFS_BTREE_TRACE_CURSOR(cur, XBT_EXIT); | 1233 | XFS_BTREE_TRACE_CURSOR(cur, XBT_EXIT); |
1234 | } | 1234 | } |
1235 | 1235 | ||
1236 | /* | 1236 | /* |
1237 | * Log block pointer fields from a btree block (nonleaf). | 1237 | * Log block pointer fields from a btree block (nonleaf). |
1238 | */ | 1238 | */ |
1239 | STATIC void | 1239 | STATIC void |
1240 | xfs_btree_log_ptrs( | 1240 | xfs_btree_log_ptrs( |
1241 | struct xfs_btree_cur *cur, /* btree cursor */ | 1241 | struct xfs_btree_cur *cur, /* btree cursor */ |
1242 | struct xfs_buf *bp, /* buffer containing btree block */ | 1242 | struct xfs_buf *bp, /* buffer containing btree block */ |
1243 | int first, /* index of first pointer to log */ | 1243 | int first, /* index of first pointer to log */ |
1244 | int last) /* index of last pointer to log */ | 1244 | int last) /* index of last pointer to log */ |
1245 | { | 1245 | { |
1246 | XFS_BTREE_TRACE_CURSOR(cur, XBT_ENTRY); | 1246 | XFS_BTREE_TRACE_CURSOR(cur, XBT_ENTRY); |
1247 | XFS_BTREE_TRACE_ARGBII(cur, bp, first, last); | 1247 | XFS_BTREE_TRACE_ARGBII(cur, bp, first, last); |
1248 | 1248 | ||
1249 | if (bp) { | 1249 | if (bp) { |
1250 | struct xfs_btree_block *block = XFS_BUF_TO_BLOCK(bp); | 1250 | struct xfs_btree_block *block = XFS_BUF_TO_BLOCK(bp); |
1251 | int level = xfs_btree_get_level(block); | 1251 | int level = xfs_btree_get_level(block); |
1252 | 1252 | ||
1253 | xfs_trans_log_buf(cur->bc_tp, bp, | 1253 | xfs_trans_log_buf(cur->bc_tp, bp, |
1254 | xfs_btree_ptr_offset(cur, first, level), | 1254 | xfs_btree_ptr_offset(cur, first, level), |
1255 | xfs_btree_ptr_offset(cur, last + 1, level) - 1); | 1255 | xfs_btree_ptr_offset(cur, last + 1, level) - 1); |
1256 | } else { | 1256 | } else { |
1257 | xfs_trans_log_inode(cur->bc_tp, cur->bc_private.b.ip, | 1257 | xfs_trans_log_inode(cur->bc_tp, cur->bc_private.b.ip, |
1258 | xfs_ilog_fbroot(cur->bc_private.b.whichfork)); | 1258 | xfs_ilog_fbroot(cur->bc_private.b.whichfork)); |
1259 | } | 1259 | } |
1260 | 1260 | ||
1261 | XFS_BTREE_TRACE_CURSOR(cur, XBT_EXIT); | 1261 | XFS_BTREE_TRACE_CURSOR(cur, XBT_EXIT); |
1262 | } | 1262 | } |
1263 | 1263 | ||
1264 | /* | 1264 | /* |
1265 | * Log fields from a btree block header. | 1265 | * Log fields from a btree block header. |
1266 | */ | 1266 | */ |
1267 | STATIC void | 1267 | STATIC void |
1268 | xfs_btree_log_block( | 1268 | xfs_btree_log_block( |
1269 | struct xfs_btree_cur *cur, /* btree cursor */ | 1269 | struct xfs_btree_cur *cur, /* btree cursor */ |
1270 | struct xfs_buf *bp, /* buffer containing btree block */ | 1270 | struct xfs_buf *bp, /* buffer containing btree block */ |
1271 | int fields) /* mask of fields: XFS_BB_... */ | 1271 | int fields) /* mask of fields: XFS_BB_... */ |
1272 | { | 1272 | { |
1273 | int first; /* first byte offset logged */ | 1273 | int first; /* first byte offset logged */ |
1274 | int last; /* last byte offset logged */ | 1274 | int last; /* last byte offset logged */ |
1275 | static const short soffsets[] = { /* table of offsets (short) */ | 1275 | static const short soffsets[] = { /* table of offsets (short) */ |
1276 | offsetof(struct xfs_btree_sblock, bb_magic), | 1276 | offsetof(struct xfs_btree_sblock, bb_magic), |
1277 | offsetof(struct xfs_btree_sblock, bb_level), | 1277 | offsetof(struct xfs_btree_sblock, bb_level), |
1278 | offsetof(struct xfs_btree_sblock, bb_numrecs), | 1278 | offsetof(struct xfs_btree_sblock, bb_numrecs), |
1279 | offsetof(struct xfs_btree_sblock, bb_leftsib), | 1279 | offsetof(struct xfs_btree_sblock, bb_leftsib), |
1280 | offsetof(struct xfs_btree_sblock, bb_rightsib), | 1280 | offsetof(struct xfs_btree_sblock, bb_rightsib), |
1281 | sizeof(struct xfs_btree_sblock) | 1281 | sizeof(struct xfs_btree_sblock) |
1282 | }; | 1282 | }; |
1283 | static const short loffsets[] = { /* table of offsets (long) */ | 1283 | static const short loffsets[] = { /* table of offsets (long) */ |
1284 | offsetof(struct xfs_btree_lblock, bb_magic), | 1284 | offsetof(struct xfs_btree_lblock, bb_magic), |
1285 | offsetof(struct xfs_btree_lblock, bb_level), | 1285 | offsetof(struct xfs_btree_lblock, bb_level), |
1286 | offsetof(struct xfs_btree_lblock, bb_numrecs), | 1286 | offsetof(struct xfs_btree_lblock, bb_numrecs), |
1287 | offsetof(struct xfs_btree_lblock, bb_leftsib), | 1287 | offsetof(struct xfs_btree_lblock, bb_leftsib), |
1288 | offsetof(struct xfs_btree_lblock, bb_rightsib), | 1288 | offsetof(struct xfs_btree_lblock, bb_rightsib), |
1289 | sizeof(struct xfs_btree_lblock) | 1289 | sizeof(struct xfs_btree_lblock) |
1290 | }; | 1290 | }; |
1291 | 1291 | ||
1292 | XFS_BTREE_TRACE_CURSOR(cur, XBT_ENTRY); | 1292 | XFS_BTREE_TRACE_CURSOR(cur, XBT_ENTRY); |
1293 | XFS_BTREE_TRACE_ARGBI(cur, bp, fields); | 1293 | XFS_BTREE_TRACE_ARGBI(cur, bp, fields); |
1294 | 1294 | ||
1295 | if (bp) { | 1295 | if (bp) { |
1296 | xfs_btree_offsets(fields, | 1296 | xfs_btree_offsets(fields, |
1297 | (cur->bc_flags & XFS_BTREE_LONG_PTRS) ? | 1297 | (cur->bc_flags & XFS_BTREE_LONG_PTRS) ? |
1298 | loffsets : soffsets, | 1298 | loffsets : soffsets, |
1299 | XFS_BB_NUM_BITS, &first, &last); | 1299 | XFS_BB_NUM_BITS, &first, &last); |
1300 | xfs_trans_log_buf(cur->bc_tp, bp, first, last); | 1300 | xfs_trans_log_buf(cur->bc_tp, bp, first, last); |
1301 | } else { | 1301 | } else { |
1302 | xfs_trans_log_inode(cur->bc_tp, cur->bc_private.b.ip, | 1302 | xfs_trans_log_inode(cur->bc_tp, cur->bc_private.b.ip, |
1303 | xfs_ilog_fbroot(cur->bc_private.b.whichfork)); | 1303 | xfs_ilog_fbroot(cur->bc_private.b.whichfork)); |
1304 | } | 1304 | } |
1305 | 1305 | ||
1306 | XFS_BTREE_TRACE_CURSOR(cur, XBT_EXIT); | 1306 | XFS_BTREE_TRACE_CURSOR(cur, XBT_EXIT); |
1307 | } | 1307 | } |
1308 | 1308 | ||
1309 | /* | 1309 | /* |
1310 | * Increment cursor by one record at the level. | 1310 | * Increment cursor by one record at the level. |
1311 | * For nonzero levels the leaf-ward information is untouched. | 1311 | * For nonzero levels the leaf-ward information is untouched. |
1312 | */ | 1312 | */ |
1313 | int /* error */ | 1313 | int /* error */ |
1314 | xfs_btree_increment( | 1314 | xfs_btree_increment( |
1315 | struct xfs_btree_cur *cur, | 1315 | struct xfs_btree_cur *cur, |
1316 | int level, | 1316 | int level, |
1317 | int *stat) /* success/failure */ | 1317 | int *stat) /* success/failure */ |
1318 | { | 1318 | { |
1319 | struct xfs_btree_block *block; | 1319 | struct xfs_btree_block *block; |
1320 | union xfs_btree_ptr ptr; | 1320 | union xfs_btree_ptr ptr; |
1321 | struct xfs_buf *bp; | 1321 | struct xfs_buf *bp; |
1322 | int error; /* error return value */ | 1322 | int error; /* error return value */ |
1323 | int lev; | 1323 | int lev; |
1324 | 1324 | ||
1325 | XFS_BTREE_TRACE_CURSOR(cur, XBT_ENTRY); | 1325 | XFS_BTREE_TRACE_CURSOR(cur, XBT_ENTRY); |
1326 | XFS_BTREE_TRACE_ARGI(cur, level); | 1326 | XFS_BTREE_TRACE_ARGI(cur, level); |
1327 | 1327 | ||
1328 | ASSERT(level < cur->bc_nlevels); | 1328 | ASSERT(level < cur->bc_nlevels); |
1329 | 1329 | ||
1330 | /* Read-ahead to the right at this level. */ | 1330 | /* Read-ahead to the right at this level. */ |
1331 | xfs_btree_readahead(cur, level, XFS_BTCUR_RIGHTRA); | 1331 | xfs_btree_readahead(cur, level, XFS_BTCUR_RIGHTRA); |
1332 | 1332 | ||
1333 | /* Get a pointer to the btree block. */ | 1333 | /* Get a pointer to the btree block. */ |
1334 | block = xfs_btree_get_block(cur, level, &bp); | 1334 | block = xfs_btree_get_block(cur, level, &bp); |
1335 | 1335 | ||
1336 | #ifdef DEBUG | 1336 | #ifdef DEBUG |
1337 | error = xfs_btree_check_block(cur, block, level, bp); | 1337 | error = xfs_btree_check_block(cur, block, level, bp); |
1338 | if (error) | 1338 | if (error) |
1339 | goto error0; | 1339 | goto error0; |
1340 | #endif | 1340 | #endif |
1341 | 1341 | ||
1342 | /* We're done if we remain in the block after the increment. */ | 1342 | /* We're done if we remain in the block after the increment. */ |
1343 | if (++cur->bc_ptrs[level] <= xfs_btree_get_numrecs(block)) | 1343 | if (++cur->bc_ptrs[level] <= xfs_btree_get_numrecs(block)) |
1344 | goto out1; | 1344 | goto out1; |
1345 | 1345 | ||
1346 | /* Fail if we just went off the right edge of the tree. */ | 1346 | /* Fail if we just went off the right edge of the tree. */ |
1347 | xfs_btree_get_sibling(cur, block, &ptr, XFS_BB_RIGHTSIB); | 1347 | xfs_btree_get_sibling(cur, block, &ptr, XFS_BB_RIGHTSIB); |
1348 | if (xfs_btree_ptr_is_null(cur, &ptr)) | 1348 | if (xfs_btree_ptr_is_null(cur, &ptr)) |
1349 | goto out0; | 1349 | goto out0; |
1350 | 1350 | ||
1351 | XFS_BTREE_STATS_INC(cur, increment); | 1351 | XFS_BTREE_STATS_INC(cur, increment); |
1352 | 1352 | ||
1353 | /* | 1353 | /* |
1354 | * March up the tree incrementing pointers. | 1354 | * March up the tree incrementing pointers. |
1355 | * Stop when we don't go off the right edge of a block. | 1355 | * Stop when we don't go off the right edge of a block. |
1356 | */ | 1356 | */ |
1357 | for (lev = level + 1; lev < cur->bc_nlevels; lev++) { | 1357 | for (lev = level + 1; lev < cur->bc_nlevels; lev++) { |
1358 | block = xfs_btree_get_block(cur, lev, &bp); | 1358 | block = xfs_btree_get_block(cur, lev, &bp); |
1359 | 1359 | ||
1360 | #ifdef DEBUG | 1360 | #ifdef DEBUG |
1361 | error = xfs_btree_check_block(cur, block, lev, bp); | 1361 | error = xfs_btree_check_block(cur, block, lev, bp); |
1362 | if (error) | 1362 | if (error) |
1363 | goto error0; | 1363 | goto error0; |
1364 | #endif | 1364 | #endif |
1365 | 1365 | ||
1366 | if (++cur->bc_ptrs[lev] <= xfs_btree_get_numrecs(block)) | 1366 | if (++cur->bc_ptrs[lev] <= xfs_btree_get_numrecs(block)) |
1367 | break; | 1367 | break; |
1368 | 1368 | ||
1369 | /* Read-ahead the right block for the next loop. */ | 1369 | /* Read-ahead the right block for the next loop. */ |
1370 | xfs_btree_readahead(cur, lev, XFS_BTCUR_RIGHTRA); | 1370 | xfs_btree_readahead(cur, lev, XFS_BTCUR_RIGHTRA); |
1371 | } | 1371 | } |
1372 | 1372 | ||
1373 | /* | 1373 | /* |
1374 | * If we went off the root then we are either seriously | 1374 | * If we went off the root then we are either seriously |
1375 | * confused or have the tree root in an inode. | 1375 | * confused or have the tree root in an inode. |
1376 | */ | 1376 | */ |
1377 | if (lev == cur->bc_nlevels) { | 1377 | if (lev == cur->bc_nlevels) { |
1378 | if (cur->bc_flags & XFS_BTREE_ROOT_IN_INODE) | 1378 | if (cur->bc_flags & XFS_BTREE_ROOT_IN_INODE) |
1379 | goto out0; | 1379 | goto out0; |
1380 | ASSERT(0); | 1380 | ASSERT(0); |
1381 | error = EFSCORRUPTED; | 1381 | error = EFSCORRUPTED; |
1382 | goto error0; | 1382 | goto error0; |
1383 | } | 1383 | } |
1384 | ASSERT(lev < cur->bc_nlevels); | 1384 | ASSERT(lev < cur->bc_nlevels); |
1385 | 1385 | ||
1386 | /* | 1386 | /* |
1387 | * Now walk back down the tree, fixing up the cursor's buffer | 1387 | * Now walk back down the tree, fixing up the cursor's buffer |
1388 | * pointers and key numbers. | 1388 | * pointers and key numbers. |
1389 | */ | 1389 | */ |
1390 | for (block = xfs_btree_get_block(cur, lev, &bp); lev > level; ) { | 1390 | for (block = xfs_btree_get_block(cur, lev, &bp); lev > level; ) { |
1391 | union xfs_btree_ptr *ptrp; | 1391 | union xfs_btree_ptr *ptrp; |
1392 | 1392 | ||
1393 | ptrp = xfs_btree_ptr_addr(cur, cur->bc_ptrs[lev], block); | 1393 | ptrp = xfs_btree_ptr_addr(cur, cur->bc_ptrs[lev], block); |
1394 | error = xfs_btree_read_buf_block(cur, ptrp, --lev, | 1394 | error = xfs_btree_read_buf_block(cur, ptrp, --lev, |
1395 | 0, &block, &bp); | 1395 | 0, &block, &bp); |
1396 | if (error) | 1396 | if (error) |
1397 | goto error0; | 1397 | goto error0; |
1398 | 1398 | ||
1399 | xfs_btree_setbuf(cur, lev, bp); | 1399 | xfs_btree_setbuf(cur, lev, bp); |
1400 | cur->bc_ptrs[lev] = 1; | 1400 | cur->bc_ptrs[lev] = 1; |
1401 | } | 1401 | } |
1402 | out1: | 1402 | out1: |
1403 | XFS_BTREE_TRACE_CURSOR(cur, XBT_EXIT); | 1403 | XFS_BTREE_TRACE_CURSOR(cur, XBT_EXIT); |
1404 | *stat = 1; | 1404 | *stat = 1; |
1405 | return 0; | 1405 | return 0; |
1406 | 1406 | ||
1407 | out0: | 1407 | out0: |
1408 | XFS_BTREE_TRACE_CURSOR(cur, XBT_EXIT); | 1408 | XFS_BTREE_TRACE_CURSOR(cur, XBT_EXIT); |
1409 | *stat = 0; | 1409 | *stat = 0; |
1410 | return 0; | 1410 | return 0; |
1411 | 1411 | ||
1412 | error0: | 1412 | error0: |
1413 | XFS_BTREE_TRACE_CURSOR(cur, XBT_ERROR); | 1413 | XFS_BTREE_TRACE_CURSOR(cur, XBT_ERROR); |
1414 | return error; | 1414 | return error; |
1415 | } | 1415 | } |
1416 | 1416 | ||
1417 | /* | 1417 | /* |
1418 | * Decrement cursor by one record at the level. | 1418 | * Decrement cursor by one record at the level. |
1419 | * For nonzero levels the leaf-ward information is untouched. | 1419 | * For nonzero levels the leaf-ward information is untouched. |
1420 | */ | 1420 | */ |
1421 | int /* error */ | 1421 | int /* error */ |
1422 | xfs_btree_decrement( | 1422 | xfs_btree_decrement( |
1423 | struct xfs_btree_cur *cur, | 1423 | struct xfs_btree_cur *cur, |
1424 | int level, | 1424 | int level, |
1425 | int *stat) /* success/failure */ | 1425 | int *stat) /* success/failure */ |
1426 | { | 1426 | { |
1427 | struct xfs_btree_block *block; | 1427 | struct xfs_btree_block *block; |
1428 | xfs_buf_t *bp; | 1428 | xfs_buf_t *bp; |
1429 | int error; /* error return value */ | 1429 | int error; /* error return value */ |
1430 | int lev; | 1430 | int lev; |
1431 | union xfs_btree_ptr ptr; | 1431 | union xfs_btree_ptr ptr; |
1432 | 1432 | ||
1433 | XFS_BTREE_TRACE_CURSOR(cur, XBT_ENTRY); | 1433 | XFS_BTREE_TRACE_CURSOR(cur, XBT_ENTRY); |
1434 | XFS_BTREE_TRACE_ARGI(cur, level); | 1434 | XFS_BTREE_TRACE_ARGI(cur, level); |
1435 | 1435 | ||
1436 | ASSERT(level < cur->bc_nlevels); | 1436 | ASSERT(level < cur->bc_nlevels); |
1437 | 1437 | ||
1438 | /* Read-ahead to the left at this level. */ | 1438 | /* Read-ahead to the left at this level. */ |
1439 | xfs_btree_readahead(cur, level, XFS_BTCUR_LEFTRA); | 1439 | xfs_btree_readahead(cur, level, XFS_BTCUR_LEFTRA); |
1440 | 1440 | ||
1441 | /* We're done if we remain in the block after the decrement. */ | 1441 | /* We're done if we remain in the block after the decrement. */ |
1442 | if (--cur->bc_ptrs[level] > 0) | 1442 | if (--cur->bc_ptrs[level] > 0) |
1443 | goto out1; | 1443 | goto out1; |
1444 | 1444 | ||
1445 | /* Get a pointer to the btree block. */ | 1445 | /* Get a pointer to the btree block. */ |
1446 | block = xfs_btree_get_block(cur, level, &bp); | 1446 | block = xfs_btree_get_block(cur, level, &bp); |
1447 | 1447 | ||
1448 | #ifdef DEBUG | 1448 | #ifdef DEBUG |
1449 | error = xfs_btree_check_block(cur, block, level, bp); | 1449 | error = xfs_btree_check_block(cur, block, level, bp); |
1450 | if (error) | 1450 | if (error) |
1451 | goto error0; | 1451 | goto error0; |
1452 | #endif | 1452 | #endif |
1453 | 1453 | ||
1454 | /* Fail if we just went off the left edge of the tree. */ | 1454 | /* Fail if we just went off the left edge of the tree. */ |
1455 | xfs_btree_get_sibling(cur, block, &ptr, XFS_BB_LEFTSIB); | 1455 | xfs_btree_get_sibling(cur, block, &ptr, XFS_BB_LEFTSIB); |
1456 | if (xfs_btree_ptr_is_null(cur, &ptr)) | 1456 | if (xfs_btree_ptr_is_null(cur, &ptr)) |
1457 | goto out0; | 1457 | goto out0; |
1458 | 1458 | ||
1459 | XFS_BTREE_STATS_INC(cur, decrement); | 1459 | XFS_BTREE_STATS_INC(cur, decrement); |
1460 | 1460 | ||
1461 | /* | 1461 | /* |
1462 | * March up the tree decrementing pointers. | 1462 | * March up the tree decrementing pointers. |
1463 | * Stop when we don't go off the left edge of a block. | 1463 | * Stop when we don't go off the left edge of a block. |
1464 | */ | 1464 | */ |
1465 | for (lev = level + 1; lev < cur->bc_nlevels; lev++) { | 1465 | for (lev = level + 1; lev < cur->bc_nlevels; lev++) { |
1466 | if (--cur->bc_ptrs[lev] > 0) | 1466 | if (--cur->bc_ptrs[lev] > 0) |
1467 | break; | 1467 | break; |
1468 | /* Read-ahead the left block for the next loop. */ | 1468 | /* Read-ahead the left block for the next loop. */ |
1469 | xfs_btree_readahead(cur, lev, XFS_BTCUR_LEFTRA); | 1469 | xfs_btree_readahead(cur, lev, XFS_BTCUR_LEFTRA); |
1470 | } | 1470 | } |
1471 | 1471 | ||
1472 | /* | 1472 | /* |
1473 | * If we went off the root then we are seriously confused. | 1473 | * If we went off the root then we are seriously confused. |
1474 | * or the root of the tree is in an inode. | 1474 | * or the root of the tree is in an inode. |
1475 | */ | 1475 | */ |
1476 | if (lev == cur->bc_nlevels) { | 1476 | if (lev == cur->bc_nlevels) { |
1477 | if (cur->bc_flags & XFS_BTREE_ROOT_IN_INODE) | 1477 | if (cur->bc_flags & XFS_BTREE_ROOT_IN_INODE) |
1478 | goto out0; | 1478 | goto out0; |
1479 | ASSERT(0); | 1479 | ASSERT(0); |
1480 | error = EFSCORRUPTED; | 1480 | error = EFSCORRUPTED; |
1481 | goto error0; | 1481 | goto error0; |
1482 | } | 1482 | } |
1483 | ASSERT(lev < cur->bc_nlevels); | 1483 | ASSERT(lev < cur->bc_nlevels); |
1484 | 1484 | ||
1485 | /* | 1485 | /* |
1486 | * Now walk back down the tree, fixing up the cursor's buffer | 1486 | * Now walk back down the tree, fixing up the cursor's buffer |
1487 | * pointers and key numbers. | 1487 | * pointers and key numbers. |
1488 | */ | 1488 | */ |
1489 | for (block = xfs_btree_get_block(cur, lev, &bp); lev > level; ) { | 1489 | for (block = xfs_btree_get_block(cur, lev, &bp); lev > level; ) { |
1490 | union xfs_btree_ptr *ptrp; | 1490 | union xfs_btree_ptr *ptrp; |
1491 | 1491 | ||
1492 | ptrp = xfs_btree_ptr_addr(cur, cur->bc_ptrs[lev], block); | 1492 | ptrp = xfs_btree_ptr_addr(cur, cur->bc_ptrs[lev], block); |
1493 | error = xfs_btree_read_buf_block(cur, ptrp, --lev, | 1493 | error = xfs_btree_read_buf_block(cur, ptrp, --lev, |
1494 | 0, &block, &bp); | 1494 | 0, &block, &bp); |
1495 | if (error) | 1495 | if (error) |
1496 | goto error0; | 1496 | goto error0; |
1497 | xfs_btree_setbuf(cur, lev, bp); | 1497 | xfs_btree_setbuf(cur, lev, bp); |
1498 | cur->bc_ptrs[lev] = xfs_btree_get_numrecs(block); | 1498 | cur->bc_ptrs[lev] = xfs_btree_get_numrecs(block); |
1499 | } | 1499 | } |
1500 | out1: | 1500 | out1: |
1501 | XFS_BTREE_TRACE_CURSOR(cur, XBT_EXIT); | 1501 | XFS_BTREE_TRACE_CURSOR(cur, XBT_EXIT); |
1502 | *stat = 1; | 1502 | *stat = 1; |
1503 | return 0; | 1503 | return 0; |
1504 | 1504 | ||
1505 | out0: | 1505 | out0: |
1506 | XFS_BTREE_TRACE_CURSOR(cur, XBT_EXIT); | 1506 | XFS_BTREE_TRACE_CURSOR(cur, XBT_EXIT); |
1507 | *stat = 0; | 1507 | *stat = 0; |
1508 | return 0; | 1508 | return 0; |
1509 | 1509 | ||
1510 | error0: | 1510 | error0: |
1511 | XFS_BTREE_TRACE_CURSOR(cur, XBT_ERROR); | 1511 | XFS_BTREE_TRACE_CURSOR(cur, XBT_ERROR); |
1512 | return error; | 1512 | return error; |
1513 | } | 1513 | } |
1514 | 1514 | ||
1515 | STATIC int | 1515 | STATIC int |
1516 | xfs_btree_lookup_get_block( | 1516 | xfs_btree_lookup_get_block( |
1517 | struct xfs_btree_cur *cur, /* btree cursor */ | 1517 | struct xfs_btree_cur *cur, /* btree cursor */ |
1518 | int level, /* level in the btree */ | 1518 | int level, /* level in the btree */ |
1519 | union xfs_btree_ptr *pp, /* ptr to btree block */ | 1519 | union xfs_btree_ptr *pp, /* ptr to btree block */ |
1520 | struct xfs_btree_block **blkp) /* return btree block */ | 1520 | struct xfs_btree_block **blkp) /* return btree block */ |
1521 | { | 1521 | { |
1522 | struct xfs_buf *bp; /* buffer pointer for btree block */ | 1522 | struct xfs_buf *bp; /* buffer pointer for btree block */ |
1523 | int error = 0; | 1523 | int error = 0; |
1524 | 1524 | ||
1525 | /* special case the root block if in an inode */ | 1525 | /* special case the root block if in an inode */ |
1526 | if ((cur->bc_flags & XFS_BTREE_ROOT_IN_INODE) && | 1526 | if ((cur->bc_flags & XFS_BTREE_ROOT_IN_INODE) && |
1527 | (level == cur->bc_nlevels - 1)) { | 1527 | (level == cur->bc_nlevels - 1)) { |
1528 | *blkp = xfs_btree_get_iroot(cur); | 1528 | *blkp = xfs_btree_get_iroot(cur); |
1529 | return 0; | 1529 | return 0; |
1530 | } | 1530 | } |
1531 | 1531 | ||
1532 | /* | 1532 | /* |
1533 | * If the old buffer at this level for the disk address we are | 1533 | * If the old buffer at this level for the disk address we are |
1534 | * looking for re-use it. | 1534 | * looking for re-use it. |
1535 | * | 1535 | * |
1536 | * Otherwise throw it away and get a new one. | 1536 | * Otherwise throw it away and get a new one. |
1537 | */ | 1537 | */ |
1538 | bp = cur->bc_bufs[level]; | 1538 | bp = cur->bc_bufs[level]; |
1539 | if (bp && XFS_BUF_ADDR(bp) == xfs_btree_ptr_to_daddr(cur, pp)) { | 1539 | if (bp && XFS_BUF_ADDR(bp) == xfs_btree_ptr_to_daddr(cur, pp)) { |
1540 | *blkp = XFS_BUF_TO_BLOCK(bp); | 1540 | *blkp = XFS_BUF_TO_BLOCK(bp); |
1541 | return 0; | 1541 | return 0; |
1542 | } | 1542 | } |
1543 | 1543 | ||
1544 | error = xfs_btree_read_buf_block(cur, pp, level, 0, blkp, &bp); | 1544 | error = xfs_btree_read_buf_block(cur, pp, level, 0, blkp, &bp); |
1545 | if (error) | 1545 | if (error) |
1546 | return error; | 1546 | return error; |
1547 | 1547 | ||
1548 | xfs_btree_setbuf(cur, level, bp); | 1548 | xfs_btree_setbuf(cur, level, bp); |
1549 | return 0; | 1549 | return 0; |
1550 | } | 1550 | } |
1551 | 1551 | ||
1552 | /* | 1552 | /* |
1553 | * Get current search key. For level 0 we don't actually have a key | 1553 | * Get current search key. For level 0 we don't actually have a key |
1554 | * structure so we make one up from the record. For all other levels | 1554 | * structure so we make one up from the record. For all other levels |
1555 | * we just return the right key. | 1555 | * we just return the right key. |
1556 | */ | 1556 | */ |
1557 | STATIC union xfs_btree_key * | 1557 | STATIC union xfs_btree_key * |
1558 | xfs_lookup_get_search_key( | 1558 | xfs_lookup_get_search_key( |
1559 | struct xfs_btree_cur *cur, | 1559 | struct xfs_btree_cur *cur, |
1560 | int level, | 1560 | int level, |
1561 | int keyno, | 1561 | int keyno, |
1562 | struct xfs_btree_block *block, | 1562 | struct xfs_btree_block *block, |
1563 | union xfs_btree_key *kp) | 1563 | union xfs_btree_key *kp) |
1564 | { | 1564 | { |
1565 | if (level == 0) { | 1565 | if (level == 0) { |
1566 | cur->bc_ops->init_key_from_rec(kp, | 1566 | cur->bc_ops->init_key_from_rec(kp, |
1567 | xfs_btree_rec_addr(cur, keyno, block)); | 1567 | xfs_btree_rec_addr(cur, keyno, block)); |
1568 | return kp; | 1568 | return kp; |
1569 | } | 1569 | } |
1570 | 1570 | ||
1571 | return xfs_btree_key_addr(cur, keyno, block); | 1571 | return xfs_btree_key_addr(cur, keyno, block); |
1572 | } | 1572 | } |
1573 | 1573 | ||
1574 | /* | 1574 | /* |
1575 | * Lookup the record. The cursor is made to point to it, based on dir. | 1575 | * Lookup the record. The cursor is made to point to it, based on dir. |
1576 | * Return 0 if can't find any such record, 1 for success. | 1576 | * Return 0 if can't find any such record, 1 for success. |
1577 | */ | 1577 | */ |
1578 | int /* error */ | 1578 | int /* error */ |
1579 | xfs_btree_lookup( | 1579 | xfs_btree_lookup( |
1580 | struct xfs_btree_cur *cur, /* btree cursor */ | 1580 | struct xfs_btree_cur *cur, /* btree cursor */ |
1581 | xfs_lookup_t dir, /* <=, ==, or >= */ | 1581 | xfs_lookup_t dir, /* <=, ==, or >= */ |
1582 | int *stat) /* success/failure */ | 1582 | int *stat) /* success/failure */ |
1583 | { | 1583 | { |
1584 | struct xfs_btree_block *block; /* current btree block */ | 1584 | struct xfs_btree_block *block; /* current btree block */ |
1585 | __int64_t diff; /* difference for the current key */ | 1585 | __int64_t diff; /* difference for the current key */ |
1586 | int error; /* error return value */ | 1586 | int error; /* error return value */ |
1587 | int keyno; /* current key number */ | 1587 | int keyno; /* current key number */ |
1588 | int level; /* level in the btree */ | 1588 | int level; /* level in the btree */ |
1589 | union xfs_btree_ptr *pp; /* ptr to btree block */ | 1589 | union xfs_btree_ptr *pp; /* ptr to btree block */ |
1590 | union xfs_btree_ptr ptr; /* ptr to btree block */ | 1590 | union xfs_btree_ptr ptr; /* ptr to btree block */ |
1591 | 1591 | ||
1592 | XFS_BTREE_TRACE_CURSOR(cur, XBT_ENTRY); | 1592 | XFS_BTREE_TRACE_CURSOR(cur, XBT_ENTRY); |
1593 | XFS_BTREE_TRACE_ARGI(cur, dir); | 1593 | XFS_BTREE_TRACE_ARGI(cur, dir); |
1594 | 1594 | ||
1595 | XFS_BTREE_STATS_INC(cur, lookup); | 1595 | XFS_BTREE_STATS_INC(cur, lookup); |
1596 | 1596 | ||
1597 | block = NULL; | 1597 | block = NULL; |
1598 | keyno = 0; | 1598 | keyno = 0; |
1599 | 1599 | ||
1600 | /* initialise start pointer from cursor */ | 1600 | /* initialise start pointer from cursor */ |
1601 | cur->bc_ops->init_ptr_from_cur(cur, &ptr); | 1601 | cur->bc_ops->init_ptr_from_cur(cur, &ptr); |
1602 | pp = &ptr; | 1602 | pp = &ptr; |
1603 | 1603 | ||
1604 | /* | 1604 | /* |
1605 | * Iterate over each level in the btree, starting at the root. | 1605 | * Iterate over each level in the btree, starting at the root. |
1606 | * For each level above the leaves, find the key we need, based | 1606 | * For each level above the leaves, find the key we need, based |
1607 | * on the lookup record, then follow the corresponding block | 1607 | * on the lookup record, then follow the corresponding block |
1608 | * pointer down to the next level. | 1608 | * pointer down to the next level. |
1609 | */ | 1609 | */ |
1610 | for (level = cur->bc_nlevels - 1, diff = 1; level >= 0; level--) { | 1610 | for (level = cur->bc_nlevels - 1, diff = 1; level >= 0; level--) { |
1611 | /* Get the block we need to do the lookup on. */ | 1611 | /* Get the block we need to do the lookup on. */ |
1612 | error = xfs_btree_lookup_get_block(cur, level, pp, &block); | 1612 | error = xfs_btree_lookup_get_block(cur, level, pp, &block); |
1613 | if (error) | 1613 | if (error) |
1614 | goto error0; | 1614 | goto error0; |
1615 | 1615 | ||
1616 | if (diff == 0) { | 1616 | if (diff == 0) { |
1617 | /* | 1617 | /* |
1618 | * If we already had a key match at a higher level, we | 1618 | * If we already had a key match at a higher level, we |
1619 | * know we need to use the first entry in this block. | 1619 | * know we need to use the first entry in this block. |
1620 | */ | 1620 | */ |
1621 | keyno = 1; | 1621 | keyno = 1; |
1622 | } else { | 1622 | } else { |
1623 | /* Otherwise search this block. Do a binary search. */ | 1623 | /* Otherwise search this block. Do a binary search. */ |
1624 | 1624 | ||
1625 | int high; /* high entry number */ | 1625 | int high; /* high entry number */ |
1626 | int low; /* low entry number */ | 1626 | int low; /* low entry number */ |
1627 | 1627 | ||
1628 | /* Set low and high entry numbers, 1-based. */ | 1628 | /* Set low and high entry numbers, 1-based. */ |
1629 | low = 1; | 1629 | low = 1; |
1630 | high = xfs_btree_get_numrecs(block); | 1630 | high = xfs_btree_get_numrecs(block); |
1631 | if (!high) { | 1631 | if (!high) { |
1632 | /* Block is empty, must be an empty leaf. */ | 1632 | /* Block is empty, must be an empty leaf. */ |
1633 | ASSERT(level == 0 && cur->bc_nlevels == 1); | 1633 | ASSERT(level == 0 && cur->bc_nlevels == 1); |
1634 | 1634 | ||
1635 | cur->bc_ptrs[0] = dir != XFS_LOOKUP_LE; | 1635 | cur->bc_ptrs[0] = dir != XFS_LOOKUP_LE; |
1636 | XFS_BTREE_TRACE_CURSOR(cur, XBT_EXIT); | 1636 | XFS_BTREE_TRACE_CURSOR(cur, XBT_EXIT); |
1637 | *stat = 0; | 1637 | *stat = 0; |
1638 | return 0; | 1638 | return 0; |
1639 | } | 1639 | } |
1640 | 1640 | ||
1641 | /* Binary search the block. */ | 1641 | /* Binary search the block. */ |
1642 | while (low <= high) { | 1642 | while (low <= high) { |
1643 | union xfs_btree_key key; | 1643 | union xfs_btree_key key; |
1644 | union xfs_btree_key *kp; | 1644 | union xfs_btree_key *kp; |
1645 | 1645 | ||
1646 | XFS_BTREE_STATS_INC(cur, compare); | 1646 | XFS_BTREE_STATS_INC(cur, compare); |
1647 | 1647 | ||
1648 | /* keyno is average of low and high. */ | 1648 | /* keyno is average of low and high. */ |
1649 | keyno = (low + high) >> 1; | 1649 | keyno = (low + high) >> 1; |
1650 | 1650 | ||
1651 | /* Get current search key */ | 1651 | /* Get current search key */ |
1652 | kp = xfs_lookup_get_search_key(cur, level, | 1652 | kp = xfs_lookup_get_search_key(cur, level, |
1653 | keyno, block, &key); | 1653 | keyno, block, &key); |
1654 | 1654 | ||
1655 | /* | 1655 | /* |
1656 | * Compute difference to get next direction: | 1656 | * Compute difference to get next direction: |
1657 | * - less than, move right | 1657 | * - less than, move right |
1658 | * - greater than, move left | 1658 | * - greater than, move left |
1659 | * - equal, we're done | 1659 | * - equal, we're done |
1660 | */ | 1660 | */ |
1661 | diff = cur->bc_ops->key_diff(cur, kp); | 1661 | diff = cur->bc_ops->key_diff(cur, kp); |
1662 | if (diff < 0) | 1662 | if (diff < 0) |
1663 | low = keyno + 1; | 1663 | low = keyno + 1; |
1664 | else if (diff > 0) | 1664 | else if (diff > 0) |
1665 | high = keyno - 1; | 1665 | high = keyno - 1; |
1666 | else | 1666 | else |
1667 | break; | 1667 | break; |
1668 | } | 1668 | } |
1669 | } | 1669 | } |
1670 | 1670 | ||
1671 | /* | 1671 | /* |
1672 | * If there are more levels, set up for the next level | 1672 | * If there are more levels, set up for the next level |
1673 | * by getting the block number and filling in the cursor. | 1673 | * by getting the block number and filling in the cursor. |
1674 | */ | 1674 | */ |
1675 | if (level > 0) { | 1675 | if (level > 0) { |
1676 | /* | 1676 | /* |
1677 | * If we moved left, need the previous key number, | 1677 | * If we moved left, need the previous key number, |
1678 | * unless there isn't one. | 1678 | * unless there isn't one. |
1679 | */ | 1679 | */ |
1680 | if (diff > 0 && --keyno < 1) | 1680 | if (diff > 0 && --keyno < 1) |
1681 | keyno = 1; | 1681 | keyno = 1; |
1682 | pp = xfs_btree_ptr_addr(cur, keyno, block); | 1682 | pp = xfs_btree_ptr_addr(cur, keyno, block); |
1683 | 1683 | ||
1684 | #ifdef DEBUG | 1684 | #ifdef DEBUG |
1685 | error = xfs_btree_check_ptr(cur, pp, 0, level); | 1685 | error = xfs_btree_check_ptr(cur, pp, 0, level); |
1686 | if (error) | 1686 | if (error) |
1687 | goto error0; | 1687 | goto error0; |
1688 | #endif | 1688 | #endif |
1689 | cur->bc_ptrs[level] = keyno; | 1689 | cur->bc_ptrs[level] = keyno; |
1690 | } | 1690 | } |
1691 | } | 1691 | } |
1692 | 1692 | ||
1693 | /* Done with the search. See if we need to adjust the results. */ | 1693 | /* Done with the search. See if we need to adjust the results. */ |
1694 | if (dir != XFS_LOOKUP_LE && diff < 0) { | 1694 | if (dir != XFS_LOOKUP_LE && diff < 0) { |
1695 | keyno++; | 1695 | keyno++; |
1696 | /* | 1696 | /* |
1697 | * If ge search and we went off the end of the block, but it's | 1697 | * If ge search and we went off the end of the block, but it's |
1698 | * not the last block, we're in the wrong block. | 1698 | * not the last block, we're in the wrong block. |
1699 | */ | 1699 | */ |
1700 | xfs_btree_get_sibling(cur, block, &ptr, XFS_BB_RIGHTSIB); | 1700 | xfs_btree_get_sibling(cur, block, &ptr, XFS_BB_RIGHTSIB); |
1701 | if (dir == XFS_LOOKUP_GE && | 1701 | if (dir == XFS_LOOKUP_GE && |
1702 | keyno > xfs_btree_get_numrecs(block) && | 1702 | keyno > xfs_btree_get_numrecs(block) && |
1703 | !xfs_btree_ptr_is_null(cur, &ptr)) { | 1703 | !xfs_btree_ptr_is_null(cur, &ptr)) { |
1704 | int i; | 1704 | int i; |
1705 | 1705 | ||
1706 | cur->bc_ptrs[0] = keyno; | 1706 | cur->bc_ptrs[0] = keyno; |
1707 | error = xfs_btree_increment(cur, 0, &i); | 1707 | error = xfs_btree_increment(cur, 0, &i); |
1708 | if (error) | 1708 | if (error) |
1709 | goto error0; | 1709 | goto error0; |
1710 | XFS_WANT_CORRUPTED_RETURN(i == 1); | 1710 | XFS_WANT_CORRUPTED_RETURN(i == 1); |
1711 | XFS_BTREE_TRACE_CURSOR(cur, XBT_EXIT); | 1711 | XFS_BTREE_TRACE_CURSOR(cur, XBT_EXIT); |
1712 | *stat = 1; | 1712 | *stat = 1; |
1713 | return 0; | 1713 | return 0; |
1714 | } | 1714 | } |
1715 | } else if (dir == XFS_LOOKUP_LE && diff > 0) | 1715 | } else if (dir == XFS_LOOKUP_LE && diff > 0) |
1716 | keyno--; | 1716 | keyno--; |
1717 | cur->bc_ptrs[0] = keyno; | 1717 | cur->bc_ptrs[0] = keyno; |
1718 | 1718 | ||
1719 | /* Return if we succeeded or not. */ | 1719 | /* Return if we succeeded or not. */ |
1720 | if (keyno == 0 || keyno > xfs_btree_get_numrecs(block)) | 1720 | if (keyno == 0 || keyno > xfs_btree_get_numrecs(block)) |
1721 | *stat = 0; | 1721 | *stat = 0; |
1722 | else if (dir != XFS_LOOKUP_EQ || diff == 0) | 1722 | else if (dir != XFS_LOOKUP_EQ || diff == 0) |
1723 | *stat = 1; | 1723 | *stat = 1; |
1724 | else | 1724 | else |
1725 | *stat = 0; | 1725 | *stat = 0; |
1726 | XFS_BTREE_TRACE_CURSOR(cur, XBT_EXIT); | 1726 | XFS_BTREE_TRACE_CURSOR(cur, XBT_EXIT); |
1727 | return 0; | 1727 | return 0; |
1728 | 1728 | ||
1729 | error0: | 1729 | error0: |
1730 | XFS_BTREE_TRACE_CURSOR(cur, XBT_ERROR); | 1730 | XFS_BTREE_TRACE_CURSOR(cur, XBT_ERROR); |
1731 | return error; | 1731 | return error; |
1732 | } | 1732 | } |
1733 | 1733 | ||
1734 | /* | 1734 | /* |
1735 | * Update keys at all levels from here to the root along the cursor's path. | 1735 | * Update keys at all levels from here to the root along the cursor's path. |
1736 | */ | 1736 | */ |
1737 | int | 1737 | int |
1738 | xfs_btree_updkey( | 1738 | xfs_btree_updkey( |
1739 | struct xfs_btree_cur *cur, | 1739 | struct xfs_btree_cur *cur, |
1740 | union xfs_btree_key *keyp, | 1740 | union xfs_btree_key *keyp, |
1741 | int level) | 1741 | int level) |
1742 | { | 1742 | { |
1743 | struct xfs_btree_block *block; | 1743 | struct xfs_btree_block *block; |
1744 | struct xfs_buf *bp; | 1744 | struct xfs_buf *bp; |
1745 | union xfs_btree_key *kp; | 1745 | union xfs_btree_key *kp; |
1746 | int ptr; | 1746 | int ptr; |
1747 | 1747 | ||
1748 | XFS_BTREE_TRACE_CURSOR(cur, XBT_ENTRY); | 1748 | XFS_BTREE_TRACE_CURSOR(cur, XBT_ENTRY); |
1749 | XFS_BTREE_TRACE_ARGIK(cur, level, keyp); | 1749 | XFS_BTREE_TRACE_ARGIK(cur, level, keyp); |
1750 | 1750 | ||
1751 | ASSERT(!(cur->bc_flags & XFS_BTREE_ROOT_IN_INODE) || level >= 1); | 1751 | ASSERT(!(cur->bc_flags & XFS_BTREE_ROOT_IN_INODE) || level >= 1); |
1752 | 1752 | ||
1753 | /* | 1753 | /* |
1754 | * Go up the tree from this level toward the root. | 1754 | * Go up the tree from this level toward the root. |
1755 | * At each level, update the key value to the value input. | 1755 | * At each level, update the key value to the value input. |
1756 | * Stop when we reach a level where the cursor isn't pointing | 1756 | * Stop when we reach a level where the cursor isn't pointing |
1757 | * at the first entry in the block. | 1757 | * at the first entry in the block. |
1758 | */ | 1758 | */ |
1759 | for (ptr = 1; ptr == 1 && level < cur->bc_nlevels; level++) { | 1759 | for (ptr = 1; ptr == 1 && level < cur->bc_nlevels; level++) { |
1760 | #ifdef DEBUG | 1760 | #ifdef DEBUG |
1761 | int error; | 1761 | int error; |
1762 | #endif | 1762 | #endif |
1763 | block = xfs_btree_get_block(cur, level, &bp); | 1763 | block = xfs_btree_get_block(cur, level, &bp); |
1764 | #ifdef DEBUG | 1764 | #ifdef DEBUG |
1765 | error = xfs_btree_check_block(cur, block, level, bp); | 1765 | error = xfs_btree_check_block(cur, block, level, bp); |
1766 | if (error) { | 1766 | if (error) { |
1767 | XFS_BTREE_TRACE_CURSOR(cur, XBT_ERROR); | 1767 | XFS_BTREE_TRACE_CURSOR(cur, XBT_ERROR); |
1768 | return error; | 1768 | return error; |
1769 | } | 1769 | } |
1770 | #endif | 1770 | #endif |
1771 | ptr = cur->bc_ptrs[level]; | 1771 | ptr = cur->bc_ptrs[level]; |
1772 | kp = xfs_btree_key_addr(cur, ptr, block); | 1772 | kp = xfs_btree_key_addr(cur, ptr, block); |
1773 | xfs_btree_copy_keys(cur, kp, keyp, 1); | 1773 | xfs_btree_copy_keys(cur, kp, keyp, 1); |
1774 | xfs_btree_log_keys(cur, bp, ptr, ptr); | 1774 | xfs_btree_log_keys(cur, bp, ptr, ptr); |
1775 | } | 1775 | } |
1776 | 1776 | ||
1777 | XFS_BTREE_TRACE_CURSOR(cur, XBT_EXIT); | 1777 | XFS_BTREE_TRACE_CURSOR(cur, XBT_EXIT); |
1778 | return 0; | 1778 | return 0; |
1779 | } | 1779 | } |
1780 | 1780 | ||
1781 | /* | 1781 | /* |
1782 | * Update the record referred to by cur to the value in the | 1782 | * Update the record referred to by cur to the value in the |
1783 | * given record. This either works (return 0) or gets an | 1783 | * given record. This either works (return 0) or gets an |
1784 | * EFSCORRUPTED error. | 1784 | * EFSCORRUPTED error. |
1785 | */ | 1785 | */ |
1786 | int | 1786 | int |
1787 | xfs_btree_update( | 1787 | xfs_btree_update( |
1788 | struct xfs_btree_cur *cur, | 1788 | struct xfs_btree_cur *cur, |
1789 | union xfs_btree_rec *rec) | 1789 | union xfs_btree_rec *rec) |
1790 | { | 1790 | { |
1791 | struct xfs_btree_block *block; | 1791 | struct xfs_btree_block *block; |
1792 | struct xfs_buf *bp; | 1792 | struct xfs_buf *bp; |
1793 | int error; | 1793 | int error; |
1794 | int ptr; | 1794 | int ptr; |
1795 | union xfs_btree_rec *rp; | 1795 | union xfs_btree_rec *rp; |
1796 | 1796 | ||
1797 | XFS_BTREE_TRACE_CURSOR(cur, XBT_ENTRY); | 1797 | XFS_BTREE_TRACE_CURSOR(cur, XBT_ENTRY); |
1798 | XFS_BTREE_TRACE_ARGR(cur, rec); | 1798 | XFS_BTREE_TRACE_ARGR(cur, rec); |
1799 | 1799 | ||
1800 | /* Pick up the current block. */ | 1800 | /* Pick up the current block. */ |
1801 | block = xfs_btree_get_block(cur, 0, &bp); | 1801 | block = xfs_btree_get_block(cur, 0, &bp); |
1802 | 1802 | ||
1803 | #ifdef DEBUG | 1803 | #ifdef DEBUG |
1804 | error = xfs_btree_check_block(cur, block, 0, bp); | 1804 | error = xfs_btree_check_block(cur, block, 0, bp); |
1805 | if (error) | 1805 | if (error) |
1806 | goto error0; | 1806 | goto error0; |
1807 | #endif | 1807 | #endif |
1808 | /* Get the address of the rec to be updated. */ | 1808 | /* Get the address of the rec to be updated. */ |
1809 | ptr = cur->bc_ptrs[0]; | 1809 | ptr = cur->bc_ptrs[0]; |
1810 | rp = xfs_btree_rec_addr(cur, ptr, block); | 1810 | rp = xfs_btree_rec_addr(cur, ptr, block); |
1811 | 1811 | ||
1812 | /* Fill in the new contents and log them. */ | 1812 | /* Fill in the new contents and log them. */ |
1813 | xfs_btree_copy_recs(cur, rp, rec, 1); | 1813 | xfs_btree_copy_recs(cur, rp, rec, 1); |
1814 | xfs_btree_log_recs(cur, bp, ptr, ptr); | 1814 | xfs_btree_log_recs(cur, bp, ptr, ptr); |
1815 | 1815 | ||
1816 | /* | 1816 | /* |
1817 | * If we are tracking the last record in the tree and | 1817 | * If we are tracking the last record in the tree and |
1818 | * we are at the far right edge of the tree, update it. | 1818 | * we are at the far right edge of the tree, update it. |
1819 | */ | 1819 | */ |
1820 | if (xfs_btree_is_lastrec(cur, block, 0)) { | 1820 | if (xfs_btree_is_lastrec(cur, block, 0)) { |
1821 | cur->bc_ops->update_lastrec(cur, block, rec, | 1821 | cur->bc_ops->update_lastrec(cur, block, rec, |
1822 | ptr, LASTREC_UPDATE); | 1822 | ptr, LASTREC_UPDATE); |
1823 | } | 1823 | } |
1824 | 1824 | ||
1825 | /* Updating first rec in leaf. Pass new key value up to our parent. */ | 1825 | /* Updating first rec in leaf. Pass new key value up to our parent. */ |
1826 | if (ptr == 1) { | 1826 | if (ptr == 1) { |
1827 | union xfs_btree_key key; | 1827 | union xfs_btree_key key; |
1828 | 1828 | ||
1829 | cur->bc_ops->init_key_from_rec(&key, rec); | 1829 | cur->bc_ops->init_key_from_rec(&key, rec); |
1830 | error = xfs_btree_updkey(cur, &key, 1); | 1830 | error = xfs_btree_updkey(cur, &key, 1); |
1831 | if (error) | 1831 | if (error) |
1832 | goto error0; | 1832 | goto error0; |
1833 | } | 1833 | } |
1834 | 1834 | ||
1835 | XFS_BTREE_TRACE_CURSOR(cur, XBT_EXIT); | 1835 | XFS_BTREE_TRACE_CURSOR(cur, XBT_EXIT); |
1836 | return 0; | 1836 | return 0; |
1837 | 1837 | ||
1838 | error0: | 1838 | error0: |
1839 | XFS_BTREE_TRACE_CURSOR(cur, XBT_ERROR); | 1839 | XFS_BTREE_TRACE_CURSOR(cur, XBT_ERROR); |
1840 | return error; | 1840 | return error; |
1841 | } | 1841 | } |
1842 | 1842 | ||
1843 | /* | 1843 | /* |
1844 | * Move 1 record left from cur/level if possible. | ||
1845 | * Update cur to reflect the new path. | ||
1846 | */ | ||
1847 | int /* error */ | ||
1848 | xfs_btree_lshift( | ||
1849 | struct xfs_btree_cur *cur, | ||
1850 | int level, | ||
1851 | int *stat) /* success/failure */ | ||
1852 | { | ||
1853 | union xfs_btree_key key; /* btree key */ | ||
1854 | struct xfs_buf *lbp; /* left buffer pointer */ | ||
1855 | struct xfs_btree_block *left; /* left btree block */ | ||
1856 | int lrecs; /* left record count */ | ||
1857 | struct xfs_buf *rbp; /* right buffer pointer */ | ||
1858 | struct xfs_btree_block *right; /* right btree block */ | ||
1859 | int rrecs; /* right record count */ | ||
1860 | union xfs_btree_ptr lptr; /* left btree pointer */ | ||
1861 | union xfs_btree_key *rkp = NULL; /* right btree key */ | ||
1862 | union xfs_btree_ptr *rpp = NULL; /* right address pointer */ | ||
1863 | union xfs_btree_rec *rrp = NULL; /* right record pointer */ | ||
1864 | int error; /* error return value */ | ||
1865 | |||
1866 | XFS_BTREE_TRACE_CURSOR(cur, XBT_ENTRY); | ||
1867 | XFS_BTREE_TRACE_ARGI(cur, level); | ||
1868 | |||
1869 | if ((cur->bc_flags & XFS_BTREE_ROOT_IN_INODE) && | ||
1870 | level == cur->bc_nlevels - 1) | ||
1871 | goto out0; | ||
1872 | |||
1873 | /* Set up variables for this block as "right". */ | ||
1874 | right = xfs_btree_get_block(cur, level, &rbp); | ||
1875 | |||
1876 | #ifdef DEBUG | ||
1877 | error = xfs_btree_check_block(cur, right, level, rbp); | ||
1878 | if (error) | ||
1879 | goto error0; | ||
1880 | #endif | ||
1881 | |||
1882 | /* If we've got no left sibling then we can't shift an entry left. */ | ||
1883 | xfs_btree_get_sibling(cur, right, &lptr, XFS_BB_LEFTSIB); | ||
1884 | if (xfs_btree_ptr_is_null(cur, &lptr)) | ||
1885 | goto out0; | ||
1886 | |||
1887 | /* | ||
1888 | * If the cursor entry is the one that would be moved, don't | ||
1889 | * do it... it's too complicated. | ||
1890 | */ | ||
1891 | if (cur->bc_ptrs[level] <= 1) | ||
1892 | goto out0; | ||
1893 | |||
1894 | /* Set up the left neighbor as "left". */ | ||
1895 | error = xfs_btree_read_buf_block(cur, &lptr, level, 0, &left, &lbp); | ||
1896 | if (error) | ||
1897 | goto error0; | ||
1898 | |||
1899 | /* If it's full, it can't take another entry. */ | ||
1900 | lrecs = xfs_btree_get_numrecs(left); | ||
1901 | if (lrecs == cur->bc_ops->get_maxrecs(cur, level)) | ||
1902 | goto out0; | ||
1903 | |||
1904 | rrecs = xfs_btree_get_numrecs(right); | ||
1905 | |||
1906 | /* | ||
1907 | * We add one entry to the left side and remove one for the right side. | ||
1908 | * Accout for it here, the changes will be updated on disk and logged | ||
1909 | * later. | ||
1910 | */ | ||
1911 | lrecs++; | ||
1912 | rrecs--; | ||
1913 | |||
1914 | XFS_BTREE_STATS_INC(cur, lshift); | ||
1915 | XFS_BTREE_STATS_ADD(cur, moves, 1); | ||
1916 | |||
1917 | /* | ||
1918 | * If non-leaf, copy a key and a ptr to the left block. | ||
1919 | * Log the changes to the left block. | ||
1920 | */ | ||
1921 | if (level > 0) { | ||
1922 | /* It's a non-leaf. Move keys and pointers. */ | ||
1923 | union xfs_btree_key *lkp; /* left btree key */ | ||
1924 | union xfs_btree_ptr *lpp; /* left address pointer */ | ||
1925 | |||
1926 | lkp = xfs_btree_key_addr(cur, lrecs, left); | ||
1927 | rkp = xfs_btree_key_addr(cur, 1, right); | ||
1928 | |||
1929 | lpp = xfs_btree_ptr_addr(cur, lrecs, left); | ||
1930 | rpp = xfs_btree_ptr_addr(cur, 1, right); | ||
1931 | #ifdef DEBUG | ||
1932 | error = xfs_btree_check_ptr(cur, rpp, 0, level); | ||
1933 | if (error) | ||
1934 | goto error0; | ||
1935 | #endif | ||
1936 | xfs_btree_copy_keys(cur, lkp, rkp, 1); | ||
1937 | xfs_btree_copy_ptrs(cur, lpp, rpp, 1); | ||
1938 | |||
1939 | xfs_btree_log_keys(cur, lbp, lrecs, lrecs); | ||
1940 | xfs_btree_log_ptrs(cur, lbp, lrecs, lrecs); | ||
1941 | |||
1942 | xfs_btree_check_key(cur->bc_btnum, | ||
1943 | xfs_btree_key_addr(cur, lrecs - 1, left), | ||
1944 | lkp); | ||
1945 | } else { | ||
1946 | /* It's a leaf. Move records. */ | ||
1947 | union xfs_btree_rec *lrp; /* left record pointer */ | ||
1948 | |||
1949 | lrp = xfs_btree_rec_addr(cur, lrecs, left); | ||
1950 | rrp = xfs_btree_rec_addr(cur, 1, right); | ||
1951 | |||
1952 | xfs_btree_copy_recs(cur, lrp, rrp, 1); | ||
1953 | xfs_btree_log_recs(cur, lbp, lrecs, lrecs); | ||
1954 | |||
1955 | xfs_btree_check_rec(cur->bc_btnum, | ||
1956 | xfs_btree_rec_addr(cur, lrecs - 1, left), | ||
1957 | lrp); | ||
1958 | } | ||
1959 | |||
1960 | xfs_btree_set_numrecs(left, lrecs); | ||
1961 | xfs_btree_log_block(cur, lbp, XFS_BB_NUMRECS); | ||
1962 | |||
1963 | xfs_btree_set_numrecs(right, rrecs); | ||
1964 | xfs_btree_log_block(cur, rbp, XFS_BB_NUMRECS); | ||
1965 | |||
1966 | /* | ||
1967 | * Slide the contents of right down one entry. | ||
1968 | */ | ||
1969 | XFS_BTREE_STATS_ADD(cur, moves, rrecs - 1); | ||
1970 | if (level > 0) { | ||
1971 | /* It's a nonleaf. operate on keys and ptrs */ | ||
1972 | #ifdef DEBUG | ||
1973 | int i; /* loop index */ | ||
1974 | |||
1975 | for (i = 0; i < rrecs; i++) { | ||
1976 | error = xfs_btree_check_ptr(cur, rpp, i + 1, level); | ||
1977 | if (error) | ||
1978 | goto error0; | ||
1979 | } | ||
1980 | #endif | ||
1981 | xfs_btree_shift_keys(cur, | ||
1982 | xfs_btree_key_addr(cur, 2, right), | ||
1983 | -1, rrecs); | ||
1984 | xfs_btree_shift_ptrs(cur, | ||
1985 | xfs_btree_ptr_addr(cur, 2, right), | ||
1986 | -1, rrecs); | ||
1987 | |||
1988 | xfs_btree_log_keys(cur, rbp, 1, rrecs); | ||
1989 | xfs_btree_log_ptrs(cur, rbp, 1, rrecs); | ||
1990 | } else { | ||
1991 | /* It's a leaf. operate on records */ | ||
1992 | xfs_btree_shift_recs(cur, | ||
1993 | xfs_btree_rec_addr(cur, 2, right), | ||
1994 | -1, rrecs); | ||
1995 | xfs_btree_log_recs(cur, rbp, 1, rrecs); | ||
1996 | |||
1997 | /* | ||
1998 | * If it's the first record in the block, we'll need a key | ||
1999 | * structure to pass up to the next level (updkey). | ||
2000 | */ | ||
2001 | cur->bc_ops->init_key_from_rec(&key, | ||
2002 | xfs_btree_rec_addr(cur, 1, right)); | ||
2003 | rkp = &key; | ||
2004 | } | ||
2005 | |||
2006 | /* Update the parent key values of right. */ | ||
2007 | error = xfs_btree_updkey(cur, rkp, level + 1); | ||
2008 | if (error) | ||
2009 | goto error0; | ||
2010 | |||
2011 | /* Slide the cursor value left one. */ | ||
2012 | cur->bc_ptrs[level]--; | ||
2013 | |||
2014 | XFS_BTREE_TRACE_CURSOR(cur, XBT_EXIT); | ||
2015 | *stat = 1; | ||
2016 | return 0; | ||
2017 | |||
2018 | out0: | ||
2019 | XFS_BTREE_TRACE_CURSOR(cur, XBT_EXIT); | ||
2020 | *stat = 0; | ||
2021 | return 0; | ||
2022 | |||
2023 | error0: | ||
2024 | XFS_BTREE_TRACE_CURSOR(cur, XBT_ERROR); | ||
2025 | return error; | ||
2026 | } | ||
2027 | |||
2028 | /* | ||
1844 | * Move 1 record right from cur/level if possible. | 2029 | * Move 1 record right from cur/level if possible. |
1845 | * Update cur to reflect the new path. | 2030 | * Update cur to reflect the new path. |
1846 | */ | 2031 | */ |
1847 | int /* error */ | 2032 | int /* error */ |
1848 | xfs_btree_rshift( | 2033 | xfs_btree_rshift( |
1849 | struct xfs_btree_cur *cur, | 2034 | struct xfs_btree_cur *cur, |
1850 | int level, | 2035 | int level, |
1851 | int *stat) /* success/failure */ | 2036 | int *stat) /* success/failure */ |
1852 | { | 2037 | { |
1853 | union xfs_btree_key key; /* btree key */ | 2038 | union xfs_btree_key key; /* btree key */ |
1854 | struct xfs_buf *lbp; /* left buffer pointer */ | 2039 | struct xfs_buf *lbp; /* left buffer pointer */ |
1855 | struct xfs_btree_block *left; /* left btree block */ | 2040 | struct xfs_btree_block *left; /* left btree block */ |
1856 | struct xfs_buf *rbp; /* right buffer pointer */ | 2041 | struct xfs_buf *rbp; /* right buffer pointer */ |
1857 | struct xfs_btree_block *right; /* right btree block */ | 2042 | struct xfs_btree_block *right; /* right btree block */ |
1858 | struct xfs_btree_cur *tcur; /* temporary btree cursor */ | 2043 | struct xfs_btree_cur *tcur; /* temporary btree cursor */ |
1859 | union xfs_btree_ptr rptr; /* right block pointer */ | 2044 | union xfs_btree_ptr rptr; /* right block pointer */ |
1860 | union xfs_btree_key *rkp; /* right btree key */ | 2045 | union xfs_btree_key *rkp; /* right btree key */ |
1861 | int rrecs; /* right record count */ | 2046 | int rrecs; /* right record count */ |
1862 | int lrecs; /* left record count */ | 2047 | int lrecs; /* left record count */ |
1863 | int error; /* error return value */ | 2048 | int error; /* error return value */ |
1864 | int i; /* loop counter */ | 2049 | int i; /* loop counter */ |
1865 | 2050 | ||
1866 | XFS_BTREE_TRACE_CURSOR(cur, XBT_ENTRY); | 2051 | XFS_BTREE_TRACE_CURSOR(cur, XBT_ENTRY); |
1867 | XFS_BTREE_TRACE_ARGI(cur, level); | 2052 | XFS_BTREE_TRACE_ARGI(cur, level); |
1868 | 2053 | ||
1869 | if ((cur->bc_flags & XFS_BTREE_ROOT_IN_INODE) && | 2054 | if ((cur->bc_flags & XFS_BTREE_ROOT_IN_INODE) && |
1870 | (level == cur->bc_nlevels - 1)) | 2055 | (level == cur->bc_nlevels - 1)) |
1871 | goto out0; | 2056 | goto out0; |
1872 | 2057 | ||
1873 | /* Set up variables for this block as "left". */ | 2058 | /* Set up variables for this block as "left". */ |
1874 | left = xfs_btree_get_block(cur, level, &lbp); | 2059 | left = xfs_btree_get_block(cur, level, &lbp); |
1875 | 2060 | ||
1876 | #ifdef DEBUG | 2061 | #ifdef DEBUG |
1877 | error = xfs_btree_check_block(cur, left, level, lbp); | 2062 | error = xfs_btree_check_block(cur, left, level, lbp); |
1878 | if (error) | 2063 | if (error) |
1879 | goto error0; | 2064 | goto error0; |
1880 | #endif | 2065 | #endif |
1881 | 2066 | ||
1882 | /* If we've got no right sibling then we can't shift an entry right. */ | 2067 | /* If we've got no right sibling then we can't shift an entry right. */ |
1883 | xfs_btree_get_sibling(cur, left, &rptr, XFS_BB_RIGHTSIB); | 2068 | xfs_btree_get_sibling(cur, left, &rptr, XFS_BB_RIGHTSIB); |
1884 | if (xfs_btree_ptr_is_null(cur, &rptr)) | 2069 | if (xfs_btree_ptr_is_null(cur, &rptr)) |
1885 | goto out0; | 2070 | goto out0; |
1886 | 2071 | ||
1887 | /* | 2072 | /* |
1888 | * If the cursor entry is the one that would be moved, don't | 2073 | * If the cursor entry is the one that would be moved, don't |
1889 | * do it... it's too complicated. | 2074 | * do it... it's too complicated. |
1890 | */ | 2075 | */ |
1891 | lrecs = xfs_btree_get_numrecs(left); | 2076 | lrecs = xfs_btree_get_numrecs(left); |
1892 | if (cur->bc_ptrs[level] >= lrecs) | 2077 | if (cur->bc_ptrs[level] >= lrecs) |
1893 | goto out0; | 2078 | goto out0; |
1894 | 2079 | ||
1895 | /* Set up the right neighbor as "right". */ | 2080 | /* Set up the right neighbor as "right". */ |
1896 | error = xfs_btree_read_buf_block(cur, &rptr, level, 0, &right, &rbp); | 2081 | error = xfs_btree_read_buf_block(cur, &rptr, level, 0, &right, &rbp); |
1897 | if (error) | 2082 | if (error) |
1898 | goto error0; | 2083 | goto error0; |
1899 | 2084 | ||
1900 | /* If it's full, it can't take another entry. */ | 2085 | /* If it's full, it can't take another entry. */ |
1901 | rrecs = xfs_btree_get_numrecs(right); | 2086 | rrecs = xfs_btree_get_numrecs(right); |
1902 | if (rrecs == cur->bc_ops->get_maxrecs(cur, level)) | 2087 | if (rrecs == cur->bc_ops->get_maxrecs(cur, level)) |
1903 | goto out0; | 2088 | goto out0; |
1904 | 2089 | ||
1905 | XFS_BTREE_STATS_INC(cur, rshift); | 2090 | XFS_BTREE_STATS_INC(cur, rshift); |
1906 | XFS_BTREE_STATS_ADD(cur, moves, rrecs); | 2091 | XFS_BTREE_STATS_ADD(cur, moves, rrecs); |
1907 | 2092 | ||
1908 | /* | 2093 | /* |
1909 | * Make a hole at the start of the right neighbor block, then | 2094 | * Make a hole at the start of the right neighbor block, then |
1910 | * copy the last left block entry to the hole. | 2095 | * copy the last left block entry to the hole. |
1911 | */ | 2096 | */ |
1912 | if (level > 0) { | 2097 | if (level > 0) { |
1913 | /* It's a nonleaf. make a hole in the keys and ptrs */ | 2098 | /* It's a nonleaf. make a hole in the keys and ptrs */ |
1914 | union xfs_btree_key *lkp; | 2099 | union xfs_btree_key *lkp; |
1915 | union xfs_btree_ptr *lpp; | 2100 | union xfs_btree_ptr *lpp; |
1916 | union xfs_btree_ptr *rpp; | 2101 | union xfs_btree_ptr *rpp; |
1917 | 2102 | ||
1918 | lkp = xfs_btree_key_addr(cur, lrecs, left); | 2103 | lkp = xfs_btree_key_addr(cur, lrecs, left); |
1919 | lpp = xfs_btree_ptr_addr(cur, lrecs, left); | 2104 | lpp = xfs_btree_ptr_addr(cur, lrecs, left); |
1920 | rkp = xfs_btree_key_addr(cur, 1, right); | 2105 | rkp = xfs_btree_key_addr(cur, 1, right); |
1921 | rpp = xfs_btree_ptr_addr(cur, 1, right); | 2106 | rpp = xfs_btree_ptr_addr(cur, 1, right); |
1922 | 2107 | ||
1923 | #ifdef DEBUG | 2108 | #ifdef DEBUG |
1924 | for (i = rrecs - 1; i >= 0; i--) { | 2109 | for (i = rrecs - 1; i >= 0; i--) { |
1925 | error = xfs_btree_check_ptr(cur, rpp, i, level); | 2110 | error = xfs_btree_check_ptr(cur, rpp, i, level); |
1926 | if (error) | 2111 | if (error) |
1927 | goto error0; | 2112 | goto error0; |
1928 | } | 2113 | } |
1929 | #endif | 2114 | #endif |
1930 | 2115 | ||
1931 | xfs_btree_shift_keys(cur, rkp, 1, rrecs); | 2116 | xfs_btree_shift_keys(cur, rkp, 1, rrecs); |
1932 | xfs_btree_shift_ptrs(cur, rpp, 1, rrecs); | 2117 | xfs_btree_shift_ptrs(cur, rpp, 1, rrecs); |
1933 | 2118 | ||
1934 | #ifdef DEBUG | 2119 | #ifdef DEBUG |
1935 | error = xfs_btree_check_ptr(cur, lpp, 0, level); | 2120 | error = xfs_btree_check_ptr(cur, lpp, 0, level); |
1936 | if (error) | 2121 | if (error) |
1937 | goto error0; | 2122 | goto error0; |
1938 | #endif | 2123 | #endif |
1939 | 2124 | ||
1940 | /* Now put the new data in, and log it. */ | 2125 | /* Now put the new data in, and log it. */ |
1941 | xfs_btree_copy_keys(cur, rkp, lkp, 1); | 2126 | xfs_btree_copy_keys(cur, rkp, lkp, 1); |
1942 | xfs_btree_copy_ptrs(cur, rpp, lpp, 1); | 2127 | xfs_btree_copy_ptrs(cur, rpp, lpp, 1); |
1943 | 2128 | ||
1944 | xfs_btree_log_keys(cur, rbp, 1, rrecs + 1); | 2129 | xfs_btree_log_keys(cur, rbp, 1, rrecs + 1); |
1945 | xfs_btree_log_ptrs(cur, rbp, 1, rrecs + 1); | 2130 | xfs_btree_log_ptrs(cur, rbp, 1, rrecs + 1); |
1946 | 2131 | ||
1947 | xfs_btree_check_key(cur->bc_btnum, rkp, | 2132 | xfs_btree_check_key(cur->bc_btnum, rkp, |
1948 | xfs_btree_key_addr(cur, 2, right)); | 2133 | xfs_btree_key_addr(cur, 2, right)); |
1949 | } else { | 2134 | } else { |
1950 | /* It's a leaf. make a hole in the records */ | 2135 | /* It's a leaf. make a hole in the records */ |
1951 | union xfs_btree_rec *lrp; | 2136 | union xfs_btree_rec *lrp; |
1952 | union xfs_btree_rec *rrp; | 2137 | union xfs_btree_rec *rrp; |
1953 | 2138 | ||
1954 | lrp = xfs_btree_rec_addr(cur, lrecs, left); | 2139 | lrp = xfs_btree_rec_addr(cur, lrecs, left); |
1955 | rrp = xfs_btree_rec_addr(cur, 1, right); | 2140 | rrp = xfs_btree_rec_addr(cur, 1, right); |
1956 | 2141 | ||
1957 | xfs_btree_shift_recs(cur, rrp, 1, rrecs); | 2142 | xfs_btree_shift_recs(cur, rrp, 1, rrecs); |
1958 | 2143 | ||
1959 | /* Now put the new data in, and log it. */ | 2144 | /* Now put the new data in, and log it. */ |
1960 | xfs_btree_copy_recs(cur, rrp, lrp, 1); | 2145 | xfs_btree_copy_recs(cur, rrp, lrp, 1); |
1961 | xfs_btree_log_recs(cur, rbp, 1, rrecs + 1); | 2146 | xfs_btree_log_recs(cur, rbp, 1, rrecs + 1); |
1962 | 2147 | ||
1963 | cur->bc_ops->init_key_from_rec(&key, rrp); | 2148 | cur->bc_ops->init_key_from_rec(&key, rrp); |
1964 | rkp = &key; | 2149 | rkp = &key; |
1965 | 2150 | ||
1966 | xfs_btree_check_rec(cur->bc_btnum, rrp, | 2151 | xfs_btree_check_rec(cur->bc_btnum, rrp, |
1967 | xfs_btree_rec_addr(cur, 2, right)); | 2152 | xfs_btree_rec_addr(cur, 2, right)); |
1968 | } | 2153 | } |
1969 | 2154 | ||
1970 | /* | 2155 | /* |
1971 | * Decrement and log left's numrecs, bump and log right's numrecs. | 2156 | * Decrement and log left's numrecs, bump and log right's numrecs. |
1972 | */ | 2157 | */ |
1973 | xfs_btree_set_numrecs(left, --lrecs); | 2158 | xfs_btree_set_numrecs(left, --lrecs); |
1974 | xfs_btree_log_block(cur, lbp, XFS_BB_NUMRECS); | 2159 | xfs_btree_log_block(cur, lbp, XFS_BB_NUMRECS); |
1975 | 2160 | ||
1976 | xfs_btree_set_numrecs(right, ++rrecs); | 2161 | xfs_btree_set_numrecs(right, ++rrecs); |
1977 | xfs_btree_log_block(cur, rbp, XFS_BB_NUMRECS); | 2162 | xfs_btree_log_block(cur, rbp, XFS_BB_NUMRECS); |
1978 | 2163 | ||
1979 | /* | 2164 | /* |
1980 | * Using a temporary cursor, update the parent key values of the | 2165 | * Using a temporary cursor, update the parent key values of the |
1981 | * block on the right. | 2166 | * block on the right. |
1982 | */ | 2167 | */ |
1983 | error = xfs_btree_dup_cursor(cur, &tcur); | 2168 | error = xfs_btree_dup_cursor(cur, &tcur); |
1984 | if (error) | 2169 | if (error) |
1985 | goto error0; | 2170 | goto error0; |
1986 | i = xfs_btree_lastrec(tcur, level); | 2171 | i = xfs_btree_lastrec(tcur, level); |
1987 | XFS_WANT_CORRUPTED_GOTO(i == 1, error0); | 2172 | XFS_WANT_CORRUPTED_GOTO(i == 1, error0); |
1988 | 2173 | ||
1989 | error = xfs_btree_increment(tcur, level, &i); | 2174 | error = xfs_btree_increment(tcur, level, &i); |
1990 | if (error) | 2175 | if (error) |
1991 | goto error1; | 2176 | goto error1; |
1992 | 2177 | ||
1993 | error = xfs_btree_updkey(tcur, rkp, level + 1); | 2178 | error = xfs_btree_updkey(tcur, rkp, level + 1); |
1994 | if (error) | 2179 | if (error) |
1995 | goto error1; | 2180 | goto error1; |
1996 | 2181 | ||
1997 | xfs_btree_del_cursor(tcur, XFS_BTREE_NOERROR); | 2182 | xfs_btree_del_cursor(tcur, XFS_BTREE_NOERROR); |
1998 | 2183 | ||
1999 | XFS_BTREE_TRACE_CURSOR(cur, XBT_EXIT); | 2184 | XFS_BTREE_TRACE_CURSOR(cur, XBT_EXIT); |
2000 | *stat = 1; | 2185 | *stat = 1; |
2001 | return 0; | 2186 | return 0; |
2002 | 2187 | ||
2003 | out0: | 2188 | out0: |
2004 | XFS_BTREE_TRACE_CURSOR(cur, XBT_EXIT); | 2189 | XFS_BTREE_TRACE_CURSOR(cur, XBT_EXIT); |
2005 | *stat = 0; | 2190 | *stat = 0; |
2006 | return 0; | 2191 | return 0; |
2007 | 2192 | ||
2008 | error0: | 2193 | error0: |
2009 | XFS_BTREE_TRACE_CURSOR(cur, XBT_ERROR); | 2194 | XFS_BTREE_TRACE_CURSOR(cur, XBT_ERROR); |
2010 | return error; | 2195 | return error; |
2011 | 2196 | ||
2012 | error1: | 2197 | error1: |
2013 | XFS_BTREE_TRACE_CURSOR(tcur, XBT_ERROR); | 2198 | XFS_BTREE_TRACE_CURSOR(tcur, XBT_ERROR); |
2014 | xfs_btree_del_cursor(tcur, XFS_BTREE_ERROR); | 2199 | xfs_btree_del_cursor(tcur, XFS_BTREE_ERROR); |
2015 | return error; | 2200 | return error; |
2016 | } | 2201 | } |
2017 | 2202 |
fs/xfs/xfs_btree.h
1 | /* | 1 | /* |
2 | * Copyright (c) 2000-2001,2005 Silicon Graphics, Inc. | 2 | * Copyright (c) 2000-2001,2005 Silicon Graphics, Inc. |
3 | * All Rights Reserved. | 3 | * All Rights Reserved. |
4 | * | 4 | * |
5 | * This program is free software; you can redistribute it and/or | 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 | 6 | * modify it under the terms of the GNU General Public License as |
7 | * published by the Free Software Foundation. | 7 | * published by the Free Software Foundation. |
8 | * | 8 | * |
9 | * This program is distributed in the hope that it would be useful, | 9 | * This program is distributed in the hope that it would be useful, |
10 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | 10 | * but WITHOUT ANY WARRANTY; without even the implied warranty of |
11 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | 11 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
12 | * GNU General Public License for more details. | 12 | * GNU General Public License for more details. |
13 | * | 13 | * |
14 | * You should have received a copy of the GNU General Public License | 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, | 15 | * along with this program; if not, write the Free Software Foundation, |
16 | * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA | 16 | * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA |
17 | */ | 17 | */ |
18 | #ifndef __XFS_BTREE_H__ | 18 | #ifndef __XFS_BTREE_H__ |
19 | #define __XFS_BTREE_H__ | 19 | #define __XFS_BTREE_H__ |
20 | 20 | ||
21 | struct xfs_buf; | 21 | struct xfs_buf; |
22 | struct xfs_bmap_free; | 22 | struct xfs_bmap_free; |
23 | struct xfs_inode; | 23 | struct xfs_inode; |
24 | struct xfs_mount; | 24 | struct xfs_mount; |
25 | struct xfs_trans; | 25 | struct xfs_trans; |
26 | 26 | ||
27 | extern kmem_zone_t *xfs_btree_cur_zone; | 27 | extern kmem_zone_t *xfs_btree_cur_zone; |
28 | 28 | ||
29 | /* | 29 | /* |
30 | * This nonsense is to make -wlint happy. | 30 | * This nonsense is to make -wlint happy. |
31 | */ | 31 | */ |
32 | #define XFS_LOOKUP_EQ ((xfs_lookup_t)XFS_LOOKUP_EQi) | 32 | #define XFS_LOOKUP_EQ ((xfs_lookup_t)XFS_LOOKUP_EQi) |
33 | #define XFS_LOOKUP_LE ((xfs_lookup_t)XFS_LOOKUP_LEi) | 33 | #define XFS_LOOKUP_LE ((xfs_lookup_t)XFS_LOOKUP_LEi) |
34 | #define XFS_LOOKUP_GE ((xfs_lookup_t)XFS_LOOKUP_GEi) | 34 | #define XFS_LOOKUP_GE ((xfs_lookup_t)XFS_LOOKUP_GEi) |
35 | 35 | ||
36 | #define XFS_BTNUM_BNO ((xfs_btnum_t)XFS_BTNUM_BNOi) | 36 | #define XFS_BTNUM_BNO ((xfs_btnum_t)XFS_BTNUM_BNOi) |
37 | #define XFS_BTNUM_CNT ((xfs_btnum_t)XFS_BTNUM_CNTi) | 37 | #define XFS_BTNUM_CNT ((xfs_btnum_t)XFS_BTNUM_CNTi) |
38 | #define XFS_BTNUM_BMAP ((xfs_btnum_t)XFS_BTNUM_BMAPi) | 38 | #define XFS_BTNUM_BMAP ((xfs_btnum_t)XFS_BTNUM_BMAPi) |
39 | #define XFS_BTNUM_INO ((xfs_btnum_t)XFS_BTNUM_INOi) | 39 | #define XFS_BTNUM_INO ((xfs_btnum_t)XFS_BTNUM_INOi) |
40 | 40 | ||
41 | /* | 41 | /* |
42 | * Short form header: space allocation btrees. | 42 | * Short form header: space allocation btrees. |
43 | */ | 43 | */ |
44 | typedef struct xfs_btree_sblock { | 44 | typedef struct xfs_btree_sblock { |
45 | __be32 bb_magic; /* magic number for block type */ | 45 | __be32 bb_magic; /* magic number for block type */ |
46 | __be16 bb_level; /* 0 is a leaf */ | 46 | __be16 bb_level; /* 0 is a leaf */ |
47 | __be16 bb_numrecs; /* current # of data records */ | 47 | __be16 bb_numrecs; /* current # of data records */ |
48 | __be32 bb_leftsib; /* left sibling block or NULLAGBLOCK */ | 48 | __be32 bb_leftsib; /* left sibling block or NULLAGBLOCK */ |
49 | __be32 bb_rightsib; /* right sibling block or NULLAGBLOCK */ | 49 | __be32 bb_rightsib; /* right sibling block or NULLAGBLOCK */ |
50 | } xfs_btree_sblock_t; | 50 | } xfs_btree_sblock_t; |
51 | 51 | ||
52 | /* | 52 | /* |
53 | * Long form header: bmap btrees. | 53 | * Long form header: bmap btrees. |
54 | */ | 54 | */ |
55 | typedef struct xfs_btree_lblock { | 55 | typedef struct xfs_btree_lblock { |
56 | __be32 bb_magic; /* magic number for block type */ | 56 | __be32 bb_magic; /* magic number for block type */ |
57 | __be16 bb_level; /* 0 is a leaf */ | 57 | __be16 bb_level; /* 0 is a leaf */ |
58 | __be16 bb_numrecs; /* current # of data records */ | 58 | __be16 bb_numrecs; /* current # of data records */ |
59 | __be64 bb_leftsib; /* left sibling block or NULLDFSBNO */ | 59 | __be64 bb_leftsib; /* left sibling block or NULLDFSBNO */ |
60 | __be64 bb_rightsib; /* right sibling block or NULLDFSBNO */ | 60 | __be64 bb_rightsib; /* right sibling block or NULLDFSBNO */ |
61 | } xfs_btree_lblock_t; | 61 | } xfs_btree_lblock_t; |
62 | 62 | ||
63 | /* | 63 | /* |
64 | * Combined header and structure, used by common code. | 64 | * Combined header and structure, used by common code. |
65 | */ | 65 | */ |
66 | typedef struct xfs_btree_block { | 66 | typedef struct xfs_btree_block { |
67 | __be32 bb_magic; /* magic number for block type */ | 67 | __be32 bb_magic; /* magic number for block type */ |
68 | __be16 bb_level; /* 0 is a leaf */ | 68 | __be16 bb_level; /* 0 is a leaf */ |
69 | __be16 bb_numrecs; /* current # of data records */ | 69 | __be16 bb_numrecs; /* current # of data records */ |
70 | union { | 70 | union { |
71 | struct { | 71 | struct { |
72 | __be32 bb_leftsib; | 72 | __be32 bb_leftsib; |
73 | __be32 bb_rightsib; | 73 | __be32 bb_rightsib; |
74 | } s; /* short form pointers */ | 74 | } s; /* short form pointers */ |
75 | struct { | 75 | struct { |
76 | __be64 bb_leftsib; | 76 | __be64 bb_leftsib; |
77 | __be64 bb_rightsib; | 77 | __be64 bb_rightsib; |
78 | } l; /* long form pointers */ | 78 | } l; /* long form pointers */ |
79 | } bb_u; /* rest */ | 79 | } bb_u; /* rest */ |
80 | } xfs_btree_block_t; | 80 | } xfs_btree_block_t; |
81 | 81 | ||
82 | /* | 82 | /* |
83 | * Generic key, ptr and record wrapper structures. | 83 | * Generic key, ptr and record wrapper structures. |
84 | * | 84 | * |
85 | * These are disk format structures, and are converted where necessary | 85 | * These are disk format structures, and are converted where necessary |
86 | * by the btree specific code that needs to interpret them. | 86 | * by the btree specific code that needs to interpret them. |
87 | */ | 87 | */ |
88 | union xfs_btree_ptr { | 88 | union xfs_btree_ptr { |
89 | __be32 s; /* short form ptr */ | 89 | __be32 s; /* short form ptr */ |
90 | __be64 l; /* long form ptr */ | 90 | __be64 l; /* long form ptr */ |
91 | }; | 91 | }; |
92 | 92 | ||
93 | union xfs_btree_key { | 93 | union xfs_btree_key { |
94 | xfs_bmbt_key_t bmbt; | 94 | xfs_bmbt_key_t bmbt; |
95 | xfs_bmdr_key_t bmbr; /* bmbt root block */ | 95 | xfs_bmdr_key_t bmbr; /* bmbt root block */ |
96 | xfs_alloc_key_t alloc; | 96 | xfs_alloc_key_t alloc; |
97 | xfs_inobt_key_t inobt; | 97 | xfs_inobt_key_t inobt; |
98 | }; | 98 | }; |
99 | 99 | ||
100 | union xfs_btree_rec { | 100 | union xfs_btree_rec { |
101 | xfs_bmbt_rec_t bmbt; | 101 | xfs_bmbt_rec_t bmbt; |
102 | xfs_bmdr_rec_t bmbr; /* bmbt root block */ | 102 | xfs_bmdr_rec_t bmbr; /* bmbt root block */ |
103 | xfs_alloc_rec_t alloc; | 103 | xfs_alloc_rec_t alloc; |
104 | xfs_inobt_rec_t inobt; | 104 | xfs_inobt_rec_t inobt; |
105 | }; | 105 | }; |
106 | 106 | ||
107 | /* | 107 | /* |
108 | * For logging record fields. | 108 | * For logging record fields. |
109 | */ | 109 | */ |
110 | #define XFS_BB_MAGIC 0x01 | 110 | #define XFS_BB_MAGIC 0x01 |
111 | #define XFS_BB_LEVEL 0x02 | 111 | #define XFS_BB_LEVEL 0x02 |
112 | #define XFS_BB_NUMRECS 0x04 | 112 | #define XFS_BB_NUMRECS 0x04 |
113 | #define XFS_BB_LEFTSIB 0x08 | 113 | #define XFS_BB_LEFTSIB 0x08 |
114 | #define XFS_BB_RIGHTSIB 0x10 | 114 | #define XFS_BB_RIGHTSIB 0x10 |
115 | #define XFS_BB_NUM_BITS 5 | 115 | #define XFS_BB_NUM_BITS 5 |
116 | #define XFS_BB_ALL_BITS ((1 << XFS_BB_NUM_BITS) - 1) | 116 | #define XFS_BB_ALL_BITS ((1 << XFS_BB_NUM_BITS) - 1) |
117 | 117 | ||
118 | /* | 118 | /* |
119 | * Magic numbers for btree blocks. | 119 | * Magic numbers for btree blocks. |
120 | */ | 120 | */ |
121 | extern const __uint32_t xfs_magics[]; | 121 | extern const __uint32_t xfs_magics[]; |
122 | 122 | ||
123 | /* | 123 | /* |
124 | * Generic stats interface | 124 | * Generic stats interface |
125 | */ | 125 | */ |
126 | #define __XFS_BTREE_STATS_INC(type, stat) \ | 126 | #define __XFS_BTREE_STATS_INC(type, stat) \ |
127 | XFS_STATS_INC(xs_ ## type ## _2_ ## stat) | 127 | XFS_STATS_INC(xs_ ## type ## _2_ ## stat) |
128 | #define XFS_BTREE_STATS_INC(cur, stat) \ | 128 | #define XFS_BTREE_STATS_INC(cur, stat) \ |
129 | do { \ | 129 | do { \ |
130 | switch (cur->bc_btnum) { \ | 130 | switch (cur->bc_btnum) { \ |
131 | case XFS_BTNUM_BNO: __XFS_BTREE_STATS_INC(abtb, stat); break; \ | 131 | case XFS_BTNUM_BNO: __XFS_BTREE_STATS_INC(abtb, stat); break; \ |
132 | case XFS_BTNUM_CNT: __XFS_BTREE_STATS_INC(abtc, stat); break; \ | 132 | case XFS_BTNUM_CNT: __XFS_BTREE_STATS_INC(abtc, stat); break; \ |
133 | case XFS_BTNUM_BMAP: __XFS_BTREE_STATS_INC(bmbt, stat); break; \ | 133 | case XFS_BTNUM_BMAP: __XFS_BTREE_STATS_INC(bmbt, stat); break; \ |
134 | case XFS_BTNUM_INO: __XFS_BTREE_STATS_INC(ibt, stat); break; \ | 134 | case XFS_BTNUM_INO: __XFS_BTREE_STATS_INC(ibt, stat); break; \ |
135 | case XFS_BTNUM_MAX: ASSERT(0); /* fucking gcc */ ; break; \ | 135 | case XFS_BTNUM_MAX: ASSERT(0); /* fucking gcc */ ; break; \ |
136 | } \ | 136 | } \ |
137 | } while (0) | 137 | } while (0) |
138 | 138 | ||
139 | #define __XFS_BTREE_STATS_ADD(type, stat, val) \ | 139 | #define __XFS_BTREE_STATS_ADD(type, stat, val) \ |
140 | XFS_STATS_ADD(xs_ ## type ## _2_ ## stat, val) | 140 | XFS_STATS_ADD(xs_ ## type ## _2_ ## stat, val) |
141 | #define XFS_BTREE_STATS_ADD(cur, stat, val) \ | 141 | #define XFS_BTREE_STATS_ADD(cur, stat, val) \ |
142 | do { \ | 142 | do { \ |
143 | switch (cur->bc_btnum) { \ | 143 | switch (cur->bc_btnum) { \ |
144 | case XFS_BTNUM_BNO: __XFS_BTREE_STATS_ADD(abtb, stat, val); break; \ | 144 | case XFS_BTNUM_BNO: __XFS_BTREE_STATS_ADD(abtb, stat, val); break; \ |
145 | case XFS_BTNUM_CNT: __XFS_BTREE_STATS_ADD(abtc, stat, val); break; \ | 145 | case XFS_BTNUM_CNT: __XFS_BTREE_STATS_ADD(abtc, stat, val); break; \ |
146 | case XFS_BTNUM_BMAP: __XFS_BTREE_STATS_ADD(bmbt, stat, val); break; \ | 146 | case XFS_BTNUM_BMAP: __XFS_BTREE_STATS_ADD(bmbt, stat, val); break; \ |
147 | case XFS_BTNUM_INO: __XFS_BTREE_STATS_ADD(ibt, stat, val); break; \ | 147 | case XFS_BTNUM_INO: __XFS_BTREE_STATS_ADD(ibt, stat, val); break; \ |
148 | case XFS_BTNUM_MAX: ASSERT(0); /* fucking gcc */ ; break; \ | 148 | case XFS_BTNUM_MAX: ASSERT(0); /* fucking gcc */ ; break; \ |
149 | } \ | 149 | } \ |
150 | } while (0) | 150 | } while (0) |
151 | /* | 151 | /* |
152 | * Maximum and minimum records in a btree block. | 152 | * Maximum and minimum records in a btree block. |
153 | * Given block size, type prefix, and leaf flag (0 or 1). | 153 | * Given block size, type prefix, and leaf flag (0 or 1). |
154 | * The divisor below is equivalent to lf ? (e1) : (e2) but that produces | 154 | * The divisor below is equivalent to lf ? (e1) : (e2) but that produces |
155 | * compiler warnings. | 155 | * compiler warnings. |
156 | */ | 156 | */ |
157 | #define XFS_BTREE_BLOCK_MAXRECS(bsz,t,lf) \ | 157 | #define XFS_BTREE_BLOCK_MAXRECS(bsz,t,lf) \ |
158 | ((int)(((bsz) - (uint)sizeof(t ## _block_t)) / \ | 158 | ((int)(((bsz) - (uint)sizeof(t ## _block_t)) / \ |
159 | (((lf) * (uint)sizeof(t ## _rec_t)) + \ | 159 | (((lf) * (uint)sizeof(t ## _rec_t)) + \ |
160 | ((1 - (lf)) * \ | 160 | ((1 - (lf)) * \ |
161 | ((uint)sizeof(t ## _key_t) + (uint)sizeof(t ## _ptr_t)))))) | 161 | ((uint)sizeof(t ## _key_t) + (uint)sizeof(t ## _ptr_t)))))) |
162 | #define XFS_BTREE_BLOCK_MINRECS(bsz,t,lf) \ | 162 | #define XFS_BTREE_BLOCK_MINRECS(bsz,t,lf) \ |
163 | (XFS_BTREE_BLOCK_MAXRECS(bsz,t,lf) / 2) | 163 | (XFS_BTREE_BLOCK_MAXRECS(bsz,t,lf) / 2) |
164 | 164 | ||
165 | /* | 165 | /* |
166 | * Record, key, and pointer address calculation macros. | 166 | * Record, key, and pointer address calculation macros. |
167 | * Given block size, type prefix, block pointer, and index of requested entry | 167 | * Given block size, type prefix, block pointer, and index of requested entry |
168 | * (first entry numbered 1). | 168 | * (first entry numbered 1). |
169 | */ | 169 | */ |
170 | #define XFS_BTREE_REC_ADDR(t,bb,i) \ | 170 | #define XFS_BTREE_REC_ADDR(t,bb,i) \ |
171 | ((t ## _rec_t *)((char *)(bb) + sizeof(t ## _block_t) + \ | 171 | ((t ## _rec_t *)((char *)(bb) + sizeof(t ## _block_t) + \ |
172 | ((i) - 1) * sizeof(t ## _rec_t))) | 172 | ((i) - 1) * sizeof(t ## _rec_t))) |
173 | #define XFS_BTREE_KEY_ADDR(t,bb,i) \ | 173 | #define XFS_BTREE_KEY_ADDR(t,bb,i) \ |
174 | ((t ## _key_t *)((char *)(bb) + sizeof(t ## _block_t) + \ | 174 | ((t ## _key_t *)((char *)(bb) + sizeof(t ## _block_t) + \ |
175 | ((i) - 1) * sizeof(t ## _key_t))) | 175 | ((i) - 1) * sizeof(t ## _key_t))) |
176 | #define XFS_BTREE_PTR_ADDR(t,bb,i,mxr) \ | 176 | #define XFS_BTREE_PTR_ADDR(t,bb,i,mxr) \ |
177 | ((t ## _ptr_t *)((char *)(bb) + sizeof(t ## _block_t) + \ | 177 | ((t ## _ptr_t *)((char *)(bb) + sizeof(t ## _block_t) + \ |
178 | (mxr) * sizeof(t ## _key_t) + ((i) - 1) * sizeof(t ## _ptr_t))) | 178 | (mxr) * sizeof(t ## _key_t) + ((i) - 1) * sizeof(t ## _ptr_t))) |
179 | 179 | ||
180 | #define XFS_BTREE_MAXLEVELS 8 /* max of all btrees */ | 180 | #define XFS_BTREE_MAXLEVELS 8 /* max of all btrees */ |
181 | 181 | ||
182 | struct xfs_btree_ops { | 182 | struct xfs_btree_ops { |
183 | /* size of the key and record structures */ | 183 | /* size of the key and record structures */ |
184 | size_t key_len; | 184 | size_t key_len; |
185 | size_t rec_len; | 185 | size_t rec_len; |
186 | 186 | ||
187 | /* cursor operations */ | 187 | /* cursor operations */ |
188 | struct xfs_btree_cur *(*dup_cursor)(struct xfs_btree_cur *); | 188 | struct xfs_btree_cur *(*dup_cursor)(struct xfs_btree_cur *); |
189 | 189 | ||
190 | /* update last record information */ | 190 | /* update last record information */ |
191 | void (*update_lastrec)(struct xfs_btree_cur *cur, | 191 | void (*update_lastrec)(struct xfs_btree_cur *cur, |
192 | struct xfs_btree_block *block, | 192 | struct xfs_btree_block *block, |
193 | union xfs_btree_rec *rec, | 193 | union xfs_btree_rec *rec, |
194 | int ptr, int reason); | 194 | int ptr, int reason); |
195 | 195 | ||
196 | /* records in block/level */ | 196 | /* records in block/level */ |
197 | int (*get_maxrecs)(struct xfs_btree_cur *cur, int level); | 197 | int (*get_maxrecs)(struct xfs_btree_cur *cur, int level); |
198 | 198 | ||
199 | /* init values of btree structures */ | 199 | /* init values of btree structures */ |
200 | void (*init_key_from_rec)(union xfs_btree_key *key, | 200 | void (*init_key_from_rec)(union xfs_btree_key *key, |
201 | union xfs_btree_rec *rec); | 201 | union xfs_btree_rec *rec); |
202 | void (*init_ptr_from_cur)(struct xfs_btree_cur *cur, | 202 | void (*init_ptr_from_cur)(struct xfs_btree_cur *cur, |
203 | union xfs_btree_ptr *ptr); | 203 | union xfs_btree_ptr *ptr); |
204 | 204 | ||
205 | /* difference between key value and cursor value */ | 205 | /* difference between key value and cursor value */ |
206 | __int64_t (*key_diff)(struct xfs_btree_cur *cur, | 206 | __int64_t (*key_diff)(struct xfs_btree_cur *cur, |
207 | union xfs_btree_key *key); | 207 | union xfs_btree_key *key); |
208 | 208 | ||
209 | /* btree tracing */ | 209 | /* btree tracing */ |
210 | #ifdef XFS_BTREE_TRACE | 210 | #ifdef XFS_BTREE_TRACE |
211 | void (*trace_enter)(struct xfs_btree_cur *, const char *, | 211 | void (*trace_enter)(struct xfs_btree_cur *, const char *, |
212 | char *, int, int, __psunsigned_t, | 212 | char *, int, int, __psunsigned_t, |
213 | __psunsigned_t, __psunsigned_t, | 213 | __psunsigned_t, __psunsigned_t, |
214 | __psunsigned_t, __psunsigned_t, | 214 | __psunsigned_t, __psunsigned_t, |
215 | __psunsigned_t, __psunsigned_t, | 215 | __psunsigned_t, __psunsigned_t, |
216 | __psunsigned_t, __psunsigned_t, | 216 | __psunsigned_t, __psunsigned_t, |
217 | __psunsigned_t, __psunsigned_t); | 217 | __psunsigned_t, __psunsigned_t); |
218 | void (*trace_cursor)(struct xfs_btree_cur *, __uint32_t *, | 218 | void (*trace_cursor)(struct xfs_btree_cur *, __uint32_t *, |
219 | __uint64_t *, __uint64_t *); | 219 | __uint64_t *, __uint64_t *); |
220 | void (*trace_key)(struct xfs_btree_cur *, | 220 | void (*trace_key)(struct xfs_btree_cur *, |
221 | union xfs_btree_key *, __uint64_t *, | 221 | union xfs_btree_key *, __uint64_t *, |
222 | __uint64_t *); | 222 | __uint64_t *); |
223 | void (*trace_record)(struct xfs_btree_cur *, | 223 | void (*trace_record)(struct xfs_btree_cur *, |
224 | union xfs_btree_rec *, __uint64_t *, | 224 | union xfs_btree_rec *, __uint64_t *, |
225 | __uint64_t *, __uint64_t *); | 225 | __uint64_t *, __uint64_t *); |
226 | #endif | 226 | #endif |
227 | }; | 227 | }; |
228 | 228 | ||
229 | /* | 229 | /* |
230 | * Reasons for the update_lastrec method to be called. | 230 | * Reasons for the update_lastrec method to be called. |
231 | */ | 231 | */ |
232 | #define LASTREC_UPDATE 0 | 232 | #define LASTREC_UPDATE 0 |
233 | 233 | ||
234 | 234 | ||
235 | /* | 235 | /* |
236 | * Btree cursor structure. | 236 | * Btree cursor structure. |
237 | * This collects all information needed by the btree code in one place. | 237 | * This collects all information needed by the btree code in one place. |
238 | */ | 238 | */ |
239 | typedef struct xfs_btree_cur | 239 | typedef struct xfs_btree_cur |
240 | { | 240 | { |
241 | struct xfs_trans *bc_tp; /* transaction we're in, if any */ | 241 | struct xfs_trans *bc_tp; /* transaction we're in, if any */ |
242 | struct xfs_mount *bc_mp; /* file system mount struct */ | 242 | struct xfs_mount *bc_mp; /* file system mount struct */ |
243 | const struct xfs_btree_ops *bc_ops; | 243 | const struct xfs_btree_ops *bc_ops; |
244 | uint bc_flags; /* btree features - below */ | 244 | uint bc_flags; /* btree features - below */ |
245 | union { | 245 | union { |
246 | xfs_alloc_rec_incore_t a; | 246 | xfs_alloc_rec_incore_t a; |
247 | xfs_bmbt_irec_t b; | 247 | xfs_bmbt_irec_t b; |
248 | xfs_inobt_rec_incore_t i; | 248 | xfs_inobt_rec_incore_t i; |
249 | } bc_rec; /* current insert/search record value */ | 249 | } bc_rec; /* current insert/search record value */ |
250 | struct xfs_buf *bc_bufs[XFS_BTREE_MAXLEVELS]; /* buf ptr per level */ | 250 | struct xfs_buf *bc_bufs[XFS_BTREE_MAXLEVELS]; /* buf ptr per level */ |
251 | int bc_ptrs[XFS_BTREE_MAXLEVELS]; /* key/record # */ | 251 | int bc_ptrs[XFS_BTREE_MAXLEVELS]; /* key/record # */ |
252 | __uint8_t bc_ra[XFS_BTREE_MAXLEVELS]; /* readahead bits */ | 252 | __uint8_t bc_ra[XFS_BTREE_MAXLEVELS]; /* readahead bits */ |
253 | #define XFS_BTCUR_LEFTRA 1 /* left sibling has been read-ahead */ | 253 | #define XFS_BTCUR_LEFTRA 1 /* left sibling has been read-ahead */ |
254 | #define XFS_BTCUR_RIGHTRA 2 /* right sibling has been read-ahead */ | 254 | #define XFS_BTCUR_RIGHTRA 2 /* right sibling has been read-ahead */ |
255 | __uint8_t bc_nlevels; /* number of levels in the tree */ | 255 | __uint8_t bc_nlevels; /* number of levels in the tree */ |
256 | __uint8_t bc_blocklog; /* log2(blocksize) of btree blocks */ | 256 | __uint8_t bc_blocklog; /* log2(blocksize) of btree blocks */ |
257 | xfs_btnum_t bc_btnum; /* identifies which btree type */ | 257 | xfs_btnum_t bc_btnum; /* identifies which btree type */ |
258 | union { | 258 | union { |
259 | struct { /* needed for BNO, CNT, INO */ | 259 | struct { /* needed for BNO, CNT, INO */ |
260 | struct xfs_buf *agbp; /* agf/agi buffer pointer */ | 260 | struct xfs_buf *agbp; /* agf/agi buffer pointer */ |
261 | xfs_agnumber_t agno; /* ag number */ | 261 | xfs_agnumber_t agno; /* ag number */ |
262 | } a; | 262 | } a; |
263 | struct { /* needed for BMAP */ | 263 | struct { /* needed for BMAP */ |
264 | struct xfs_inode *ip; /* pointer to our inode */ | 264 | struct xfs_inode *ip; /* pointer to our inode */ |
265 | struct xfs_bmap_free *flist; /* list to free after */ | 265 | struct xfs_bmap_free *flist; /* list to free after */ |
266 | xfs_fsblock_t firstblock; /* 1st blk allocated */ | 266 | xfs_fsblock_t firstblock; /* 1st blk allocated */ |
267 | int allocated; /* count of alloced */ | 267 | int allocated; /* count of alloced */ |
268 | short forksize; /* fork's inode space */ | 268 | short forksize; /* fork's inode space */ |
269 | char whichfork; /* data or attr fork */ | 269 | char whichfork; /* data or attr fork */ |
270 | char flags; /* flags */ | 270 | char flags; /* flags */ |
271 | #define XFS_BTCUR_BPRV_WASDEL 1 /* was delayed */ | 271 | #define XFS_BTCUR_BPRV_WASDEL 1 /* was delayed */ |
272 | } b; | 272 | } b; |
273 | } bc_private; /* per-btree type data */ | 273 | } bc_private; /* per-btree type data */ |
274 | } xfs_btree_cur_t; | 274 | } xfs_btree_cur_t; |
275 | 275 | ||
276 | /* cursor flags */ | 276 | /* cursor flags */ |
277 | #define XFS_BTREE_LONG_PTRS (1<<0) /* pointers are 64bits long */ | 277 | #define XFS_BTREE_LONG_PTRS (1<<0) /* pointers are 64bits long */ |
278 | #define XFS_BTREE_ROOT_IN_INODE (1<<1) /* root may be variable size */ | 278 | #define XFS_BTREE_ROOT_IN_INODE (1<<1) /* root may be variable size */ |
279 | #define XFS_BTREE_LASTREC_UPDATE (1<<2) /* track last rec externally */ | 279 | #define XFS_BTREE_LASTREC_UPDATE (1<<2) /* track last rec externally */ |
280 | 280 | ||
281 | 281 | ||
282 | #define XFS_BTREE_NOERROR 0 | 282 | #define XFS_BTREE_NOERROR 0 |
283 | #define XFS_BTREE_ERROR 1 | 283 | #define XFS_BTREE_ERROR 1 |
284 | 284 | ||
285 | /* | 285 | /* |
286 | * Convert from buffer to btree block header. | 286 | * Convert from buffer to btree block header. |
287 | */ | 287 | */ |
288 | #define XFS_BUF_TO_BLOCK(bp) ((xfs_btree_block_t *)XFS_BUF_PTR(bp)) | 288 | #define XFS_BUF_TO_BLOCK(bp) ((xfs_btree_block_t *)XFS_BUF_PTR(bp)) |
289 | #define XFS_BUF_TO_LBLOCK(bp) ((xfs_btree_lblock_t *)XFS_BUF_PTR(bp)) | 289 | #define XFS_BUF_TO_LBLOCK(bp) ((xfs_btree_lblock_t *)XFS_BUF_PTR(bp)) |
290 | #define XFS_BUF_TO_SBLOCK(bp) ((xfs_btree_sblock_t *)XFS_BUF_PTR(bp)) | 290 | #define XFS_BUF_TO_SBLOCK(bp) ((xfs_btree_sblock_t *)XFS_BUF_PTR(bp)) |
291 | 291 | ||
292 | 292 | ||
293 | #ifdef __KERNEL__ | 293 | #ifdef __KERNEL__ |
294 | 294 | ||
295 | /* | 295 | /* |
296 | * Check that long form block header is ok. | 296 | * Check that long form block header is ok. |
297 | */ | 297 | */ |
298 | int /* error (0 or EFSCORRUPTED) */ | 298 | int /* error (0 or EFSCORRUPTED) */ |
299 | xfs_btree_check_lblock( | 299 | xfs_btree_check_lblock( |
300 | struct xfs_btree_cur *cur, /* btree cursor */ | 300 | struct xfs_btree_cur *cur, /* btree cursor */ |
301 | struct xfs_btree_lblock *block, /* btree long form block pointer */ | 301 | struct xfs_btree_lblock *block, /* btree long form block pointer */ |
302 | int level, /* level of the btree block */ | 302 | int level, /* level of the btree block */ |
303 | struct xfs_buf *bp); /* buffer containing block, if any */ | 303 | struct xfs_buf *bp); /* buffer containing block, if any */ |
304 | 304 | ||
305 | /* | 305 | /* |
306 | * Check that short form block header is ok. | 306 | * Check that short form block header is ok. |
307 | */ | 307 | */ |
308 | int /* error (0 or EFSCORRUPTED) */ | 308 | int /* error (0 or EFSCORRUPTED) */ |
309 | xfs_btree_check_sblock( | 309 | xfs_btree_check_sblock( |
310 | struct xfs_btree_cur *cur, /* btree cursor */ | 310 | struct xfs_btree_cur *cur, /* btree cursor */ |
311 | struct xfs_btree_sblock *block, /* btree short form block pointer */ | 311 | struct xfs_btree_sblock *block, /* btree short form block pointer */ |
312 | int level, /* level of the btree block */ | 312 | int level, /* level of the btree block */ |
313 | struct xfs_buf *bp); /* buffer containing block */ | 313 | struct xfs_buf *bp); /* buffer containing block */ |
314 | 314 | ||
315 | /* | 315 | /* |
316 | * Check that block header is ok. | 316 | * Check that block header is ok. |
317 | */ | 317 | */ |
318 | int | 318 | int |
319 | xfs_btree_check_block( | 319 | xfs_btree_check_block( |
320 | struct xfs_btree_cur *cur, /* btree cursor */ | 320 | struct xfs_btree_cur *cur, /* btree cursor */ |
321 | struct xfs_btree_block *block, /* generic btree block pointer */ | 321 | struct xfs_btree_block *block, /* generic btree block pointer */ |
322 | int level, /* level of the btree block */ | 322 | int level, /* level of the btree block */ |
323 | struct xfs_buf *bp); /* buffer containing block, if any */ | 323 | struct xfs_buf *bp); /* buffer containing block, if any */ |
324 | 324 | ||
325 | /* | 325 | /* |
326 | * Check that (long) pointer is ok. | 326 | * Check that (long) pointer is ok. |
327 | */ | 327 | */ |
328 | int /* error (0 or EFSCORRUPTED) */ | 328 | int /* error (0 or EFSCORRUPTED) */ |
329 | xfs_btree_check_lptr( | 329 | xfs_btree_check_lptr( |
330 | struct xfs_btree_cur *cur, /* btree cursor */ | 330 | struct xfs_btree_cur *cur, /* btree cursor */ |
331 | xfs_dfsbno_t ptr, /* btree block disk address */ | 331 | xfs_dfsbno_t ptr, /* btree block disk address */ |
332 | int level); /* btree block level */ | 332 | int level); /* btree block level */ |
333 | 333 | ||
334 | #define xfs_btree_check_lptr_disk(cur, ptr, level) \ | 334 | #define xfs_btree_check_lptr_disk(cur, ptr, level) \ |
335 | xfs_btree_check_lptr(cur, be64_to_cpu(ptr), level) | 335 | xfs_btree_check_lptr(cur, be64_to_cpu(ptr), level) |
336 | 336 | ||
337 | 337 | ||
338 | /* | 338 | /* |
339 | * Check that (short) pointer is ok. | 339 | * Check that (short) pointer is ok. |
340 | */ | 340 | */ |
341 | int /* error (0 or EFSCORRUPTED) */ | 341 | int /* error (0 or EFSCORRUPTED) */ |
342 | xfs_btree_check_sptr( | 342 | xfs_btree_check_sptr( |
343 | struct xfs_btree_cur *cur, /* btree cursor */ | 343 | struct xfs_btree_cur *cur, /* btree cursor */ |
344 | xfs_agblock_t ptr, /* btree block disk address */ | 344 | xfs_agblock_t ptr, /* btree block disk address */ |
345 | int level); /* btree block level */ | 345 | int level); /* btree block level */ |
346 | 346 | ||
347 | /* | 347 | /* |
348 | * Check that (short) pointer is ok. | 348 | * Check that (short) pointer is ok. |
349 | */ | 349 | */ |
350 | int /* error (0 or EFSCORRUPTED) */ | 350 | int /* error (0 or EFSCORRUPTED) */ |
351 | xfs_btree_check_ptr( | 351 | xfs_btree_check_ptr( |
352 | struct xfs_btree_cur *cur, /* btree cursor */ | 352 | struct xfs_btree_cur *cur, /* btree cursor */ |
353 | union xfs_btree_ptr *ptr, /* btree block disk address */ | 353 | union xfs_btree_ptr *ptr, /* btree block disk address */ |
354 | int index, /* offset from ptr to check */ | 354 | int index, /* offset from ptr to check */ |
355 | int level); /* btree block level */ | 355 | int level); /* btree block level */ |
356 | 356 | ||
357 | #ifdef DEBUG | 357 | #ifdef DEBUG |
358 | 358 | ||
359 | /* | 359 | /* |
360 | * Debug routine: check that keys are in the right order. | 360 | * Debug routine: check that keys are in the right order. |
361 | */ | 361 | */ |
362 | void | 362 | void |
363 | xfs_btree_check_key( | 363 | xfs_btree_check_key( |
364 | xfs_btnum_t btnum, /* btree identifier */ | 364 | xfs_btnum_t btnum, /* btree identifier */ |
365 | void *ak1, /* pointer to left (lower) key */ | 365 | void *ak1, /* pointer to left (lower) key */ |
366 | void *ak2); /* pointer to right (higher) key */ | 366 | void *ak2); /* pointer to right (higher) key */ |
367 | 367 | ||
368 | /* | 368 | /* |
369 | * Debug routine: check that records are in the right order. | 369 | * Debug routine: check that records are in the right order. |
370 | */ | 370 | */ |
371 | void | 371 | void |
372 | xfs_btree_check_rec( | 372 | xfs_btree_check_rec( |
373 | xfs_btnum_t btnum, /* btree identifier */ | 373 | xfs_btnum_t btnum, /* btree identifier */ |
374 | void *ar1, /* pointer to left (lower) record */ | 374 | void *ar1, /* pointer to left (lower) record */ |
375 | void *ar2); /* pointer to right (higher) record */ | 375 | void *ar2); /* pointer to right (higher) record */ |
376 | #else | 376 | #else |
377 | #define xfs_btree_check_key(a, b, c) | 377 | #define xfs_btree_check_key(a, b, c) |
378 | #define xfs_btree_check_rec(a, b, c) | 378 | #define xfs_btree_check_rec(a, b, c) |
379 | #endif /* DEBUG */ | 379 | #endif /* DEBUG */ |
380 | 380 | ||
381 | /* | 381 | /* |
382 | * Delete the btree cursor. | 382 | * Delete the btree cursor. |
383 | */ | 383 | */ |
384 | void | 384 | void |
385 | xfs_btree_del_cursor( | 385 | xfs_btree_del_cursor( |
386 | xfs_btree_cur_t *cur, /* btree cursor */ | 386 | xfs_btree_cur_t *cur, /* btree cursor */ |
387 | int error); /* del because of error */ | 387 | int error); /* del because of error */ |
388 | 388 | ||
389 | /* | 389 | /* |
390 | * Duplicate the btree cursor. | 390 | * Duplicate the btree cursor. |
391 | * Allocate a new one, copy the record, re-get the buffers. | 391 | * Allocate a new one, copy the record, re-get the buffers. |
392 | */ | 392 | */ |
393 | int /* error */ | 393 | int /* error */ |
394 | xfs_btree_dup_cursor( | 394 | xfs_btree_dup_cursor( |
395 | xfs_btree_cur_t *cur, /* input cursor */ | 395 | xfs_btree_cur_t *cur, /* input cursor */ |
396 | xfs_btree_cur_t **ncur);/* output cursor */ | 396 | xfs_btree_cur_t **ncur);/* output cursor */ |
397 | 397 | ||
398 | /* | 398 | /* |
399 | * Change the cursor to point to the first record in the current block | 399 | * Change the cursor to point to the first record in the current block |
400 | * at the given level. Other levels are unaffected. | 400 | * at the given level. Other levels are unaffected. |
401 | */ | 401 | */ |
402 | int /* success=1, failure=0 */ | 402 | int /* success=1, failure=0 */ |
403 | xfs_btree_firstrec( | 403 | xfs_btree_firstrec( |
404 | xfs_btree_cur_t *cur, /* btree cursor */ | 404 | xfs_btree_cur_t *cur, /* btree cursor */ |
405 | int level); /* level to change */ | 405 | int level); /* level to change */ |
406 | 406 | ||
407 | /* | 407 | /* |
408 | * Get a buffer for the block, return it with no data read. | 408 | * Get a buffer for the block, return it with no data read. |
409 | * Long-form addressing. | 409 | * Long-form addressing. |
410 | */ | 410 | */ |
411 | struct xfs_buf * /* buffer for fsbno */ | 411 | struct xfs_buf * /* buffer for fsbno */ |
412 | xfs_btree_get_bufl( | 412 | xfs_btree_get_bufl( |
413 | struct xfs_mount *mp, /* file system mount point */ | 413 | struct xfs_mount *mp, /* file system mount point */ |
414 | struct xfs_trans *tp, /* transaction pointer */ | 414 | struct xfs_trans *tp, /* transaction pointer */ |
415 | xfs_fsblock_t fsbno, /* file system block number */ | 415 | xfs_fsblock_t fsbno, /* file system block number */ |
416 | uint lock); /* lock flags for get_buf */ | 416 | uint lock); /* lock flags for get_buf */ |
417 | 417 | ||
418 | /* | 418 | /* |
419 | * Get a buffer for the block, return it with no data read. | 419 | * Get a buffer for the block, return it with no data read. |
420 | * Short-form addressing. | 420 | * Short-form addressing. |
421 | */ | 421 | */ |
422 | struct xfs_buf * /* buffer for agno/agbno */ | 422 | struct xfs_buf * /* buffer for agno/agbno */ |
423 | xfs_btree_get_bufs( | 423 | xfs_btree_get_bufs( |
424 | struct xfs_mount *mp, /* file system mount point */ | 424 | struct xfs_mount *mp, /* file system mount point */ |
425 | struct xfs_trans *tp, /* transaction pointer */ | 425 | struct xfs_trans *tp, /* transaction pointer */ |
426 | xfs_agnumber_t agno, /* allocation group number */ | 426 | xfs_agnumber_t agno, /* allocation group number */ |
427 | xfs_agblock_t agbno, /* allocation group block number */ | 427 | xfs_agblock_t agbno, /* allocation group block number */ |
428 | uint lock); /* lock flags for get_buf */ | 428 | uint lock); /* lock flags for get_buf */ |
429 | 429 | ||
430 | /* | 430 | /* |
431 | * Check for the cursor referring to the last block at the given level. | 431 | * Check for the cursor referring to the last block at the given level. |
432 | */ | 432 | */ |
433 | int /* 1=is last block, 0=not last block */ | 433 | int /* 1=is last block, 0=not last block */ |
434 | xfs_btree_islastblock( | 434 | xfs_btree_islastblock( |
435 | xfs_btree_cur_t *cur, /* btree cursor */ | 435 | xfs_btree_cur_t *cur, /* btree cursor */ |
436 | int level); /* level to check */ | 436 | int level); /* level to check */ |
437 | 437 | ||
438 | /* | 438 | /* |
439 | * Change the cursor to point to the last record in the current block | 439 | * Change the cursor to point to the last record in the current block |
440 | * at the given level. Other levels are unaffected. | 440 | * at the given level. Other levels are unaffected. |
441 | */ | 441 | */ |
442 | int /* success=1, failure=0 */ | 442 | int /* success=1, failure=0 */ |
443 | xfs_btree_lastrec( | 443 | xfs_btree_lastrec( |
444 | xfs_btree_cur_t *cur, /* btree cursor */ | 444 | xfs_btree_cur_t *cur, /* btree cursor */ |
445 | int level); /* level to change */ | 445 | int level); /* level to change */ |
446 | 446 | ||
447 | /* | 447 | /* |
448 | * Compute first and last byte offsets for the fields given. | 448 | * Compute first and last byte offsets for the fields given. |
449 | * Interprets the offsets table, which contains struct field offsets. | 449 | * Interprets the offsets table, which contains struct field offsets. |
450 | */ | 450 | */ |
451 | void | 451 | void |
452 | xfs_btree_offsets( | 452 | xfs_btree_offsets( |
453 | __int64_t fields, /* bitmask of fields */ | 453 | __int64_t fields, /* bitmask of fields */ |
454 | const short *offsets,/* table of field offsets */ | 454 | const short *offsets,/* table of field offsets */ |
455 | int nbits, /* number of bits to inspect */ | 455 | int nbits, /* number of bits to inspect */ |
456 | int *first, /* output: first byte offset */ | 456 | int *first, /* output: first byte offset */ |
457 | int *last); /* output: last byte offset */ | 457 | int *last); /* output: last byte offset */ |
458 | 458 | ||
459 | /* | 459 | /* |
460 | * Get a buffer for the block, return it read in. | 460 | * Get a buffer for the block, return it read in. |
461 | * Long-form addressing. | 461 | * Long-form addressing. |
462 | */ | 462 | */ |
463 | int /* error */ | 463 | int /* error */ |
464 | xfs_btree_read_bufl( | 464 | xfs_btree_read_bufl( |
465 | struct xfs_mount *mp, /* file system mount point */ | 465 | struct xfs_mount *mp, /* file system mount point */ |
466 | struct xfs_trans *tp, /* transaction pointer */ | 466 | struct xfs_trans *tp, /* transaction pointer */ |
467 | xfs_fsblock_t fsbno, /* file system block number */ | 467 | xfs_fsblock_t fsbno, /* file system block number */ |
468 | uint lock, /* lock flags for read_buf */ | 468 | uint lock, /* lock flags for read_buf */ |
469 | struct xfs_buf **bpp, /* buffer for fsbno */ | 469 | struct xfs_buf **bpp, /* buffer for fsbno */ |
470 | int refval);/* ref count value for buffer */ | 470 | int refval);/* ref count value for buffer */ |
471 | 471 | ||
472 | /* | 472 | /* |
473 | * Get a buffer for the block, return it read in. | 473 | * Get a buffer for the block, return it read in. |
474 | * Short-form addressing. | 474 | * Short-form addressing. |
475 | */ | 475 | */ |
476 | int /* error */ | 476 | int /* error */ |
477 | xfs_btree_read_bufs( | 477 | xfs_btree_read_bufs( |
478 | struct xfs_mount *mp, /* file system mount point */ | 478 | struct xfs_mount *mp, /* file system mount point */ |
479 | struct xfs_trans *tp, /* transaction pointer */ | 479 | struct xfs_trans *tp, /* transaction pointer */ |
480 | xfs_agnumber_t agno, /* allocation group number */ | 480 | xfs_agnumber_t agno, /* allocation group number */ |
481 | xfs_agblock_t agbno, /* allocation group block number */ | 481 | xfs_agblock_t agbno, /* allocation group block number */ |
482 | uint lock, /* lock flags for read_buf */ | 482 | uint lock, /* lock flags for read_buf */ |
483 | struct xfs_buf **bpp, /* buffer for agno/agbno */ | 483 | struct xfs_buf **bpp, /* buffer for agno/agbno */ |
484 | int refval);/* ref count value for buffer */ | 484 | int refval);/* ref count value for buffer */ |
485 | 485 | ||
486 | /* | 486 | /* |
487 | * Read-ahead the block, don't wait for it, don't return a buffer. | 487 | * Read-ahead the block, don't wait for it, don't return a buffer. |
488 | * Long-form addressing. | 488 | * Long-form addressing. |
489 | */ | 489 | */ |
490 | void /* error */ | 490 | void /* error */ |
491 | xfs_btree_reada_bufl( | 491 | xfs_btree_reada_bufl( |
492 | struct xfs_mount *mp, /* file system mount point */ | 492 | struct xfs_mount *mp, /* file system mount point */ |
493 | xfs_fsblock_t fsbno, /* file system block number */ | 493 | xfs_fsblock_t fsbno, /* file system block number */ |
494 | xfs_extlen_t count); /* count of filesystem blocks */ | 494 | xfs_extlen_t count); /* count of filesystem blocks */ |
495 | 495 | ||
496 | /* | 496 | /* |
497 | * Read-ahead the block, don't wait for it, don't return a buffer. | 497 | * Read-ahead the block, don't wait for it, don't return a buffer. |
498 | * Short-form addressing. | 498 | * Short-form addressing. |
499 | */ | 499 | */ |
500 | void /* error */ | 500 | void /* error */ |
501 | xfs_btree_reada_bufs( | 501 | xfs_btree_reada_bufs( |
502 | struct xfs_mount *mp, /* file system mount point */ | 502 | struct xfs_mount *mp, /* file system mount point */ |
503 | xfs_agnumber_t agno, /* allocation group number */ | 503 | xfs_agnumber_t agno, /* allocation group number */ |
504 | xfs_agblock_t agbno, /* allocation group block number */ | 504 | xfs_agblock_t agbno, /* allocation group block number */ |
505 | xfs_extlen_t count); /* count of filesystem blocks */ | 505 | xfs_extlen_t count); /* count of filesystem blocks */ |
506 | 506 | ||
507 | /* | 507 | /* |
508 | * Read-ahead btree blocks, at the given level. | 508 | * Read-ahead btree blocks, at the given level. |
509 | * Bits in lr are set from XFS_BTCUR_{LEFT,RIGHT}RA. | 509 | * Bits in lr are set from XFS_BTCUR_{LEFT,RIGHT}RA. |
510 | */ | 510 | */ |
511 | int /* readahead block count */ | 511 | int /* readahead block count */ |
512 | xfs_btree_readahead( | 512 | xfs_btree_readahead( |
513 | xfs_btree_cur_t *cur, /* btree cursor */ | 513 | xfs_btree_cur_t *cur, /* btree cursor */ |
514 | int lev, /* level in btree */ | 514 | int lev, /* level in btree */ |
515 | int lr); /* left/right bits */ | 515 | int lr); /* left/right bits */ |
516 | 516 | ||
517 | /* | 517 | /* |
518 | * Set the buffer for level "lev" in the cursor to bp, releasing | 518 | * Set the buffer for level "lev" in the cursor to bp, releasing |
519 | * any previous buffer. | 519 | * any previous buffer. |
520 | */ | 520 | */ |
521 | void | 521 | void |
522 | xfs_btree_setbuf( | 522 | xfs_btree_setbuf( |
523 | xfs_btree_cur_t *cur, /* btree cursor */ | 523 | xfs_btree_cur_t *cur, /* btree cursor */ |
524 | int lev, /* level in btree */ | 524 | int lev, /* level in btree */ |
525 | struct xfs_buf *bp); /* new buffer to set */ | 525 | struct xfs_buf *bp); /* new buffer to set */ |
526 | 526 | ||
527 | 527 | ||
528 | /* | 528 | /* |
529 | * Common btree core entry points. | 529 | * Common btree core entry points. |
530 | */ | 530 | */ |
531 | int xfs_btree_increment(struct xfs_btree_cur *, int, int *); | 531 | int xfs_btree_increment(struct xfs_btree_cur *, int, int *); |
532 | int xfs_btree_decrement(struct xfs_btree_cur *, int, int *); | 532 | int xfs_btree_decrement(struct xfs_btree_cur *, int, int *); |
533 | int xfs_btree_lookup(struct xfs_btree_cur *, xfs_lookup_t, int *); | 533 | int xfs_btree_lookup(struct xfs_btree_cur *, xfs_lookup_t, int *); |
534 | int xfs_btree_updkey(struct xfs_btree_cur *, union xfs_btree_key *, int); | 534 | int xfs_btree_updkey(struct xfs_btree_cur *, union xfs_btree_key *, int); |
535 | int xfs_btree_update(struct xfs_btree_cur *, union xfs_btree_rec *); | 535 | int xfs_btree_update(struct xfs_btree_cur *, union xfs_btree_rec *); |
536 | int xfs_btree_lshift(struct xfs_btree_cur *, int, int *); | ||
536 | int xfs_btree_rshift(struct xfs_btree_cur *, int, int *); | 537 | int xfs_btree_rshift(struct xfs_btree_cur *, int, int *); |
537 | 538 | ||
538 | /* | 539 | /* |
539 | * Helpers. | 540 | * Helpers. |
540 | */ | 541 | */ |
541 | static inline int xfs_btree_get_numrecs(struct xfs_btree_block *block) | 542 | static inline int xfs_btree_get_numrecs(struct xfs_btree_block *block) |
542 | { | 543 | { |
543 | return be16_to_cpu(block->bb_numrecs); | 544 | return be16_to_cpu(block->bb_numrecs); |
544 | } | 545 | } |
545 | 546 | ||
546 | static inline void xfs_btree_set_numrecs(struct xfs_btree_block *block, | 547 | static inline void xfs_btree_set_numrecs(struct xfs_btree_block *block, |
547 | __uint16_t numrecs) | 548 | __uint16_t numrecs) |
548 | { | 549 | { |
549 | block->bb_numrecs = cpu_to_be16(numrecs); | 550 | block->bb_numrecs = cpu_to_be16(numrecs); |
550 | } | 551 | } |
551 | 552 | ||
552 | static inline int xfs_btree_get_level(struct xfs_btree_block *block) | 553 | static inline int xfs_btree_get_level(struct xfs_btree_block *block) |
553 | { | 554 | { |
554 | return be16_to_cpu(block->bb_level); | 555 | return be16_to_cpu(block->bb_level); |
555 | } | 556 | } |
556 | 557 | ||
557 | #endif /* __KERNEL__ */ | 558 | #endif /* __KERNEL__ */ |
558 | 559 | ||
559 | 560 | ||
560 | /* | 561 | /* |
561 | * Min and max functions for extlen, agblock, fileoff, and filblks types. | 562 | * Min and max functions for extlen, agblock, fileoff, and filblks types. |
562 | */ | 563 | */ |
563 | #define XFS_EXTLEN_MIN(a,b) min_t(xfs_extlen_t, (a), (b)) | 564 | #define XFS_EXTLEN_MIN(a,b) min_t(xfs_extlen_t, (a), (b)) |
564 | #define XFS_EXTLEN_MAX(a,b) max_t(xfs_extlen_t, (a), (b)) | 565 | #define XFS_EXTLEN_MAX(a,b) max_t(xfs_extlen_t, (a), (b)) |
565 | #define XFS_AGBLOCK_MIN(a,b) min_t(xfs_agblock_t, (a), (b)) | 566 | #define XFS_AGBLOCK_MIN(a,b) min_t(xfs_agblock_t, (a), (b)) |
566 | #define XFS_AGBLOCK_MAX(a,b) max_t(xfs_agblock_t, (a), (b)) | 567 | #define XFS_AGBLOCK_MAX(a,b) max_t(xfs_agblock_t, (a), (b)) |
567 | #define XFS_FILEOFF_MIN(a,b) min_t(xfs_fileoff_t, (a), (b)) | 568 | #define XFS_FILEOFF_MIN(a,b) min_t(xfs_fileoff_t, (a), (b)) |
568 | #define XFS_FILEOFF_MAX(a,b) max_t(xfs_fileoff_t, (a), (b)) | 569 | #define XFS_FILEOFF_MAX(a,b) max_t(xfs_fileoff_t, (a), (b)) |
569 | #define XFS_FILBLKS_MIN(a,b) min_t(xfs_filblks_t, (a), (b)) | 570 | #define XFS_FILBLKS_MIN(a,b) min_t(xfs_filblks_t, (a), (b)) |
570 | #define XFS_FILBLKS_MAX(a,b) max_t(xfs_filblks_t, (a), (b)) | 571 | #define XFS_FILBLKS_MAX(a,b) max_t(xfs_filblks_t, (a), (b)) |
571 | 572 | ||
572 | #define XFS_FSB_SANITY_CHECK(mp,fsb) \ | 573 | #define XFS_FSB_SANITY_CHECK(mp,fsb) \ |
573 | (XFS_FSB_TO_AGNO(mp, fsb) < mp->m_sb.sb_agcount && \ | 574 | (XFS_FSB_TO_AGNO(mp, fsb) < mp->m_sb.sb_agcount && \ |
574 | XFS_FSB_TO_AGBNO(mp, fsb) < mp->m_sb.sb_agblocks) | 575 | XFS_FSB_TO_AGBNO(mp, fsb) < mp->m_sb.sb_agblocks) |
575 | 576 | ||
576 | #endif /* __XFS_BTREE_H__ */ | 577 | #endif /* __XFS_BTREE_H__ */ |
577 | 578 |
fs/xfs/xfs_ialloc_btree.c
1 | /* | 1 | /* |
2 | * Copyright (c) 2000-2001,2005 Silicon Graphics, Inc. | 2 | * Copyright (c) 2000-2001,2005 Silicon Graphics, Inc. |
3 | * All Rights Reserved. | 3 | * All Rights Reserved. |
4 | * | 4 | * |
5 | * This program is free software; you can redistribute it and/or | 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 | 6 | * modify it under the terms of the GNU General Public License as |
7 | * published by the Free Software Foundation. | 7 | * published by the Free Software Foundation. |
8 | * | 8 | * |
9 | * This program is distributed in the hope that it would be useful, | 9 | * This program is distributed in the hope that it would be useful, |
10 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | 10 | * but WITHOUT ANY WARRANTY; without even the implied warranty of |
11 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | 11 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
12 | * GNU General Public License for more details. | 12 | * GNU General Public License for more details. |
13 | * | 13 | * |
14 | * You should have received a copy of the GNU General Public License | 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, | 15 | * along with this program; if not, write the Free Software Foundation, |
16 | * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA | 16 | * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA |
17 | */ | 17 | */ |
18 | #include "xfs.h" | 18 | #include "xfs.h" |
19 | #include "xfs_fs.h" | 19 | #include "xfs_fs.h" |
20 | #include "xfs_types.h" | 20 | #include "xfs_types.h" |
21 | #include "xfs_bit.h" | 21 | #include "xfs_bit.h" |
22 | #include "xfs_log.h" | 22 | #include "xfs_log.h" |
23 | #include "xfs_inum.h" | 23 | #include "xfs_inum.h" |
24 | #include "xfs_trans.h" | 24 | #include "xfs_trans.h" |
25 | #include "xfs_sb.h" | 25 | #include "xfs_sb.h" |
26 | #include "xfs_ag.h" | 26 | #include "xfs_ag.h" |
27 | #include "xfs_dir2.h" | 27 | #include "xfs_dir2.h" |
28 | #include "xfs_dmapi.h" | 28 | #include "xfs_dmapi.h" |
29 | #include "xfs_mount.h" | 29 | #include "xfs_mount.h" |
30 | #include "xfs_bmap_btree.h" | 30 | #include "xfs_bmap_btree.h" |
31 | #include "xfs_alloc_btree.h" | 31 | #include "xfs_alloc_btree.h" |
32 | #include "xfs_ialloc_btree.h" | 32 | #include "xfs_ialloc_btree.h" |
33 | #include "xfs_dir2_sf.h" | 33 | #include "xfs_dir2_sf.h" |
34 | #include "xfs_attr_sf.h" | 34 | #include "xfs_attr_sf.h" |
35 | #include "xfs_dinode.h" | 35 | #include "xfs_dinode.h" |
36 | #include "xfs_inode.h" | 36 | #include "xfs_inode.h" |
37 | #include "xfs_btree.h" | 37 | #include "xfs_btree.h" |
38 | #include "xfs_ialloc.h" | 38 | #include "xfs_ialloc.h" |
39 | #include "xfs_alloc.h" | 39 | #include "xfs_alloc.h" |
40 | #include "xfs_error.h" | 40 | #include "xfs_error.h" |
41 | 41 | ||
42 | STATIC void xfs_inobt_log_block(xfs_trans_t *, xfs_buf_t *, int); | 42 | STATIC void xfs_inobt_log_block(xfs_trans_t *, xfs_buf_t *, int); |
43 | STATIC void xfs_inobt_log_keys(xfs_btree_cur_t *, xfs_buf_t *, int, int); | 43 | STATIC void xfs_inobt_log_keys(xfs_btree_cur_t *, xfs_buf_t *, int, int); |
44 | STATIC void xfs_inobt_log_ptrs(xfs_btree_cur_t *, xfs_buf_t *, int, int); | 44 | STATIC void xfs_inobt_log_ptrs(xfs_btree_cur_t *, xfs_buf_t *, int, int); |
45 | STATIC void xfs_inobt_log_recs(xfs_btree_cur_t *, xfs_buf_t *, int, int); | 45 | STATIC void xfs_inobt_log_recs(xfs_btree_cur_t *, xfs_buf_t *, int, int); |
46 | STATIC int xfs_inobt_lshift(xfs_btree_cur_t *, int, int *); | ||
47 | STATIC int xfs_inobt_newroot(xfs_btree_cur_t *, int *); | 46 | STATIC int xfs_inobt_newroot(xfs_btree_cur_t *, int *); |
48 | STATIC int xfs_inobt_split(xfs_btree_cur_t *, int, xfs_agblock_t *, | 47 | STATIC int xfs_inobt_split(xfs_btree_cur_t *, int, xfs_agblock_t *, |
49 | xfs_inobt_key_t *, xfs_btree_cur_t **, int *); | 48 | xfs_inobt_key_t *, xfs_btree_cur_t **, int *); |
50 | 49 | ||
51 | /* | 50 | /* |
52 | * Single level of the xfs_inobt_delete record deletion routine. | 51 | * Single level of the xfs_inobt_delete record deletion routine. |
53 | * Delete record pointed to by cur/level. | 52 | * Delete record pointed to by cur/level. |
54 | * Remove the record from its block then rebalance the tree. | 53 | * Remove the record from its block then rebalance the tree. |
55 | * Return 0 for error, 1 for done, 2 to go on to the next level. | 54 | * Return 0 for error, 1 for done, 2 to go on to the next level. |
56 | */ | 55 | */ |
57 | STATIC int /* error */ | 56 | STATIC int /* error */ |
58 | xfs_inobt_delrec( | 57 | xfs_inobt_delrec( |
59 | xfs_btree_cur_t *cur, /* btree cursor */ | 58 | xfs_btree_cur_t *cur, /* btree cursor */ |
60 | int level, /* level removing record from */ | 59 | int level, /* level removing record from */ |
61 | int *stat) /* fail/done/go-on */ | 60 | int *stat) /* fail/done/go-on */ |
62 | { | 61 | { |
63 | xfs_buf_t *agbp; /* buffer for a.g. inode header */ | 62 | xfs_buf_t *agbp; /* buffer for a.g. inode header */ |
64 | xfs_mount_t *mp; /* mount structure */ | 63 | xfs_mount_t *mp; /* mount structure */ |
65 | xfs_agi_t *agi; /* allocation group inode header */ | 64 | xfs_agi_t *agi; /* allocation group inode header */ |
66 | xfs_inobt_block_t *block; /* btree block record/key lives in */ | 65 | xfs_inobt_block_t *block; /* btree block record/key lives in */ |
67 | xfs_agblock_t bno; /* btree block number */ | 66 | xfs_agblock_t bno; /* btree block number */ |
68 | xfs_buf_t *bp; /* buffer for block */ | 67 | xfs_buf_t *bp; /* buffer for block */ |
69 | int error; /* error return value */ | 68 | int error; /* error return value */ |
70 | int i; /* loop index */ | 69 | int i; /* loop index */ |
71 | xfs_inobt_key_t key; /* kp points here if block is level 0 */ | 70 | xfs_inobt_key_t key; /* kp points here if block is level 0 */ |
72 | xfs_inobt_key_t *kp = NULL; /* pointer to btree keys */ | 71 | xfs_inobt_key_t *kp = NULL; /* pointer to btree keys */ |
73 | xfs_agblock_t lbno; /* left block's block number */ | 72 | xfs_agblock_t lbno; /* left block's block number */ |
74 | xfs_buf_t *lbp; /* left block's buffer pointer */ | 73 | xfs_buf_t *lbp; /* left block's buffer pointer */ |
75 | xfs_inobt_block_t *left; /* left btree block */ | 74 | xfs_inobt_block_t *left; /* left btree block */ |
76 | xfs_inobt_key_t *lkp; /* left block key pointer */ | 75 | xfs_inobt_key_t *lkp; /* left block key pointer */ |
77 | xfs_inobt_ptr_t *lpp; /* left block address pointer */ | 76 | xfs_inobt_ptr_t *lpp; /* left block address pointer */ |
78 | int lrecs = 0; /* number of records in left block */ | 77 | int lrecs = 0; /* number of records in left block */ |
79 | xfs_inobt_rec_t *lrp; /* left block record pointer */ | 78 | xfs_inobt_rec_t *lrp; /* left block record pointer */ |
80 | xfs_inobt_ptr_t *pp = NULL; /* pointer to btree addresses */ | 79 | xfs_inobt_ptr_t *pp = NULL; /* pointer to btree addresses */ |
81 | int ptr; /* index in btree block for this rec */ | 80 | int ptr; /* index in btree block for this rec */ |
82 | xfs_agblock_t rbno; /* right block's block number */ | 81 | xfs_agblock_t rbno; /* right block's block number */ |
83 | xfs_buf_t *rbp; /* right block's buffer pointer */ | 82 | xfs_buf_t *rbp; /* right block's buffer pointer */ |
84 | xfs_inobt_block_t *right; /* right btree block */ | 83 | xfs_inobt_block_t *right; /* right btree block */ |
85 | xfs_inobt_key_t *rkp; /* right block key pointer */ | 84 | xfs_inobt_key_t *rkp; /* right block key pointer */ |
86 | xfs_inobt_rec_t *rp; /* pointer to btree records */ | 85 | xfs_inobt_rec_t *rp; /* pointer to btree records */ |
87 | xfs_inobt_ptr_t *rpp; /* right block address pointer */ | 86 | xfs_inobt_ptr_t *rpp; /* right block address pointer */ |
88 | int rrecs = 0; /* number of records in right block */ | 87 | int rrecs = 0; /* number of records in right block */ |
89 | int numrecs; | 88 | int numrecs; |
90 | xfs_inobt_rec_t *rrp; /* right block record pointer */ | 89 | xfs_inobt_rec_t *rrp; /* right block record pointer */ |
91 | xfs_btree_cur_t *tcur; /* temporary btree cursor */ | 90 | xfs_btree_cur_t *tcur; /* temporary btree cursor */ |
92 | 91 | ||
93 | mp = cur->bc_mp; | 92 | mp = cur->bc_mp; |
94 | 93 | ||
95 | /* | 94 | /* |
96 | * Get the index of the entry being deleted, check for nothing there. | 95 | * Get the index of the entry being deleted, check for nothing there. |
97 | */ | 96 | */ |
98 | ptr = cur->bc_ptrs[level]; | 97 | ptr = cur->bc_ptrs[level]; |
99 | if (ptr == 0) { | 98 | if (ptr == 0) { |
100 | *stat = 0; | 99 | *stat = 0; |
101 | return 0; | 100 | return 0; |
102 | } | 101 | } |
103 | 102 | ||
104 | /* | 103 | /* |
105 | * Get the buffer & block containing the record or key/ptr. | 104 | * Get the buffer & block containing the record or key/ptr. |
106 | */ | 105 | */ |
107 | bp = cur->bc_bufs[level]; | 106 | bp = cur->bc_bufs[level]; |
108 | block = XFS_BUF_TO_INOBT_BLOCK(bp); | 107 | block = XFS_BUF_TO_INOBT_BLOCK(bp); |
109 | #ifdef DEBUG | 108 | #ifdef DEBUG |
110 | if ((error = xfs_btree_check_sblock(cur, block, level, bp))) | 109 | if ((error = xfs_btree_check_sblock(cur, block, level, bp))) |
111 | return error; | 110 | return error; |
112 | #endif | 111 | #endif |
113 | /* | 112 | /* |
114 | * Fail if we're off the end of the block. | 113 | * Fail if we're off the end of the block. |
115 | */ | 114 | */ |
116 | 115 | ||
117 | numrecs = be16_to_cpu(block->bb_numrecs); | 116 | numrecs = be16_to_cpu(block->bb_numrecs); |
118 | if (ptr > numrecs) { | 117 | if (ptr > numrecs) { |
119 | *stat = 0; | 118 | *stat = 0; |
120 | return 0; | 119 | return 0; |
121 | } | 120 | } |
122 | /* | 121 | /* |
123 | * It's a nonleaf. Excise the key and ptr being deleted, by | 122 | * It's a nonleaf. Excise the key and ptr being deleted, by |
124 | * sliding the entries past them down one. | 123 | * sliding the entries past them down one. |
125 | * Log the changed areas of the block. | 124 | * Log the changed areas of the block. |
126 | */ | 125 | */ |
127 | if (level > 0) { | 126 | if (level > 0) { |
128 | kp = XFS_INOBT_KEY_ADDR(block, 1, cur); | 127 | kp = XFS_INOBT_KEY_ADDR(block, 1, cur); |
129 | pp = XFS_INOBT_PTR_ADDR(block, 1, cur); | 128 | pp = XFS_INOBT_PTR_ADDR(block, 1, cur); |
130 | #ifdef DEBUG | 129 | #ifdef DEBUG |
131 | for (i = ptr; i < numrecs; i++) { | 130 | for (i = ptr; i < numrecs; i++) { |
132 | if ((error = xfs_btree_check_sptr(cur, be32_to_cpu(pp[i]), level))) | 131 | if ((error = xfs_btree_check_sptr(cur, be32_to_cpu(pp[i]), level))) |
133 | return error; | 132 | return error; |
134 | } | 133 | } |
135 | #endif | 134 | #endif |
136 | if (ptr < numrecs) { | 135 | if (ptr < numrecs) { |
137 | memmove(&kp[ptr - 1], &kp[ptr], | 136 | memmove(&kp[ptr - 1], &kp[ptr], |
138 | (numrecs - ptr) * sizeof(*kp)); | 137 | (numrecs - ptr) * sizeof(*kp)); |
139 | memmove(&pp[ptr - 1], &pp[ptr], | 138 | memmove(&pp[ptr - 1], &pp[ptr], |
140 | (numrecs - ptr) * sizeof(*kp)); | 139 | (numrecs - ptr) * sizeof(*kp)); |
141 | xfs_inobt_log_keys(cur, bp, ptr, numrecs - 1); | 140 | xfs_inobt_log_keys(cur, bp, ptr, numrecs - 1); |
142 | xfs_inobt_log_ptrs(cur, bp, ptr, numrecs - 1); | 141 | xfs_inobt_log_ptrs(cur, bp, ptr, numrecs - 1); |
143 | } | 142 | } |
144 | } | 143 | } |
145 | /* | 144 | /* |
146 | * It's a leaf. Excise the record being deleted, by sliding the | 145 | * It's a leaf. Excise the record being deleted, by sliding the |
147 | * entries past it down one. Log the changed areas of the block. | 146 | * entries past it down one. Log the changed areas of the block. |
148 | */ | 147 | */ |
149 | else { | 148 | else { |
150 | rp = XFS_INOBT_REC_ADDR(block, 1, cur); | 149 | rp = XFS_INOBT_REC_ADDR(block, 1, cur); |
151 | if (ptr < numrecs) { | 150 | if (ptr < numrecs) { |
152 | memmove(&rp[ptr - 1], &rp[ptr], | 151 | memmove(&rp[ptr - 1], &rp[ptr], |
153 | (numrecs - ptr) * sizeof(*rp)); | 152 | (numrecs - ptr) * sizeof(*rp)); |
154 | xfs_inobt_log_recs(cur, bp, ptr, numrecs - 1); | 153 | xfs_inobt_log_recs(cur, bp, ptr, numrecs - 1); |
155 | } | 154 | } |
156 | /* | 155 | /* |
157 | * If it's the first record in the block, we'll need a key | 156 | * If it's the first record in the block, we'll need a key |
158 | * structure to pass up to the next level (updkey). | 157 | * structure to pass up to the next level (updkey). |
159 | */ | 158 | */ |
160 | if (ptr == 1) { | 159 | if (ptr == 1) { |
161 | key.ir_startino = rp->ir_startino; | 160 | key.ir_startino = rp->ir_startino; |
162 | kp = &key; | 161 | kp = &key; |
163 | } | 162 | } |
164 | } | 163 | } |
165 | /* | 164 | /* |
166 | * Decrement and log the number of entries in the block. | 165 | * Decrement and log the number of entries in the block. |
167 | */ | 166 | */ |
168 | numrecs--; | 167 | numrecs--; |
169 | block->bb_numrecs = cpu_to_be16(numrecs); | 168 | block->bb_numrecs = cpu_to_be16(numrecs); |
170 | xfs_inobt_log_block(cur->bc_tp, bp, XFS_BB_NUMRECS); | 169 | xfs_inobt_log_block(cur->bc_tp, bp, XFS_BB_NUMRECS); |
171 | /* | 170 | /* |
172 | * Is this the root level? If so, we're almost done. | 171 | * Is this the root level? If so, we're almost done. |
173 | */ | 172 | */ |
174 | if (level == cur->bc_nlevels - 1) { | 173 | if (level == cur->bc_nlevels - 1) { |
175 | /* | 174 | /* |
176 | * If this is the root level, | 175 | * If this is the root level, |
177 | * and there's only one entry left, | 176 | * and there's only one entry left, |
178 | * and it's NOT the leaf level, | 177 | * and it's NOT the leaf level, |
179 | * then we can get rid of this level. | 178 | * then we can get rid of this level. |
180 | */ | 179 | */ |
181 | if (numrecs == 1 && level > 0) { | 180 | if (numrecs == 1 && level > 0) { |
182 | agbp = cur->bc_private.a.agbp; | 181 | agbp = cur->bc_private.a.agbp; |
183 | agi = XFS_BUF_TO_AGI(agbp); | 182 | agi = XFS_BUF_TO_AGI(agbp); |
184 | /* | 183 | /* |
185 | * pp is still set to the first pointer in the block. | 184 | * pp is still set to the first pointer in the block. |
186 | * Make it the new root of the btree. | 185 | * Make it the new root of the btree. |
187 | */ | 186 | */ |
188 | bno = be32_to_cpu(agi->agi_root); | 187 | bno = be32_to_cpu(agi->agi_root); |
189 | agi->agi_root = *pp; | 188 | agi->agi_root = *pp; |
190 | be32_add_cpu(&agi->agi_level, -1); | 189 | be32_add_cpu(&agi->agi_level, -1); |
191 | /* | 190 | /* |
192 | * Free the block. | 191 | * Free the block. |
193 | */ | 192 | */ |
194 | if ((error = xfs_free_extent(cur->bc_tp, | 193 | if ((error = xfs_free_extent(cur->bc_tp, |
195 | XFS_AGB_TO_FSB(mp, cur->bc_private.a.agno, bno), 1))) | 194 | XFS_AGB_TO_FSB(mp, cur->bc_private.a.agno, bno), 1))) |
196 | return error; | 195 | return error; |
197 | xfs_trans_binval(cur->bc_tp, bp); | 196 | xfs_trans_binval(cur->bc_tp, bp); |
198 | xfs_ialloc_log_agi(cur->bc_tp, agbp, | 197 | xfs_ialloc_log_agi(cur->bc_tp, agbp, |
199 | XFS_AGI_ROOT | XFS_AGI_LEVEL); | 198 | XFS_AGI_ROOT | XFS_AGI_LEVEL); |
200 | /* | 199 | /* |
201 | * Update the cursor so there's one fewer level. | 200 | * Update the cursor so there's one fewer level. |
202 | */ | 201 | */ |
203 | cur->bc_bufs[level] = NULL; | 202 | cur->bc_bufs[level] = NULL; |
204 | cur->bc_nlevels--; | 203 | cur->bc_nlevels--; |
205 | } else if (level > 0 && | 204 | } else if (level > 0 && |
206 | (error = xfs_btree_decrement(cur, level, &i))) | 205 | (error = xfs_btree_decrement(cur, level, &i))) |
207 | return error; | 206 | return error; |
208 | *stat = 1; | 207 | *stat = 1; |
209 | return 0; | 208 | return 0; |
210 | } | 209 | } |
211 | /* | 210 | /* |
212 | * If we deleted the leftmost entry in the block, update the | 211 | * If we deleted the leftmost entry in the block, update the |
213 | * key values above us in the tree. | 212 | * key values above us in the tree. |
214 | */ | 213 | */ |
215 | if (ptr == 1 && (error = xfs_btree_updkey(cur, (union xfs_btree_key *)kp, level + 1))) | 214 | if (ptr == 1 && (error = xfs_btree_updkey(cur, (union xfs_btree_key *)kp, level + 1))) |
216 | return error; | 215 | return error; |
217 | /* | 216 | /* |
218 | * If the number of records remaining in the block is at least | 217 | * If the number of records remaining in the block is at least |
219 | * the minimum, we're done. | 218 | * the minimum, we're done. |
220 | */ | 219 | */ |
221 | if (numrecs >= XFS_INOBT_BLOCK_MINRECS(level, cur)) { | 220 | if (numrecs >= XFS_INOBT_BLOCK_MINRECS(level, cur)) { |
222 | if (level > 0 && | 221 | if (level > 0 && |
223 | (error = xfs_btree_decrement(cur, level, &i))) | 222 | (error = xfs_btree_decrement(cur, level, &i))) |
224 | return error; | 223 | return error; |
225 | *stat = 1; | 224 | *stat = 1; |
226 | return 0; | 225 | return 0; |
227 | } | 226 | } |
228 | /* | 227 | /* |
229 | * Otherwise, we have to move some records around to keep the | 228 | * Otherwise, we have to move some records around to keep the |
230 | * tree balanced. Look at the left and right sibling blocks to | 229 | * tree balanced. Look at the left and right sibling blocks to |
231 | * see if we can re-balance by moving only one record. | 230 | * see if we can re-balance by moving only one record. |
232 | */ | 231 | */ |
233 | rbno = be32_to_cpu(block->bb_rightsib); | 232 | rbno = be32_to_cpu(block->bb_rightsib); |
234 | lbno = be32_to_cpu(block->bb_leftsib); | 233 | lbno = be32_to_cpu(block->bb_leftsib); |
235 | bno = NULLAGBLOCK; | 234 | bno = NULLAGBLOCK; |
236 | ASSERT(rbno != NULLAGBLOCK || lbno != NULLAGBLOCK); | 235 | ASSERT(rbno != NULLAGBLOCK || lbno != NULLAGBLOCK); |
237 | /* | 236 | /* |
238 | * Duplicate the cursor so our btree manipulations here won't | 237 | * Duplicate the cursor so our btree manipulations here won't |
239 | * disrupt the next level up. | 238 | * disrupt the next level up. |
240 | */ | 239 | */ |
241 | if ((error = xfs_btree_dup_cursor(cur, &tcur))) | 240 | if ((error = xfs_btree_dup_cursor(cur, &tcur))) |
242 | return error; | 241 | return error; |
243 | /* | 242 | /* |
244 | * If there's a right sibling, see if it's ok to shift an entry | 243 | * If there's a right sibling, see if it's ok to shift an entry |
245 | * out of it. | 244 | * out of it. |
246 | */ | 245 | */ |
247 | if (rbno != NULLAGBLOCK) { | 246 | if (rbno != NULLAGBLOCK) { |
248 | /* | 247 | /* |
249 | * Move the temp cursor to the last entry in the next block. | 248 | * Move the temp cursor to the last entry in the next block. |
250 | * Actually any entry but the first would suffice. | 249 | * Actually any entry but the first would suffice. |
251 | */ | 250 | */ |
252 | i = xfs_btree_lastrec(tcur, level); | 251 | i = xfs_btree_lastrec(tcur, level); |
253 | XFS_WANT_CORRUPTED_GOTO(i == 1, error0); | 252 | XFS_WANT_CORRUPTED_GOTO(i == 1, error0); |
254 | if ((error = xfs_btree_increment(tcur, level, &i))) | 253 | if ((error = xfs_btree_increment(tcur, level, &i))) |
255 | goto error0; | 254 | goto error0; |
256 | XFS_WANT_CORRUPTED_GOTO(i == 1, error0); | 255 | XFS_WANT_CORRUPTED_GOTO(i == 1, error0); |
257 | i = xfs_btree_lastrec(tcur, level); | 256 | i = xfs_btree_lastrec(tcur, level); |
258 | XFS_WANT_CORRUPTED_GOTO(i == 1, error0); | 257 | XFS_WANT_CORRUPTED_GOTO(i == 1, error0); |
259 | /* | 258 | /* |
260 | * Grab a pointer to the block. | 259 | * Grab a pointer to the block. |
261 | */ | 260 | */ |
262 | rbp = tcur->bc_bufs[level]; | 261 | rbp = tcur->bc_bufs[level]; |
263 | right = XFS_BUF_TO_INOBT_BLOCK(rbp); | 262 | right = XFS_BUF_TO_INOBT_BLOCK(rbp); |
264 | #ifdef DEBUG | 263 | #ifdef DEBUG |
265 | if ((error = xfs_btree_check_sblock(cur, right, level, rbp))) | 264 | if ((error = xfs_btree_check_sblock(cur, right, level, rbp))) |
266 | goto error0; | 265 | goto error0; |
267 | #endif | 266 | #endif |
268 | /* | 267 | /* |
269 | * Grab the current block number, for future use. | 268 | * Grab the current block number, for future use. |
270 | */ | 269 | */ |
271 | bno = be32_to_cpu(right->bb_leftsib); | 270 | bno = be32_to_cpu(right->bb_leftsib); |
272 | /* | 271 | /* |
273 | * If right block is full enough so that removing one entry | 272 | * If right block is full enough so that removing one entry |
274 | * won't make it too empty, and left-shifting an entry out | 273 | * won't make it too empty, and left-shifting an entry out |
275 | * of right to us works, we're done. | 274 | * of right to us works, we're done. |
276 | */ | 275 | */ |
277 | if (be16_to_cpu(right->bb_numrecs) - 1 >= | 276 | if (be16_to_cpu(right->bb_numrecs) - 1 >= |
278 | XFS_INOBT_BLOCK_MINRECS(level, cur)) { | 277 | XFS_INOBT_BLOCK_MINRECS(level, cur)) { |
279 | if ((error = xfs_inobt_lshift(tcur, level, &i))) | 278 | if ((error = xfs_btree_lshift(tcur, level, &i))) |
280 | goto error0; | 279 | goto error0; |
281 | if (i) { | 280 | if (i) { |
282 | ASSERT(be16_to_cpu(block->bb_numrecs) >= | 281 | ASSERT(be16_to_cpu(block->bb_numrecs) >= |
283 | XFS_INOBT_BLOCK_MINRECS(level, cur)); | 282 | XFS_INOBT_BLOCK_MINRECS(level, cur)); |
284 | xfs_btree_del_cursor(tcur, | 283 | xfs_btree_del_cursor(tcur, |
285 | XFS_BTREE_NOERROR); | 284 | XFS_BTREE_NOERROR); |
286 | if (level > 0 && | 285 | if (level > 0 && |
287 | (error = xfs_btree_decrement(cur, level, | 286 | (error = xfs_btree_decrement(cur, level, |
288 | &i))) | 287 | &i))) |
289 | return error; | 288 | return error; |
290 | *stat = 1; | 289 | *stat = 1; |
291 | return 0; | 290 | return 0; |
292 | } | 291 | } |
293 | } | 292 | } |
294 | /* | 293 | /* |
295 | * Otherwise, grab the number of records in right for | 294 | * Otherwise, grab the number of records in right for |
296 | * future reference, and fix up the temp cursor to point | 295 | * future reference, and fix up the temp cursor to point |
297 | * to our block again (last record). | 296 | * to our block again (last record). |
298 | */ | 297 | */ |
299 | rrecs = be16_to_cpu(right->bb_numrecs); | 298 | rrecs = be16_to_cpu(right->bb_numrecs); |
300 | if (lbno != NULLAGBLOCK) { | 299 | if (lbno != NULLAGBLOCK) { |
301 | xfs_btree_firstrec(tcur, level); | 300 | xfs_btree_firstrec(tcur, level); |
302 | if ((error = xfs_btree_decrement(tcur, level, &i))) | 301 | if ((error = xfs_btree_decrement(tcur, level, &i))) |
303 | goto error0; | 302 | goto error0; |
304 | } | 303 | } |
305 | } | 304 | } |
306 | /* | 305 | /* |
307 | * If there's a left sibling, see if it's ok to shift an entry | 306 | * If there's a left sibling, see if it's ok to shift an entry |
308 | * out of it. | 307 | * out of it. |
309 | */ | 308 | */ |
310 | if (lbno != NULLAGBLOCK) { | 309 | if (lbno != NULLAGBLOCK) { |
311 | /* | 310 | /* |
312 | * Move the temp cursor to the first entry in the | 311 | * Move the temp cursor to the first entry in the |
313 | * previous block. | 312 | * previous block. |
314 | */ | 313 | */ |
315 | xfs_btree_firstrec(tcur, level); | 314 | xfs_btree_firstrec(tcur, level); |
316 | if ((error = xfs_btree_decrement(tcur, level, &i))) | 315 | if ((error = xfs_btree_decrement(tcur, level, &i))) |
317 | goto error0; | 316 | goto error0; |
318 | xfs_btree_firstrec(tcur, level); | 317 | xfs_btree_firstrec(tcur, level); |
319 | /* | 318 | /* |
320 | * Grab a pointer to the block. | 319 | * Grab a pointer to the block. |
321 | */ | 320 | */ |
322 | lbp = tcur->bc_bufs[level]; | 321 | lbp = tcur->bc_bufs[level]; |
323 | left = XFS_BUF_TO_INOBT_BLOCK(lbp); | 322 | left = XFS_BUF_TO_INOBT_BLOCK(lbp); |
324 | #ifdef DEBUG | 323 | #ifdef DEBUG |
325 | if ((error = xfs_btree_check_sblock(cur, left, level, lbp))) | 324 | if ((error = xfs_btree_check_sblock(cur, left, level, lbp))) |
326 | goto error0; | 325 | goto error0; |
327 | #endif | 326 | #endif |
328 | /* | 327 | /* |
329 | * Grab the current block number, for future use. | 328 | * Grab the current block number, for future use. |
330 | */ | 329 | */ |
331 | bno = be32_to_cpu(left->bb_rightsib); | 330 | bno = be32_to_cpu(left->bb_rightsib); |
332 | /* | 331 | /* |
333 | * If left block is full enough so that removing one entry | 332 | * If left block is full enough so that removing one entry |
334 | * won't make it too empty, and right-shifting an entry out | 333 | * won't make it too empty, and right-shifting an entry out |
335 | * of left to us works, we're done. | 334 | * of left to us works, we're done. |
336 | */ | 335 | */ |
337 | if (be16_to_cpu(left->bb_numrecs) - 1 >= | 336 | if (be16_to_cpu(left->bb_numrecs) - 1 >= |
338 | XFS_INOBT_BLOCK_MINRECS(level, cur)) { | 337 | XFS_INOBT_BLOCK_MINRECS(level, cur)) { |
339 | if ((error = xfs_btree_rshift(tcur, level, &i))) | 338 | if ((error = xfs_btree_rshift(tcur, level, &i))) |
340 | goto error0; | 339 | goto error0; |
341 | if (i) { | 340 | if (i) { |
342 | ASSERT(be16_to_cpu(block->bb_numrecs) >= | 341 | ASSERT(be16_to_cpu(block->bb_numrecs) >= |
343 | XFS_INOBT_BLOCK_MINRECS(level, cur)); | 342 | XFS_INOBT_BLOCK_MINRECS(level, cur)); |
344 | xfs_btree_del_cursor(tcur, | 343 | xfs_btree_del_cursor(tcur, |
345 | XFS_BTREE_NOERROR); | 344 | XFS_BTREE_NOERROR); |
346 | if (level == 0) | 345 | if (level == 0) |
347 | cur->bc_ptrs[0]++; | 346 | cur->bc_ptrs[0]++; |
348 | *stat = 1; | 347 | *stat = 1; |
349 | return 0; | 348 | return 0; |
350 | } | 349 | } |
351 | } | 350 | } |
352 | /* | 351 | /* |
353 | * Otherwise, grab the number of records in right for | 352 | * Otherwise, grab the number of records in right for |
354 | * future reference. | 353 | * future reference. |
355 | */ | 354 | */ |
356 | lrecs = be16_to_cpu(left->bb_numrecs); | 355 | lrecs = be16_to_cpu(left->bb_numrecs); |
357 | } | 356 | } |
358 | /* | 357 | /* |
359 | * Delete the temp cursor, we're done with it. | 358 | * Delete the temp cursor, we're done with it. |
360 | */ | 359 | */ |
361 | xfs_btree_del_cursor(tcur, XFS_BTREE_NOERROR); | 360 | xfs_btree_del_cursor(tcur, XFS_BTREE_NOERROR); |
362 | /* | 361 | /* |
363 | * If here, we need to do a join to keep the tree balanced. | 362 | * If here, we need to do a join to keep the tree balanced. |
364 | */ | 363 | */ |
365 | ASSERT(bno != NULLAGBLOCK); | 364 | ASSERT(bno != NULLAGBLOCK); |
366 | /* | 365 | /* |
367 | * See if we can join with the left neighbor block. | 366 | * See if we can join with the left neighbor block. |
368 | */ | 367 | */ |
369 | if (lbno != NULLAGBLOCK && | 368 | if (lbno != NULLAGBLOCK && |
370 | lrecs + numrecs <= XFS_INOBT_BLOCK_MAXRECS(level, cur)) { | 369 | lrecs + numrecs <= XFS_INOBT_BLOCK_MAXRECS(level, cur)) { |
371 | /* | 370 | /* |
372 | * Set "right" to be the starting block, | 371 | * Set "right" to be the starting block, |
373 | * "left" to be the left neighbor. | 372 | * "left" to be the left neighbor. |
374 | */ | 373 | */ |
375 | rbno = bno; | 374 | rbno = bno; |
376 | right = block; | 375 | right = block; |
377 | rrecs = be16_to_cpu(right->bb_numrecs); | 376 | rrecs = be16_to_cpu(right->bb_numrecs); |
378 | rbp = bp; | 377 | rbp = bp; |
379 | if ((error = xfs_btree_read_bufs(mp, cur->bc_tp, | 378 | if ((error = xfs_btree_read_bufs(mp, cur->bc_tp, |
380 | cur->bc_private.a.agno, lbno, 0, &lbp, | 379 | cur->bc_private.a.agno, lbno, 0, &lbp, |
381 | XFS_INO_BTREE_REF))) | 380 | XFS_INO_BTREE_REF))) |
382 | return error; | 381 | return error; |
383 | left = XFS_BUF_TO_INOBT_BLOCK(lbp); | 382 | left = XFS_BUF_TO_INOBT_BLOCK(lbp); |
384 | lrecs = be16_to_cpu(left->bb_numrecs); | 383 | lrecs = be16_to_cpu(left->bb_numrecs); |
385 | if ((error = xfs_btree_check_sblock(cur, left, level, lbp))) | 384 | if ((error = xfs_btree_check_sblock(cur, left, level, lbp))) |
386 | return error; | 385 | return error; |
387 | } | 386 | } |
388 | /* | 387 | /* |
389 | * If that won't work, see if we can join with the right neighbor block. | 388 | * If that won't work, see if we can join with the right neighbor block. |
390 | */ | 389 | */ |
391 | else if (rbno != NULLAGBLOCK && | 390 | else if (rbno != NULLAGBLOCK && |
392 | rrecs + numrecs <= XFS_INOBT_BLOCK_MAXRECS(level, cur)) { | 391 | rrecs + numrecs <= XFS_INOBT_BLOCK_MAXRECS(level, cur)) { |
393 | /* | 392 | /* |
394 | * Set "left" to be the starting block, | 393 | * Set "left" to be the starting block, |
395 | * "right" to be the right neighbor. | 394 | * "right" to be the right neighbor. |
396 | */ | 395 | */ |
397 | lbno = bno; | 396 | lbno = bno; |
398 | left = block; | 397 | left = block; |
399 | lrecs = be16_to_cpu(left->bb_numrecs); | 398 | lrecs = be16_to_cpu(left->bb_numrecs); |
400 | lbp = bp; | 399 | lbp = bp; |
401 | if ((error = xfs_btree_read_bufs(mp, cur->bc_tp, | 400 | if ((error = xfs_btree_read_bufs(mp, cur->bc_tp, |
402 | cur->bc_private.a.agno, rbno, 0, &rbp, | 401 | cur->bc_private.a.agno, rbno, 0, &rbp, |
403 | XFS_INO_BTREE_REF))) | 402 | XFS_INO_BTREE_REF))) |
404 | return error; | 403 | return error; |
405 | right = XFS_BUF_TO_INOBT_BLOCK(rbp); | 404 | right = XFS_BUF_TO_INOBT_BLOCK(rbp); |
406 | rrecs = be16_to_cpu(right->bb_numrecs); | 405 | rrecs = be16_to_cpu(right->bb_numrecs); |
407 | if ((error = xfs_btree_check_sblock(cur, right, level, rbp))) | 406 | if ((error = xfs_btree_check_sblock(cur, right, level, rbp))) |
408 | return error; | 407 | return error; |
409 | } | 408 | } |
410 | /* | 409 | /* |
411 | * Otherwise, we can't fix the imbalance. | 410 | * Otherwise, we can't fix the imbalance. |
412 | * Just return. This is probably a logic error, but it's not fatal. | 411 | * Just return. This is probably a logic error, but it's not fatal. |
413 | */ | 412 | */ |
414 | else { | 413 | else { |
415 | if (level > 0 && (error = xfs_btree_decrement(cur, level, &i))) | 414 | if (level > 0 && (error = xfs_btree_decrement(cur, level, &i))) |
416 | return error; | 415 | return error; |
417 | *stat = 1; | 416 | *stat = 1; |
418 | return 0; | 417 | return 0; |
419 | } | 418 | } |
420 | /* | 419 | /* |
421 | * We're now going to join "left" and "right" by moving all the stuff | 420 | * We're now going to join "left" and "right" by moving all the stuff |
422 | * in "right" to "left" and deleting "right". | 421 | * in "right" to "left" and deleting "right". |
423 | */ | 422 | */ |
424 | if (level > 0) { | 423 | if (level > 0) { |
425 | /* | 424 | /* |
426 | * It's a non-leaf. Move keys and pointers. | 425 | * It's a non-leaf. Move keys and pointers. |
427 | */ | 426 | */ |
428 | lkp = XFS_INOBT_KEY_ADDR(left, lrecs + 1, cur); | 427 | lkp = XFS_INOBT_KEY_ADDR(left, lrecs + 1, cur); |
429 | lpp = XFS_INOBT_PTR_ADDR(left, lrecs + 1, cur); | 428 | lpp = XFS_INOBT_PTR_ADDR(left, lrecs + 1, cur); |
430 | rkp = XFS_INOBT_KEY_ADDR(right, 1, cur); | 429 | rkp = XFS_INOBT_KEY_ADDR(right, 1, cur); |
431 | rpp = XFS_INOBT_PTR_ADDR(right, 1, cur); | 430 | rpp = XFS_INOBT_PTR_ADDR(right, 1, cur); |
432 | #ifdef DEBUG | 431 | #ifdef DEBUG |
433 | for (i = 0; i < rrecs; i++) { | 432 | for (i = 0; i < rrecs; i++) { |
434 | if ((error = xfs_btree_check_sptr(cur, be32_to_cpu(rpp[i]), level))) | 433 | if ((error = xfs_btree_check_sptr(cur, be32_to_cpu(rpp[i]), level))) |
435 | return error; | 434 | return error; |
436 | } | 435 | } |
437 | #endif | 436 | #endif |
438 | memcpy(lkp, rkp, rrecs * sizeof(*lkp)); | 437 | memcpy(lkp, rkp, rrecs * sizeof(*lkp)); |
439 | memcpy(lpp, rpp, rrecs * sizeof(*lpp)); | 438 | memcpy(lpp, rpp, rrecs * sizeof(*lpp)); |
440 | xfs_inobt_log_keys(cur, lbp, lrecs + 1, lrecs + rrecs); | 439 | xfs_inobt_log_keys(cur, lbp, lrecs + 1, lrecs + rrecs); |
441 | xfs_inobt_log_ptrs(cur, lbp, lrecs + 1, lrecs + rrecs); | 440 | xfs_inobt_log_ptrs(cur, lbp, lrecs + 1, lrecs + rrecs); |
442 | } else { | 441 | } else { |
443 | /* | 442 | /* |
444 | * It's a leaf. Move records. | 443 | * It's a leaf. Move records. |
445 | */ | 444 | */ |
446 | lrp = XFS_INOBT_REC_ADDR(left, lrecs + 1, cur); | 445 | lrp = XFS_INOBT_REC_ADDR(left, lrecs + 1, cur); |
447 | rrp = XFS_INOBT_REC_ADDR(right, 1, cur); | 446 | rrp = XFS_INOBT_REC_ADDR(right, 1, cur); |
448 | memcpy(lrp, rrp, rrecs * sizeof(*lrp)); | 447 | memcpy(lrp, rrp, rrecs * sizeof(*lrp)); |
449 | xfs_inobt_log_recs(cur, lbp, lrecs + 1, lrecs + rrecs); | 448 | xfs_inobt_log_recs(cur, lbp, lrecs + 1, lrecs + rrecs); |
450 | } | 449 | } |
451 | /* | 450 | /* |
452 | * If we joined with the left neighbor, set the buffer in the | 451 | * If we joined with the left neighbor, set the buffer in the |
453 | * cursor to the left block, and fix up the index. | 452 | * cursor to the left block, and fix up the index. |
454 | */ | 453 | */ |
455 | if (bp != lbp) { | 454 | if (bp != lbp) { |
456 | xfs_btree_setbuf(cur, level, lbp); | 455 | xfs_btree_setbuf(cur, level, lbp); |
457 | cur->bc_ptrs[level] += lrecs; | 456 | cur->bc_ptrs[level] += lrecs; |
458 | } | 457 | } |
459 | /* | 458 | /* |
460 | * If we joined with the right neighbor and there's a level above | 459 | * If we joined with the right neighbor and there's a level above |
461 | * us, increment the cursor at that level. | 460 | * us, increment the cursor at that level. |
462 | */ | 461 | */ |
463 | else if (level + 1 < cur->bc_nlevels && | 462 | else if (level + 1 < cur->bc_nlevels && |
464 | (error = xfs_btree_increment(cur, level + 1, &i))) | 463 | (error = xfs_btree_increment(cur, level + 1, &i))) |
465 | return error; | 464 | return error; |
466 | /* | 465 | /* |
467 | * Fix up the number of records in the surviving block. | 466 | * Fix up the number of records in the surviving block. |
468 | */ | 467 | */ |
469 | lrecs += rrecs; | 468 | lrecs += rrecs; |
470 | left->bb_numrecs = cpu_to_be16(lrecs); | 469 | left->bb_numrecs = cpu_to_be16(lrecs); |
471 | /* | 470 | /* |
472 | * Fix up the right block pointer in the surviving block, and log it. | 471 | * Fix up the right block pointer in the surviving block, and log it. |
473 | */ | 472 | */ |
474 | left->bb_rightsib = right->bb_rightsib; | 473 | left->bb_rightsib = right->bb_rightsib; |
475 | xfs_inobt_log_block(cur->bc_tp, lbp, XFS_BB_NUMRECS | XFS_BB_RIGHTSIB); | 474 | xfs_inobt_log_block(cur->bc_tp, lbp, XFS_BB_NUMRECS | XFS_BB_RIGHTSIB); |
476 | /* | 475 | /* |
477 | * If there is a right sibling now, make it point to the | 476 | * If there is a right sibling now, make it point to the |
478 | * remaining block. | 477 | * remaining block. |
479 | */ | 478 | */ |
480 | if (be32_to_cpu(left->bb_rightsib) != NULLAGBLOCK) { | 479 | if (be32_to_cpu(left->bb_rightsib) != NULLAGBLOCK) { |
481 | xfs_inobt_block_t *rrblock; | 480 | xfs_inobt_block_t *rrblock; |
482 | xfs_buf_t *rrbp; | 481 | xfs_buf_t *rrbp; |
483 | 482 | ||
484 | if ((error = xfs_btree_read_bufs(mp, cur->bc_tp, | 483 | if ((error = xfs_btree_read_bufs(mp, cur->bc_tp, |
485 | cur->bc_private.a.agno, be32_to_cpu(left->bb_rightsib), 0, | 484 | cur->bc_private.a.agno, be32_to_cpu(left->bb_rightsib), 0, |
486 | &rrbp, XFS_INO_BTREE_REF))) | 485 | &rrbp, XFS_INO_BTREE_REF))) |
487 | return error; | 486 | return error; |
488 | rrblock = XFS_BUF_TO_INOBT_BLOCK(rrbp); | 487 | rrblock = XFS_BUF_TO_INOBT_BLOCK(rrbp); |
489 | if ((error = xfs_btree_check_sblock(cur, rrblock, level, rrbp))) | 488 | if ((error = xfs_btree_check_sblock(cur, rrblock, level, rrbp))) |
490 | return error; | 489 | return error; |
491 | rrblock->bb_leftsib = cpu_to_be32(lbno); | 490 | rrblock->bb_leftsib = cpu_to_be32(lbno); |
492 | xfs_inobt_log_block(cur->bc_tp, rrbp, XFS_BB_LEFTSIB); | 491 | xfs_inobt_log_block(cur->bc_tp, rrbp, XFS_BB_LEFTSIB); |
493 | } | 492 | } |
494 | /* | 493 | /* |
495 | * Free the deleting block. | 494 | * Free the deleting block. |
496 | */ | 495 | */ |
497 | if ((error = xfs_free_extent(cur->bc_tp, XFS_AGB_TO_FSB(mp, | 496 | if ((error = xfs_free_extent(cur->bc_tp, XFS_AGB_TO_FSB(mp, |
498 | cur->bc_private.a.agno, rbno), 1))) | 497 | cur->bc_private.a.agno, rbno), 1))) |
499 | return error; | 498 | return error; |
500 | xfs_trans_binval(cur->bc_tp, rbp); | 499 | xfs_trans_binval(cur->bc_tp, rbp); |
501 | /* | 500 | /* |
502 | * Readjust the ptr at this level if it's not a leaf, since it's | 501 | * Readjust the ptr at this level if it's not a leaf, since it's |
503 | * still pointing at the deletion point, which makes the cursor | 502 | * still pointing at the deletion point, which makes the cursor |
504 | * inconsistent. If this makes the ptr 0, the caller fixes it up. | 503 | * inconsistent. If this makes the ptr 0, the caller fixes it up. |
505 | * We can't use decrement because it would change the next level up. | 504 | * We can't use decrement because it would change the next level up. |
506 | */ | 505 | */ |
507 | if (level > 0) | 506 | if (level > 0) |
508 | cur->bc_ptrs[level]--; | 507 | cur->bc_ptrs[level]--; |
509 | /* | 508 | /* |
510 | * Return value means the next level up has something to do. | 509 | * Return value means the next level up has something to do. |
511 | */ | 510 | */ |
512 | *stat = 2; | 511 | *stat = 2; |
513 | return 0; | 512 | return 0; |
514 | 513 | ||
515 | error0: | 514 | error0: |
516 | xfs_btree_del_cursor(tcur, XFS_BTREE_ERROR); | 515 | xfs_btree_del_cursor(tcur, XFS_BTREE_ERROR); |
517 | return error; | 516 | return error; |
518 | } | 517 | } |
519 | 518 | ||
520 | /* | 519 | /* |
521 | * Insert one record/level. Return information to the caller | 520 | * Insert one record/level. Return information to the caller |
522 | * allowing the next level up to proceed if necessary. | 521 | * allowing the next level up to proceed if necessary. |
523 | */ | 522 | */ |
524 | STATIC int /* error */ | 523 | STATIC int /* error */ |
525 | xfs_inobt_insrec( | 524 | xfs_inobt_insrec( |
526 | xfs_btree_cur_t *cur, /* btree cursor */ | 525 | xfs_btree_cur_t *cur, /* btree cursor */ |
527 | int level, /* level to insert record at */ | 526 | int level, /* level to insert record at */ |
528 | xfs_agblock_t *bnop, /* i/o: block number inserted */ | 527 | xfs_agblock_t *bnop, /* i/o: block number inserted */ |
529 | xfs_inobt_rec_t *recp, /* i/o: record data inserted */ | 528 | xfs_inobt_rec_t *recp, /* i/o: record data inserted */ |
530 | xfs_btree_cur_t **curp, /* output: new cursor replacing cur */ | 529 | xfs_btree_cur_t **curp, /* output: new cursor replacing cur */ |
531 | int *stat) /* success/failure */ | 530 | int *stat) /* success/failure */ |
532 | { | 531 | { |
533 | xfs_inobt_block_t *block; /* btree block record/key lives in */ | 532 | xfs_inobt_block_t *block; /* btree block record/key lives in */ |
534 | xfs_buf_t *bp; /* buffer for block */ | 533 | xfs_buf_t *bp; /* buffer for block */ |
535 | int error; /* error return value */ | 534 | int error; /* error return value */ |
536 | int i; /* loop index */ | 535 | int i; /* loop index */ |
537 | xfs_inobt_key_t key; /* key value being inserted */ | 536 | xfs_inobt_key_t key; /* key value being inserted */ |
538 | xfs_inobt_key_t *kp=NULL; /* pointer to btree keys */ | 537 | xfs_inobt_key_t *kp=NULL; /* pointer to btree keys */ |
539 | xfs_agblock_t nbno; /* block number of allocated block */ | 538 | xfs_agblock_t nbno; /* block number of allocated block */ |
540 | xfs_btree_cur_t *ncur; /* new cursor to be used at next lvl */ | 539 | xfs_btree_cur_t *ncur; /* new cursor to be used at next lvl */ |
541 | xfs_inobt_key_t nkey; /* new key value, from split */ | 540 | xfs_inobt_key_t nkey; /* new key value, from split */ |
542 | xfs_inobt_rec_t nrec; /* new record value, for caller */ | 541 | xfs_inobt_rec_t nrec; /* new record value, for caller */ |
543 | int numrecs; | 542 | int numrecs; |
544 | int optr; /* old ptr value */ | 543 | int optr; /* old ptr value */ |
545 | xfs_inobt_ptr_t *pp; /* pointer to btree addresses */ | 544 | xfs_inobt_ptr_t *pp; /* pointer to btree addresses */ |
546 | int ptr; /* index in btree block for this rec */ | 545 | int ptr; /* index in btree block for this rec */ |
547 | xfs_inobt_rec_t *rp=NULL; /* pointer to btree records */ | 546 | xfs_inobt_rec_t *rp=NULL; /* pointer to btree records */ |
548 | 547 | ||
549 | /* | 548 | /* |
550 | * GCC doesn't understand the (arguably complex) control flow in | 549 | * GCC doesn't understand the (arguably complex) control flow in |
551 | * this function and complains about uninitialized structure fields | 550 | * this function and complains about uninitialized structure fields |
552 | * without this. | 551 | * without this. |
553 | */ | 552 | */ |
554 | memset(&nrec, 0, sizeof(nrec)); | 553 | memset(&nrec, 0, sizeof(nrec)); |
555 | 554 | ||
556 | /* | 555 | /* |
557 | * If we made it to the root level, allocate a new root block | 556 | * If we made it to the root level, allocate a new root block |
558 | * and we're done. | 557 | * and we're done. |
559 | */ | 558 | */ |
560 | if (level >= cur->bc_nlevels) { | 559 | if (level >= cur->bc_nlevels) { |
561 | error = xfs_inobt_newroot(cur, &i); | 560 | error = xfs_inobt_newroot(cur, &i); |
562 | *bnop = NULLAGBLOCK; | 561 | *bnop = NULLAGBLOCK; |
563 | *stat = i; | 562 | *stat = i; |
564 | return error; | 563 | return error; |
565 | } | 564 | } |
566 | /* | 565 | /* |
567 | * Make a key out of the record data to be inserted, and save it. | 566 | * Make a key out of the record data to be inserted, and save it. |
568 | */ | 567 | */ |
569 | key.ir_startino = recp->ir_startino; | 568 | key.ir_startino = recp->ir_startino; |
570 | optr = ptr = cur->bc_ptrs[level]; | 569 | optr = ptr = cur->bc_ptrs[level]; |
571 | /* | 570 | /* |
572 | * If we're off the left edge, return failure. | 571 | * If we're off the left edge, return failure. |
573 | */ | 572 | */ |
574 | if (ptr == 0) { | 573 | if (ptr == 0) { |
575 | *stat = 0; | 574 | *stat = 0; |
576 | return 0; | 575 | return 0; |
577 | } | 576 | } |
578 | /* | 577 | /* |
579 | * Get pointers to the btree buffer and block. | 578 | * Get pointers to the btree buffer and block. |
580 | */ | 579 | */ |
581 | bp = cur->bc_bufs[level]; | 580 | bp = cur->bc_bufs[level]; |
582 | block = XFS_BUF_TO_INOBT_BLOCK(bp); | 581 | block = XFS_BUF_TO_INOBT_BLOCK(bp); |
583 | numrecs = be16_to_cpu(block->bb_numrecs); | 582 | numrecs = be16_to_cpu(block->bb_numrecs); |
584 | #ifdef DEBUG | 583 | #ifdef DEBUG |
585 | if ((error = xfs_btree_check_sblock(cur, block, level, bp))) | 584 | if ((error = xfs_btree_check_sblock(cur, block, level, bp))) |
586 | return error; | 585 | return error; |
587 | /* | 586 | /* |
588 | * Check that the new entry is being inserted in the right place. | 587 | * Check that the new entry is being inserted in the right place. |
589 | */ | 588 | */ |
590 | if (ptr <= numrecs) { | 589 | if (ptr <= numrecs) { |
591 | if (level == 0) { | 590 | if (level == 0) { |
592 | rp = XFS_INOBT_REC_ADDR(block, ptr, cur); | 591 | rp = XFS_INOBT_REC_ADDR(block, ptr, cur); |
593 | xfs_btree_check_rec(cur->bc_btnum, recp, rp); | 592 | xfs_btree_check_rec(cur->bc_btnum, recp, rp); |
594 | } else { | 593 | } else { |
595 | kp = XFS_INOBT_KEY_ADDR(block, ptr, cur); | 594 | kp = XFS_INOBT_KEY_ADDR(block, ptr, cur); |
596 | xfs_btree_check_key(cur->bc_btnum, &key, kp); | 595 | xfs_btree_check_key(cur->bc_btnum, &key, kp); |
597 | } | 596 | } |
598 | } | 597 | } |
599 | #endif | 598 | #endif |
600 | nbno = NULLAGBLOCK; | 599 | nbno = NULLAGBLOCK; |
601 | ncur = NULL; | 600 | ncur = NULL; |
602 | /* | 601 | /* |
603 | * If the block is full, we can't insert the new entry until we | 602 | * If the block is full, we can't insert the new entry until we |
604 | * make the block un-full. | 603 | * make the block un-full. |
605 | */ | 604 | */ |
606 | if (numrecs == XFS_INOBT_BLOCK_MAXRECS(level, cur)) { | 605 | if (numrecs == XFS_INOBT_BLOCK_MAXRECS(level, cur)) { |
607 | /* | 606 | /* |
608 | * First, try shifting an entry to the right neighbor. | 607 | * First, try shifting an entry to the right neighbor. |
609 | */ | 608 | */ |
610 | if ((error = xfs_btree_rshift(cur, level, &i))) | 609 | if ((error = xfs_btree_rshift(cur, level, &i))) |
611 | return error; | 610 | return error; |
612 | if (i) { | 611 | if (i) { |
613 | /* nothing */ | 612 | /* nothing */ |
614 | } | 613 | } |
615 | /* | 614 | /* |
616 | * Next, try shifting an entry to the left neighbor. | 615 | * Next, try shifting an entry to the left neighbor. |
617 | */ | 616 | */ |
618 | else { | 617 | else { |
619 | if ((error = xfs_inobt_lshift(cur, level, &i))) | 618 | if ((error = xfs_btree_lshift(cur, level, &i))) |
620 | return error; | 619 | return error; |
621 | if (i) { | 620 | if (i) { |
622 | optr = ptr = cur->bc_ptrs[level]; | 621 | optr = ptr = cur->bc_ptrs[level]; |
623 | } else { | 622 | } else { |
624 | /* | 623 | /* |
625 | * Next, try splitting the current block | 624 | * Next, try splitting the current block |
626 | * in half. If this works we have to | 625 | * in half. If this works we have to |
627 | * re-set our variables because | 626 | * re-set our variables because |
628 | * we could be in a different block now. | 627 | * we could be in a different block now. |
629 | */ | 628 | */ |
630 | if ((error = xfs_inobt_split(cur, level, &nbno, | 629 | if ((error = xfs_inobt_split(cur, level, &nbno, |
631 | &nkey, &ncur, &i))) | 630 | &nkey, &ncur, &i))) |
632 | return error; | 631 | return error; |
633 | if (i) { | 632 | if (i) { |
634 | bp = cur->bc_bufs[level]; | 633 | bp = cur->bc_bufs[level]; |
635 | block = XFS_BUF_TO_INOBT_BLOCK(bp); | 634 | block = XFS_BUF_TO_INOBT_BLOCK(bp); |
636 | #ifdef DEBUG | 635 | #ifdef DEBUG |
637 | if ((error = xfs_btree_check_sblock(cur, | 636 | if ((error = xfs_btree_check_sblock(cur, |
638 | block, level, bp))) | 637 | block, level, bp))) |
639 | return error; | 638 | return error; |
640 | #endif | 639 | #endif |
641 | ptr = cur->bc_ptrs[level]; | 640 | ptr = cur->bc_ptrs[level]; |
642 | nrec.ir_startino = nkey.ir_startino; | 641 | nrec.ir_startino = nkey.ir_startino; |
643 | } else { | 642 | } else { |
644 | /* | 643 | /* |
645 | * Otherwise the insert fails. | 644 | * Otherwise the insert fails. |
646 | */ | 645 | */ |
647 | *stat = 0; | 646 | *stat = 0; |
648 | return 0; | 647 | return 0; |
649 | } | 648 | } |
650 | } | 649 | } |
651 | } | 650 | } |
652 | } | 651 | } |
653 | /* | 652 | /* |
654 | * At this point we know there's room for our new entry in the block | 653 | * At this point we know there's room for our new entry in the block |
655 | * we're pointing at. | 654 | * we're pointing at. |
656 | */ | 655 | */ |
657 | numrecs = be16_to_cpu(block->bb_numrecs); | 656 | numrecs = be16_to_cpu(block->bb_numrecs); |
658 | if (level > 0) { | 657 | if (level > 0) { |
659 | /* | 658 | /* |
660 | * It's a non-leaf entry. Make a hole for the new data | 659 | * It's a non-leaf entry. Make a hole for the new data |
661 | * in the key and ptr regions of the block. | 660 | * in the key and ptr regions of the block. |
662 | */ | 661 | */ |
663 | kp = XFS_INOBT_KEY_ADDR(block, 1, cur); | 662 | kp = XFS_INOBT_KEY_ADDR(block, 1, cur); |
664 | pp = XFS_INOBT_PTR_ADDR(block, 1, cur); | 663 | pp = XFS_INOBT_PTR_ADDR(block, 1, cur); |
665 | #ifdef DEBUG | 664 | #ifdef DEBUG |
666 | for (i = numrecs; i >= ptr; i--) { | 665 | for (i = numrecs; i >= ptr; i--) { |
667 | if ((error = xfs_btree_check_sptr(cur, be32_to_cpu(pp[i - 1]), level))) | 666 | if ((error = xfs_btree_check_sptr(cur, be32_to_cpu(pp[i - 1]), level))) |
668 | return error; | 667 | return error; |
669 | } | 668 | } |
670 | #endif | 669 | #endif |
671 | memmove(&kp[ptr], &kp[ptr - 1], | 670 | memmove(&kp[ptr], &kp[ptr - 1], |
672 | (numrecs - ptr + 1) * sizeof(*kp)); | 671 | (numrecs - ptr + 1) * sizeof(*kp)); |
673 | memmove(&pp[ptr], &pp[ptr - 1], | 672 | memmove(&pp[ptr], &pp[ptr - 1], |
674 | (numrecs - ptr + 1) * sizeof(*pp)); | 673 | (numrecs - ptr + 1) * sizeof(*pp)); |
675 | /* | 674 | /* |
676 | * Now stuff the new data in, bump numrecs and log the new data. | 675 | * Now stuff the new data in, bump numrecs and log the new data. |
677 | */ | 676 | */ |
678 | #ifdef DEBUG | 677 | #ifdef DEBUG |
679 | if ((error = xfs_btree_check_sptr(cur, *bnop, level))) | 678 | if ((error = xfs_btree_check_sptr(cur, *bnop, level))) |
680 | return error; | 679 | return error; |
681 | #endif | 680 | #endif |
682 | kp[ptr - 1] = key; | 681 | kp[ptr - 1] = key; |
683 | pp[ptr - 1] = cpu_to_be32(*bnop); | 682 | pp[ptr - 1] = cpu_to_be32(*bnop); |
684 | numrecs++; | 683 | numrecs++; |
685 | block->bb_numrecs = cpu_to_be16(numrecs); | 684 | block->bb_numrecs = cpu_to_be16(numrecs); |
686 | xfs_inobt_log_keys(cur, bp, ptr, numrecs); | 685 | xfs_inobt_log_keys(cur, bp, ptr, numrecs); |
687 | xfs_inobt_log_ptrs(cur, bp, ptr, numrecs); | 686 | xfs_inobt_log_ptrs(cur, bp, ptr, numrecs); |
688 | } else { | 687 | } else { |
689 | /* | 688 | /* |
690 | * It's a leaf entry. Make a hole for the new record. | 689 | * It's a leaf entry. Make a hole for the new record. |
691 | */ | 690 | */ |
692 | rp = XFS_INOBT_REC_ADDR(block, 1, cur); | 691 | rp = XFS_INOBT_REC_ADDR(block, 1, cur); |
693 | memmove(&rp[ptr], &rp[ptr - 1], | 692 | memmove(&rp[ptr], &rp[ptr - 1], |
694 | (numrecs - ptr + 1) * sizeof(*rp)); | 693 | (numrecs - ptr + 1) * sizeof(*rp)); |
695 | /* | 694 | /* |
696 | * Now stuff the new record in, bump numrecs | 695 | * Now stuff the new record in, bump numrecs |
697 | * and log the new data. | 696 | * and log the new data. |
698 | */ | 697 | */ |
699 | rp[ptr - 1] = *recp; | 698 | rp[ptr - 1] = *recp; |
700 | numrecs++; | 699 | numrecs++; |
701 | block->bb_numrecs = cpu_to_be16(numrecs); | 700 | block->bb_numrecs = cpu_to_be16(numrecs); |
702 | xfs_inobt_log_recs(cur, bp, ptr, numrecs); | 701 | xfs_inobt_log_recs(cur, bp, ptr, numrecs); |
703 | } | 702 | } |
704 | /* | 703 | /* |
705 | * Log the new number of records in the btree header. | 704 | * Log the new number of records in the btree header. |
706 | */ | 705 | */ |
707 | xfs_inobt_log_block(cur->bc_tp, bp, XFS_BB_NUMRECS); | 706 | xfs_inobt_log_block(cur->bc_tp, bp, XFS_BB_NUMRECS); |
708 | #ifdef DEBUG | 707 | #ifdef DEBUG |
709 | /* | 708 | /* |
710 | * Check that the key/record is in the right place, now. | 709 | * Check that the key/record is in the right place, now. |
711 | */ | 710 | */ |
712 | if (ptr < numrecs) { | 711 | if (ptr < numrecs) { |
713 | if (level == 0) | 712 | if (level == 0) |
714 | xfs_btree_check_rec(cur->bc_btnum, rp + ptr - 1, | 713 | xfs_btree_check_rec(cur->bc_btnum, rp + ptr - 1, |
715 | rp + ptr); | 714 | rp + ptr); |
716 | else | 715 | else |
717 | xfs_btree_check_key(cur->bc_btnum, kp + ptr - 1, | 716 | xfs_btree_check_key(cur->bc_btnum, kp + ptr - 1, |
718 | kp + ptr); | 717 | kp + ptr); |
719 | } | 718 | } |
720 | #endif | 719 | #endif |
721 | /* | 720 | /* |
722 | * If we inserted at the start of a block, update the parents' keys. | 721 | * If we inserted at the start of a block, update the parents' keys. |
723 | */ | 722 | */ |
724 | if (optr == 1 && (error = xfs_btree_updkey(cur, (union xfs_btree_key *)&key, level + 1))) | 723 | if (optr == 1 && (error = xfs_btree_updkey(cur, (union xfs_btree_key *)&key, level + 1))) |
725 | return error; | 724 | return error; |
726 | /* | 725 | /* |
727 | * Return the new block number, if any. | 726 | * Return the new block number, if any. |
728 | * If there is one, give back a record value and a cursor too. | 727 | * If there is one, give back a record value and a cursor too. |
729 | */ | 728 | */ |
730 | *bnop = nbno; | 729 | *bnop = nbno; |
731 | if (nbno != NULLAGBLOCK) { | 730 | if (nbno != NULLAGBLOCK) { |
732 | *recp = nrec; | 731 | *recp = nrec; |
733 | *curp = ncur; | 732 | *curp = ncur; |
734 | } | 733 | } |
735 | *stat = 1; | 734 | *stat = 1; |
736 | return 0; | 735 | return 0; |
737 | } | 736 | } |
738 | 737 | ||
739 | /* | 738 | /* |
740 | * Log header fields from a btree block. | 739 | * Log header fields from a btree block. |
741 | */ | 740 | */ |
742 | STATIC void | 741 | STATIC void |
743 | xfs_inobt_log_block( | 742 | xfs_inobt_log_block( |
744 | xfs_trans_t *tp, /* transaction pointer */ | 743 | xfs_trans_t *tp, /* transaction pointer */ |
745 | xfs_buf_t *bp, /* buffer containing btree block */ | 744 | xfs_buf_t *bp, /* buffer containing btree block */ |
746 | int fields) /* mask of fields: XFS_BB_... */ | 745 | int fields) /* mask of fields: XFS_BB_... */ |
747 | { | 746 | { |
748 | int first; /* first byte offset logged */ | 747 | int first; /* first byte offset logged */ |
749 | int last; /* last byte offset logged */ | 748 | int last; /* last byte offset logged */ |
750 | static const short offsets[] = { /* table of offsets */ | 749 | static const short offsets[] = { /* table of offsets */ |
751 | offsetof(xfs_inobt_block_t, bb_magic), | 750 | offsetof(xfs_inobt_block_t, bb_magic), |
752 | offsetof(xfs_inobt_block_t, bb_level), | 751 | offsetof(xfs_inobt_block_t, bb_level), |
753 | offsetof(xfs_inobt_block_t, bb_numrecs), | 752 | offsetof(xfs_inobt_block_t, bb_numrecs), |
754 | offsetof(xfs_inobt_block_t, bb_leftsib), | 753 | offsetof(xfs_inobt_block_t, bb_leftsib), |
755 | offsetof(xfs_inobt_block_t, bb_rightsib), | 754 | offsetof(xfs_inobt_block_t, bb_rightsib), |
756 | sizeof(xfs_inobt_block_t) | 755 | sizeof(xfs_inobt_block_t) |
757 | }; | 756 | }; |
758 | 757 | ||
759 | xfs_btree_offsets(fields, offsets, XFS_BB_NUM_BITS, &first, &last); | 758 | xfs_btree_offsets(fields, offsets, XFS_BB_NUM_BITS, &first, &last); |
760 | xfs_trans_log_buf(tp, bp, first, last); | 759 | xfs_trans_log_buf(tp, bp, first, last); |
761 | } | 760 | } |
762 | 761 | ||
763 | /* | 762 | /* |
764 | * Log keys from a btree block (nonleaf). | 763 | * Log keys from a btree block (nonleaf). |
765 | */ | 764 | */ |
766 | STATIC void | 765 | STATIC void |
767 | xfs_inobt_log_keys( | 766 | xfs_inobt_log_keys( |
768 | xfs_btree_cur_t *cur, /* btree cursor */ | 767 | xfs_btree_cur_t *cur, /* btree cursor */ |
769 | xfs_buf_t *bp, /* buffer containing btree block */ | 768 | xfs_buf_t *bp, /* buffer containing btree block */ |
770 | int kfirst, /* index of first key to log */ | 769 | int kfirst, /* index of first key to log */ |
771 | int klast) /* index of last key to log */ | 770 | int klast) /* index of last key to log */ |
772 | { | 771 | { |
773 | xfs_inobt_block_t *block; /* btree block to log from */ | 772 | xfs_inobt_block_t *block; /* btree block to log from */ |
774 | int first; /* first byte offset logged */ | 773 | int first; /* first byte offset logged */ |
775 | xfs_inobt_key_t *kp; /* key pointer in btree block */ | 774 | xfs_inobt_key_t *kp; /* key pointer in btree block */ |
776 | int last; /* last byte offset logged */ | 775 | int last; /* last byte offset logged */ |
777 | 776 | ||
778 | block = XFS_BUF_TO_INOBT_BLOCK(bp); | 777 | block = XFS_BUF_TO_INOBT_BLOCK(bp); |
779 | kp = XFS_INOBT_KEY_ADDR(block, 1, cur); | 778 | kp = XFS_INOBT_KEY_ADDR(block, 1, cur); |
780 | first = (int)((xfs_caddr_t)&kp[kfirst - 1] - (xfs_caddr_t)block); | 779 | first = (int)((xfs_caddr_t)&kp[kfirst - 1] - (xfs_caddr_t)block); |
781 | last = (int)(((xfs_caddr_t)&kp[klast] - 1) - (xfs_caddr_t)block); | 780 | last = (int)(((xfs_caddr_t)&kp[klast] - 1) - (xfs_caddr_t)block); |
782 | xfs_trans_log_buf(cur->bc_tp, bp, first, last); | 781 | xfs_trans_log_buf(cur->bc_tp, bp, first, last); |
783 | } | 782 | } |
784 | 783 | ||
785 | /* | 784 | /* |
786 | * Log block pointer fields from a btree block (nonleaf). | 785 | * Log block pointer fields from a btree block (nonleaf). |
787 | */ | 786 | */ |
788 | STATIC void | 787 | STATIC void |
789 | xfs_inobt_log_ptrs( | 788 | xfs_inobt_log_ptrs( |
790 | xfs_btree_cur_t *cur, /* btree cursor */ | 789 | xfs_btree_cur_t *cur, /* btree cursor */ |
791 | xfs_buf_t *bp, /* buffer containing btree block */ | 790 | xfs_buf_t *bp, /* buffer containing btree block */ |
792 | int pfirst, /* index of first pointer to log */ | 791 | int pfirst, /* index of first pointer to log */ |
793 | int plast) /* index of last pointer to log */ | 792 | int plast) /* index of last pointer to log */ |
794 | { | 793 | { |
795 | xfs_inobt_block_t *block; /* btree block to log from */ | 794 | xfs_inobt_block_t *block; /* btree block to log from */ |
796 | int first; /* first byte offset logged */ | 795 | int first; /* first byte offset logged */ |
797 | int last; /* last byte offset logged */ | 796 | int last; /* last byte offset logged */ |
798 | xfs_inobt_ptr_t *pp; /* block-pointer pointer in btree blk */ | 797 | xfs_inobt_ptr_t *pp; /* block-pointer pointer in btree blk */ |
799 | 798 | ||
800 | block = XFS_BUF_TO_INOBT_BLOCK(bp); | 799 | block = XFS_BUF_TO_INOBT_BLOCK(bp); |
801 | pp = XFS_INOBT_PTR_ADDR(block, 1, cur); | 800 | pp = XFS_INOBT_PTR_ADDR(block, 1, cur); |
802 | first = (int)((xfs_caddr_t)&pp[pfirst - 1] - (xfs_caddr_t)block); | 801 | first = (int)((xfs_caddr_t)&pp[pfirst - 1] - (xfs_caddr_t)block); |
803 | last = (int)(((xfs_caddr_t)&pp[plast] - 1) - (xfs_caddr_t)block); | 802 | last = (int)(((xfs_caddr_t)&pp[plast] - 1) - (xfs_caddr_t)block); |
804 | xfs_trans_log_buf(cur->bc_tp, bp, first, last); | 803 | xfs_trans_log_buf(cur->bc_tp, bp, first, last); |
805 | } | 804 | } |
806 | 805 | ||
807 | /* | 806 | /* |
808 | * Log records from a btree block (leaf). | 807 | * Log records from a btree block (leaf). |
809 | */ | 808 | */ |
810 | STATIC void | 809 | STATIC void |
811 | xfs_inobt_log_recs( | 810 | xfs_inobt_log_recs( |
812 | xfs_btree_cur_t *cur, /* btree cursor */ | 811 | xfs_btree_cur_t *cur, /* btree cursor */ |
813 | xfs_buf_t *bp, /* buffer containing btree block */ | 812 | xfs_buf_t *bp, /* buffer containing btree block */ |
814 | int rfirst, /* index of first record to log */ | 813 | int rfirst, /* index of first record to log */ |
815 | int rlast) /* index of last record to log */ | 814 | int rlast) /* index of last record to log */ |
816 | { | 815 | { |
817 | xfs_inobt_block_t *block; /* btree block to log from */ | 816 | xfs_inobt_block_t *block; /* btree block to log from */ |
818 | int first; /* first byte offset logged */ | 817 | int first; /* first byte offset logged */ |
819 | int last; /* last byte offset logged */ | 818 | int last; /* last byte offset logged */ |
820 | xfs_inobt_rec_t *rp; /* record pointer for btree block */ | 819 | xfs_inobt_rec_t *rp; /* record pointer for btree block */ |
821 | 820 | ||
822 | block = XFS_BUF_TO_INOBT_BLOCK(bp); | 821 | block = XFS_BUF_TO_INOBT_BLOCK(bp); |
823 | rp = XFS_INOBT_REC_ADDR(block, 1, cur); | 822 | rp = XFS_INOBT_REC_ADDR(block, 1, cur); |
824 | first = (int)((xfs_caddr_t)&rp[rfirst - 1] - (xfs_caddr_t)block); | 823 | first = (int)((xfs_caddr_t)&rp[rfirst - 1] - (xfs_caddr_t)block); |
825 | last = (int)(((xfs_caddr_t)&rp[rlast] - 1) - (xfs_caddr_t)block); | 824 | last = (int)(((xfs_caddr_t)&rp[rlast] - 1) - (xfs_caddr_t)block); |
826 | xfs_trans_log_buf(cur->bc_tp, bp, first, last); | 825 | xfs_trans_log_buf(cur->bc_tp, bp, first, last); |
827 | } | ||
828 | |||
829 | /* | ||
830 | * Move 1 record left from cur/level if possible. | ||
831 | * Update cur to reflect the new path. | ||
832 | */ | ||
833 | STATIC int /* error */ | ||
834 | xfs_inobt_lshift( | ||
835 | xfs_btree_cur_t *cur, /* btree cursor */ | ||
836 | int level, /* level to shift record on */ | ||
837 | int *stat) /* success/failure */ | ||
838 | { | ||
839 | int error; /* error return value */ | ||
840 | #ifdef DEBUG | ||
841 | int i; /* loop index */ | ||
842 | #endif | ||
843 | xfs_inobt_key_t key; /* key value for leaf level upward */ | ||
844 | xfs_buf_t *lbp; /* buffer for left neighbor block */ | ||
845 | xfs_inobt_block_t *left; /* left neighbor btree block */ | ||
846 | xfs_inobt_key_t *lkp=NULL; /* key pointer for left block */ | ||
847 | xfs_inobt_ptr_t *lpp; /* address pointer for left block */ | ||
848 | xfs_inobt_rec_t *lrp=NULL; /* record pointer for left block */ | ||
849 | int nrec; /* new number of left block entries */ | ||
850 | xfs_buf_t *rbp; /* buffer for right (current) block */ | ||
851 | xfs_inobt_block_t *right; /* right (current) btree block */ | ||
852 | xfs_inobt_key_t *rkp=NULL; /* key pointer for right block */ | ||
853 | xfs_inobt_ptr_t *rpp=NULL; /* address pointer for right block */ | ||
854 | xfs_inobt_rec_t *rrp=NULL; /* record pointer for right block */ | ||
855 | |||
856 | /* | ||
857 | * Set up variables for this block as "right". | ||
858 | */ | ||
859 | rbp = cur->bc_bufs[level]; | ||
860 | right = XFS_BUF_TO_INOBT_BLOCK(rbp); | ||
861 | #ifdef DEBUG | ||
862 | if ((error = xfs_btree_check_sblock(cur, right, level, rbp))) | ||
863 | return error; | ||
864 | #endif | ||
865 | /* | ||
866 | * If we've got no left sibling then we can't shift an entry left. | ||
867 | */ | ||
868 | if (be32_to_cpu(right->bb_leftsib) == NULLAGBLOCK) { | ||
869 | *stat = 0; | ||
870 | return 0; | ||
871 | } | ||
872 | /* | ||
873 | * If the cursor entry is the one that would be moved, don't | ||
874 | * do it... it's too complicated. | ||
875 | */ | ||
876 | if (cur->bc_ptrs[level] <= 1) { | ||
877 | *stat = 0; | ||
878 | return 0; | ||
879 | } | ||
880 | /* | ||
881 | * Set up the left neighbor as "left". | ||
882 | */ | ||
883 | if ((error = xfs_btree_read_bufs(cur->bc_mp, cur->bc_tp, | ||
884 | cur->bc_private.a.agno, be32_to_cpu(right->bb_leftsib), | ||
885 | 0, &lbp, XFS_INO_BTREE_REF))) | ||
886 | return error; | ||
887 | left = XFS_BUF_TO_INOBT_BLOCK(lbp); | ||
888 | if ((error = xfs_btree_check_sblock(cur, left, level, lbp))) | ||
889 | return error; | ||
890 | /* | ||
891 | * If it's full, it can't take another entry. | ||
892 | */ | ||
893 | if (be16_to_cpu(left->bb_numrecs) == XFS_INOBT_BLOCK_MAXRECS(level, cur)) { | ||
894 | *stat = 0; | ||
895 | return 0; | ||
896 | } | ||
897 | nrec = be16_to_cpu(left->bb_numrecs) + 1; | ||
898 | /* | ||
899 | * If non-leaf, copy a key and a ptr to the left block. | ||
900 | */ | ||
901 | if (level > 0) { | ||
902 | lkp = XFS_INOBT_KEY_ADDR(left, nrec, cur); | ||
903 | rkp = XFS_INOBT_KEY_ADDR(right, 1, cur); | ||
904 | *lkp = *rkp; | ||
905 | xfs_inobt_log_keys(cur, lbp, nrec, nrec); | ||
906 | lpp = XFS_INOBT_PTR_ADDR(left, nrec, cur); | ||
907 | rpp = XFS_INOBT_PTR_ADDR(right, 1, cur); | ||
908 | #ifdef DEBUG | ||
909 | if ((error = xfs_btree_check_sptr(cur, be32_to_cpu(*rpp), level))) | ||
910 | return error; | ||
911 | #endif | ||
912 | *lpp = *rpp; | ||
913 | xfs_inobt_log_ptrs(cur, lbp, nrec, nrec); | ||
914 | } | ||
915 | /* | ||
916 | * If leaf, copy a record to the left block. | ||
917 | */ | ||
918 | else { | ||
919 | lrp = XFS_INOBT_REC_ADDR(left, nrec, cur); | ||
920 | rrp = XFS_INOBT_REC_ADDR(right, 1, cur); | ||
921 | *lrp = *rrp; | ||
922 | xfs_inobt_log_recs(cur, lbp, nrec, nrec); | ||
923 | } | ||
924 | /* | ||
925 | * Bump and log left's numrecs, decrement and log right's numrecs. | ||
926 | */ | ||
927 | be16_add_cpu(&left->bb_numrecs, 1); | ||
928 | xfs_inobt_log_block(cur->bc_tp, lbp, XFS_BB_NUMRECS); | ||
929 | #ifdef DEBUG | ||
930 | if (level > 0) | ||
931 | xfs_btree_check_key(cur->bc_btnum, lkp - 1, lkp); | ||
932 | else | ||
933 | xfs_btree_check_rec(cur->bc_btnum, lrp - 1, lrp); | ||
934 | #endif | ||
935 | be16_add_cpu(&right->bb_numrecs, -1); | ||
936 | xfs_inobt_log_block(cur->bc_tp, rbp, XFS_BB_NUMRECS); | ||
937 | /* | ||
938 | * Slide the contents of right down one entry. | ||
939 | */ | ||
940 | if (level > 0) { | ||
941 | #ifdef DEBUG | ||
942 | for (i = 0; i < be16_to_cpu(right->bb_numrecs); i++) { | ||
943 | if ((error = xfs_btree_check_sptr(cur, be32_to_cpu(rpp[i + 1]), | ||
944 | level))) | ||
945 | return error; | ||
946 | } | ||
947 | #endif | ||
948 | memmove(rkp, rkp + 1, be16_to_cpu(right->bb_numrecs) * sizeof(*rkp)); | ||
949 | memmove(rpp, rpp + 1, be16_to_cpu(right->bb_numrecs) * sizeof(*rpp)); | ||
950 | xfs_inobt_log_keys(cur, rbp, 1, be16_to_cpu(right->bb_numrecs)); | ||
951 | xfs_inobt_log_ptrs(cur, rbp, 1, be16_to_cpu(right->bb_numrecs)); | ||
952 | } else { | ||
953 | memmove(rrp, rrp + 1, be16_to_cpu(right->bb_numrecs) * sizeof(*rrp)); | ||
954 | xfs_inobt_log_recs(cur, rbp, 1, be16_to_cpu(right->bb_numrecs)); | ||
955 | key.ir_startino = rrp->ir_startino; | ||
956 | rkp = &key; | ||
957 | } | ||
958 | /* | ||
959 | * Update the parent key values of right. | ||
960 | */ | ||
961 | if ((error = xfs_btree_updkey(cur, (union xfs_btree_key *)rkp, level + 1))) | ||
962 | return error; | ||
963 | /* | ||
964 | * Slide the cursor value left one. | ||
965 | */ | ||
966 | cur->bc_ptrs[level]--; | ||
967 | *stat = 1; | ||
968 | return 0; | ||
969 | } | 826 | } |
970 | 827 | ||
971 | /* | 828 | /* |
972 | * Allocate a new root block, fill it in. | 829 | * Allocate a new root block, fill it in. |
973 | */ | 830 | */ |
974 | STATIC int /* error */ | 831 | STATIC int /* error */ |
975 | xfs_inobt_newroot( | 832 | xfs_inobt_newroot( |
976 | xfs_btree_cur_t *cur, /* btree cursor */ | 833 | xfs_btree_cur_t *cur, /* btree cursor */ |
977 | int *stat) /* success/failure */ | 834 | int *stat) /* success/failure */ |
978 | { | 835 | { |
979 | xfs_agi_t *agi; /* a.g. inode header */ | 836 | xfs_agi_t *agi; /* a.g. inode header */ |
980 | xfs_alloc_arg_t args; /* allocation argument structure */ | 837 | xfs_alloc_arg_t args; /* allocation argument structure */ |
981 | xfs_inobt_block_t *block; /* one half of the old root block */ | 838 | xfs_inobt_block_t *block; /* one half of the old root block */ |
982 | xfs_buf_t *bp; /* buffer containing block */ | 839 | xfs_buf_t *bp; /* buffer containing block */ |
983 | int error; /* error return value */ | 840 | int error; /* error return value */ |
984 | xfs_inobt_key_t *kp; /* btree key pointer */ | 841 | xfs_inobt_key_t *kp; /* btree key pointer */ |
985 | xfs_agblock_t lbno; /* left block number */ | 842 | xfs_agblock_t lbno; /* left block number */ |
986 | xfs_buf_t *lbp; /* left buffer pointer */ | 843 | xfs_buf_t *lbp; /* left buffer pointer */ |
987 | xfs_inobt_block_t *left; /* left btree block */ | 844 | xfs_inobt_block_t *left; /* left btree block */ |
988 | xfs_buf_t *nbp; /* new (root) buffer */ | 845 | xfs_buf_t *nbp; /* new (root) buffer */ |
989 | xfs_inobt_block_t *new; /* new (root) btree block */ | 846 | xfs_inobt_block_t *new; /* new (root) btree block */ |
990 | int nptr; /* new value for key index, 1 or 2 */ | 847 | int nptr; /* new value for key index, 1 or 2 */ |
991 | xfs_inobt_ptr_t *pp; /* btree address pointer */ | 848 | xfs_inobt_ptr_t *pp; /* btree address pointer */ |
992 | xfs_agblock_t rbno; /* right block number */ | 849 | xfs_agblock_t rbno; /* right block number */ |
993 | xfs_buf_t *rbp; /* right buffer pointer */ | 850 | xfs_buf_t *rbp; /* right buffer pointer */ |
994 | xfs_inobt_block_t *right; /* right btree block */ | 851 | xfs_inobt_block_t *right; /* right btree block */ |
995 | xfs_inobt_rec_t *rp; /* btree record pointer */ | 852 | xfs_inobt_rec_t *rp; /* btree record pointer */ |
996 | 853 | ||
997 | ASSERT(cur->bc_nlevels < XFS_IN_MAXLEVELS(cur->bc_mp)); | 854 | ASSERT(cur->bc_nlevels < XFS_IN_MAXLEVELS(cur->bc_mp)); |
998 | 855 | ||
999 | /* | 856 | /* |
1000 | * Get a block & a buffer. | 857 | * Get a block & a buffer. |
1001 | */ | 858 | */ |
1002 | agi = XFS_BUF_TO_AGI(cur->bc_private.a.agbp); | 859 | agi = XFS_BUF_TO_AGI(cur->bc_private.a.agbp); |
1003 | args.tp = cur->bc_tp; | 860 | args.tp = cur->bc_tp; |
1004 | args.mp = cur->bc_mp; | 861 | args.mp = cur->bc_mp; |
1005 | args.fsbno = XFS_AGB_TO_FSB(args.mp, cur->bc_private.a.agno, | 862 | args.fsbno = XFS_AGB_TO_FSB(args.mp, cur->bc_private.a.agno, |
1006 | be32_to_cpu(agi->agi_root)); | 863 | be32_to_cpu(agi->agi_root)); |
1007 | args.mod = args.minleft = args.alignment = args.total = args.wasdel = | 864 | args.mod = args.minleft = args.alignment = args.total = args.wasdel = |
1008 | args.isfl = args.userdata = args.minalignslop = 0; | 865 | args.isfl = args.userdata = args.minalignslop = 0; |
1009 | args.minlen = args.maxlen = args.prod = 1; | 866 | args.minlen = args.maxlen = args.prod = 1; |
1010 | args.type = XFS_ALLOCTYPE_NEAR_BNO; | 867 | args.type = XFS_ALLOCTYPE_NEAR_BNO; |
1011 | if ((error = xfs_alloc_vextent(&args))) | 868 | if ((error = xfs_alloc_vextent(&args))) |
1012 | return error; | 869 | return error; |
1013 | /* | 870 | /* |
1014 | * None available, we fail. | 871 | * None available, we fail. |
1015 | */ | 872 | */ |
1016 | if (args.fsbno == NULLFSBLOCK) { | 873 | if (args.fsbno == NULLFSBLOCK) { |
1017 | *stat = 0; | 874 | *stat = 0; |
1018 | return 0; | 875 | return 0; |
1019 | } | 876 | } |
1020 | ASSERT(args.len == 1); | 877 | ASSERT(args.len == 1); |
1021 | nbp = xfs_btree_get_bufs(args.mp, args.tp, args.agno, args.agbno, 0); | 878 | nbp = xfs_btree_get_bufs(args.mp, args.tp, args.agno, args.agbno, 0); |
1022 | new = XFS_BUF_TO_INOBT_BLOCK(nbp); | 879 | new = XFS_BUF_TO_INOBT_BLOCK(nbp); |
1023 | /* | 880 | /* |
1024 | * Set the root data in the a.g. inode structure. | 881 | * Set the root data in the a.g. inode structure. |
1025 | */ | 882 | */ |
1026 | agi->agi_root = cpu_to_be32(args.agbno); | 883 | agi->agi_root = cpu_to_be32(args.agbno); |
1027 | be32_add_cpu(&agi->agi_level, 1); | 884 | be32_add_cpu(&agi->agi_level, 1); |
1028 | xfs_ialloc_log_agi(args.tp, cur->bc_private.a.agbp, | 885 | xfs_ialloc_log_agi(args.tp, cur->bc_private.a.agbp, |
1029 | XFS_AGI_ROOT | XFS_AGI_LEVEL); | 886 | XFS_AGI_ROOT | XFS_AGI_LEVEL); |
1030 | /* | 887 | /* |
1031 | * At the previous root level there are now two blocks: the old | 888 | * At the previous root level there are now two blocks: the old |
1032 | * root, and the new block generated when it was split. | 889 | * root, and the new block generated when it was split. |
1033 | * We don't know which one the cursor is pointing at, so we | 890 | * We don't know which one the cursor is pointing at, so we |
1034 | * set up variables "left" and "right" for each case. | 891 | * set up variables "left" and "right" for each case. |
1035 | */ | 892 | */ |
1036 | bp = cur->bc_bufs[cur->bc_nlevels - 1]; | 893 | bp = cur->bc_bufs[cur->bc_nlevels - 1]; |
1037 | block = XFS_BUF_TO_INOBT_BLOCK(bp); | 894 | block = XFS_BUF_TO_INOBT_BLOCK(bp); |
1038 | #ifdef DEBUG | 895 | #ifdef DEBUG |
1039 | if ((error = xfs_btree_check_sblock(cur, block, cur->bc_nlevels - 1, bp))) | 896 | if ((error = xfs_btree_check_sblock(cur, block, cur->bc_nlevels - 1, bp))) |
1040 | return error; | 897 | return error; |
1041 | #endif | 898 | #endif |
1042 | if (be32_to_cpu(block->bb_rightsib) != NULLAGBLOCK) { | 899 | if (be32_to_cpu(block->bb_rightsib) != NULLAGBLOCK) { |
1043 | /* | 900 | /* |
1044 | * Our block is left, pick up the right block. | 901 | * Our block is left, pick up the right block. |
1045 | */ | 902 | */ |
1046 | lbp = bp; | 903 | lbp = bp; |
1047 | lbno = XFS_DADDR_TO_AGBNO(args.mp, XFS_BUF_ADDR(lbp)); | 904 | lbno = XFS_DADDR_TO_AGBNO(args.mp, XFS_BUF_ADDR(lbp)); |
1048 | left = block; | 905 | left = block; |
1049 | rbno = be32_to_cpu(left->bb_rightsib); | 906 | rbno = be32_to_cpu(left->bb_rightsib); |
1050 | if ((error = xfs_btree_read_bufs(args.mp, args.tp, args.agno, | 907 | if ((error = xfs_btree_read_bufs(args.mp, args.tp, args.agno, |
1051 | rbno, 0, &rbp, XFS_INO_BTREE_REF))) | 908 | rbno, 0, &rbp, XFS_INO_BTREE_REF))) |
1052 | return error; | 909 | return error; |
1053 | bp = rbp; | 910 | bp = rbp; |
1054 | right = XFS_BUF_TO_INOBT_BLOCK(rbp); | 911 | right = XFS_BUF_TO_INOBT_BLOCK(rbp); |
1055 | if ((error = xfs_btree_check_sblock(cur, right, | 912 | if ((error = xfs_btree_check_sblock(cur, right, |
1056 | cur->bc_nlevels - 1, rbp))) | 913 | cur->bc_nlevels - 1, rbp))) |
1057 | return error; | 914 | return error; |
1058 | nptr = 1; | 915 | nptr = 1; |
1059 | } else { | 916 | } else { |
1060 | /* | 917 | /* |
1061 | * Our block is right, pick up the left block. | 918 | * Our block is right, pick up the left block. |
1062 | */ | 919 | */ |
1063 | rbp = bp; | 920 | rbp = bp; |
1064 | rbno = XFS_DADDR_TO_AGBNO(args.mp, XFS_BUF_ADDR(rbp)); | 921 | rbno = XFS_DADDR_TO_AGBNO(args.mp, XFS_BUF_ADDR(rbp)); |
1065 | right = block; | 922 | right = block; |
1066 | lbno = be32_to_cpu(right->bb_leftsib); | 923 | lbno = be32_to_cpu(right->bb_leftsib); |
1067 | if ((error = xfs_btree_read_bufs(args.mp, args.tp, args.agno, | 924 | if ((error = xfs_btree_read_bufs(args.mp, args.tp, args.agno, |
1068 | lbno, 0, &lbp, XFS_INO_BTREE_REF))) | 925 | lbno, 0, &lbp, XFS_INO_BTREE_REF))) |
1069 | return error; | 926 | return error; |
1070 | bp = lbp; | 927 | bp = lbp; |
1071 | left = XFS_BUF_TO_INOBT_BLOCK(lbp); | 928 | left = XFS_BUF_TO_INOBT_BLOCK(lbp); |
1072 | if ((error = xfs_btree_check_sblock(cur, left, | 929 | if ((error = xfs_btree_check_sblock(cur, left, |
1073 | cur->bc_nlevels - 1, lbp))) | 930 | cur->bc_nlevels - 1, lbp))) |
1074 | return error; | 931 | return error; |
1075 | nptr = 2; | 932 | nptr = 2; |
1076 | } | 933 | } |
1077 | /* | 934 | /* |
1078 | * Fill in the new block's btree header and log it. | 935 | * Fill in the new block's btree header and log it. |
1079 | */ | 936 | */ |
1080 | new->bb_magic = cpu_to_be32(xfs_magics[cur->bc_btnum]); | 937 | new->bb_magic = cpu_to_be32(xfs_magics[cur->bc_btnum]); |
1081 | new->bb_level = cpu_to_be16(cur->bc_nlevels); | 938 | new->bb_level = cpu_to_be16(cur->bc_nlevels); |
1082 | new->bb_numrecs = cpu_to_be16(2); | 939 | new->bb_numrecs = cpu_to_be16(2); |
1083 | new->bb_leftsib = cpu_to_be32(NULLAGBLOCK); | 940 | new->bb_leftsib = cpu_to_be32(NULLAGBLOCK); |
1084 | new->bb_rightsib = cpu_to_be32(NULLAGBLOCK); | 941 | new->bb_rightsib = cpu_to_be32(NULLAGBLOCK); |
1085 | xfs_inobt_log_block(args.tp, nbp, XFS_BB_ALL_BITS); | 942 | xfs_inobt_log_block(args.tp, nbp, XFS_BB_ALL_BITS); |
1086 | ASSERT(lbno != NULLAGBLOCK && rbno != NULLAGBLOCK); | 943 | ASSERT(lbno != NULLAGBLOCK && rbno != NULLAGBLOCK); |
1087 | /* | 944 | /* |
1088 | * Fill in the key data in the new root. | 945 | * Fill in the key data in the new root. |
1089 | */ | 946 | */ |
1090 | kp = XFS_INOBT_KEY_ADDR(new, 1, cur); | 947 | kp = XFS_INOBT_KEY_ADDR(new, 1, cur); |
1091 | if (be16_to_cpu(left->bb_level) > 0) { | 948 | if (be16_to_cpu(left->bb_level) > 0) { |
1092 | kp[0] = *XFS_INOBT_KEY_ADDR(left, 1, cur); | 949 | kp[0] = *XFS_INOBT_KEY_ADDR(left, 1, cur); |
1093 | kp[1] = *XFS_INOBT_KEY_ADDR(right, 1, cur); | 950 | kp[1] = *XFS_INOBT_KEY_ADDR(right, 1, cur); |
1094 | } else { | 951 | } else { |
1095 | rp = XFS_INOBT_REC_ADDR(left, 1, cur); | 952 | rp = XFS_INOBT_REC_ADDR(left, 1, cur); |
1096 | kp[0].ir_startino = rp->ir_startino; | 953 | kp[0].ir_startino = rp->ir_startino; |
1097 | rp = XFS_INOBT_REC_ADDR(right, 1, cur); | 954 | rp = XFS_INOBT_REC_ADDR(right, 1, cur); |
1098 | kp[1].ir_startino = rp->ir_startino; | 955 | kp[1].ir_startino = rp->ir_startino; |
1099 | } | 956 | } |
1100 | xfs_inobt_log_keys(cur, nbp, 1, 2); | 957 | xfs_inobt_log_keys(cur, nbp, 1, 2); |
1101 | /* | 958 | /* |
1102 | * Fill in the pointer data in the new root. | 959 | * Fill in the pointer data in the new root. |
1103 | */ | 960 | */ |
1104 | pp = XFS_INOBT_PTR_ADDR(new, 1, cur); | 961 | pp = XFS_INOBT_PTR_ADDR(new, 1, cur); |
1105 | pp[0] = cpu_to_be32(lbno); | 962 | pp[0] = cpu_to_be32(lbno); |
1106 | pp[1] = cpu_to_be32(rbno); | 963 | pp[1] = cpu_to_be32(rbno); |
1107 | xfs_inobt_log_ptrs(cur, nbp, 1, 2); | 964 | xfs_inobt_log_ptrs(cur, nbp, 1, 2); |
1108 | /* | 965 | /* |
1109 | * Fix up the cursor. | 966 | * Fix up the cursor. |
1110 | */ | 967 | */ |
1111 | xfs_btree_setbuf(cur, cur->bc_nlevels, nbp); | 968 | xfs_btree_setbuf(cur, cur->bc_nlevels, nbp); |
1112 | cur->bc_ptrs[cur->bc_nlevels] = nptr; | 969 | cur->bc_ptrs[cur->bc_nlevels] = nptr; |
1113 | cur->bc_nlevels++; | 970 | cur->bc_nlevels++; |
1114 | *stat = 1; | 971 | *stat = 1; |
1115 | return 0; | 972 | return 0; |
1116 | } | 973 | } |
1117 | 974 | ||
1118 | /* | 975 | /* |
1119 | * Split cur/level block in half. | 976 | * Split cur/level block in half. |
1120 | * Return new block number and its first record (to be inserted into parent). | 977 | * Return new block number and its first record (to be inserted into parent). |
1121 | */ | 978 | */ |
1122 | STATIC int /* error */ | 979 | STATIC int /* error */ |
1123 | xfs_inobt_split( | 980 | xfs_inobt_split( |
1124 | xfs_btree_cur_t *cur, /* btree cursor */ | 981 | xfs_btree_cur_t *cur, /* btree cursor */ |
1125 | int level, /* level to split */ | 982 | int level, /* level to split */ |
1126 | xfs_agblock_t *bnop, /* output: block number allocated */ | 983 | xfs_agblock_t *bnop, /* output: block number allocated */ |
1127 | xfs_inobt_key_t *keyp, /* output: first key of new block */ | 984 | xfs_inobt_key_t *keyp, /* output: first key of new block */ |
1128 | xfs_btree_cur_t **curp, /* output: new cursor */ | 985 | xfs_btree_cur_t **curp, /* output: new cursor */ |
1129 | int *stat) /* success/failure */ | 986 | int *stat) /* success/failure */ |
1130 | { | 987 | { |
1131 | xfs_alloc_arg_t args; /* allocation argument structure */ | 988 | xfs_alloc_arg_t args; /* allocation argument structure */ |
1132 | int error; /* error return value */ | 989 | int error; /* error return value */ |
1133 | int i; /* loop index/record number */ | 990 | int i; /* loop index/record number */ |
1134 | xfs_agblock_t lbno; /* left (current) block number */ | 991 | xfs_agblock_t lbno; /* left (current) block number */ |
1135 | xfs_buf_t *lbp; /* buffer for left block */ | 992 | xfs_buf_t *lbp; /* buffer for left block */ |
1136 | xfs_inobt_block_t *left; /* left (current) btree block */ | 993 | xfs_inobt_block_t *left; /* left (current) btree block */ |
1137 | xfs_inobt_key_t *lkp; /* left btree key pointer */ | 994 | xfs_inobt_key_t *lkp; /* left btree key pointer */ |
1138 | xfs_inobt_ptr_t *lpp; /* left btree address pointer */ | 995 | xfs_inobt_ptr_t *lpp; /* left btree address pointer */ |
1139 | xfs_inobt_rec_t *lrp; /* left btree record pointer */ | 996 | xfs_inobt_rec_t *lrp; /* left btree record pointer */ |
1140 | xfs_buf_t *rbp; /* buffer for right block */ | 997 | xfs_buf_t *rbp; /* buffer for right block */ |
1141 | xfs_inobt_block_t *right; /* right (new) btree block */ | 998 | xfs_inobt_block_t *right; /* right (new) btree block */ |
1142 | xfs_inobt_key_t *rkp; /* right btree key pointer */ | 999 | xfs_inobt_key_t *rkp; /* right btree key pointer */ |
1143 | xfs_inobt_ptr_t *rpp; /* right btree address pointer */ | 1000 | xfs_inobt_ptr_t *rpp; /* right btree address pointer */ |
1144 | xfs_inobt_rec_t *rrp; /* right btree record pointer */ | 1001 | xfs_inobt_rec_t *rrp; /* right btree record pointer */ |
1145 | 1002 | ||
1146 | /* | 1003 | /* |
1147 | * Set up left block (current one). | 1004 | * Set up left block (current one). |
1148 | */ | 1005 | */ |
1149 | lbp = cur->bc_bufs[level]; | 1006 | lbp = cur->bc_bufs[level]; |
1150 | args.tp = cur->bc_tp; | 1007 | args.tp = cur->bc_tp; |
1151 | args.mp = cur->bc_mp; | 1008 | args.mp = cur->bc_mp; |
1152 | lbno = XFS_DADDR_TO_AGBNO(args.mp, XFS_BUF_ADDR(lbp)); | 1009 | lbno = XFS_DADDR_TO_AGBNO(args.mp, XFS_BUF_ADDR(lbp)); |
1153 | /* | 1010 | /* |
1154 | * Allocate the new block. | 1011 | * Allocate the new block. |
1155 | * If we can't do it, we're toast. Give up. | 1012 | * If we can't do it, we're toast. Give up. |
1156 | */ | 1013 | */ |
1157 | args.fsbno = XFS_AGB_TO_FSB(args.mp, cur->bc_private.a.agno, lbno); | 1014 | args.fsbno = XFS_AGB_TO_FSB(args.mp, cur->bc_private.a.agno, lbno); |
1158 | args.mod = args.minleft = args.alignment = args.total = args.wasdel = | 1015 | args.mod = args.minleft = args.alignment = args.total = args.wasdel = |
1159 | args.isfl = args.userdata = args.minalignslop = 0; | 1016 | args.isfl = args.userdata = args.minalignslop = 0; |
1160 | args.minlen = args.maxlen = args.prod = 1; | 1017 | args.minlen = args.maxlen = args.prod = 1; |
1161 | args.type = XFS_ALLOCTYPE_NEAR_BNO; | 1018 | args.type = XFS_ALLOCTYPE_NEAR_BNO; |
1162 | if ((error = xfs_alloc_vextent(&args))) | 1019 | if ((error = xfs_alloc_vextent(&args))) |
1163 | return error; | 1020 | return error; |
1164 | if (args.fsbno == NULLFSBLOCK) { | 1021 | if (args.fsbno == NULLFSBLOCK) { |
1165 | *stat = 0; | 1022 | *stat = 0; |
1166 | return 0; | 1023 | return 0; |
1167 | } | 1024 | } |
1168 | ASSERT(args.len == 1); | 1025 | ASSERT(args.len == 1); |
1169 | rbp = xfs_btree_get_bufs(args.mp, args.tp, args.agno, args.agbno, 0); | 1026 | rbp = xfs_btree_get_bufs(args.mp, args.tp, args.agno, args.agbno, 0); |
1170 | /* | 1027 | /* |
1171 | * Set up the new block as "right". | 1028 | * Set up the new block as "right". |
1172 | */ | 1029 | */ |
1173 | right = XFS_BUF_TO_INOBT_BLOCK(rbp); | 1030 | right = XFS_BUF_TO_INOBT_BLOCK(rbp); |
1174 | /* | 1031 | /* |
1175 | * "Left" is the current (according to the cursor) block. | 1032 | * "Left" is the current (according to the cursor) block. |
1176 | */ | 1033 | */ |
1177 | left = XFS_BUF_TO_INOBT_BLOCK(lbp); | 1034 | left = XFS_BUF_TO_INOBT_BLOCK(lbp); |
1178 | #ifdef DEBUG | 1035 | #ifdef DEBUG |
1179 | if ((error = xfs_btree_check_sblock(cur, left, level, lbp))) | 1036 | if ((error = xfs_btree_check_sblock(cur, left, level, lbp))) |
1180 | return error; | 1037 | return error; |
1181 | #endif | 1038 | #endif |
1182 | /* | 1039 | /* |
1183 | * Fill in the btree header for the new block. | 1040 | * Fill in the btree header for the new block. |
1184 | */ | 1041 | */ |
1185 | right->bb_magic = cpu_to_be32(xfs_magics[cur->bc_btnum]); | 1042 | right->bb_magic = cpu_to_be32(xfs_magics[cur->bc_btnum]); |
1186 | right->bb_level = left->bb_level; | 1043 | right->bb_level = left->bb_level; |
1187 | right->bb_numrecs = cpu_to_be16(be16_to_cpu(left->bb_numrecs) / 2); | 1044 | right->bb_numrecs = cpu_to_be16(be16_to_cpu(left->bb_numrecs) / 2); |
1188 | /* | 1045 | /* |
1189 | * Make sure that if there's an odd number of entries now, that | 1046 | * Make sure that if there's an odd number of entries now, that |
1190 | * each new block will have the same number of entries. | 1047 | * each new block will have the same number of entries. |
1191 | */ | 1048 | */ |
1192 | if ((be16_to_cpu(left->bb_numrecs) & 1) && | 1049 | if ((be16_to_cpu(left->bb_numrecs) & 1) && |
1193 | cur->bc_ptrs[level] <= be16_to_cpu(right->bb_numrecs) + 1) | 1050 | cur->bc_ptrs[level] <= be16_to_cpu(right->bb_numrecs) + 1) |
1194 | be16_add_cpu(&right->bb_numrecs, 1); | 1051 | be16_add_cpu(&right->bb_numrecs, 1); |
1195 | i = be16_to_cpu(left->bb_numrecs) - be16_to_cpu(right->bb_numrecs) + 1; | 1052 | i = be16_to_cpu(left->bb_numrecs) - be16_to_cpu(right->bb_numrecs) + 1; |
1196 | /* | 1053 | /* |
1197 | * For non-leaf blocks, copy keys and addresses over to the new block. | 1054 | * For non-leaf blocks, copy keys and addresses over to the new block. |
1198 | */ | 1055 | */ |
1199 | if (level > 0) { | 1056 | if (level > 0) { |
1200 | lkp = XFS_INOBT_KEY_ADDR(left, i, cur); | 1057 | lkp = XFS_INOBT_KEY_ADDR(left, i, cur); |
1201 | lpp = XFS_INOBT_PTR_ADDR(left, i, cur); | 1058 | lpp = XFS_INOBT_PTR_ADDR(left, i, cur); |
1202 | rkp = XFS_INOBT_KEY_ADDR(right, 1, cur); | 1059 | rkp = XFS_INOBT_KEY_ADDR(right, 1, cur); |
1203 | rpp = XFS_INOBT_PTR_ADDR(right, 1, cur); | 1060 | rpp = XFS_INOBT_PTR_ADDR(right, 1, cur); |
1204 | #ifdef DEBUG | 1061 | #ifdef DEBUG |
1205 | for (i = 0; i < be16_to_cpu(right->bb_numrecs); i++) { | 1062 | for (i = 0; i < be16_to_cpu(right->bb_numrecs); i++) { |
1206 | if ((error = xfs_btree_check_sptr(cur, be32_to_cpu(lpp[i]), level))) | 1063 | if ((error = xfs_btree_check_sptr(cur, be32_to_cpu(lpp[i]), level))) |
1207 | return error; | 1064 | return error; |
1208 | } | 1065 | } |
1209 | #endif | 1066 | #endif |
1210 | memcpy(rkp, lkp, be16_to_cpu(right->bb_numrecs) * sizeof(*rkp)); | 1067 | memcpy(rkp, lkp, be16_to_cpu(right->bb_numrecs) * sizeof(*rkp)); |
1211 | memcpy(rpp, lpp, be16_to_cpu(right->bb_numrecs) * sizeof(*rpp)); | 1068 | memcpy(rpp, lpp, be16_to_cpu(right->bb_numrecs) * sizeof(*rpp)); |
1212 | xfs_inobt_log_keys(cur, rbp, 1, be16_to_cpu(right->bb_numrecs)); | 1069 | xfs_inobt_log_keys(cur, rbp, 1, be16_to_cpu(right->bb_numrecs)); |
1213 | xfs_inobt_log_ptrs(cur, rbp, 1, be16_to_cpu(right->bb_numrecs)); | 1070 | xfs_inobt_log_ptrs(cur, rbp, 1, be16_to_cpu(right->bb_numrecs)); |
1214 | *keyp = *rkp; | 1071 | *keyp = *rkp; |
1215 | } | 1072 | } |
1216 | /* | 1073 | /* |
1217 | * For leaf blocks, copy records over to the new block. | 1074 | * For leaf blocks, copy records over to the new block. |
1218 | */ | 1075 | */ |
1219 | else { | 1076 | else { |
1220 | lrp = XFS_INOBT_REC_ADDR(left, i, cur); | 1077 | lrp = XFS_INOBT_REC_ADDR(left, i, cur); |
1221 | rrp = XFS_INOBT_REC_ADDR(right, 1, cur); | 1078 | rrp = XFS_INOBT_REC_ADDR(right, 1, cur); |
1222 | memcpy(rrp, lrp, be16_to_cpu(right->bb_numrecs) * sizeof(*rrp)); | 1079 | memcpy(rrp, lrp, be16_to_cpu(right->bb_numrecs) * sizeof(*rrp)); |
1223 | xfs_inobt_log_recs(cur, rbp, 1, be16_to_cpu(right->bb_numrecs)); | 1080 | xfs_inobt_log_recs(cur, rbp, 1, be16_to_cpu(right->bb_numrecs)); |
1224 | keyp->ir_startino = rrp->ir_startino; | 1081 | keyp->ir_startino = rrp->ir_startino; |
1225 | } | 1082 | } |
1226 | /* | 1083 | /* |
1227 | * Find the left block number by looking in the buffer. | 1084 | * Find the left block number by looking in the buffer. |
1228 | * Adjust numrecs, sibling pointers. | 1085 | * Adjust numrecs, sibling pointers. |
1229 | */ | 1086 | */ |
1230 | be16_add_cpu(&left->bb_numrecs, -(be16_to_cpu(right->bb_numrecs))); | 1087 | be16_add_cpu(&left->bb_numrecs, -(be16_to_cpu(right->bb_numrecs))); |
1231 | right->bb_rightsib = left->bb_rightsib; | 1088 | right->bb_rightsib = left->bb_rightsib; |
1232 | left->bb_rightsib = cpu_to_be32(args.agbno); | 1089 | left->bb_rightsib = cpu_to_be32(args.agbno); |
1233 | right->bb_leftsib = cpu_to_be32(lbno); | 1090 | right->bb_leftsib = cpu_to_be32(lbno); |
1234 | xfs_inobt_log_block(args.tp, rbp, XFS_BB_ALL_BITS); | 1091 | xfs_inobt_log_block(args.tp, rbp, XFS_BB_ALL_BITS); |
1235 | xfs_inobt_log_block(args.tp, lbp, XFS_BB_NUMRECS | XFS_BB_RIGHTSIB); | 1092 | xfs_inobt_log_block(args.tp, lbp, XFS_BB_NUMRECS | XFS_BB_RIGHTSIB); |
1236 | /* | 1093 | /* |
1237 | * If there's a block to the new block's right, make that block | 1094 | * If there's a block to the new block's right, make that block |
1238 | * point back to right instead of to left. | 1095 | * point back to right instead of to left. |
1239 | */ | 1096 | */ |
1240 | if (be32_to_cpu(right->bb_rightsib) != NULLAGBLOCK) { | 1097 | if (be32_to_cpu(right->bb_rightsib) != NULLAGBLOCK) { |
1241 | xfs_inobt_block_t *rrblock; /* rr btree block */ | 1098 | xfs_inobt_block_t *rrblock; /* rr btree block */ |
1242 | xfs_buf_t *rrbp; /* buffer for rrblock */ | 1099 | xfs_buf_t *rrbp; /* buffer for rrblock */ |
1243 | 1100 | ||
1244 | if ((error = xfs_btree_read_bufs(args.mp, args.tp, args.agno, | 1101 | if ((error = xfs_btree_read_bufs(args.mp, args.tp, args.agno, |
1245 | be32_to_cpu(right->bb_rightsib), 0, &rrbp, | 1102 | be32_to_cpu(right->bb_rightsib), 0, &rrbp, |
1246 | XFS_INO_BTREE_REF))) | 1103 | XFS_INO_BTREE_REF))) |
1247 | return error; | 1104 | return error; |
1248 | rrblock = XFS_BUF_TO_INOBT_BLOCK(rrbp); | 1105 | rrblock = XFS_BUF_TO_INOBT_BLOCK(rrbp); |
1249 | if ((error = xfs_btree_check_sblock(cur, rrblock, level, rrbp))) | 1106 | if ((error = xfs_btree_check_sblock(cur, rrblock, level, rrbp))) |
1250 | return error; | 1107 | return error; |
1251 | rrblock->bb_leftsib = cpu_to_be32(args.agbno); | 1108 | rrblock->bb_leftsib = cpu_to_be32(args.agbno); |
1252 | xfs_inobt_log_block(args.tp, rrbp, XFS_BB_LEFTSIB); | 1109 | xfs_inobt_log_block(args.tp, rrbp, XFS_BB_LEFTSIB); |
1253 | } | 1110 | } |
1254 | /* | 1111 | /* |
1255 | * If the cursor is really in the right block, move it there. | 1112 | * If the cursor is really in the right block, move it there. |
1256 | * If it's just pointing past the last entry in left, then we'll | 1113 | * If it's just pointing past the last entry in left, then we'll |
1257 | * insert there, so don't change anything in that case. | 1114 | * insert there, so don't change anything in that case. |
1258 | */ | 1115 | */ |
1259 | if (cur->bc_ptrs[level] > be16_to_cpu(left->bb_numrecs) + 1) { | 1116 | if (cur->bc_ptrs[level] > be16_to_cpu(left->bb_numrecs) + 1) { |
1260 | xfs_btree_setbuf(cur, level, rbp); | 1117 | xfs_btree_setbuf(cur, level, rbp); |
1261 | cur->bc_ptrs[level] -= be16_to_cpu(left->bb_numrecs); | 1118 | cur->bc_ptrs[level] -= be16_to_cpu(left->bb_numrecs); |
1262 | } | 1119 | } |
1263 | /* | 1120 | /* |
1264 | * If there are more levels, we'll need another cursor which refers | 1121 | * If there are more levels, we'll need another cursor which refers |
1265 | * the right block, no matter where this cursor was. | 1122 | * the right block, no matter where this cursor was. |
1266 | */ | 1123 | */ |
1267 | if (level + 1 < cur->bc_nlevels) { | 1124 | if (level + 1 < cur->bc_nlevels) { |
1268 | if ((error = xfs_btree_dup_cursor(cur, curp))) | 1125 | if ((error = xfs_btree_dup_cursor(cur, curp))) |
1269 | return error; | 1126 | return error; |
1270 | (*curp)->bc_ptrs[level + 1]++; | 1127 | (*curp)->bc_ptrs[level + 1]++; |
1271 | } | 1128 | } |
1272 | *bnop = args.agbno; | 1129 | *bnop = args.agbno; |
1273 | *stat = 1; | 1130 | *stat = 1; |
1274 | return 0; | 1131 | return 0; |
1275 | } | 1132 | } |
1276 | 1133 | ||
1277 | /* | 1134 | /* |
1278 | * Externally visible routines. | 1135 | * Externally visible routines. |
1279 | */ | 1136 | */ |
1280 | 1137 | ||
1281 | /* | 1138 | /* |
1282 | * Delete the record pointed to by cur. | 1139 | * Delete the record pointed to by cur. |
1283 | * The cursor refers to the place where the record was (could be inserted) | 1140 | * The cursor refers to the place where the record was (could be inserted) |
1284 | * when the operation returns. | 1141 | * when the operation returns. |
1285 | */ | 1142 | */ |
1286 | int /* error */ | 1143 | int /* error */ |
1287 | xfs_inobt_delete( | 1144 | xfs_inobt_delete( |
1288 | xfs_btree_cur_t *cur, /* btree cursor */ | 1145 | xfs_btree_cur_t *cur, /* btree cursor */ |
1289 | int *stat) /* success/failure */ | 1146 | int *stat) /* success/failure */ |
1290 | { | 1147 | { |
1291 | int error; | 1148 | int error; |
1292 | int i; /* result code */ | 1149 | int i; /* result code */ |
1293 | int level; /* btree level */ | 1150 | int level; /* btree level */ |
1294 | 1151 | ||
1295 | /* | 1152 | /* |
1296 | * Go up the tree, starting at leaf level. | 1153 | * Go up the tree, starting at leaf level. |
1297 | * If 2 is returned then a join was done; go to the next level. | 1154 | * If 2 is returned then a join was done; go to the next level. |
1298 | * Otherwise we are done. | 1155 | * Otherwise we are done. |
1299 | */ | 1156 | */ |
1300 | for (level = 0, i = 2; i == 2; level++) { | 1157 | for (level = 0, i = 2; i == 2; level++) { |
1301 | if ((error = xfs_inobt_delrec(cur, level, &i))) | 1158 | if ((error = xfs_inobt_delrec(cur, level, &i))) |
1302 | return error; | 1159 | return error; |
1303 | } | 1160 | } |
1304 | if (i == 0) { | 1161 | if (i == 0) { |
1305 | for (level = 1; level < cur->bc_nlevels; level++) { | 1162 | for (level = 1; level < cur->bc_nlevels; level++) { |
1306 | if (cur->bc_ptrs[level] == 0) { | 1163 | if (cur->bc_ptrs[level] == 0) { |
1307 | if ((error = xfs_btree_decrement(cur, level, &i))) | 1164 | if ((error = xfs_btree_decrement(cur, level, &i))) |
1308 | return error; | 1165 | return error; |
1309 | break; | 1166 | break; |
1310 | } | 1167 | } |
1311 | } | 1168 | } |
1312 | } | 1169 | } |
1313 | *stat = i; | 1170 | *stat = i; |
1314 | return 0; | 1171 | return 0; |
1315 | } | 1172 | } |
1316 | 1173 | ||
1317 | 1174 | ||
1318 | /* | 1175 | /* |
1319 | * Get the data from the pointed-to record. | 1176 | * Get the data from the pointed-to record. |
1320 | */ | 1177 | */ |
1321 | int /* error */ | 1178 | int /* error */ |
1322 | xfs_inobt_get_rec( | 1179 | xfs_inobt_get_rec( |
1323 | xfs_btree_cur_t *cur, /* btree cursor */ | 1180 | xfs_btree_cur_t *cur, /* btree cursor */ |
1324 | xfs_agino_t *ino, /* output: starting inode of chunk */ | 1181 | xfs_agino_t *ino, /* output: starting inode of chunk */ |
1325 | __int32_t *fcnt, /* output: number of free inodes */ | 1182 | __int32_t *fcnt, /* output: number of free inodes */ |
1326 | xfs_inofree_t *free, /* output: free inode mask */ | 1183 | xfs_inofree_t *free, /* output: free inode mask */ |
1327 | int *stat) /* output: success/failure */ | 1184 | int *stat) /* output: success/failure */ |
1328 | { | 1185 | { |
1329 | xfs_inobt_block_t *block; /* btree block */ | 1186 | xfs_inobt_block_t *block; /* btree block */ |
1330 | xfs_buf_t *bp; /* buffer containing btree block */ | 1187 | xfs_buf_t *bp; /* buffer containing btree block */ |
1331 | #ifdef DEBUG | 1188 | #ifdef DEBUG |
1332 | int error; /* error return value */ | 1189 | int error; /* error return value */ |
1333 | #endif | 1190 | #endif |
1334 | int ptr; /* record number */ | 1191 | int ptr; /* record number */ |
1335 | xfs_inobt_rec_t *rec; /* record data */ | 1192 | xfs_inobt_rec_t *rec; /* record data */ |
1336 | 1193 | ||
1337 | bp = cur->bc_bufs[0]; | 1194 | bp = cur->bc_bufs[0]; |
1338 | ptr = cur->bc_ptrs[0]; | 1195 | ptr = cur->bc_ptrs[0]; |
1339 | block = XFS_BUF_TO_INOBT_BLOCK(bp); | 1196 | block = XFS_BUF_TO_INOBT_BLOCK(bp); |
1340 | #ifdef DEBUG | 1197 | #ifdef DEBUG |
1341 | if ((error = xfs_btree_check_sblock(cur, block, 0, bp))) | 1198 | if ((error = xfs_btree_check_sblock(cur, block, 0, bp))) |
1342 | return error; | 1199 | return error; |
1343 | #endif | 1200 | #endif |
1344 | /* | 1201 | /* |
1345 | * Off the right end or left end, return failure. | 1202 | * Off the right end or left end, return failure. |
1346 | */ | 1203 | */ |
1347 | if (ptr > be16_to_cpu(block->bb_numrecs) || ptr <= 0) { | 1204 | if (ptr > be16_to_cpu(block->bb_numrecs) || ptr <= 0) { |
1348 | *stat = 0; | 1205 | *stat = 0; |
1349 | return 0; | 1206 | return 0; |
1350 | } | 1207 | } |
1351 | /* | 1208 | /* |
1352 | * Point to the record and extract its data. | 1209 | * Point to the record and extract its data. |
1353 | */ | 1210 | */ |
1354 | rec = XFS_INOBT_REC_ADDR(block, ptr, cur); | 1211 | rec = XFS_INOBT_REC_ADDR(block, ptr, cur); |
1355 | *ino = be32_to_cpu(rec->ir_startino); | 1212 | *ino = be32_to_cpu(rec->ir_startino); |
1356 | *fcnt = be32_to_cpu(rec->ir_freecount); | 1213 | *fcnt = be32_to_cpu(rec->ir_freecount); |
1357 | *free = be64_to_cpu(rec->ir_free); | 1214 | *free = be64_to_cpu(rec->ir_free); |
1358 | *stat = 1; | 1215 | *stat = 1; |
1359 | return 0; | 1216 | return 0; |
1360 | } | 1217 | } |
1361 | 1218 | ||
1362 | /* | 1219 | /* |
1363 | * Insert the current record at the point referenced by cur. | 1220 | * Insert the current record at the point referenced by cur. |
1364 | * The cursor may be inconsistent on return if splits have been done. | 1221 | * The cursor may be inconsistent on return if splits have been done. |
1365 | */ | 1222 | */ |
1366 | int /* error */ | 1223 | int /* error */ |
1367 | xfs_inobt_insert( | 1224 | xfs_inobt_insert( |
1368 | xfs_btree_cur_t *cur, /* btree cursor */ | 1225 | xfs_btree_cur_t *cur, /* btree cursor */ |
1369 | int *stat) /* success/failure */ | 1226 | int *stat) /* success/failure */ |
1370 | { | 1227 | { |
1371 | int error; /* error return value */ | 1228 | int error; /* error return value */ |
1372 | int i; /* result value, 0 for failure */ | 1229 | int i; /* result value, 0 for failure */ |
1373 | int level; /* current level number in btree */ | 1230 | int level; /* current level number in btree */ |
1374 | xfs_agblock_t nbno; /* new block number (split result) */ | 1231 | xfs_agblock_t nbno; /* new block number (split result) */ |
1375 | xfs_btree_cur_t *ncur; /* new cursor (split result) */ | 1232 | xfs_btree_cur_t *ncur; /* new cursor (split result) */ |
1376 | xfs_inobt_rec_t nrec; /* record being inserted this level */ | 1233 | xfs_inobt_rec_t nrec; /* record being inserted this level */ |
1377 | xfs_btree_cur_t *pcur; /* previous level's cursor */ | 1234 | xfs_btree_cur_t *pcur; /* previous level's cursor */ |
1378 | 1235 | ||
1379 | level = 0; | 1236 | level = 0; |
1380 | nbno = NULLAGBLOCK; | 1237 | nbno = NULLAGBLOCK; |
1381 | nrec.ir_startino = cpu_to_be32(cur->bc_rec.i.ir_startino); | 1238 | nrec.ir_startino = cpu_to_be32(cur->bc_rec.i.ir_startino); |
1382 | nrec.ir_freecount = cpu_to_be32(cur->bc_rec.i.ir_freecount); | 1239 | nrec.ir_freecount = cpu_to_be32(cur->bc_rec.i.ir_freecount); |
1383 | nrec.ir_free = cpu_to_be64(cur->bc_rec.i.ir_free); | 1240 | nrec.ir_free = cpu_to_be64(cur->bc_rec.i.ir_free); |
1384 | ncur = NULL; | 1241 | ncur = NULL; |
1385 | pcur = cur; | 1242 | pcur = cur; |
1386 | /* | 1243 | /* |
1387 | * Loop going up the tree, starting at the leaf level. | 1244 | * Loop going up the tree, starting at the leaf level. |
1388 | * Stop when we don't get a split block, that must mean that | 1245 | * Stop when we don't get a split block, that must mean that |
1389 | * the insert is finished with this level. | 1246 | * the insert is finished with this level. |
1390 | */ | 1247 | */ |
1391 | do { | 1248 | do { |
1392 | /* | 1249 | /* |
1393 | * Insert nrec/nbno into this level of the tree. | 1250 | * Insert nrec/nbno into this level of the tree. |
1394 | * Note if we fail, nbno will be null. | 1251 | * Note if we fail, nbno will be null. |
1395 | */ | 1252 | */ |
1396 | if ((error = xfs_inobt_insrec(pcur, level++, &nbno, &nrec, &ncur, | 1253 | if ((error = xfs_inobt_insrec(pcur, level++, &nbno, &nrec, &ncur, |
1397 | &i))) { | 1254 | &i))) { |
1398 | if (pcur != cur) | 1255 | if (pcur != cur) |
1399 | xfs_btree_del_cursor(pcur, XFS_BTREE_ERROR); | 1256 | xfs_btree_del_cursor(pcur, XFS_BTREE_ERROR); |
1400 | return error; | 1257 | return error; |
1401 | } | 1258 | } |
1402 | /* | 1259 | /* |
1403 | * See if the cursor we just used is trash. | 1260 | * See if the cursor we just used is trash. |
1404 | * Can't trash the caller's cursor, but otherwise we should | 1261 | * Can't trash the caller's cursor, but otherwise we should |
1405 | * if ncur is a new cursor or we're about to be done. | 1262 | * if ncur is a new cursor or we're about to be done. |
1406 | */ | 1263 | */ |
1407 | if (pcur != cur && (ncur || nbno == NULLAGBLOCK)) { | 1264 | if (pcur != cur && (ncur || nbno == NULLAGBLOCK)) { |
1408 | cur->bc_nlevels = pcur->bc_nlevels; | 1265 | cur->bc_nlevels = pcur->bc_nlevels; |
1409 | xfs_btree_del_cursor(pcur, XFS_BTREE_NOERROR); | 1266 | xfs_btree_del_cursor(pcur, XFS_BTREE_NOERROR); |
1410 | } | 1267 | } |
1411 | /* | 1268 | /* |
1412 | * If we got a new cursor, switch to it. | 1269 | * If we got a new cursor, switch to it. |
1413 | */ | 1270 | */ |
1414 | if (ncur) { | 1271 | if (ncur) { |
1415 | pcur = ncur; | 1272 | pcur = ncur; |
1416 | ncur = NULL; | 1273 | ncur = NULL; |
1417 | } | 1274 | } |
1418 | } while (nbno != NULLAGBLOCK); | 1275 | } while (nbno != NULLAGBLOCK); |
1419 | *stat = i; | 1276 | *stat = i; |
1420 | return 0; | 1277 | return 0; |
1421 | } | 1278 | } |
1422 | 1279 | ||
1423 | STATIC struct xfs_btree_cur * | 1280 | STATIC struct xfs_btree_cur * |
1424 | xfs_inobt_dup_cursor( | 1281 | xfs_inobt_dup_cursor( |
1425 | struct xfs_btree_cur *cur) | 1282 | struct xfs_btree_cur *cur) |
1426 | { | 1283 | { |
1427 | return xfs_inobt_init_cursor(cur->bc_mp, cur->bc_tp, | 1284 | return xfs_inobt_init_cursor(cur->bc_mp, cur->bc_tp, |
1428 | cur->bc_private.a.agbp, cur->bc_private.a.agno); | 1285 | cur->bc_private.a.agbp, cur->bc_private.a.agno); |
1429 | } | 1286 | } |
1430 | 1287 | ||
1431 | STATIC int | 1288 | STATIC int |
1432 | xfs_inobt_get_maxrecs( | 1289 | xfs_inobt_get_maxrecs( |
1433 | struct xfs_btree_cur *cur, | 1290 | struct xfs_btree_cur *cur, |
1434 | int level) | 1291 | int level) |
1435 | { | 1292 | { |
1436 | return cur->bc_mp->m_inobt_mxr[level != 0]; | 1293 | return cur->bc_mp->m_inobt_mxr[level != 0]; |
1437 | } | 1294 | } |
1438 | 1295 | ||
1439 | STATIC void | 1296 | STATIC void |
1440 | xfs_inobt_init_key_from_rec( | 1297 | xfs_inobt_init_key_from_rec( |
1441 | union xfs_btree_key *key, | 1298 | union xfs_btree_key *key, |
1442 | union xfs_btree_rec *rec) | 1299 | union xfs_btree_rec *rec) |
1443 | { | 1300 | { |
1444 | key->inobt.ir_startino = rec->inobt.ir_startino; | 1301 | key->inobt.ir_startino = rec->inobt.ir_startino; |
1445 | } | 1302 | } |
1446 | 1303 | ||
1447 | /* | 1304 | /* |
1448 | * intial value of ptr for lookup | 1305 | * intial value of ptr for lookup |
1449 | */ | 1306 | */ |
1450 | STATIC void | 1307 | STATIC void |
1451 | xfs_inobt_init_ptr_from_cur( | 1308 | xfs_inobt_init_ptr_from_cur( |
1452 | struct xfs_btree_cur *cur, | 1309 | struct xfs_btree_cur *cur, |
1453 | union xfs_btree_ptr *ptr) | 1310 | union xfs_btree_ptr *ptr) |
1454 | { | 1311 | { |
1455 | struct xfs_agi *agi = XFS_BUF_TO_AGI(cur->bc_private.a.agbp); | 1312 | struct xfs_agi *agi = XFS_BUF_TO_AGI(cur->bc_private.a.agbp); |
1456 | 1313 | ||
1457 | ASSERT(cur->bc_private.a.agno == be32_to_cpu(agi->agi_seqno)); | 1314 | ASSERT(cur->bc_private.a.agno == be32_to_cpu(agi->agi_seqno)); |
1458 | 1315 | ||
1459 | ptr->s = agi->agi_root; | 1316 | ptr->s = agi->agi_root; |
1460 | } | 1317 | } |
1461 | 1318 | ||
1462 | STATIC __int64_t | 1319 | STATIC __int64_t |
1463 | xfs_inobt_key_diff( | 1320 | xfs_inobt_key_diff( |
1464 | struct xfs_btree_cur *cur, | 1321 | struct xfs_btree_cur *cur, |
1465 | union xfs_btree_key *key) | 1322 | union xfs_btree_key *key) |
1466 | { | 1323 | { |
1467 | return (__int64_t)be32_to_cpu(key->inobt.ir_startino) - | 1324 | return (__int64_t)be32_to_cpu(key->inobt.ir_startino) - |
1468 | cur->bc_rec.i.ir_startino; | 1325 | cur->bc_rec.i.ir_startino; |
1469 | } | 1326 | } |
1470 | 1327 | ||
1471 | #ifdef XFS_BTREE_TRACE | 1328 | #ifdef XFS_BTREE_TRACE |
1472 | ktrace_t *xfs_inobt_trace_buf; | 1329 | ktrace_t *xfs_inobt_trace_buf; |
1473 | 1330 | ||
1474 | STATIC void | 1331 | STATIC void |
1475 | xfs_inobt_trace_enter( | 1332 | xfs_inobt_trace_enter( |
1476 | struct xfs_btree_cur *cur, | 1333 | struct xfs_btree_cur *cur, |
1477 | const char *func, | 1334 | const char *func, |
1478 | char *s, | 1335 | char *s, |
1479 | int type, | 1336 | int type, |
1480 | int line, | 1337 | int line, |
1481 | __psunsigned_t a0, | 1338 | __psunsigned_t a0, |
1482 | __psunsigned_t a1, | 1339 | __psunsigned_t a1, |
1483 | __psunsigned_t a2, | 1340 | __psunsigned_t a2, |
1484 | __psunsigned_t a3, | 1341 | __psunsigned_t a3, |
1485 | __psunsigned_t a4, | 1342 | __psunsigned_t a4, |
1486 | __psunsigned_t a5, | 1343 | __psunsigned_t a5, |
1487 | __psunsigned_t a6, | 1344 | __psunsigned_t a6, |
1488 | __psunsigned_t a7, | 1345 | __psunsigned_t a7, |
1489 | __psunsigned_t a8, | 1346 | __psunsigned_t a8, |
1490 | __psunsigned_t a9, | 1347 | __psunsigned_t a9, |
1491 | __psunsigned_t a10) | 1348 | __psunsigned_t a10) |
1492 | { | 1349 | { |
1493 | ktrace_enter(xfs_inobt_trace_buf, (void *)(__psint_t)type, | 1350 | ktrace_enter(xfs_inobt_trace_buf, (void *)(__psint_t)type, |
1494 | (void *)func, (void *)s, NULL, (void *)cur, | 1351 | (void *)func, (void *)s, NULL, (void *)cur, |
1495 | (void *)a0, (void *)a1, (void *)a2, (void *)a3, | 1352 | (void *)a0, (void *)a1, (void *)a2, (void *)a3, |
1496 | (void *)a4, (void *)a5, (void *)a6, (void *)a7, | 1353 | (void *)a4, (void *)a5, (void *)a6, (void *)a7, |
1497 | (void *)a8, (void *)a9, (void *)a10); | 1354 | (void *)a8, (void *)a9, (void *)a10); |
1498 | } | 1355 | } |
1499 | 1356 | ||
1500 | STATIC void | 1357 | STATIC void |
1501 | xfs_inobt_trace_cursor( | 1358 | xfs_inobt_trace_cursor( |
1502 | struct xfs_btree_cur *cur, | 1359 | struct xfs_btree_cur *cur, |
1503 | __uint32_t *s0, | 1360 | __uint32_t *s0, |
1504 | __uint64_t *l0, | 1361 | __uint64_t *l0, |
1505 | __uint64_t *l1) | 1362 | __uint64_t *l1) |
1506 | { | 1363 | { |
1507 | *s0 = cur->bc_private.a.agno; | 1364 | *s0 = cur->bc_private.a.agno; |
1508 | *l0 = cur->bc_rec.i.ir_startino; | 1365 | *l0 = cur->bc_rec.i.ir_startino; |
1509 | *l1 = cur->bc_rec.i.ir_free; | 1366 | *l1 = cur->bc_rec.i.ir_free; |
1510 | } | 1367 | } |
1511 | 1368 | ||
1512 | STATIC void | 1369 | STATIC void |
1513 | xfs_inobt_trace_key( | 1370 | xfs_inobt_trace_key( |
1514 | struct xfs_btree_cur *cur, | 1371 | struct xfs_btree_cur *cur, |
1515 | union xfs_btree_key *key, | 1372 | union xfs_btree_key *key, |
1516 | __uint64_t *l0, | 1373 | __uint64_t *l0, |
1517 | __uint64_t *l1) | 1374 | __uint64_t *l1) |
1518 | { | 1375 | { |
1519 | *l0 = be32_to_cpu(key->inobt.ir_startino); | 1376 | *l0 = be32_to_cpu(key->inobt.ir_startino); |
1520 | *l1 = 0; | 1377 | *l1 = 0; |
1521 | } | 1378 | } |
1522 | 1379 | ||
1523 | STATIC void | 1380 | STATIC void |
1524 | xfs_inobt_trace_record( | 1381 | xfs_inobt_trace_record( |
1525 | struct xfs_btree_cur *cur, | 1382 | struct xfs_btree_cur *cur, |
1526 | union xfs_btree_rec *rec, | 1383 | union xfs_btree_rec *rec, |
1527 | __uint64_t *l0, | 1384 | __uint64_t *l0, |
1528 | __uint64_t *l1, | 1385 | __uint64_t *l1, |
1529 | __uint64_t *l2) | 1386 | __uint64_t *l2) |
1530 | { | 1387 | { |
1531 | *l0 = be32_to_cpu(rec->inobt.ir_startino); | 1388 | *l0 = be32_to_cpu(rec->inobt.ir_startino); |
1532 | *l1 = be32_to_cpu(rec->inobt.ir_freecount); | 1389 | *l1 = be32_to_cpu(rec->inobt.ir_freecount); |
1533 | *l2 = be64_to_cpu(rec->inobt.ir_free); | 1390 | *l2 = be64_to_cpu(rec->inobt.ir_free); |
1534 | } | 1391 | } |
1535 | #endif /* XFS_BTREE_TRACE */ | 1392 | #endif /* XFS_BTREE_TRACE */ |
1536 | 1393 | ||
1537 | static const struct xfs_btree_ops xfs_inobt_ops = { | 1394 | static const struct xfs_btree_ops xfs_inobt_ops = { |
1538 | .rec_len = sizeof(xfs_inobt_rec_t), | 1395 | .rec_len = sizeof(xfs_inobt_rec_t), |
1539 | .key_len = sizeof(xfs_inobt_key_t), | 1396 | .key_len = sizeof(xfs_inobt_key_t), |
1540 | 1397 | ||
1541 | .dup_cursor = xfs_inobt_dup_cursor, | 1398 | .dup_cursor = xfs_inobt_dup_cursor, |
1542 | .get_maxrecs = xfs_inobt_get_maxrecs, | 1399 | .get_maxrecs = xfs_inobt_get_maxrecs, |
1543 | .init_key_from_rec = xfs_inobt_init_key_from_rec, | 1400 | .init_key_from_rec = xfs_inobt_init_key_from_rec, |
1544 | .init_ptr_from_cur = xfs_inobt_init_ptr_from_cur, | 1401 | .init_ptr_from_cur = xfs_inobt_init_ptr_from_cur, |
1545 | .key_diff = xfs_inobt_key_diff, | 1402 | .key_diff = xfs_inobt_key_diff, |
1546 | 1403 | ||
1547 | #ifdef XFS_BTREE_TRACE | 1404 | #ifdef XFS_BTREE_TRACE |
1548 | .trace_enter = xfs_inobt_trace_enter, | 1405 | .trace_enter = xfs_inobt_trace_enter, |
1549 | .trace_cursor = xfs_inobt_trace_cursor, | 1406 | .trace_cursor = xfs_inobt_trace_cursor, |
1550 | .trace_key = xfs_inobt_trace_key, | 1407 | .trace_key = xfs_inobt_trace_key, |
1551 | .trace_record = xfs_inobt_trace_record, | 1408 | .trace_record = xfs_inobt_trace_record, |
1552 | #endif | 1409 | #endif |
1553 | }; | 1410 | }; |
1554 | 1411 | ||
1555 | /* | 1412 | /* |
1556 | * Allocate a new inode btree cursor. | 1413 | * Allocate a new inode btree cursor. |
1557 | */ | 1414 | */ |
1558 | struct xfs_btree_cur * /* new inode btree cursor */ | 1415 | struct xfs_btree_cur * /* new inode btree cursor */ |
1559 | xfs_inobt_init_cursor( | 1416 | xfs_inobt_init_cursor( |
1560 | struct xfs_mount *mp, /* file system mount point */ | 1417 | struct xfs_mount *mp, /* file system mount point */ |
1561 | struct xfs_trans *tp, /* transaction pointer */ | 1418 | struct xfs_trans *tp, /* transaction pointer */ |
1562 | struct xfs_buf *agbp, /* buffer for agi structure */ | 1419 | struct xfs_buf *agbp, /* buffer for agi structure */ |
1563 | xfs_agnumber_t agno) /* allocation group number */ | 1420 | xfs_agnumber_t agno) /* allocation group number */ |
1564 | { | 1421 | { |
1565 | struct xfs_agi *agi = XFS_BUF_TO_AGI(agbp); | 1422 | struct xfs_agi *agi = XFS_BUF_TO_AGI(agbp); |
1566 | struct xfs_btree_cur *cur; | 1423 | struct xfs_btree_cur *cur; |
1567 | 1424 | ||
1568 | cur = kmem_zone_zalloc(xfs_btree_cur_zone, KM_SLEEP); | 1425 | cur = kmem_zone_zalloc(xfs_btree_cur_zone, KM_SLEEP); |
1569 | 1426 | ||
1570 | cur->bc_tp = tp; | 1427 | cur->bc_tp = tp; |
1571 | cur->bc_mp = mp; | 1428 | cur->bc_mp = mp; |
1572 | cur->bc_nlevels = be32_to_cpu(agi->agi_level); | 1429 | cur->bc_nlevels = be32_to_cpu(agi->agi_level); |
1573 | cur->bc_btnum = XFS_BTNUM_INO; | 1430 | cur->bc_btnum = XFS_BTNUM_INO; |
1574 | cur->bc_blocklog = mp->m_sb.sb_blocklog; | 1431 | cur->bc_blocklog = mp->m_sb.sb_blocklog; |
1575 | 1432 | ||
1576 | cur->bc_ops = &xfs_inobt_ops; | 1433 | cur->bc_ops = &xfs_inobt_ops; |
1577 | 1434 | ||
1578 | cur->bc_private.a.agbp = agbp; | 1435 | cur->bc_private.a.agbp = agbp; |
1579 | cur->bc_private.a.agno = agno; | 1436 | cur->bc_private.a.agno = agno; |
1580 | 1437 | ||
1581 | return cur; | 1438 | return cur; |
1582 | } | 1439 | } |
1583 | 1440 |