diff options
Diffstat (limited to 'fs/xfs/xfs_bmap_btree.c')
-rw-r--r-- | fs/xfs/xfs_bmap_btree.c | 2617 |
1 files changed, 469 insertions, 2148 deletions
diff --git a/fs/xfs/xfs_bmap_btree.c b/fs/xfs/xfs_bmap_btree.c index 23efad29a5c..8f1ec73725d 100644 --- a/fs/xfs/xfs_bmap_btree.c +++ b/fs/xfs/xfs_bmap_btree.c | |||
@@ -37,1406 +37,13 @@ | |||
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_ialloc.h" | 41 | #include "xfs_ialloc.h" |
41 | #include "xfs_itable.h" | 42 | #include "xfs_itable.h" |
42 | #include "xfs_bmap.h" | 43 | #include "xfs_bmap.h" |
43 | #include "xfs_error.h" | 44 | #include "xfs_error.h" |
44 | #include "xfs_quota.h" | 45 | #include "xfs_quota.h" |
45 | 46 | ||
46 | #if defined(XFS_BMBT_TRACE) | ||
47 | ktrace_t *xfs_bmbt_trace_buf; | ||
48 | #endif | ||
49 | |||
50 | /* | ||
51 | * Prototypes for internal btree functions. | ||
52 | */ | ||
53 | |||
54 | |||
55 | STATIC int xfs_bmbt_killroot(xfs_btree_cur_t *); | ||
56 | STATIC void xfs_bmbt_log_keys(xfs_btree_cur_t *, xfs_buf_t *, int, int); | ||
57 | STATIC void xfs_bmbt_log_ptrs(xfs_btree_cur_t *, xfs_buf_t *, int, int); | ||
58 | STATIC int xfs_bmbt_lshift(xfs_btree_cur_t *, int, int *); | ||
59 | STATIC int xfs_bmbt_rshift(xfs_btree_cur_t *, int, int *); | ||
60 | STATIC int xfs_bmbt_split(xfs_btree_cur_t *, int, xfs_fsblock_t *, | ||
61 | __uint64_t *, xfs_btree_cur_t **, int *); | ||
62 | STATIC int xfs_bmbt_updkey(xfs_btree_cur_t *, xfs_bmbt_key_t *, int); | ||
63 | |||
64 | |||
65 | #if defined(XFS_BMBT_TRACE) | ||
66 | |||
67 | static char ARGS[] = "args"; | ||
68 | static char ENTRY[] = "entry"; | ||
69 | static char ERROR[] = "error"; | ||
70 | #undef EXIT | ||
71 | static char EXIT[] = "exit"; | ||
72 | |||
73 | /* | ||
74 | * Add a trace buffer entry for the arguments given to the routine, | ||
75 | * generic form. | ||
76 | */ | ||
77 | STATIC void | ||
78 | xfs_bmbt_trace_enter( | ||
79 | const char *func, | ||
80 | xfs_btree_cur_t *cur, | ||
81 | char *s, | ||
82 | int type, | ||
83 | int line, | ||
84 | __psunsigned_t a0, | ||
85 | __psunsigned_t a1, | ||
86 | __psunsigned_t a2, | ||
87 | __psunsigned_t a3, | ||
88 | __psunsigned_t a4, | ||
89 | __psunsigned_t a5, | ||
90 | __psunsigned_t a6, | ||
91 | __psunsigned_t a7, | ||
92 | __psunsigned_t a8, | ||
93 | __psunsigned_t a9, | ||
94 | __psunsigned_t a10) | ||
95 | { | ||
96 | xfs_inode_t *ip; | ||
97 | int whichfork; | ||
98 | |||
99 | ip = cur->bc_private.b.ip; | ||
100 | whichfork = cur->bc_private.b.whichfork; | ||
101 | ktrace_enter(xfs_bmbt_trace_buf, | ||
102 | (void *)((__psint_t)type | (whichfork << 8) | (line << 16)), | ||
103 | (void *)func, (void *)s, (void *)ip, (void *)cur, | ||
104 | (void *)a0, (void *)a1, (void *)a2, (void *)a3, | ||
105 | (void *)a4, (void *)a5, (void *)a6, (void *)a7, | ||
106 | (void *)a8, (void *)a9, (void *)a10); | ||
107 | ASSERT(ip->i_btrace); | ||
108 | ktrace_enter(ip->i_btrace, | ||
109 | (void *)((__psint_t)type | (whichfork << 8) | (line << 16)), | ||
110 | (void *)func, (void *)s, (void *)ip, (void *)cur, | ||
111 | (void *)a0, (void *)a1, (void *)a2, (void *)a3, | ||
112 | (void *)a4, (void *)a5, (void *)a6, (void *)a7, | ||
113 | (void *)a8, (void *)a9, (void *)a10); | ||
114 | } | ||
115 | /* | ||
116 | * Add a trace buffer entry for arguments, for a buffer & 1 integer arg. | ||
117 | */ | ||
118 | STATIC void | ||
119 | xfs_bmbt_trace_argbi( | ||
120 | const char *func, | ||
121 | xfs_btree_cur_t *cur, | ||
122 | xfs_buf_t *b, | ||
123 | int i, | ||
124 | int line) | ||
125 | { | ||
126 | xfs_bmbt_trace_enter(func, cur, ARGS, XFS_BMBT_KTRACE_ARGBI, line, | ||
127 | (__psunsigned_t)b, i, 0, 0, | ||
128 | 0, 0, 0, 0, | ||
129 | 0, 0, 0); | ||
130 | } | ||
131 | |||
132 | /* | ||
133 | * Add a trace buffer entry for arguments, for a buffer & 2 integer args. | ||
134 | */ | ||
135 | STATIC void | ||
136 | xfs_bmbt_trace_argbii( | ||
137 | const char *func, | ||
138 | xfs_btree_cur_t *cur, | ||
139 | xfs_buf_t *b, | ||
140 | int i0, | ||
141 | int i1, | ||
142 | int line) | ||
143 | { | ||
144 | xfs_bmbt_trace_enter(func, cur, ARGS, XFS_BMBT_KTRACE_ARGBII, line, | ||
145 | (__psunsigned_t)b, i0, i1, 0, | ||
146 | 0, 0, 0, 0, | ||
147 | 0, 0, 0); | ||
148 | } | ||
149 | |||
150 | /* | ||
151 | * Add a trace buffer entry for arguments, for 3 block-length args | ||
152 | * and an integer arg. | ||
153 | */ | ||
154 | STATIC void | ||
155 | xfs_bmbt_trace_argfffi( | ||
156 | const char *func, | ||
157 | xfs_btree_cur_t *cur, | ||
158 | xfs_dfiloff_t o, | ||
159 | xfs_dfsbno_t b, | ||
160 | xfs_dfilblks_t i, | ||
161 | int j, | ||
162 | int line) | ||
163 | { | ||
164 | xfs_bmbt_trace_enter(func, cur, ARGS, XFS_BMBT_KTRACE_ARGFFFI, line, | ||
165 | o >> 32, (int)o, b >> 32, (int)b, | ||
166 | i >> 32, (int)i, (int)j, 0, | ||
167 | 0, 0, 0); | ||
168 | } | ||
169 | |||
170 | /* | ||
171 | * Add a trace buffer entry for arguments, for one integer arg. | ||
172 | */ | ||
173 | STATIC void | ||
174 | xfs_bmbt_trace_argi( | ||
175 | const char *func, | ||
176 | xfs_btree_cur_t *cur, | ||
177 | int i, | ||
178 | int line) | ||
179 | { | ||
180 | xfs_bmbt_trace_enter(func, cur, ARGS, XFS_BMBT_KTRACE_ARGI, line, | ||
181 | i, 0, 0, 0, | ||
182 | 0, 0, 0, 0, | ||
183 | 0, 0, 0); | ||
184 | } | ||
185 | |||
186 | /* | ||
187 | * Add a trace buffer entry for arguments, for int, fsblock, key. | ||
188 | */ | ||
189 | STATIC void | ||
190 | xfs_bmbt_trace_argifk( | ||
191 | const char *func, | ||
192 | xfs_btree_cur_t *cur, | ||
193 | int i, | ||
194 | xfs_fsblock_t f, | ||
195 | xfs_dfiloff_t o, | ||
196 | int line) | ||
197 | { | ||
198 | xfs_bmbt_trace_enter(func, cur, ARGS, XFS_BMBT_KTRACE_ARGIFK, line, | ||
199 | i, (xfs_dfsbno_t)f >> 32, (int)f, o >> 32, | ||
200 | (int)o, 0, 0, 0, | ||
201 | 0, 0, 0); | ||
202 | } | ||
203 | |||
204 | /* | ||
205 | * Add a trace buffer entry for arguments, for int, fsblock, rec. | ||
206 | */ | ||
207 | STATIC void | ||
208 | xfs_bmbt_trace_argifr( | ||
209 | const char *func, | ||
210 | xfs_btree_cur_t *cur, | ||
211 | int i, | ||
212 | xfs_fsblock_t f, | ||
213 | xfs_bmbt_rec_t *r, | ||
214 | int line) | ||
215 | { | ||
216 | xfs_dfsbno_t b; | ||
217 | xfs_dfilblks_t c; | ||
218 | xfs_dfsbno_t d; | ||
219 | xfs_dfiloff_t o; | ||
220 | xfs_bmbt_irec_t s; | ||
221 | |||
222 | d = (xfs_dfsbno_t)f; | ||
223 | xfs_bmbt_disk_get_all(r, &s); | ||
224 | o = (xfs_dfiloff_t)s.br_startoff; | ||
225 | b = (xfs_dfsbno_t)s.br_startblock; | ||
226 | c = s.br_blockcount; | ||
227 | xfs_bmbt_trace_enter(func, cur, ARGS, XFS_BMBT_KTRACE_ARGIFR, line, | ||
228 | i, d >> 32, (int)d, o >> 32, | ||
229 | (int)o, b >> 32, (int)b, c >> 32, | ||
230 | (int)c, 0, 0); | ||
231 | } | ||
232 | |||
233 | /* | ||
234 | * Add a trace buffer entry for arguments, for int, key. | ||
235 | */ | ||
236 | STATIC void | ||
237 | xfs_bmbt_trace_argik( | ||
238 | const char *func, | ||
239 | xfs_btree_cur_t *cur, | ||
240 | int i, | ||
241 | xfs_bmbt_key_t *k, | ||
242 | int line) | ||
243 | { | ||
244 | xfs_dfiloff_t o; | ||
245 | |||
246 | o = be64_to_cpu(k->br_startoff); | ||
247 | xfs_bmbt_trace_enter(func, cur, ARGS, XFS_BMBT_KTRACE_ARGIFK, line, | ||
248 | i, o >> 32, (int)o, 0, | ||
249 | 0, 0, 0, 0, | ||
250 | 0, 0, 0); | ||
251 | } | ||
252 | |||
253 | /* | ||
254 | * Add a trace buffer entry for the cursor/operation. | ||
255 | */ | ||
256 | STATIC void | ||
257 | xfs_bmbt_trace_cursor( | ||
258 | const char *func, | ||
259 | xfs_btree_cur_t *cur, | ||
260 | char *s, | ||
261 | int line) | ||
262 | { | ||
263 | xfs_bmbt_rec_host_t r; | ||
264 | |||
265 | xfs_bmbt_set_all(&r, &cur->bc_rec.b); | ||
266 | xfs_bmbt_trace_enter(func, cur, s, XFS_BMBT_KTRACE_CUR, line, | ||
267 | (cur->bc_nlevels << 24) | (cur->bc_private.b.flags << 16) | | ||
268 | cur->bc_private.b.allocated, | ||
269 | r.l0 >> 32, (int)r.l0, | ||
270 | r.l1 >> 32, (int)r.l1, | ||
271 | (unsigned long)cur->bc_bufs[0], (unsigned long)cur->bc_bufs[1], | ||
272 | (unsigned long)cur->bc_bufs[2], (unsigned long)cur->bc_bufs[3], | ||
273 | (cur->bc_ptrs[0] << 16) | cur->bc_ptrs[1], | ||
274 | (cur->bc_ptrs[2] << 16) | cur->bc_ptrs[3]); | ||
275 | } | ||
276 | |||
277 | #define XFS_BMBT_TRACE_ARGBI(c,b,i) \ | ||
278 | xfs_bmbt_trace_argbi(__func__, c, b, i, __LINE__) | ||
279 | #define XFS_BMBT_TRACE_ARGBII(c,b,i,j) \ | ||
280 | xfs_bmbt_trace_argbii(__func__, c, b, i, j, __LINE__) | ||
281 | #define XFS_BMBT_TRACE_ARGFFFI(c,o,b,i,j) \ | ||
282 | xfs_bmbt_trace_argfffi(__func__, c, o, b, i, j, __LINE__) | ||
283 | #define XFS_BMBT_TRACE_ARGI(c,i) \ | ||
284 | xfs_bmbt_trace_argi(__func__, c, i, __LINE__) | ||
285 | #define XFS_BMBT_TRACE_ARGIFK(c,i,f,s) \ | ||
286 | xfs_bmbt_trace_argifk(__func__, c, i, f, s, __LINE__) | ||
287 | #define XFS_BMBT_TRACE_ARGIFR(c,i,f,r) \ | ||
288 | xfs_bmbt_trace_argifr(__func__, c, i, f, r, __LINE__) | ||
289 | #define XFS_BMBT_TRACE_ARGIK(c,i,k) \ | ||
290 | xfs_bmbt_trace_argik(__func__, c, i, k, __LINE__) | ||
291 | #define XFS_BMBT_TRACE_CURSOR(c,s) \ | ||
292 | xfs_bmbt_trace_cursor(__func__, c, s, __LINE__) | ||
293 | #else | ||
294 | #define XFS_BMBT_TRACE_ARGBI(c,b,i) | ||
295 | #define XFS_BMBT_TRACE_ARGBII(c,b,i,j) | ||
296 | #define XFS_BMBT_TRACE_ARGFFFI(c,o,b,i,j) | ||
297 | #define XFS_BMBT_TRACE_ARGI(c,i) | ||
298 | #define XFS_BMBT_TRACE_ARGIFK(c,i,f,s) | ||
299 | #define XFS_BMBT_TRACE_ARGIFR(c,i,f,r) | ||
300 | #define XFS_BMBT_TRACE_ARGIK(c,i,k) | ||
301 | #define XFS_BMBT_TRACE_CURSOR(c,s) | ||
302 | #endif /* XFS_BMBT_TRACE */ | ||
303 | |||
304 | |||
305 | /* | ||
306 | * Internal functions. | ||
307 | */ | ||
308 | |||
309 | /* | ||
310 | * Delete record pointed to by cur/level. | ||
311 | */ | ||
312 | STATIC int /* error */ | ||
313 | xfs_bmbt_delrec( | ||
314 | xfs_btree_cur_t *cur, | ||
315 | int level, | ||
316 | int *stat) /* success/failure */ | ||
317 | { | ||
318 | xfs_bmbt_block_t *block; /* bmap btree block */ | ||
319 | xfs_fsblock_t bno; /* fs-relative block number */ | ||
320 | xfs_buf_t *bp; /* buffer for block */ | ||
321 | int error; /* error return value */ | ||
322 | int i; /* loop counter */ | ||
323 | int j; /* temp state */ | ||
324 | xfs_bmbt_key_t key; /* bmap btree key */ | ||
325 | xfs_bmbt_key_t *kp=NULL; /* pointer to bmap btree key */ | ||
326 | xfs_fsblock_t lbno; /* left sibling block number */ | ||
327 | xfs_buf_t *lbp; /* left buffer pointer */ | ||
328 | xfs_bmbt_block_t *left; /* left btree block */ | ||
329 | xfs_bmbt_key_t *lkp; /* left btree key */ | ||
330 | xfs_bmbt_ptr_t *lpp; /* left address pointer */ | ||
331 | int lrecs=0; /* left record count */ | ||
332 | xfs_bmbt_rec_t *lrp; /* left record pointer */ | ||
333 | xfs_mount_t *mp; /* file system mount point */ | ||
334 | xfs_bmbt_ptr_t *pp; /* pointer to bmap block addr */ | ||
335 | int ptr; /* key/record index */ | ||
336 | xfs_fsblock_t rbno; /* right sibling block number */ | ||
337 | xfs_buf_t *rbp; /* right buffer pointer */ | ||
338 | xfs_bmbt_block_t *right; /* right btree block */ | ||
339 | xfs_bmbt_key_t *rkp; /* right btree key */ | ||
340 | xfs_bmbt_rec_t *rp; /* pointer to bmap btree rec */ | ||
341 | xfs_bmbt_ptr_t *rpp; /* right address pointer */ | ||
342 | xfs_bmbt_block_t *rrblock; /* right-right btree block */ | ||
343 | xfs_buf_t *rrbp; /* right-right buffer pointer */ | ||
344 | int rrecs=0; /* right record count */ | ||
345 | xfs_bmbt_rec_t *rrp; /* right record pointer */ | ||
346 | xfs_btree_cur_t *tcur; /* temporary btree cursor */ | ||
347 | int numrecs; /* temporary numrec count */ | ||
348 | int numlrecs, numrrecs; | ||
349 | |||
350 | XFS_BMBT_TRACE_CURSOR(cur, ENTRY); | ||
351 | XFS_BMBT_TRACE_ARGI(cur, level); | ||
352 | ptr = cur->bc_ptrs[level]; | ||
353 | tcur = NULL; | ||
354 | if (ptr == 0) { | ||
355 | XFS_BMBT_TRACE_CURSOR(cur, EXIT); | ||
356 | *stat = 0; | ||
357 | return 0; | ||
358 | } | ||
359 | block = xfs_bmbt_get_block(cur, level, &bp); | ||
360 | numrecs = be16_to_cpu(block->bb_numrecs); | ||
361 | #ifdef DEBUG | ||
362 | if ((error = xfs_btree_check_lblock(cur, block, level, bp))) { | ||
363 | XFS_BMBT_TRACE_CURSOR(cur, ERROR); | ||
364 | goto error0; | ||
365 | } | ||
366 | #endif | ||
367 | if (ptr > numrecs) { | ||
368 | XFS_BMBT_TRACE_CURSOR(cur, EXIT); | ||
369 | *stat = 0; | ||
370 | return 0; | ||
371 | } | ||
372 | XFS_STATS_INC(xs_bmbt_delrec); | ||
373 | if (level > 0) { | ||
374 | kp = XFS_BMAP_KEY_IADDR(block, 1, cur); | ||
375 | pp = XFS_BMAP_PTR_IADDR(block, 1, cur); | ||
376 | #ifdef DEBUG | ||
377 | for (i = ptr; i < numrecs; i++) { | ||
378 | if ((error = xfs_btree_check_lptr_disk(cur, pp[i], level))) { | ||
379 | XFS_BMBT_TRACE_CURSOR(cur, ERROR); | ||
380 | goto error0; | ||
381 | } | ||
382 | } | ||
383 | #endif | ||
384 | if (ptr < numrecs) { | ||
385 | memmove(&kp[ptr - 1], &kp[ptr], | ||
386 | (numrecs - ptr) * sizeof(*kp)); | ||
387 | memmove(&pp[ptr - 1], &pp[ptr], | ||
388 | (numrecs - ptr) * sizeof(*pp)); | ||
389 | xfs_bmbt_log_ptrs(cur, bp, ptr, numrecs - 1); | ||
390 | xfs_bmbt_log_keys(cur, bp, ptr, numrecs - 1); | ||
391 | } | ||
392 | } else { | ||
393 | rp = XFS_BMAP_REC_IADDR(block, 1, cur); | ||
394 | if (ptr < numrecs) { | ||
395 | memmove(&rp[ptr - 1], &rp[ptr], | ||
396 | (numrecs - ptr) * sizeof(*rp)); | ||
397 | xfs_bmbt_log_recs(cur, bp, ptr, numrecs - 1); | ||
398 | } | ||
399 | if (ptr == 1) { | ||
400 | key.br_startoff = | ||
401 | cpu_to_be64(xfs_bmbt_disk_get_startoff(rp)); | ||
402 | kp = &key; | ||
403 | } | ||
404 | } | ||
405 | numrecs--; | ||
406 | block->bb_numrecs = cpu_to_be16(numrecs); | ||
407 | xfs_bmbt_log_block(cur, bp, XFS_BB_NUMRECS); | ||
408 | /* | ||
409 | * We're at the root level. | ||
410 | * First, shrink the root block in-memory. | ||
411 | * Try to get rid of the next level down. | ||
412 | * If we can't then there's nothing left to do. | ||
413 | */ | ||
414 | if (level == cur->bc_nlevels - 1) { | ||
415 | xfs_iroot_realloc(cur->bc_private.b.ip, -1, | ||
416 | cur->bc_private.b.whichfork); | ||
417 | if ((error = xfs_bmbt_killroot(cur))) { | ||
418 | XFS_BMBT_TRACE_CURSOR(cur, ERROR); | ||
419 | goto error0; | ||
420 | } | ||
421 | if (level > 0 && (error = xfs_bmbt_decrement(cur, level, &j))) { | ||
422 | XFS_BMBT_TRACE_CURSOR(cur, ERROR); | ||
423 | goto error0; | ||
424 | } | ||
425 | XFS_BMBT_TRACE_CURSOR(cur, EXIT); | ||
426 | *stat = 1; | ||
427 | return 0; | ||
428 | } | ||
429 | if (ptr == 1 && (error = xfs_bmbt_updkey(cur, kp, level + 1))) { | ||
430 | XFS_BMBT_TRACE_CURSOR(cur, ERROR); | ||
431 | goto error0; | ||
432 | } | ||
433 | if (numrecs >= XFS_BMAP_BLOCK_IMINRECS(level, cur)) { | ||
434 | if (level > 0 && (error = xfs_bmbt_decrement(cur, level, &j))) { | ||
435 | XFS_BMBT_TRACE_CURSOR(cur, ERROR); | ||
436 | goto error0; | ||
437 | } | ||
438 | XFS_BMBT_TRACE_CURSOR(cur, EXIT); | ||
439 | *stat = 1; | ||
440 | return 0; | ||
441 | } | ||
442 | rbno = be64_to_cpu(block->bb_rightsib); | ||
443 | lbno = be64_to_cpu(block->bb_leftsib); | ||
444 | /* | ||
445 | * One child of root, need to get a chance to copy its contents | ||
446 | * into the root and delete it. Can't go up to next level, | ||
447 | * there's nothing to delete there. | ||
448 | */ | ||
449 | if (lbno == NULLFSBLOCK && rbno == NULLFSBLOCK && | ||
450 | level == cur->bc_nlevels - 2) { | ||
451 | if ((error = xfs_bmbt_killroot(cur))) { | ||
452 | XFS_BMBT_TRACE_CURSOR(cur, ERROR); | ||
453 | goto error0; | ||
454 | } | ||
455 | if (level > 0 && (error = xfs_bmbt_decrement(cur, level, &i))) { | ||
456 | XFS_BMBT_TRACE_CURSOR(cur, ERROR); | ||
457 | goto error0; | ||
458 | } | ||
459 | XFS_BMBT_TRACE_CURSOR(cur, EXIT); | ||
460 | *stat = 1; | ||
461 | return 0; | ||
462 | } | ||
463 | ASSERT(rbno != NULLFSBLOCK || lbno != NULLFSBLOCK); | ||
464 | if ((error = xfs_btree_dup_cursor(cur, &tcur))) { | ||
465 | XFS_BMBT_TRACE_CURSOR(cur, ERROR); | ||
466 | goto error0; | ||
467 | } | ||
468 | bno = NULLFSBLOCK; | ||
469 | if (rbno != NULLFSBLOCK) { | ||
470 | i = xfs_btree_lastrec(tcur, level); | ||
471 | XFS_WANT_CORRUPTED_GOTO(i == 1, error0); | ||
472 | if ((error = xfs_bmbt_increment(tcur, level, &i))) { | ||
473 | XFS_BMBT_TRACE_CURSOR(cur, ERROR); | ||
474 | goto error0; | ||
475 | } | ||
476 | XFS_WANT_CORRUPTED_GOTO(i == 1, error0); | ||
477 | i = xfs_btree_lastrec(tcur, level); | ||
478 | XFS_WANT_CORRUPTED_GOTO(i == 1, error0); | ||
479 | rbp = tcur->bc_bufs[level]; | ||
480 | right = XFS_BUF_TO_BMBT_BLOCK(rbp); | ||
481 | #ifdef DEBUG | ||
482 | if ((error = xfs_btree_check_lblock(cur, right, level, rbp))) { | ||
483 | XFS_BMBT_TRACE_CURSOR(cur, ERROR); | ||
484 | goto error0; | ||
485 | } | ||
486 | #endif | ||
487 | bno = be64_to_cpu(right->bb_leftsib); | ||
488 | if (be16_to_cpu(right->bb_numrecs) - 1 >= | ||
489 | XFS_BMAP_BLOCK_IMINRECS(level, cur)) { | ||
490 | if ((error = xfs_bmbt_lshift(tcur, level, &i))) { | ||
491 | XFS_BMBT_TRACE_CURSOR(cur, ERROR); | ||
492 | goto error0; | ||
493 | } | ||
494 | if (i) { | ||
495 | ASSERT(be16_to_cpu(block->bb_numrecs) >= | ||
496 | XFS_BMAP_BLOCK_IMINRECS(level, tcur)); | ||
497 | xfs_btree_del_cursor(tcur, XFS_BTREE_NOERROR); | ||
498 | tcur = NULL; | ||
499 | if (level > 0) { | ||
500 | if ((error = xfs_bmbt_decrement(cur, | ||
501 | level, &i))) { | ||
502 | XFS_BMBT_TRACE_CURSOR(cur, | ||
503 | ERROR); | ||
504 | goto error0; | ||
505 | } | ||
506 | } | ||
507 | XFS_BMBT_TRACE_CURSOR(cur, EXIT); | ||
508 | *stat = 1; | ||
509 | return 0; | ||
510 | } | ||
511 | } | ||
512 | rrecs = be16_to_cpu(right->bb_numrecs); | ||
513 | if (lbno != NULLFSBLOCK) { | ||
514 | i = xfs_btree_firstrec(tcur, level); | ||
515 | XFS_WANT_CORRUPTED_GOTO(i == 1, error0); | ||
516 | if ((error = xfs_bmbt_decrement(tcur, level, &i))) { | ||
517 | XFS_BMBT_TRACE_CURSOR(cur, ERROR); | ||
518 | goto error0; | ||
519 | } | ||
520 | XFS_WANT_CORRUPTED_GOTO(i == 1, error0); | ||
521 | } | ||
522 | } | ||
523 | if (lbno != NULLFSBLOCK) { | ||
524 | i = xfs_btree_firstrec(tcur, level); | ||
525 | XFS_WANT_CORRUPTED_GOTO(i == 1, error0); | ||
526 | /* | ||
527 | * decrement to last in block | ||
528 | */ | ||
529 | if ((error = xfs_bmbt_decrement(tcur, level, &i))) { | ||
530 | XFS_BMBT_TRACE_CURSOR(cur, ERROR); | ||
531 | goto error0; | ||
532 | } | ||
533 | i = xfs_btree_firstrec(tcur, level); | ||
534 | XFS_WANT_CORRUPTED_GOTO(i == 1, error0); | ||
535 | lbp = tcur->bc_bufs[level]; | ||
536 | left = XFS_BUF_TO_BMBT_BLOCK(lbp); | ||
537 | #ifdef DEBUG | ||
538 | if ((error = xfs_btree_check_lblock(cur, left, level, lbp))) { | ||
539 | XFS_BMBT_TRACE_CURSOR(cur, ERROR); | ||
540 | goto error0; | ||
541 | } | ||
542 | #endif | ||
543 | bno = be64_to_cpu(left->bb_rightsib); | ||
544 | if (be16_to_cpu(left->bb_numrecs) - 1 >= | ||
545 | XFS_BMAP_BLOCK_IMINRECS(level, cur)) { | ||
546 | if ((error = xfs_bmbt_rshift(tcur, level, &i))) { | ||
547 | XFS_BMBT_TRACE_CURSOR(cur, ERROR); | ||
548 | goto error0; | ||
549 | } | ||
550 | if (i) { | ||
551 | ASSERT(be16_to_cpu(block->bb_numrecs) >= | ||
552 | XFS_BMAP_BLOCK_IMINRECS(level, tcur)); | ||
553 | xfs_btree_del_cursor(tcur, XFS_BTREE_NOERROR); | ||
554 | tcur = NULL; | ||
555 | if (level == 0) | ||
556 | cur->bc_ptrs[0]++; | ||
557 | XFS_BMBT_TRACE_CURSOR(cur, EXIT); | ||
558 | *stat = 1; | ||
559 | return 0; | ||
560 | } | ||
561 | } | ||
562 | lrecs = be16_to_cpu(left->bb_numrecs); | ||
563 | } | ||
564 | xfs_btree_del_cursor(tcur, XFS_BTREE_NOERROR); | ||
565 | tcur = NULL; | ||
566 | mp = cur->bc_mp; | ||
567 | ASSERT(bno != NULLFSBLOCK); | ||
568 | if (lbno != NULLFSBLOCK && | ||
569 | lrecs + be16_to_cpu(block->bb_numrecs) <= XFS_BMAP_BLOCK_IMAXRECS(level, cur)) { | ||
570 | rbno = bno; | ||
571 | right = block; | ||
572 | rbp = bp; | ||
573 | if ((error = xfs_btree_read_bufl(mp, cur->bc_tp, lbno, 0, &lbp, | ||
574 | XFS_BMAP_BTREE_REF))) { | ||
575 | XFS_BMBT_TRACE_CURSOR(cur, ERROR); | ||
576 | goto error0; | ||
577 | } | ||
578 | left = XFS_BUF_TO_BMBT_BLOCK(lbp); | ||
579 | if ((error = xfs_btree_check_lblock(cur, left, level, lbp))) { | ||
580 | XFS_BMBT_TRACE_CURSOR(cur, ERROR); | ||
581 | goto error0; | ||
582 | } | ||
583 | } else if (rbno != NULLFSBLOCK && | ||
584 | rrecs + be16_to_cpu(block->bb_numrecs) <= | ||
585 | XFS_BMAP_BLOCK_IMAXRECS(level, cur)) { | ||
586 | lbno = bno; | ||
587 | left = block; | ||
588 | lbp = bp; | ||
589 | if ((error = xfs_btree_read_bufl(mp, cur->bc_tp, rbno, 0, &rbp, | ||
590 | XFS_BMAP_BTREE_REF))) { | ||
591 | XFS_BMBT_TRACE_CURSOR(cur, ERROR); | ||
592 | goto error0; | ||
593 | } | ||
594 | right = XFS_BUF_TO_BMBT_BLOCK(rbp); | ||
595 | if ((error = xfs_btree_check_lblock(cur, right, level, rbp))) { | ||
596 | XFS_BMBT_TRACE_CURSOR(cur, ERROR); | ||
597 | goto error0; | ||
598 | } | ||
599 | lrecs = be16_to_cpu(left->bb_numrecs); | ||
600 | } else { | ||
601 | if (level > 0 && (error = xfs_bmbt_decrement(cur, level, &i))) { | ||
602 | XFS_BMBT_TRACE_CURSOR(cur, ERROR); | ||
603 | goto error0; | ||
604 | } | ||
605 | XFS_BMBT_TRACE_CURSOR(cur, EXIT); | ||
606 | *stat = 1; | ||
607 | return 0; | ||
608 | } | ||
609 | numlrecs = be16_to_cpu(left->bb_numrecs); | ||
610 | numrrecs = be16_to_cpu(right->bb_numrecs); | ||
611 | if (level > 0) { | ||
612 | lkp = XFS_BMAP_KEY_IADDR(left, numlrecs + 1, cur); | ||
613 | lpp = XFS_BMAP_PTR_IADDR(left, numlrecs + 1, cur); | ||
614 | rkp = XFS_BMAP_KEY_IADDR(right, 1, cur); | ||
615 | rpp = XFS_BMAP_PTR_IADDR(right, 1, cur); | ||
616 | #ifdef DEBUG | ||
617 | for (i = 0; i < numrrecs; i++) { | ||
618 | if ((error = xfs_btree_check_lptr_disk(cur, rpp[i], level))) { | ||
619 | XFS_BMBT_TRACE_CURSOR(cur, ERROR); | ||
620 | goto error0; | ||
621 | } | ||
622 | } | ||
623 | #endif | ||
624 | memcpy(lkp, rkp, numrrecs * sizeof(*lkp)); | ||
625 | memcpy(lpp, rpp, numrrecs * sizeof(*lpp)); | ||
626 | xfs_bmbt_log_keys(cur, lbp, numlrecs + 1, numlrecs + numrrecs); | ||
627 | xfs_bmbt_log_ptrs(cur, lbp, numlrecs + 1, numlrecs + numrrecs); | ||
628 | } else { | ||
629 | lrp = XFS_BMAP_REC_IADDR(left, numlrecs + 1, cur); | ||
630 | rrp = XFS_BMAP_REC_IADDR(right, 1, cur); | ||
631 | memcpy(lrp, rrp, numrrecs * sizeof(*lrp)); | ||
632 | xfs_bmbt_log_recs(cur, lbp, numlrecs + 1, numlrecs + numrrecs); | ||
633 | } | ||
634 | be16_add_cpu(&left->bb_numrecs, numrrecs); | ||
635 | left->bb_rightsib = right->bb_rightsib; | ||
636 | xfs_bmbt_log_block(cur, lbp, XFS_BB_RIGHTSIB | XFS_BB_NUMRECS); | ||
637 | if (be64_to_cpu(left->bb_rightsib) != NULLDFSBNO) { | ||
638 | if ((error = xfs_btree_read_bufl(mp, cur->bc_tp, | ||
639 | be64_to_cpu(left->bb_rightsib), | ||
640 | 0, &rrbp, XFS_BMAP_BTREE_REF))) { | ||
641 | XFS_BMBT_TRACE_CURSOR(cur, ERROR); | ||
642 | goto error0; | ||
643 | } | ||
644 | rrblock = XFS_BUF_TO_BMBT_BLOCK(rrbp); | ||
645 | if ((error = xfs_btree_check_lblock(cur, rrblock, level, rrbp))) { | ||
646 | XFS_BMBT_TRACE_CURSOR(cur, ERROR); | ||
647 | goto error0; | ||
648 | } | ||
649 | rrblock->bb_leftsib = cpu_to_be64(lbno); | ||
650 | xfs_bmbt_log_block(cur, rrbp, XFS_BB_LEFTSIB); | ||
651 | } | ||
652 | xfs_bmap_add_free(XFS_DADDR_TO_FSB(mp, XFS_BUF_ADDR(rbp)), 1, | ||
653 | cur->bc_private.b.flist, mp); | ||
654 | cur->bc_private.b.ip->i_d.di_nblocks--; | ||
655 | xfs_trans_log_inode(cur->bc_tp, cur->bc_private.b.ip, XFS_ILOG_CORE); | ||
656 | XFS_TRANS_MOD_DQUOT_BYINO(mp, cur->bc_tp, cur->bc_private.b.ip, | ||
657 | XFS_TRANS_DQ_BCOUNT, -1L); | ||
658 | xfs_trans_binval(cur->bc_tp, rbp); | ||
659 | if (bp != lbp) { | ||
660 | cur->bc_bufs[level] = lbp; | ||
661 | cur->bc_ptrs[level] += lrecs; | ||
662 | cur->bc_ra[level] = 0; | ||
663 | } else if ((error = xfs_bmbt_increment(cur, level + 1, &i))) { | ||
664 | XFS_BMBT_TRACE_CURSOR(cur, ERROR); | ||
665 | goto error0; | ||
666 | } | ||
667 | if (level > 0) | ||
668 | cur->bc_ptrs[level]--; | ||
669 | XFS_BMBT_TRACE_CURSOR(cur, EXIT); | ||
670 | *stat = 2; | ||
671 | return 0; | ||
672 | |||
673 | error0: | ||
674 | if (tcur) | ||
675 | xfs_btree_del_cursor(tcur, XFS_BTREE_ERROR); | ||
676 | return error; | ||
677 | } | ||
678 | |||
679 | /* | ||
680 | * Insert one record/level. Return information to the caller | ||
681 | * allowing the next level up to proceed if necessary. | ||
682 | */ | ||
683 | STATIC int /* error */ | ||
684 | xfs_bmbt_insrec( | ||
685 | xfs_btree_cur_t *cur, | ||
686 | int level, | ||
687 | xfs_fsblock_t *bnop, | ||
688 | xfs_bmbt_rec_t *recp, | ||
689 | xfs_btree_cur_t **curp, | ||
690 | int *stat) /* no-go/done/continue */ | ||
691 | { | ||
692 | xfs_bmbt_block_t *block; /* bmap btree block */ | ||
693 | xfs_buf_t *bp; /* buffer for block */ | ||
694 | int error; /* error return value */ | ||
695 | int i; /* loop index */ | ||
696 | xfs_bmbt_key_t key; /* bmap btree key */ | ||
697 | xfs_bmbt_key_t *kp=NULL; /* pointer to bmap btree key */ | ||
698 | int logflags; /* inode logging flags */ | ||
699 | xfs_fsblock_t nbno; /* new block number */ | ||
700 | struct xfs_btree_cur *ncur; /* new btree cursor */ | ||
701 | __uint64_t startoff; /* new btree key value */ | ||
702 | xfs_bmbt_rec_t nrec; /* new record count */ | ||
703 | int optr; /* old key/record index */ | ||
704 | xfs_bmbt_ptr_t *pp; /* pointer to bmap block addr */ | ||
705 | int ptr; /* key/record index */ | ||
706 | xfs_bmbt_rec_t *rp=NULL; /* pointer to bmap btree rec */ | ||
707 | int numrecs; | ||
708 | |||
709 | ASSERT(level < cur->bc_nlevels); | ||
710 | XFS_BMBT_TRACE_CURSOR(cur, ENTRY); | ||
711 | XFS_BMBT_TRACE_ARGIFR(cur, level, *bnop, recp); | ||
712 | ncur = NULL; | ||
713 | key.br_startoff = cpu_to_be64(xfs_bmbt_disk_get_startoff(recp)); | ||
714 | optr = ptr = cur->bc_ptrs[level]; | ||
715 | if (ptr == 0) { | ||
716 | XFS_BMBT_TRACE_CURSOR(cur, EXIT); | ||
717 | *stat = 0; | ||
718 | return 0; | ||
719 | } | ||
720 | XFS_STATS_INC(xs_bmbt_insrec); | ||
721 | block = xfs_bmbt_get_block(cur, level, &bp); | ||
722 | numrecs = be16_to_cpu(block->bb_numrecs); | ||
723 | #ifdef DEBUG | ||
724 | if ((error = xfs_btree_check_lblock(cur, block, level, bp))) { | ||
725 | XFS_BMBT_TRACE_CURSOR(cur, ERROR); | ||
726 | return error; | ||
727 | } | ||
728 | if (ptr <= numrecs) { | ||
729 | if (level == 0) { | ||
730 | rp = XFS_BMAP_REC_IADDR(block, ptr, cur); | ||
731 | xfs_btree_check_rec(XFS_BTNUM_BMAP, recp, rp); | ||
732 | } else { | ||
733 | kp = XFS_BMAP_KEY_IADDR(block, ptr, cur); | ||
734 | xfs_btree_check_key(XFS_BTNUM_BMAP, &key, kp); | ||
735 | } | ||
736 | } | ||
737 | #endif | ||
738 | nbno = NULLFSBLOCK; | ||
739 | if (numrecs == XFS_BMAP_BLOCK_IMAXRECS(level, cur)) { | ||
740 | if (numrecs < XFS_BMAP_BLOCK_DMAXRECS(level, cur)) { | ||
741 | /* | ||
742 | * A root block, that can be made bigger. | ||
743 | */ | ||
744 | xfs_iroot_realloc(cur->bc_private.b.ip, 1, | ||
745 | cur->bc_private.b.whichfork); | ||
746 | block = xfs_bmbt_get_block(cur, level, &bp); | ||
747 | } else if (level == cur->bc_nlevels - 1) { | ||
748 | if ((error = xfs_bmbt_newroot(cur, &logflags, stat)) || | ||
749 | *stat == 0) { | ||
750 | XFS_BMBT_TRACE_CURSOR(cur, ERROR); | ||
751 | return error; | ||
752 | } | ||
753 | xfs_trans_log_inode(cur->bc_tp, cur->bc_private.b.ip, | ||
754 | logflags); | ||
755 | block = xfs_bmbt_get_block(cur, level, &bp); | ||
756 | } else { | ||
757 | if ((error = xfs_bmbt_rshift(cur, level, &i))) { | ||
758 | XFS_BMBT_TRACE_CURSOR(cur, ERROR); | ||
759 | return error; | ||
760 | } | ||
761 | if (i) { | ||
762 | /* nothing */ | ||
763 | } else { | ||
764 | if ((error = xfs_bmbt_lshift(cur, level, &i))) { | ||
765 | XFS_BMBT_TRACE_CURSOR(cur, ERROR); | ||
766 | return error; | ||
767 | } | ||
768 | if (i) { | ||
769 | optr = ptr = cur->bc_ptrs[level]; | ||
770 | } else { | ||
771 | if ((error = xfs_bmbt_split(cur, level, | ||
772 | &nbno, &startoff, &ncur, | ||
773 | &i))) { | ||
774 | XFS_BMBT_TRACE_CURSOR(cur, | ||
775 | ERROR); | ||
776 | return error; | ||
777 | } | ||
778 | if (i) { | ||
779 | block = xfs_bmbt_get_block( | ||
780 | cur, level, &bp); | ||
781 | #ifdef DEBUG | ||
782 | if ((error = | ||
783 | xfs_btree_check_lblock(cur, | ||
784 | block, level, bp))) { | ||
785 | XFS_BMBT_TRACE_CURSOR( | ||
786 | cur, ERROR); | ||
787 | return error; | ||
788 | } | ||
789 | #endif | ||
790 | ptr = cur->bc_ptrs[level]; | ||
791 | xfs_bmbt_disk_set_allf(&nrec, | ||
792 | startoff, 0, 0, | ||
793 | XFS_EXT_NORM); | ||
794 | } else { | ||
795 | XFS_BMBT_TRACE_CURSOR(cur, | ||
796 | EXIT); | ||
797 | *stat = 0; | ||
798 | return 0; | ||
799 | } | ||
800 | } | ||
801 | } | ||
802 | } | ||
803 | } | ||
804 | numrecs = be16_to_cpu(block->bb_numrecs); | ||
805 | if (level > 0) { | ||
806 | kp = XFS_BMAP_KEY_IADDR(block, 1, cur); | ||
807 | pp = XFS_BMAP_PTR_IADDR(block, 1, cur); | ||
808 | #ifdef DEBUG | ||
809 | for (i = numrecs; i >= ptr; i--) { | ||
810 | if ((error = xfs_btree_check_lptr_disk(cur, pp[i - 1], | ||
811 | level))) { | ||
812 | XFS_BMBT_TRACE_CURSOR(cur, ERROR); | ||
813 | return error; | ||
814 | } | ||
815 | } | ||
816 | #endif | ||
817 | memmove(&kp[ptr], &kp[ptr - 1], | ||
818 | (numrecs - ptr + 1) * sizeof(*kp)); | ||
819 | memmove(&pp[ptr], &pp[ptr - 1], | ||
820 | (numrecs - ptr + 1) * sizeof(*pp)); | ||
821 | #ifdef DEBUG | ||
822 | if ((error = xfs_btree_check_lptr(cur, *bnop, level))) { | ||
823 | XFS_BMBT_TRACE_CURSOR(cur, ERROR); | ||
824 | return error; | ||
825 | } | ||
826 | #endif | ||
827 | kp[ptr - 1] = key; | ||
828 | pp[ptr - 1] = cpu_to_be64(*bnop); | ||
829 | numrecs++; | ||
830 | block->bb_numrecs = cpu_to_be16(numrecs); | ||
831 | xfs_bmbt_log_keys(cur, bp, ptr, numrecs); | ||
832 | xfs_bmbt_log_ptrs(cur, bp, ptr, numrecs); | ||
833 | } else { | ||
834 | rp = XFS_BMAP_REC_IADDR(block, 1, cur); | ||
835 | memmove(&rp[ptr], &rp[ptr - 1], | ||
836 | (numrecs - ptr + 1) * sizeof(*rp)); | ||
837 | rp[ptr - 1] = *recp; | ||
838 | numrecs++; | ||
839 | block->bb_numrecs = cpu_to_be16(numrecs); | ||
840 | xfs_bmbt_log_recs(cur, bp, ptr, numrecs); | ||
841 | } | ||
842 | xfs_bmbt_log_block(cur, bp, XFS_BB_NUMRECS); | ||
843 | #ifdef DEBUG | ||
844 | if (ptr < numrecs) { | ||
845 | if (level == 0) | ||
846 | xfs_btree_check_rec(XFS_BTNUM_BMAP, rp + ptr - 1, | ||
847 | rp + ptr); | ||
848 | else | ||
849 | xfs_btree_check_key(XFS_BTNUM_BMAP, kp + ptr - 1, | ||
850 | kp + ptr); | ||
851 | } | ||
852 | #endif | ||
853 | if (optr == 1 && (error = xfs_bmbt_updkey(cur, &key, level + 1))) { | ||
854 | XFS_BMBT_TRACE_CURSOR(cur, ERROR); | ||
855 | return error; | ||
856 | } | ||
857 | *bnop = nbno; | ||
858 | if (nbno != NULLFSBLOCK) { | ||
859 | *recp = nrec; | ||
860 | *curp = ncur; | ||
861 | } | ||
862 | XFS_BMBT_TRACE_CURSOR(cur, EXIT); | ||
863 | *stat = 1; | ||
864 | return 0; | ||
865 | } | ||
866 | |||
867 | STATIC int | ||
868 | xfs_bmbt_killroot( | ||
869 | xfs_btree_cur_t *cur) | ||
870 | { | ||
871 | xfs_bmbt_block_t *block; | ||
872 | xfs_bmbt_block_t *cblock; | ||
873 | xfs_buf_t *cbp; | ||
874 | xfs_bmbt_key_t *ckp; | ||
875 | xfs_bmbt_ptr_t *cpp; | ||
876 | #ifdef DEBUG | ||
877 | int error; | ||
878 | #endif | ||
879 | int i; | ||
880 | xfs_bmbt_key_t *kp; | ||
881 | xfs_inode_t *ip; | ||
882 | xfs_ifork_t *ifp; | ||
883 | int level; | ||
884 | xfs_bmbt_ptr_t *pp; | ||
885 | |||
886 | XFS_BMBT_TRACE_CURSOR(cur, ENTRY); | ||
887 | level = cur->bc_nlevels - 1; | ||
888 | ASSERT(level >= 1); | ||
889 | /* | ||
890 | * Don't deal with the root block needs to be a leaf case. | ||
891 | * We're just going to turn the thing back into extents anyway. | ||
892 | */ | ||
893 | if (level == 1) { | ||
894 | XFS_BMBT_TRACE_CURSOR(cur, EXIT); | ||
895 | return 0; | ||
896 | } | ||
897 | block = xfs_bmbt_get_block(cur, level, &cbp); | ||
898 | /* | ||
899 | * Give up if the root has multiple children. | ||
900 | */ | ||
901 | if (be16_to_cpu(block->bb_numrecs) != 1) { | ||
902 | XFS_BMBT_TRACE_CURSOR(cur, EXIT); | ||
903 | return 0; | ||
904 | } | ||
905 | /* | ||
906 | * Only do this if the next level will fit. | ||
907 | * Then the data must be copied up to the inode, | ||
908 | * instead of freeing the root you free the next level. | ||
909 | */ | ||
910 | cbp = cur->bc_bufs[level - 1]; | ||
911 | cblock = XFS_BUF_TO_BMBT_BLOCK(cbp); | ||
912 | if (be16_to_cpu(cblock->bb_numrecs) > XFS_BMAP_BLOCK_DMAXRECS(level, cur)) { | ||
913 | XFS_BMBT_TRACE_CURSOR(cur, EXIT); | ||
914 | return 0; | ||
915 | } | ||
916 | ASSERT(be64_to_cpu(cblock->bb_leftsib) == NULLDFSBNO); | ||
917 | ASSERT(be64_to_cpu(cblock->bb_rightsib) == NULLDFSBNO); | ||
918 | ip = cur->bc_private.b.ip; | ||
919 | ifp = XFS_IFORK_PTR(ip, cur->bc_private.b.whichfork); | ||
920 | ASSERT(XFS_BMAP_BLOCK_IMAXRECS(level, cur) == | ||
921 | XFS_BMAP_BROOT_MAXRECS(ifp->if_broot_bytes)); | ||
922 | i = (int)(be16_to_cpu(cblock->bb_numrecs) - XFS_BMAP_BLOCK_IMAXRECS(level, cur)); | ||
923 | if (i) { | ||
924 | xfs_iroot_realloc(ip, i, cur->bc_private.b.whichfork); | ||
925 | block = ifp->if_broot; | ||
926 | } | ||
927 | be16_add_cpu(&block->bb_numrecs, i); | ||
928 | ASSERT(block->bb_numrecs == cblock->bb_numrecs); | ||
929 | kp = XFS_BMAP_KEY_IADDR(block, 1, cur); | ||
930 | ckp = XFS_BMAP_KEY_IADDR(cblock, 1, cur); | ||
931 | memcpy(kp, ckp, be16_to_cpu(block->bb_numrecs) * sizeof(*kp)); | ||
932 | pp = XFS_BMAP_PTR_IADDR(block, 1, cur); | ||
933 | cpp = XFS_BMAP_PTR_IADDR(cblock, 1, cur); | ||
934 | #ifdef DEBUG | ||
935 | for (i = 0; i < be16_to_cpu(cblock->bb_numrecs); i++) { | ||
936 | if ((error = xfs_btree_check_lptr_disk(cur, cpp[i], level - 1))) { | ||
937 | XFS_BMBT_TRACE_CURSOR(cur, ERROR); | ||
938 | return error; | ||
939 | } | ||
940 | } | ||
941 | #endif | ||
942 | memcpy(pp, cpp, be16_to_cpu(block->bb_numrecs) * sizeof(*pp)); | ||
943 | xfs_bmap_add_free(XFS_DADDR_TO_FSB(cur->bc_mp, XFS_BUF_ADDR(cbp)), 1, | ||
944 | cur->bc_private.b.flist, cur->bc_mp); | ||
945 | ip->i_d.di_nblocks--; | ||
946 | XFS_TRANS_MOD_DQUOT_BYINO(cur->bc_mp, cur->bc_tp, ip, | ||
947 | XFS_TRANS_DQ_BCOUNT, -1L); | ||
948 | xfs_trans_binval(cur->bc_tp, cbp); | ||
949 | cur->bc_bufs[level - 1] = NULL; | ||
950 | be16_add_cpu(&block->bb_level, -1); | ||
951 | xfs_trans_log_inode(cur->bc_tp, ip, | ||
952 | XFS_ILOG_CORE | XFS_ILOG_FBROOT(cur->bc_private.b.whichfork)); | ||
953 | cur->bc_nlevels--; | ||
954 | XFS_BMBT_TRACE_CURSOR(cur, EXIT); | ||
955 | return 0; | ||
956 | } | ||
957 | |||
958 | /* | ||
959 | * Log key values from the btree block. | ||
960 | */ | ||
961 | STATIC void | ||
962 | xfs_bmbt_log_keys( | ||
963 | xfs_btree_cur_t *cur, | ||
964 | xfs_buf_t *bp, | ||
965 | int kfirst, | ||
966 | int klast) | ||
967 | { | ||
968 | xfs_trans_t *tp; | ||
969 | |||
970 | XFS_BMBT_TRACE_CURSOR(cur, ENTRY); | ||
971 | XFS_BMBT_TRACE_ARGBII(cur, bp, kfirst, klast); | ||
972 | tp = cur->bc_tp; | ||
973 | if (bp) { | ||
974 | xfs_bmbt_block_t *block; | ||
975 | int first; | ||
976 | xfs_bmbt_key_t *kp; | ||
977 | int last; | ||
978 | |||
979 | block = XFS_BUF_TO_BMBT_BLOCK(bp); | ||
980 | kp = XFS_BMAP_KEY_DADDR(block, 1, cur); | ||
981 | first = (int)((xfs_caddr_t)&kp[kfirst - 1] - (xfs_caddr_t)block); | ||
982 | last = (int)(((xfs_caddr_t)&kp[klast] - 1) - (xfs_caddr_t)block); | ||
983 | xfs_trans_log_buf(tp, bp, first, last); | ||
984 | } else { | ||
985 | xfs_inode_t *ip; | ||
986 | |||
987 | ip = cur->bc_private.b.ip; | ||
988 | xfs_trans_log_inode(tp, ip, | ||
989 | XFS_ILOG_FBROOT(cur->bc_private.b.whichfork)); | ||
990 | } | ||
991 | XFS_BMBT_TRACE_CURSOR(cur, EXIT); | ||
992 | } | ||
993 | |||
994 | /* | ||
995 | * Log pointer values from the btree block. | ||
996 | */ | ||
997 | STATIC void | ||
998 | xfs_bmbt_log_ptrs( | ||
999 | xfs_btree_cur_t *cur, | ||
1000 | xfs_buf_t *bp, | ||
1001 | int pfirst, | ||
1002 | int plast) | ||
1003 | { | ||
1004 | xfs_trans_t *tp; | ||
1005 | |||
1006 | XFS_BMBT_TRACE_CURSOR(cur, ENTRY); | ||
1007 | XFS_BMBT_TRACE_ARGBII(cur, bp, pfirst, plast); | ||
1008 | tp = cur->bc_tp; | ||
1009 | if (bp) { | ||
1010 | xfs_bmbt_block_t *block; | ||
1011 | int first; | ||
1012 | int last; | ||
1013 | xfs_bmbt_ptr_t *pp; | ||
1014 | |||
1015 | block = XFS_BUF_TO_BMBT_BLOCK(bp); | ||
1016 | pp = XFS_BMAP_PTR_DADDR(block, 1, cur); | ||
1017 | first = (int)((xfs_caddr_t)&pp[pfirst - 1] - (xfs_caddr_t)block); | ||
1018 | last = (int)(((xfs_caddr_t)&pp[plast] - 1) - (xfs_caddr_t)block); | ||
1019 | xfs_trans_log_buf(tp, bp, first, last); | ||
1020 | } else { | ||
1021 | xfs_inode_t *ip; | ||
1022 | |||
1023 | ip = cur->bc_private.b.ip; | ||
1024 | xfs_trans_log_inode(tp, ip, | ||
1025 | XFS_ILOG_FBROOT(cur->bc_private.b.whichfork)); | ||
1026 | } | ||
1027 | XFS_BMBT_TRACE_CURSOR(cur, EXIT); | ||
1028 | } | ||
1029 | |||
1030 | /* | ||
1031 | * Lookup the record. The cursor is made to point to it, based on dir. | ||
1032 | */ | ||
1033 | STATIC int /* error */ | ||
1034 | xfs_bmbt_lookup( | ||
1035 | xfs_btree_cur_t *cur, | ||
1036 | xfs_lookup_t dir, | ||
1037 | int *stat) /* success/failure */ | ||
1038 | { | ||
1039 | xfs_bmbt_block_t *block=NULL; | ||
1040 | xfs_buf_t *bp; | ||
1041 | xfs_daddr_t d; | ||
1042 | xfs_sfiloff_t diff; | ||
1043 | int error; /* error return value */ | ||
1044 | xfs_fsblock_t fsbno=0; | ||
1045 | int high; | ||
1046 | int i; | ||
1047 | int keyno=0; | ||
1048 | xfs_bmbt_key_t *kkbase=NULL; | ||
1049 | xfs_bmbt_key_t *kkp; | ||
1050 | xfs_bmbt_rec_t *krbase=NULL; | ||
1051 | xfs_bmbt_rec_t *krp; | ||
1052 | int level; | ||
1053 | int low; | ||
1054 | xfs_mount_t *mp; | ||
1055 | xfs_bmbt_ptr_t *pp; | ||
1056 | xfs_bmbt_irec_t *rp; | ||
1057 | xfs_fileoff_t startoff; | ||
1058 | xfs_trans_t *tp; | ||
1059 | |||
1060 | XFS_STATS_INC(xs_bmbt_lookup); | ||
1061 | XFS_BMBT_TRACE_CURSOR(cur, ENTRY); | ||
1062 | XFS_BMBT_TRACE_ARGI(cur, (int)dir); | ||
1063 | tp = cur->bc_tp; | ||
1064 | mp = cur->bc_mp; | ||
1065 | rp = &cur->bc_rec.b; | ||
1066 | for (level = cur->bc_nlevels - 1, diff = 1; level >= 0; level--) { | ||
1067 | if (level < cur->bc_nlevels - 1) { | ||
1068 | d = XFS_FSB_TO_DADDR(mp, fsbno); | ||
1069 | bp = cur->bc_bufs[level]; | ||
1070 | if (bp && XFS_BUF_ADDR(bp) != d) | ||
1071 | bp = NULL; | ||
1072 | if (!bp) { | ||
1073 | if ((error = xfs_btree_read_bufl(mp, tp, fsbno, | ||
1074 | 0, &bp, XFS_BMAP_BTREE_REF))) { | ||
1075 | XFS_BMBT_TRACE_CURSOR(cur, ERROR); | ||
1076 | return error; | ||
1077 | } | ||
1078 | xfs_btree_setbuf(cur, level, bp); | ||
1079 | block = XFS_BUF_TO_BMBT_BLOCK(bp); | ||
1080 | if ((error = xfs_btree_check_lblock(cur, block, | ||
1081 | level, bp))) { | ||
1082 | XFS_BMBT_TRACE_CURSOR(cur, ERROR); | ||
1083 | return error; | ||
1084 | } | ||
1085 | } else | ||
1086 | block = XFS_BUF_TO_BMBT_BLOCK(bp); | ||
1087 | } else | ||
1088 | block = xfs_bmbt_get_block(cur, level, &bp); | ||
1089 | if (diff == 0) | ||
1090 | keyno = 1; | ||
1091 | else { | ||
1092 | if (level > 0) | ||
1093 | kkbase = XFS_BMAP_KEY_IADDR(block, 1, cur); | ||
1094 | else | ||
1095 | krbase = XFS_BMAP_REC_IADDR(block, 1, cur); | ||
1096 | low = 1; | ||
1097 | if (!(high = be16_to_cpu(block->bb_numrecs))) { | ||
1098 | ASSERT(level == 0); | ||
1099 | cur->bc_ptrs[0] = dir != XFS_LOOKUP_LE; | ||
1100 | XFS_BMBT_TRACE_CURSOR(cur, EXIT); | ||
1101 | *stat = 0; | ||
1102 | return 0; | ||
1103 | } | ||
1104 | while (low <= high) { | ||
1105 | XFS_STATS_INC(xs_bmbt_compare); | ||
1106 | keyno = (low + high) >> 1; | ||
1107 | if (level > 0) { | ||
1108 | kkp = kkbase + keyno - 1; | ||
1109 | startoff = be64_to_cpu(kkp->br_startoff); | ||
1110 | } else { | ||
1111 | krp = krbase + keyno - 1; | ||
1112 | startoff = xfs_bmbt_disk_get_startoff(krp); | ||
1113 | } | ||
1114 | diff = (xfs_sfiloff_t) | ||
1115 | (startoff - rp->br_startoff); | ||
1116 | if (diff < 0) | ||
1117 | low = keyno + 1; | ||
1118 | else if (diff > 0) | ||
1119 | high = keyno - 1; | ||
1120 | else | ||
1121 | break; | ||
1122 | } | ||
1123 | } | ||
1124 | if (level > 0) { | ||
1125 | if (diff > 0 && --keyno < 1) | ||
1126 | keyno = 1; | ||
1127 | pp = XFS_BMAP_PTR_IADDR(block, keyno, cur); | ||
1128 | fsbno = be64_to_cpu(*pp); | ||
1129 | #ifdef DEBUG | ||
1130 | if ((error = xfs_btree_check_lptr(cur, fsbno, level))) { | ||
1131 | XFS_BMBT_TRACE_CURSOR(cur, ERROR); | ||
1132 | return error; | ||
1133 | } | ||
1134 | #endif | ||
1135 | cur->bc_ptrs[level] = keyno; | ||
1136 | } | ||
1137 | } | ||
1138 | if (dir != XFS_LOOKUP_LE && diff < 0) { | ||
1139 | keyno++; | ||
1140 | /* | ||
1141 | * If ge search and we went off the end of the block, but it's | ||
1142 | * not the last block, we're in the wrong block. | ||
1143 | */ | ||
1144 | if (dir == XFS_LOOKUP_GE && keyno > be16_to_cpu(block->bb_numrecs) && | ||
1145 | be64_to_cpu(block->bb_rightsib) != NULLDFSBNO) { | ||
1146 | cur->bc_ptrs[0] = keyno; | ||
1147 | if ((error = xfs_bmbt_increment(cur, 0, &i))) { | ||
1148 | XFS_BMBT_TRACE_CURSOR(cur, ERROR); | ||
1149 | return error; | ||
1150 | } | ||
1151 | XFS_WANT_CORRUPTED_RETURN(i == 1); | ||
1152 | XFS_BMBT_TRACE_CURSOR(cur, EXIT); | ||
1153 | *stat = 1; | ||
1154 | return 0; | ||
1155 | } | ||
1156 | } | ||
1157 | else if (dir == XFS_LOOKUP_LE && diff > 0) | ||
1158 | keyno--; | ||
1159 | cur->bc_ptrs[0] = keyno; | ||
1160 | if (keyno == 0 || keyno > be16_to_cpu(block->bb_numrecs)) { | ||
1161 | XFS_BMBT_TRACE_CURSOR(cur, EXIT); | ||
1162 | *stat = 0; | ||
1163 | } else { | ||
1164 | XFS_BMBT_TRACE_CURSOR(cur, EXIT); | ||
1165 | *stat = ((dir != XFS_LOOKUP_EQ) || (diff == 0)); | ||
1166 | } | ||
1167 | return 0; | ||
1168 | } | ||
1169 | |||
1170 | /* | ||
1171 | * Move 1 record left from cur/level if possible. | ||
1172 | * Update cur to reflect the new path. | ||
1173 | */ | ||
1174 | STATIC int /* error */ | ||
1175 | xfs_bmbt_lshift( | ||
1176 | xfs_btree_cur_t *cur, | ||
1177 | int level, | ||
1178 | int *stat) /* success/failure */ | ||
1179 | { | ||
1180 | int error; /* error return value */ | ||
1181 | #ifdef DEBUG | ||
1182 | int i; /* loop counter */ | ||
1183 | #endif | ||
1184 | xfs_bmbt_key_t key; /* bmap btree key */ | ||
1185 | xfs_buf_t *lbp; /* left buffer pointer */ | ||
1186 | xfs_bmbt_block_t *left; /* left btree block */ | ||
1187 | xfs_bmbt_key_t *lkp=NULL; /* left btree key */ | ||
1188 | xfs_bmbt_ptr_t *lpp; /* left address pointer */ | ||
1189 | int lrecs; /* left record count */ | ||
1190 | xfs_bmbt_rec_t *lrp=NULL; /* left record pointer */ | ||
1191 | xfs_mount_t *mp; /* file system mount point */ | ||
1192 | xfs_buf_t *rbp; /* right buffer pointer */ | ||
1193 | xfs_bmbt_block_t *right; /* right btree block */ | ||
1194 | xfs_bmbt_key_t *rkp=NULL; /* right btree key */ | ||
1195 | xfs_bmbt_ptr_t *rpp=NULL; /* right address pointer */ | ||
1196 | xfs_bmbt_rec_t *rrp=NULL; /* right record pointer */ | ||
1197 | int rrecs; /* right record count */ | ||
1198 | |||
1199 | XFS_BMBT_TRACE_CURSOR(cur, ENTRY); | ||
1200 | XFS_BMBT_TRACE_ARGI(cur, level); | ||
1201 | if (level == cur->bc_nlevels - 1) { | ||
1202 | XFS_BMBT_TRACE_CURSOR(cur, EXIT); | ||
1203 | *stat = 0; | ||
1204 | return 0; | ||
1205 | } | ||
1206 | rbp = cur->bc_bufs[level]; | ||
1207 | right = XFS_BUF_TO_BMBT_BLOCK(rbp); | ||
1208 | #ifdef DEBUG | ||
1209 | if ((error = xfs_btree_check_lblock(cur, right, level, rbp))) { | ||
1210 | XFS_BMBT_TRACE_CURSOR(cur, ERROR); | ||
1211 | return error; | ||
1212 | } | ||
1213 | #endif | ||
1214 | if (be64_to_cpu(right->bb_leftsib) == NULLDFSBNO) { | ||
1215 | XFS_BMBT_TRACE_CURSOR(cur, EXIT); | ||
1216 | *stat = 0; | ||
1217 | return 0; | ||
1218 | } | ||
1219 | if (cur->bc_ptrs[level] <= 1) { | ||
1220 | XFS_BMBT_TRACE_CURSOR(cur, EXIT); | ||
1221 | *stat = 0; | ||
1222 | return 0; | ||
1223 | } | ||
1224 | mp = cur->bc_mp; | ||
1225 | if ((error = xfs_btree_read_bufl(mp, cur->bc_tp, be64_to_cpu(right->bb_leftsib), 0, | ||
1226 | &lbp, XFS_BMAP_BTREE_REF))) { | ||
1227 | XFS_BMBT_TRACE_CURSOR(cur, ERROR); | ||
1228 | return error; | ||
1229 | } | ||
1230 | left = XFS_BUF_TO_BMBT_BLOCK(lbp); | ||
1231 | if ((error = xfs_btree_check_lblock(cur, left, level, lbp))) { | ||
1232 | XFS_BMBT_TRACE_CURSOR(cur, ERROR); | ||
1233 | return error; | ||
1234 | } | ||
1235 | if (be16_to_cpu(left->bb_numrecs) == XFS_BMAP_BLOCK_IMAXRECS(level, cur)) { | ||
1236 | XFS_BMBT_TRACE_CURSOR(cur, EXIT); | ||
1237 | *stat = 0; | ||
1238 | return 0; | ||
1239 | } | ||
1240 | lrecs = be16_to_cpu(left->bb_numrecs) + 1; | ||
1241 | if (level > 0) { | ||
1242 | lkp = XFS_BMAP_KEY_IADDR(left, lrecs, cur); | ||
1243 | rkp = XFS_BMAP_KEY_IADDR(right, 1, cur); | ||
1244 | *lkp = *rkp; | ||
1245 | xfs_bmbt_log_keys(cur, lbp, lrecs, lrecs); | ||
1246 | lpp = XFS_BMAP_PTR_IADDR(left, lrecs, cur); | ||
1247 | rpp = XFS_BMAP_PTR_IADDR(right, 1, cur); | ||
1248 | #ifdef DEBUG | ||
1249 | if ((error = xfs_btree_check_lptr_disk(cur, *rpp, level))) { | ||
1250 | XFS_BMBT_TRACE_CURSOR(cur, ERROR); | ||
1251 | return error; | ||
1252 | } | ||
1253 | #endif | ||
1254 | *lpp = *rpp; | ||
1255 | xfs_bmbt_log_ptrs(cur, lbp, lrecs, lrecs); | ||
1256 | } else { | ||
1257 | lrp = XFS_BMAP_REC_IADDR(left, lrecs, cur); | ||
1258 | rrp = XFS_BMAP_REC_IADDR(right, 1, cur); | ||
1259 | *lrp = *rrp; | ||
1260 | xfs_bmbt_log_recs(cur, lbp, lrecs, lrecs); | ||
1261 | } | ||
1262 | left->bb_numrecs = cpu_to_be16(lrecs); | ||
1263 | xfs_bmbt_log_block(cur, lbp, XFS_BB_NUMRECS); | ||
1264 | #ifdef DEBUG | ||
1265 | if (level > 0) | ||
1266 | xfs_btree_check_key(XFS_BTNUM_BMAP, lkp - 1, lkp); | ||
1267 | else | ||
1268 | xfs_btree_check_rec(XFS_BTNUM_BMAP, lrp - 1, lrp); | ||
1269 | #endif | ||
1270 | rrecs = be16_to_cpu(right->bb_numrecs) - 1; | ||
1271 | right->bb_numrecs = cpu_to_be16(rrecs); | ||
1272 | xfs_bmbt_log_block(cur, rbp, XFS_BB_NUMRECS); | ||
1273 | if (level > 0) { | ||
1274 | #ifdef DEBUG | ||
1275 | for (i = 0; i < rrecs; i++) { | ||
1276 | if ((error = xfs_btree_check_lptr_disk(cur, rpp[i + 1], | ||
1277 | level))) { | ||
1278 | XFS_BMBT_TRACE_CURSOR(cur, ERROR); | ||
1279 | return error; | ||
1280 | } | ||
1281 | } | ||
1282 | #endif | ||
1283 | memmove(rkp, rkp + 1, rrecs * sizeof(*rkp)); | ||
1284 | memmove(rpp, rpp + 1, rrecs * sizeof(*rpp)); | ||
1285 | xfs_bmbt_log_keys(cur, rbp, 1, rrecs); | ||
1286 | xfs_bmbt_log_ptrs(cur, rbp, 1, rrecs); | ||
1287 | } else { | ||
1288 | memmove(rrp, rrp + 1, rrecs * sizeof(*rrp)); | ||
1289 | xfs_bmbt_log_recs(cur, rbp, 1, rrecs); | ||
1290 | key.br_startoff = cpu_to_be64(xfs_bmbt_disk_get_startoff(rrp)); | ||
1291 | rkp = &key; | ||
1292 | } | ||
1293 | if ((error = xfs_bmbt_updkey(cur, rkp, level + 1))) { | ||
1294 | XFS_BMBT_TRACE_CURSOR(cur, ERROR); | ||
1295 | return error; | ||
1296 | } | ||
1297 | cur->bc_ptrs[level]--; | ||
1298 | XFS_BMBT_TRACE_CURSOR(cur, EXIT); | ||
1299 | *stat = 1; | ||
1300 | return 0; | ||
1301 | } | ||
1302 | |||
1303 | /* | ||
1304 | * Move 1 record right from cur/level if possible. | ||
1305 | * Update cur to reflect the new path. | ||
1306 | */ | ||
1307 | STATIC int /* error */ | ||
1308 | xfs_bmbt_rshift( | ||
1309 | xfs_btree_cur_t *cur, | ||
1310 | int level, | ||
1311 | int *stat) /* success/failure */ | ||
1312 | { | ||
1313 | int error; /* error return value */ | ||
1314 | int i; /* loop counter */ | ||
1315 | xfs_bmbt_key_t key; /* bmap btree key */ | ||
1316 | xfs_buf_t *lbp; /* left buffer pointer */ | ||
1317 | xfs_bmbt_block_t *left; /* left btree block */ | ||
1318 | xfs_bmbt_key_t *lkp; /* left btree key */ | ||
1319 | xfs_bmbt_ptr_t *lpp; /* left address pointer */ | ||
1320 | xfs_bmbt_rec_t *lrp; /* left record pointer */ | ||
1321 | xfs_mount_t *mp; /* file system mount point */ | ||
1322 | xfs_buf_t *rbp; /* right buffer pointer */ | ||
1323 | xfs_bmbt_block_t *right; /* right btree block */ | ||
1324 | xfs_bmbt_key_t *rkp; /* right btree key */ | ||
1325 | xfs_bmbt_ptr_t *rpp; /* right address pointer */ | ||
1326 | xfs_bmbt_rec_t *rrp=NULL; /* right record pointer */ | ||
1327 | struct xfs_btree_cur *tcur; /* temporary btree cursor */ | ||
1328 | |||
1329 | XFS_BMBT_TRACE_CURSOR(cur, ENTRY); | ||
1330 | XFS_BMBT_TRACE_ARGI(cur, level); | ||
1331 | if (level == cur->bc_nlevels - 1) { | ||
1332 | XFS_BMBT_TRACE_CURSOR(cur, EXIT); | ||
1333 | *stat = 0; | ||
1334 | return 0; | ||
1335 | } | ||
1336 | lbp = cur->bc_bufs[level]; | ||
1337 | left = XFS_BUF_TO_BMBT_BLOCK(lbp); | ||
1338 | #ifdef DEBUG | ||
1339 | if ((error = xfs_btree_check_lblock(cur, left, level, lbp))) { | ||
1340 | XFS_BMBT_TRACE_CURSOR(cur, ERROR); | ||
1341 | return error; | ||
1342 | } | ||
1343 | #endif | ||
1344 | if (be64_to_cpu(left->bb_rightsib) == NULLDFSBNO) { | ||
1345 | XFS_BMBT_TRACE_CURSOR(cur, EXIT); | ||
1346 | *stat = 0; | ||
1347 | return 0; | ||
1348 | } | ||
1349 | if (cur->bc_ptrs[level] >= be16_to_cpu(left->bb_numrecs)) { | ||
1350 | XFS_BMBT_TRACE_CURSOR(cur, EXIT); | ||
1351 | *stat = 0; | ||
1352 | return 0; | ||
1353 | } | ||
1354 | mp = cur->bc_mp; | ||
1355 | if ((error = xfs_btree_read_bufl(mp, cur->bc_tp, be64_to_cpu(left->bb_rightsib), 0, | ||
1356 | &rbp, XFS_BMAP_BTREE_REF))) { | ||
1357 | XFS_BMBT_TRACE_CURSOR(cur, ERROR); | ||
1358 | return error; | ||
1359 | } | ||
1360 | right = XFS_BUF_TO_BMBT_BLOCK(rbp); | ||
1361 | if ((error = xfs_btree_check_lblock(cur, right, level, rbp))) { | ||
1362 | XFS_BMBT_TRACE_CURSOR(cur, ERROR); | ||
1363 | return error; | ||
1364 | } | ||
1365 | if (be16_to_cpu(right->bb_numrecs) == XFS_BMAP_BLOCK_IMAXRECS(level, cur)) { | ||
1366 | XFS_BMBT_TRACE_CURSOR(cur, EXIT); | ||
1367 | *stat = 0; | ||
1368 | return 0; | ||
1369 | } | ||
1370 | if (level > 0) { | ||
1371 | lkp = XFS_BMAP_KEY_IADDR(left, be16_to_cpu(left->bb_numrecs), cur); | ||
1372 | lpp = XFS_BMAP_PTR_IADDR(left, be16_to_cpu(left->bb_numrecs), cur); | ||
1373 | rkp = XFS_BMAP_KEY_IADDR(right, 1, cur); | ||
1374 | rpp = XFS_BMAP_PTR_IADDR(right, 1, cur); | ||
1375 | #ifdef DEBUG | ||
1376 | for (i = be16_to_cpu(right->bb_numrecs) - 1; i >= 0; i--) { | ||
1377 | if ((error = xfs_btree_check_lptr_disk(cur, rpp[i], level))) { | ||
1378 | XFS_BMBT_TRACE_CURSOR(cur, ERROR); | ||
1379 | return error; | ||
1380 | } | ||
1381 | } | ||
1382 | #endif | ||
1383 | memmove(rkp + 1, rkp, be16_to_cpu(right->bb_numrecs) * sizeof(*rkp)); | ||
1384 | memmove(rpp + 1, rpp, be16_to_cpu(right->bb_numrecs) * sizeof(*rpp)); | ||
1385 | #ifdef DEBUG | ||
1386 | if ((error = xfs_btree_check_lptr_disk(cur, *lpp, level))) { | ||
1387 | XFS_BMBT_TRACE_CURSOR(cur, ERROR); | ||
1388 | return error; | ||
1389 | } | ||
1390 | #endif | ||
1391 | *rkp = *lkp; | ||
1392 | *rpp = *lpp; | ||
1393 | xfs_bmbt_log_keys(cur, rbp, 1, be16_to_cpu(right->bb_numrecs) + 1); | ||
1394 | xfs_bmbt_log_ptrs(cur, rbp, 1, be16_to_cpu(right->bb_numrecs) + 1); | ||
1395 | } else { | ||
1396 | lrp = XFS_BMAP_REC_IADDR(left, be16_to_cpu(left->bb_numrecs), cur); | ||
1397 | rrp = XFS_BMAP_REC_IADDR(right, 1, cur); | ||
1398 | memmove(rrp + 1, rrp, be16_to_cpu(right->bb_numrecs) * sizeof(*rrp)); | ||
1399 | *rrp = *lrp; | ||
1400 | xfs_bmbt_log_recs(cur, rbp, 1, be16_to_cpu(right->bb_numrecs) + 1); | ||
1401 | key.br_startoff = cpu_to_be64(xfs_bmbt_disk_get_startoff(rrp)); | ||
1402 | rkp = &key; | ||
1403 | } | ||
1404 | be16_add_cpu(&left->bb_numrecs, -1); | ||
1405 | xfs_bmbt_log_block(cur, lbp, XFS_BB_NUMRECS); | ||
1406 | be16_add_cpu(&right->bb_numrecs, 1); | ||
1407 | #ifdef DEBUG | ||
1408 | if (level > 0) | ||
1409 | xfs_btree_check_key(XFS_BTNUM_BMAP, rkp, rkp + 1); | ||
1410 | else | ||
1411 | xfs_btree_check_rec(XFS_BTNUM_BMAP, rrp, rrp + 1); | ||
1412 | #endif | ||
1413 | xfs_bmbt_log_block(cur, rbp, XFS_BB_NUMRECS); | ||
1414 | if ((error = xfs_btree_dup_cursor(cur, &tcur))) { | ||
1415 | XFS_BMBT_TRACE_CURSOR(cur, ERROR); | ||
1416 | return error; | ||
1417 | } | ||
1418 | i = xfs_btree_lastrec(tcur, level); | ||
1419 | XFS_WANT_CORRUPTED_GOTO(i == 1, error0); | ||
1420 | if ((error = xfs_bmbt_increment(tcur, level, &i))) { | ||
1421 | XFS_BMBT_TRACE_CURSOR(tcur, ERROR); | ||
1422 | goto error1; | ||
1423 | } | ||
1424 | XFS_WANT_CORRUPTED_GOTO(i == 1, error0); | ||
1425 | if ((error = xfs_bmbt_updkey(tcur, rkp, level + 1))) { | ||
1426 | XFS_BMBT_TRACE_CURSOR(tcur, ERROR); | ||
1427 | goto error1; | ||
1428 | } | ||
1429 | xfs_btree_del_cursor(tcur, XFS_BTREE_NOERROR); | ||
1430 | XFS_BMBT_TRACE_CURSOR(cur, EXIT); | ||
1431 | *stat = 1; | ||
1432 | return 0; | ||
1433 | error0: | ||
1434 | XFS_BMBT_TRACE_CURSOR(cur, ERROR); | ||
1435 | error1: | ||
1436 | xfs_btree_del_cursor(tcur, XFS_BTREE_ERROR); | ||
1437 | return error; | ||
1438 | } | ||
1439 | |||
1440 | /* | 47 | /* |
1441 | * Determine the extent state. | 48 | * Determine the extent state. |
1442 | */ | 49 | */ |
@@ -1453,229 +60,15 @@ xfs_extent_state( | |||
1453 | return XFS_EXT_NORM; | 60 | return XFS_EXT_NORM; |
1454 | } | 61 | } |
1455 | 62 | ||
1456 | |||
1457 | /* | ||
1458 | * Split cur/level block in half. | ||
1459 | * Return new block number and its first record (to be inserted into parent). | ||
1460 | */ | ||
1461 | STATIC int /* error */ | ||
1462 | xfs_bmbt_split( | ||
1463 | xfs_btree_cur_t *cur, | ||
1464 | int level, | ||
1465 | xfs_fsblock_t *bnop, | ||
1466 | __uint64_t *startoff, | ||
1467 | xfs_btree_cur_t **curp, | ||
1468 | int *stat) /* success/failure */ | ||
1469 | { | ||
1470 | xfs_alloc_arg_t args; /* block allocation args */ | ||
1471 | int error; /* error return value */ | ||
1472 | int i; /* loop counter */ | ||
1473 | xfs_fsblock_t lbno; /* left sibling block number */ | ||
1474 | xfs_buf_t *lbp; /* left buffer pointer */ | ||
1475 | xfs_bmbt_block_t *left; /* left btree block */ | ||
1476 | xfs_bmbt_key_t *lkp; /* left btree key */ | ||
1477 | xfs_bmbt_ptr_t *lpp; /* left address pointer */ | ||
1478 | xfs_bmbt_rec_t *lrp; /* left record pointer */ | ||
1479 | xfs_buf_t *rbp; /* right buffer pointer */ | ||
1480 | xfs_bmbt_block_t *right; /* right btree block */ | ||
1481 | xfs_bmbt_key_t *rkp; /* right btree key */ | ||
1482 | xfs_bmbt_ptr_t *rpp; /* right address pointer */ | ||
1483 | xfs_bmbt_block_t *rrblock; /* right-right btree block */ | ||
1484 | xfs_buf_t *rrbp; /* right-right buffer pointer */ | ||
1485 | xfs_bmbt_rec_t *rrp; /* right record pointer */ | ||
1486 | |||
1487 | XFS_BMBT_TRACE_CURSOR(cur, ENTRY); | ||
1488 | XFS_BMBT_TRACE_ARGIFK(cur, level, *bnop, *startoff); | ||
1489 | args.tp = cur->bc_tp; | ||
1490 | args.mp = cur->bc_mp; | ||
1491 | lbp = cur->bc_bufs[level]; | ||
1492 | lbno = XFS_DADDR_TO_FSB(args.mp, XFS_BUF_ADDR(lbp)); | ||
1493 | left = XFS_BUF_TO_BMBT_BLOCK(lbp); | ||
1494 | args.fsbno = cur->bc_private.b.firstblock; | ||
1495 | args.firstblock = args.fsbno; | ||
1496 | args.minleft = 0; | ||
1497 | if (args.fsbno == NULLFSBLOCK) { | ||
1498 | args.fsbno = lbno; | ||
1499 | args.type = XFS_ALLOCTYPE_START_BNO; | ||
1500 | /* | ||
1501 | * Make sure there is sufficient room left in the AG to | ||
1502 | * complete a full tree split for an extent insert. If | ||
1503 | * we are converting the middle part of an extent then | ||
1504 | * we may need space for two tree splits. | ||
1505 | * | ||
1506 | * We are relying on the caller to make the correct block | ||
1507 | * reservation for this operation to succeed. If the | ||
1508 | * reservation amount is insufficient then we may fail a | ||
1509 | * block allocation here and corrupt the filesystem. | ||
1510 | */ | ||
1511 | args.minleft = xfs_trans_get_block_res(args.tp); | ||
1512 | } else if (cur->bc_private.b.flist->xbf_low) | ||
1513 | args.type = XFS_ALLOCTYPE_START_BNO; | ||
1514 | else | ||
1515 | args.type = XFS_ALLOCTYPE_NEAR_BNO; | ||
1516 | args.mod = args.alignment = args.total = args.isfl = | ||
1517 | args.userdata = args.minalignslop = 0; | ||
1518 | args.minlen = args.maxlen = args.prod = 1; | ||
1519 | args.wasdel = cur->bc_private.b.flags & XFS_BTCUR_BPRV_WASDEL; | ||
1520 | if (!args.wasdel && xfs_trans_get_block_res(args.tp) == 0) { | ||
1521 | XFS_BMBT_TRACE_CURSOR(cur, ERROR); | ||
1522 | return XFS_ERROR(ENOSPC); | ||
1523 | } | ||
1524 | if ((error = xfs_alloc_vextent(&args))) { | ||
1525 | XFS_BMBT_TRACE_CURSOR(cur, ERROR); | ||
1526 | return error; | ||
1527 | } | ||
1528 | if (args.fsbno == NULLFSBLOCK && args.minleft) { | ||
1529 | /* | ||
1530 | * Could not find an AG with enough free space to satisfy | ||
1531 | * a full btree split. Try again without minleft and if | ||
1532 | * successful activate the lowspace algorithm. | ||
1533 | */ | ||
1534 | args.fsbno = 0; | ||
1535 | args.type = XFS_ALLOCTYPE_FIRST_AG; | ||
1536 | args.minleft = 0; | ||
1537 | if ((error = xfs_alloc_vextent(&args))) { | ||
1538 | XFS_BMBT_TRACE_CURSOR(cur, ERROR); | ||
1539 | return error; | ||
1540 | } | ||
1541 | cur->bc_private.b.flist->xbf_low = 1; | ||
1542 | } | ||
1543 | if (args.fsbno == NULLFSBLOCK) { | ||
1544 | XFS_BMBT_TRACE_CURSOR(cur, EXIT); | ||
1545 | *stat = 0; | ||
1546 | return 0; | ||
1547 | } | ||
1548 | ASSERT(args.len == 1); | ||
1549 | cur->bc_private.b.firstblock = args.fsbno; | ||
1550 | cur->bc_private.b.allocated++; | ||
1551 | cur->bc_private.b.ip->i_d.di_nblocks++; | ||
1552 | xfs_trans_log_inode(args.tp, cur->bc_private.b.ip, XFS_ILOG_CORE); | ||
1553 | XFS_TRANS_MOD_DQUOT_BYINO(args.mp, args.tp, cur->bc_private.b.ip, | ||
1554 | XFS_TRANS_DQ_BCOUNT, 1L); | ||
1555 | rbp = xfs_btree_get_bufl(args.mp, args.tp, args.fsbno, 0); | ||
1556 | right = XFS_BUF_TO_BMBT_BLOCK(rbp); | ||
1557 | #ifdef DEBUG | ||
1558 | if ((error = xfs_btree_check_lblock(cur, left, level, rbp))) { | ||
1559 | XFS_BMBT_TRACE_CURSOR(cur, ERROR); | ||
1560 | return error; | ||
1561 | } | ||
1562 | #endif | ||
1563 | right->bb_magic = cpu_to_be32(XFS_BMAP_MAGIC); | ||
1564 | right->bb_level = left->bb_level; | ||
1565 | right->bb_numrecs = cpu_to_be16(be16_to_cpu(left->bb_numrecs) / 2); | ||
1566 | if ((be16_to_cpu(left->bb_numrecs) & 1) && | ||
1567 | cur->bc_ptrs[level] <= be16_to_cpu(right->bb_numrecs) + 1) | ||
1568 | be16_add_cpu(&right->bb_numrecs, 1); | ||
1569 | i = be16_to_cpu(left->bb_numrecs) - be16_to_cpu(right->bb_numrecs) + 1; | ||
1570 | if (level > 0) { | ||
1571 | lkp = XFS_BMAP_KEY_IADDR(left, i, cur); | ||
1572 | lpp = XFS_BMAP_PTR_IADDR(left, i, cur); | ||
1573 | rkp = XFS_BMAP_KEY_IADDR(right, 1, cur); | ||
1574 | rpp = XFS_BMAP_PTR_IADDR(right, 1, cur); | ||
1575 | #ifdef DEBUG | ||
1576 | for (i = 0; i < be16_to_cpu(right->bb_numrecs); i++) { | ||
1577 | if ((error = xfs_btree_check_lptr_disk(cur, lpp[i], level))) { | ||
1578 | XFS_BMBT_TRACE_CURSOR(cur, ERROR); | ||
1579 | return error; | ||
1580 | } | ||
1581 | } | ||
1582 | #endif | ||
1583 | memcpy(rkp, lkp, be16_to_cpu(right->bb_numrecs) * sizeof(*rkp)); | ||
1584 | memcpy(rpp, lpp, be16_to_cpu(right->bb_numrecs) * sizeof(*rpp)); | ||
1585 | xfs_bmbt_log_keys(cur, rbp, 1, be16_to_cpu(right->bb_numrecs)); | ||
1586 | xfs_bmbt_log_ptrs(cur, rbp, 1, be16_to_cpu(right->bb_numrecs)); | ||
1587 | *startoff = be64_to_cpu(rkp->br_startoff); | ||
1588 | } else { | ||
1589 | lrp = XFS_BMAP_REC_IADDR(left, i, cur); | ||
1590 | rrp = XFS_BMAP_REC_IADDR(right, 1, cur); | ||
1591 | memcpy(rrp, lrp, be16_to_cpu(right->bb_numrecs) * sizeof(*rrp)); | ||
1592 | xfs_bmbt_log_recs(cur, rbp, 1, be16_to_cpu(right->bb_numrecs)); | ||
1593 | *startoff = xfs_bmbt_disk_get_startoff(rrp); | ||
1594 | } | ||
1595 | be16_add_cpu(&left->bb_numrecs, -(be16_to_cpu(right->bb_numrecs))); | ||
1596 | right->bb_rightsib = left->bb_rightsib; | ||
1597 | left->bb_rightsib = cpu_to_be64(args.fsbno); | ||
1598 | right->bb_leftsib = cpu_to_be64(lbno); | ||
1599 | xfs_bmbt_log_block(cur, rbp, XFS_BB_ALL_BITS); | ||
1600 | xfs_bmbt_log_block(cur, lbp, XFS_BB_NUMRECS | XFS_BB_RIGHTSIB); | ||
1601 | if (be64_to_cpu(right->bb_rightsib) != NULLDFSBNO) { | ||
1602 | if ((error = xfs_btree_read_bufl(args.mp, args.tp, | ||
1603 | be64_to_cpu(right->bb_rightsib), 0, &rrbp, | ||
1604 | XFS_BMAP_BTREE_REF))) { | ||
1605 | XFS_BMBT_TRACE_CURSOR(cur, ERROR); | ||
1606 | return error; | ||
1607 | } | ||
1608 | rrblock = XFS_BUF_TO_BMBT_BLOCK(rrbp); | ||
1609 | if ((error = xfs_btree_check_lblock(cur, rrblock, level, rrbp))) { | ||
1610 | XFS_BMBT_TRACE_CURSOR(cur, ERROR); | ||
1611 | return error; | ||
1612 | } | ||
1613 | rrblock->bb_leftsib = cpu_to_be64(args.fsbno); | ||
1614 | xfs_bmbt_log_block(cur, rrbp, XFS_BB_LEFTSIB); | ||
1615 | } | ||
1616 | if (cur->bc_ptrs[level] > be16_to_cpu(left->bb_numrecs) + 1) { | ||
1617 | xfs_btree_setbuf(cur, level, rbp); | ||
1618 | cur->bc_ptrs[level] -= be16_to_cpu(left->bb_numrecs); | ||
1619 | } | ||
1620 | if (level + 1 < cur->bc_nlevels) { | ||
1621 | if ((error = xfs_btree_dup_cursor(cur, curp))) { | ||
1622 | XFS_BMBT_TRACE_CURSOR(cur, ERROR); | ||
1623 | return error; | ||
1624 | } | ||
1625 | (*curp)->bc_ptrs[level + 1]++; | ||
1626 | } | ||
1627 | *bnop = args.fsbno; | ||
1628 | XFS_BMBT_TRACE_CURSOR(cur, EXIT); | ||
1629 | *stat = 1; | ||
1630 | return 0; | ||
1631 | } | ||
1632 | |||
1633 | |||
1634 | /* | ||
1635 | * Update keys for the record. | ||
1636 | */ | ||
1637 | STATIC int | ||
1638 | xfs_bmbt_updkey( | ||
1639 | xfs_btree_cur_t *cur, | ||
1640 | xfs_bmbt_key_t *keyp, /* on-disk format */ | ||
1641 | int level) | ||
1642 | { | ||
1643 | xfs_bmbt_block_t *block; | ||
1644 | xfs_buf_t *bp; | ||
1645 | #ifdef DEBUG | ||
1646 | int error; | ||
1647 | #endif | ||
1648 | xfs_bmbt_key_t *kp; | ||
1649 | int ptr; | ||
1650 | |||
1651 | ASSERT(level >= 1); | ||
1652 | XFS_BMBT_TRACE_CURSOR(cur, ENTRY); | ||
1653 | XFS_BMBT_TRACE_ARGIK(cur, level, keyp); | ||
1654 | for (ptr = 1; ptr == 1 && level < cur->bc_nlevels; level++) { | ||
1655 | block = xfs_bmbt_get_block(cur, level, &bp); | ||
1656 | #ifdef DEBUG | ||
1657 | if ((error = xfs_btree_check_lblock(cur, block, level, bp))) { | ||
1658 | XFS_BMBT_TRACE_CURSOR(cur, ERROR); | ||
1659 | return error; | ||
1660 | } | ||
1661 | #endif | ||
1662 | ptr = cur->bc_ptrs[level]; | ||
1663 | kp = XFS_BMAP_KEY_IADDR(block, ptr, cur); | ||
1664 | *kp = *keyp; | ||
1665 | xfs_bmbt_log_keys(cur, bp, ptr, ptr); | ||
1666 | } | ||
1667 | XFS_BMBT_TRACE_CURSOR(cur, EXIT); | ||
1668 | return 0; | ||
1669 | } | ||
1670 | |||
1671 | /* | 63 | /* |
1672 | * Convert on-disk form of btree root to in-memory form. | 64 | * Convert on-disk form of btree root to in-memory form. |
1673 | */ | 65 | */ |
1674 | void | 66 | void |
1675 | xfs_bmdr_to_bmbt( | 67 | xfs_bmdr_to_bmbt( |
68 | struct xfs_mount *mp, | ||
1676 | xfs_bmdr_block_t *dblock, | 69 | xfs_bmdr_block_t *dblock, |
1677 | int dblocklen, | 70 | int dblocklen, |
1678 | xfs_bmbt_block_t *rblock, | 71 | struct xfs_btree_block *rblock, |
1679 | int rblocklen) | 72 | int rblocklen) |
1680 | { | 73 | { |
1681 | int dmxr; | 74 | int dmxr; |
@@ -1688,129 +81,19 @@ xfs_bmdr_to_bmbt( | |||
1688 | rblock->bb_level = dblock->bb_level; | 81 | rblock->bb_level = dblock->bb_level; |
1689 | ASSERT(be16_to_cpu(rblock->bb_level) > 0); | 82 | ASSERT(be16_to_cpu(rblock->bb_level) > 0); |
1690 | rblock->bb_numrecs = dblock->bb_numrecs; | 83 | rblock->bb_numrecs = dblock->bb_numrecs; |
1691 | rblock->bb_leftsib = cpu_to_be64(NULLDFSBNO); | 84 | rblock->bb_u.l.bb_leftsib = cpu_to_be64(NULLDFSBNO); |
1692 | rblock->bb_rightsib = cpu_to_be64(NULLDFSBNO); | 85 | rblock->bb_u.l.bb_rightsib = cpu_to_be64(NULLDFSBNO); |
1693 | dmxr = (int)XFS_BTREE_BLOCK_MAXRECS(dblocklen, xfs_bmdr, 0); | 86 | dmxr = xfs_bmdr_maxrecs(mp, dblocklen, 0); |
1694 | fkp = XFS_BTREE_KEY_ADDR(xfs_bmdr, dblock, 1); | 87 | fkp = XFS_BMDR_KEY_ADDR(dblock, 1); |
1695 | tkp = XFS_BMAP_BROOT_KEY_ADDR(rblock, 1, rblocklen); | 88 | tkp = XFS_BMBT_KEY_ADDR(mp, rblock, 1); |
1696 | fpp = XFS_BTREE_PTR_ADDR(xfs_bmdr, dblock, 1, dmxr); | 89 | fpp = XFS_BMDR_PTR_ADDR(dblock, 1, dmxr); |
1697 | tpp = XFS_BMAP_BROOT_PTR_ADDR(rblock, 1, rblocklen); | 90 | tpp = XFS_BMAP_BROOT_PTR_ADDR(mp, rblock, 1, rblocklen); |
1698 | dmxr = be16_to_cpu(dblock->bb_numrecs); | 91 | dmxr = be16_to_cpu(dblock->bb_numrecs); |
1699 | memcpy(tkp, fkp, sizeof(*fkp) * dmxr); | 92 | memcpy(tkp, fkp, sizeof(*fkp) * dmxr); |
1700 | memcpy(tpp, fpp, sizeof(*fpp) * dmxr); | 93 | memcpy(tpp, fpp, sizeof(*fpp) * dmxr); |
1701 | } | 94 | } |
1702 | 95 | ||
1703 | /* | 96 | /* |
1704 | * Decrement cursor by one record at the level. | ||
1705 | * For nonzero levels the leaf-ward information is untouched. | ||
1706 | */ | ||
1707 | int /* error */ | ||
1708 | xfs_bmbt_decrement( | ||
1709 | xfs_btree_cur_t *cur, | ||
1710 | int level, | ||
1711 | int *stat) /* success/failure */ | ||
1712 | { | ||
1713 | xfs_bmbt_block_t *block; | ||
1714 | xfs_buf_t *bp; | ||
1715 | int error; /* error return value */ | ||
1716 | xfs_fsblock_t fsbno; | ||
1717 | int lev; | ||
1718 | xfs_mount_t *mp; | ||
1719 | xfs_trans_t *tp; | ||
1720 | |||
1721 | XFS_BMBT_TRACE_CURSOR(cur, ENTRY); | ||
1722 | XFS_BMBT_TRACE_ARGI(cur, level); | ||
1723 | ASSERT(level < cur->bc_nlevels); | ||
1724 | if (level < cur->bc_nlevels - 1) | ||
1725 | xfs_btree_readahead(cur, level, XFS_BTCUR_LEFTRA); | ||
1726 | if (--cur->bc_ptrs[level] > 0) { | ||
1727 | XFS_BMBT_TRACE_CURSOR(cur, EXIT); | ||
1728 | *stat = 1; | ||
1729 | return 0; | ||
1730 | } | ||
1731 | block = xfs_bmbt_get_block(cur, level, &bp); | ||
1732 | #ifdef DEBUG | ||
1733 | if ((error = xfs_btree_check_lblock(cur, block, level, bp))) { | ||
1734 | XFS_BMBT_TRACE_CURSOR(cur, ERROR); | ||
1735 | return error; | ||
1736 | } | ||
1737 | #endif | ||
1738 | if (be64_to_cpu(block->bb_leftsib) == NULLDFSBNO) { | ||
1739 | XFS_BMBT_TRACE_CURSOR(cur, EXIT); | ||
1740 | *stat = 0; | ||
1741 | return 0; | ||
1742 | } | ||
1743 | for (lev = level + 1; lev < cur->bc_nlevels; lev++) { | ||
1744 | if (--cur->bc_ptrs[lev] > 0) | ||
1745 | break; | ||
1746 | if (lev < cur->bc_nlevels - 1) | ||
1747 | xfs_btree_readahead(cur, lev, XFS_BTCUR_LEFTRA); | ||
1748 | } | ||
1749 | if (lev == cur->bc_nlevels) { | ||
1750 | XFS_BMBT_TRACE_CURSOR(cur, EXIT); | ||
1751 | *stat = 0; | ||
1752 | return 0; | ||
1753 | } | ||
1754 | tp = cur->bc_tp; | ||
1755 | mp = cur->bc_mp; | ||
1756 | for (block = xfs_bmbt_get_block(cur, lev, &bp); lev > level; ) { | ||
1757 | fsbno = be64_to_cpu(*XFS_BMAP_PTR_IADDR(block, cur->bc_ptrs[lev], cur)); | ||
1758 | if ((error = xfs_btree_read_bufl(mp, tp, fsbno, 0, &bp, | ||
1759 | XFS_BMAP_BTREE_REF))) { | ||
1760 | XFS_BMBT_TRACE_CURSOR(cur, ERROR); | ||
1761 | return error; | ||
1762 | } | ||
1763 | lev--; | ||
1764 | xfs_btree_setbuf(cur, lev, bp); | ||
1765 | block = XFS_BUF_TO_BMBT_BLOCK(bp); | ||
1766 | if ((error = xfs_btree_check_lblock(cur, block, lev, bp))) { | ||
1767 | XFS_BMBT_TRACE_CURSOR(cur, ERROR); | ||
1768 | return error; | ||
1769 | } | ||
1770 | cur->bc_ptrs[lev] = be16_to_cpu(block->bb_numrecs); | ||
1771 | } | ||
1772 | XFS_BMBT_TRACE_CURSOR(cur, EXIT); | ||
1773 | *stat = 1; | ||
1774 | return 0; | ||
1775 | } | ||
1776 | |||
1777 | /* | ||
1778 | * Delete the record pointed to by cur. | ||
1779 | */ | ||
1780 | int /* error */ | ||
1781 | xfs_bmbt_delete( | ||
1782 | xfs_btree_cur_t *cur, | ||
1783 | int *stat) /* success/failure */ | ||
1784 | { | ||
1785 | int error; /* error return value */ | ||
1786 | int i; | ||
1787 | int level; | ||
1788 | |||
1789 | XFS_BMBT_TRACE_CURSOR(cur, ENTRY); | ||
1790 | for (level = 0, i = 2; i == 2; level++) { | ||
1791 | if ((error = xfs_bmbt_delrec(cur, level, &i))) { | ||
1792 | XFS_BMBT_TRACE_CURSOR(cur, ERROR); | ||
1793 | return error; | ||
1794 | } | ||
1795 | } | ||
1796 | if (i == 0) { | ||
1797 | for (level = 1; level < cur->bc_nlevels; level++) { | ||
1798 | if (cur->bc_ptrs[level] == 0) { | ||
1799 | if ((error = xfs_bmbt_decrement(cur, level, | ||
1800 | &i))) { | ||
1801 | XFS_BMBT_TRACE_CURSOR(cur, ERROR); | ||
1802 | return error; | ||
1803 | } | ||
1804 | break; | ||
1805 | } | ||
1806 | } | ||
1807 | } | ||
1808 | XFS_BMBT_TRACE_CURSOR(cur, EXIT); | ||
1809 | *stat = i; | ||
1810 | return 0; | ||
1811 | } | ||
1812 | |||
1813 | /* | ||
1814 | * Convert a compressed bmap extent record to an uncompressed form. | 97 | * Convert a compressed bmap extent record to an uncompressed form. |
1815 | * This code must be in sync with the routines xfs_bmbt_get_startoff, | 98 | * This code must be in sync with the routines xfs_bmbt_get_startoff, |
1816 | * xfs_bmbt_get_startblock, xfs_bmbt_get_blockcount and xfs_bmbt_get_state. | 99 | * xfs_bmbt_get_startblock, xfs_bmbt_get_blockcount and xfs_bmbt_get_state. |
@@ -1864,31 +147,6 @@ xfs_bmbt_get_all( | |||
1864 | } | 147 | } |
1865 | 148 | ||
1866 | /* | 149 | /* |
1867 | * Get the block pointer for the given level of the cursor. | ||
1868 | * Fill in the buffer pointer, if applicable. | ||
1869 | */ | ||
1870 | xfs_bmbt_block_t * | ||
1871 | xfs_bmbt_get_block( | ||
1872 | xfs_btree_cur_t *cur, | ||
1873 | int level, | ||
1874 | xfs_buf_t **bpp) | ||
1875 | { | ||
1876 | xfs_ifork_t *ifp; | ||
1877 | xfs_bmbt_block_t *rval; | ||
1878 | |||
1879 | if (level < cur->bc_nlevels - 1) { | ||
1880 | *bpp = cur->bc_bufs[level]; | ||
1881 | rval = XFS_BUF_TO_BMBT_BLOCK(*bpp); | ||
1882 | } else { | ||
1883 | *bpp = NULL; | ||
1884 | ifp = XFS_IFORK_PTR(cur->bc_private.b.ip, | ||
1885 | cur->bc_private.b.whichfork); | ||
1886 | rval = ifp->if_broot; | ||
1887 | } | ||
1888 | return rval; | ||
1889 | } | ||
1890 | |||
1891 | /* | ||
1892 | * Extract the blockcount field from an in memory bmap extent record. | 150 | * Extract the blockcount field from an in memory bmap extent record. |
1893 | */ | 151 | */ |
1894 | xfs_filblks_t | 152 | xfs_filblks_t |
@@ -1950,7 +208,8 @@ xfs_bmbt_disk_get_all( | |||
1950 | xfs_bmbt_rec_t *r, | 208 | xfs_bmbt_rec_t *r, |
1951 | xfs_bmbt_irec_t *s) | 209 | xfs_bmbt_irec_t *s) |
1952 | { | 210 | { |
1953 | __xfs_bmbt_get_all(be64_to_cpu(r->l0), be64_to_cpu(r->l1), s); | 211 | __xfs_bmbt_get_all(get_unaligned_be64(&r->l0), |
212 | get_unaligned_be64(&r->l1), s); | ||
1954 | } | 213 | } |
1955 | 214 | ||
1956 | /* | 215 | /* |
@@ -1974,348 +233,6 @@ xfs_bmbt_disk_get_startoff( | |||
1974 | XFS_MASK64LO(64 - BMBT_EXNTFLAG_BITLEN)) >> 9; | 233 | XFS_MASK64LO(64 - BMBT_EXNTFLAG_BITLEN)) >> 9; |
1975 | } | 234 | } |
1976 | 235 | ||
1977 | /* | ||
1978 | * Increment cursor by one record at the level. | ||
1979 | * For nonzero levels the leaf-ward information is untouched. | ||
1980 | */ | ||
1981 | int /* error */ | ||
1982 | xfs_bmbt_increment( | ||
1983 | xfs_btree_cur_t *cur, | ||
1984 | int level, | ||
1985 | int *stat) /* success/failure */ | ||
1986 | { | ||
1987 | xfs_bmbt_block_t *block; | ||
1988 | xfs_buf_t *bp; | ||
1989 | int error; /* error return value */ | ||
1990 | xfs_fsblock_t fsbno; | ||
1991 | int lev; | ||
1992 | xfs_mount_t *mp; | ||
1993 | xfs_trans_t *tp; | ||
1994 | |||
1995 | XFS_BMBT_TRACE_CURSOR(cur, ENTRY); | ||
1996 | XFS_BMBT_TRACE_ARGI(cur, level); | ||
1997 | ASSERT(level < cur->bc_nlevels); | ||
1998 | if (level < cur->bc_nlevels - 1) | ||
1999 | xfs_btree_readahead(cur, level, XFS_BTCUR_RIGHTRA); | ||
2000 | block = xfs_bmbt_get_block(cur, level, &bp); | ||
2001 | #ifdef DEBUG | ||
2002 | if ((error = xfs_btree_check_lblock(cur, block, level, bp))) { | ||
2003 | XFS_BMBT_TRACE_CURSOR(cur, ERROR); | ||
2004 | return error; | ||
2005 | } | ||
2006 | #endif | ||
2007 | if (++cur->bc_ptrs[level] <= be16_to_cpu(block->bb_numrecs)) { | ||
2008 | XFS_BMBT_TRACE_CURSOR(cur, EXIT); | ||
2009 | *stat = 1; | ||
2010 | return 0; | ||
2011 | } | ||
2012 | if (be64_to_cpu(block->bb_rightsib) == NULLDFSBNO) { | ||
2013 | XFS_BMBT_TRACE_CURSOR(cur, EXIT); | ||
2014 | *stat = 0; | ||
2015 | return 0; | ||
2016 | } | ||
2017 | for (lev = level + 1; lev < cur->bc_nlevels; lev++) { | ||
2018 | block = xfs_bmbt_get_block(cur, lev, &bp); | ||
2019 | #ifdef DEBUG | ||
2020 | if ((error = xfs_btree_check_lblock(cur, block, lev, bp))) { | ||
2021 | XFS_BMBT_TRACE_CURSOR(cur, ERROR); | ||
2022 | return error; | ||
2023 | } | ||
2024 | #endif | ||
2025 | if (++cur->bc_ptrs[lev] <= be16_to_cpu(block->bb_numrecs)) | ||
2026 | break; | ||
2027 | if (lev < cur->bc_nlevels - 1) | ||
2028 | xfs_btree_readahead(cur, lev, XFS_BTCUR_RIGHTRA); | ||
2029 | } | ||
2030 | if (lev == cur->bc_nlevels) { | ||
2031 | XFS_BMBT_TRACE_CURSOR(cur, EXIT); | ||
2032 | *stat = 0; | ||
2033 | return 0; | ||
2034 | } | ||
2035 | tp = cur->bc_tp; | ||
2036 | mp = cur->bc_mp; | ||
2037 | for (block = xfs_bmbt_get_block(cur, lev, &bp); lev > level; ) { | ||
2038 | fsbno = be64_to_cpu(*XFS_BMAP_PTR_IADDR(block, cur->bc_ptrs[lev], cur)); | ||
2039 | if ((error = xfs_btree_read_bufl(mp, tp, fsbno, 0, &bp, | ||
2040 | XFS_BMAP_BTREE_REF))) { | ||
2041 | XFS_BMBT_TRACE_CURSOR(cur, ERROR); | ||
2042 | return error; | ||
2043 | } | ||
2044 | lev--; | ||
2045 | xfs_btree_setbuf(cur, lev, bp); | ||
2046 | block = XFS_BUF_TO_BMBT_BLOCK(bp); | ||
2047 | if ((error = xfs_btree_check_lblock(cur, block, lev, bp))) { | ||
2048 | XFS_BMBT_TRACE_CURSOR(cur, ERROR); | ||
2049 | return error; | ||
2050 | } | ||
2051 | cur->bc_ptrs[lev] = 1; | ||
2052 | } | ||
2053 | XFS_BMBT_TRACE_CURSOR(cur, EXIT); | ||
2054 | *stat = 1; | ||
2055 | return 0; | ||
2056 | } | ||
2057 | |||
2058 | /* | ||
2059 | * Insert the current record at the point referenced by cur. | ||
2060 | * | ||
2061 | * A multi-level split of the tree on insert will invalidate the original | ||
2062 | * cursor. All callers of this function should assume that the cursor is | ||
2063 | * no longer valid and revalidate it. | ||
2064 | */ | ||
2065 | int /* error */ | ||
2066 | xfs_bmbt_insert( | ||
2067 | xfs_btree_cur_t *cur, | ||
2068 | int *stat) /* success/failure */ | ||
2069 | { | ||
2070 | int error; /* error return value */ | ||
2071 | int i; | ||
2072 | int level; | ||
2073 | xfs_fsblock_t nbno; | ||
2074 | xfs_btree_cur_t *ncur; | ||
2075 | xfs_bmbt_rec_t nrec; | ||
2076 | xfs_btree_cur_t *pcur; | ||
2077 | |||
2078 | XFS_BMBT_TRACE_CURSOR(cur, ENTRY); | ||
2079 | level = 0; | ||
2080 | nbno = NULLFSBLOCK; | ||
2081 | xfs_bmbt_disk_set_all(&nrec, &cur->bc_rec.b); | ||
2082 | ncur = NULL; | ||
2083 | pcur = cur; | ||
2084 | do { | ||
2085 | if ((error = xfs_bmbt_insrec(pcur, level++, &nbno, &nrec, &ncur, | ||
2086 | &i))) { | ||
2087 | if (pcur != cur) | ||
2088 | xfs_btree_del_cursor(pcur, XFS_BTREE_ERROR); | ||
2089 | XFS_BMBT_TRACE_CURSOR(cur, ERROR); | ||
2090 | return error; | ||
2091 | } | ||
2092 | XFS_WANT_CORRUPTED_GOTO(i == 1, error0); | ||
2093 | if (pcur != cur && (ncur || nbno == NULLFSBLOCK)) { | ||
2094 | cur->bc_nlevels = pcur->bc_nlevels; | ||
2095 | cur->bc_private.b.allocated += | ||
2096 | pcur->bc_private.b.allocated; | ||
2097 | pcur->bc_private.b.allocated = 0; | ||
2098 | ASSERT((cur->bc_private.b.firstblock != NULLFSBLOCK) || | ||
2099 | XFS_IS_REALTIME_INODE(cur->bc_private.b.ip)); | ||
2100 | cur->bc_private.b.firstblock = | ||
2101 | pcur->bc_private.b.firstblock; | ||
2102 | ASSERT(cur->bc_private.b.flist == | ||
2103 | pcur->bc_private.b.flist); | ||
2104 | xfs_btree_del_cursor(pcur, XFS_BTREE_NOERROR); | ||
2105 | } | ||
2106 | if (ncur) { | ||
2107 | pcur = ncur; | ||
2108 | ncur = NULL; | ||
2109 | } | ||
2110 | } while (nbno != NULLFSBLOCK); | ||
2111 | XFS_BMBT_TRACE_CURSOR(cur, EXIT); | ||
2112 | *stat = i; | ||
2113 | return 0; | ||
2114 | error0: | ||
2115 | XFS_BMBT_TRACE_CURSOR(cur, ERROR); | ||
2116 | return error; | ||
2117 | } | ||
2118 | |||
2119 | /* | ||
2120 | * Log fields from the btree block header. | ||
2121 | */ | ||
2122 | void | ||
2123 | xfs_bmbt_log_block( | ||
2124 | xfs_btree_cur_t *cur, | ||
2125 | xfs_buf_t *bp, | ||
2126 | int fields) | ||
2127 | { | ||
2128 | int first; | ||
2129 | int last; | ||
2130 | xfs_trans_t *tp; | ||
2131 | static const short offsets[] = { | ||
2132 | offsetof(xfs_bmbt_block_t, bb_magic), | ||
2133 | offsetof(xfs_bmbt_block_t, bb_level), | ||
2134 | offsetof(xfs_bmbt_block_t, bb_numrecs), | ||
2135 | offsetof(xfs_bmbt_block_t, bb_leftsib), | ||
2136 | offsetof(xfs_bmbt_block_t, bb_rightsib), | ||
2137 | sizeof(xfs_bmbt_block_t) | ||
2138 | }; | ||
2139 | |||
2140 | XFS_BMBT_TRACE_CURSOR(cur, ENTRY); | ||
2141 | XFS_BMBT_TRACE_ARGBI(cur, bp, fields); | ||
2142 | tp = cur->bc_tp; | ||
2143 | if (bp) { | ||
2144 | xfs_btree_offsets(fields, offsets, XFS_BB_NUM_BITS, &first, | ||
2145 | &last); | ||
2146 | xfs_trans_log_buf(tp, bp, first, last); | ||
2147 | } else | ||
2148 | xfs_trans_log_inode(tp, cur->bc_private.b.ip, | ||
2149 | XFS_ILOG_FBROOT(cur->bc_private.b.whichfork)); | ||
2150 | XFS_BMBT_TRACE_CURSOR(cur, EXIT); | ||
2151 | } | ||
2152 | |||
2153 | /* | ||
2154 | * Log record values from the btree block. | ||
2155 | */ | ||
2156 | void | ||
2157 | xfs_bmbt_log_recs( | ||
2158 | xfs_btree_cur_t *cur, | ||
2159 | xfs_buf_t *bp, | ||
2160 | int rfirst, | ||
2161 | int rlast) | ||
2162 | { | ||
2163 | xfs_bmbt_block_t *block; | ||
2164 | int first; | ||
2165 | int last; | ||
2166 | xfs_bmbt_rec_t *rp; | ||
2167 | xfs_trans_t *tp; | ||
2168 | |||
2169 | XFS_BMBT_TRACE_CURSOR(cur, ENTRY); | ||
2170 | XFS_BMBT_TRACE_ARGBII(cur, bp, rfirst, rlast); | ||
2171 | ASSERT(bp); | ||
2172 | tp = cur->bc_tp; | ||
2173 | block = XFS_BUF_TO_BMBT_BLOCK(bp); | ||
2174 | rp = XFS_BMAP_REC_DADDR(block, 1, cur); | ||
2175 | first = (int)((xfs_caddr_t)&rp[rfirst - 1] - (xfs_caddr_t)block); | ||
2176 | last = (int)(((xfs_caddr_t)&rp[rlast] - 1) - (xfs_caddr_t)block); | ||
2177 | xfs_trans_log_buf(tp, bp, first, last); | ||
2178 | XFS_BMBT_TRACE_CURSOR(cur, EXIT); | ||
2179 | } | ||
2180 | |||
2181 | int /* error */ | ||
2182 | xfs_bmbt_lookup_eq( | ||
2183 | xfs_btree_cur_t *cur, | ||
2184 | xfs_fileoff_t off, | ||
2185 | xfs_fsblock_t bno, | ||
2186 | xfs_filblks_t len, | ||
2187 | int *stat) /* success/failure */ | ||
2188 | { | ||
2189 | cur->bc_rec.b.br_startoff = off; | ||
2190 | cur->bc_rec.b.br_startblock = bno; | ||
2191 | cur->bc_rec.b.br_blockcount = len; | ||
2192 | return xfs_bmbt_lookup(cur, XFS_LOOKUP_EQ, stat); | ||
2193 | } | ||
2194 | |||
2195 | int /* error */ | ||
2196 | xfs_bmbt_lookup_ge( | ||
2197 | xfs_btree_cur_t *cur, | ||
2198 | xfs_fileoff_t off, | ||
2199 | xfs_fsblock_t bno, | ||
2200 | xfs_filblks_t len, | ||
2201 | int *stat) /* success/failure */ | ||
2202 | { | ||
2203 | cur->bc_rec.b.br_startoff = off; | ||
2204 | cur->bc_rec.b.br_startblock = bno; | ||
2205 | cur->bc_rec.b.br_blockcount = len; | ||
2206 | return xfs_bmbt_lookup(cur, XFS_LOOKUP_GE, stat); | ||
2207 | } | ||
2208 | |||
2209 | /* | ||
2210 | * Give the bmap btree a new root block. Copy the old broot contents | ||
2211 | * down into a real block and make the broot point to it. | ||
2212 | */ | ||
2213 | int /* error */ | ||
2214 | xfs_bmbt_newroot( | ||
2215 | xfs_btree_cur_t *cur, /* btree cursor */ | ||
2216 | int *logflags, /* logging flags for inode */ | ||
2217 | int *stat) /* return status - 0 fail */ | ||
2218 | { | ||
2219 | xfs_alloc_arg_t args; /* allocation arguments */ | ||
2220 | xfs_bmbt_block_t *block; /* bmap btree block */ | ||
2221 | xfs_buf_t *bp; /* buffer for block */ | ||
2222 | xfs_bmbt_block_t *cblock; /* child btree block */ | ||
2223 | xfs_bmbt_key_t *ckp; /* child key pointer */ | ||
2224 | xfs_bmbt_ptr_t *cpp; /* child ptr pointer */ | ||
2225 | int error; /* error return code */ | ||
2226 | #ifdef DEBUG | ||
2227 | int i; /* loop counter */ | ||
2228 | #endif | ||
2229 | xfs_bmbt_key_t *kp; /* pointer to bmap btree key */ | ||
2230 | int level; /* btree level */ | ||
2231 | xfs_bmbt_ptr_t *pp; /* pointer to bmap block addr */ | ||
2232 | |||
2233 | XFS_BMBT_TRACE_CURSOR(cur, ENTRY); | ||
2234 | level = cur->bc_nlevels - 1; | ||
2235 | block = xfs_bmbt_get_block(cur, level, &bp); | ||
2236 | /* | ||
2237 | * Copy the root into a real block. | ||
2238 | */ | ||
2239 | args.mp = cur->bc_mp; | ||
2240 | pp = XFS_BMAP_PTR_IADDR(block, 1, cur); | ||
2241 | args.tp = cur->bc_tp; | ||
2242 | args.fsbno = cur->bc_private.b.firstblock; | ||
2243 | args.mod = args.minleft = args.alignment = args.total = args.isfl = | ||
2244 | args.userdata = args.minalignslop = 0; | ||
2245 | args.minlen = args.maxlen = args.prod = 1; | ||
2246 | args.wasdel = cur->bc_private.b.flags & XFS_BTCUR_BPRV_WASDEL; | ||
2247 | args.firstblock = args.fsbno; | ||
2248 | if (args.fsbno == NULLFSBLOCK) { | ||
2249 | #ifdef DEBUG | ||
2250 | if ((error = xfs_btree_check_lptr_disk(cur, *pp, level))) { | ||
2251 | XFS_BMBT_TRACE_CURSOR(cur, ERROR); | ||
2252 | return error; | ||
2253 | } | ||
2254 | #endif | ||
2255 | args.fsbno = be64_to_cpu(*pp); | ||
2256 | args.type = XFS_ALLOCTYPE_START_BNO; | ||
2257 | } else if (cur->bc_private.b.flist->xbf_low) | ||
2258 | args.type = XFS_ALLOCTYPE_START_BNO; | ||
2259 | else | ||
2260 | args.type = XFS_ALLOCTYPE_NEAR_BNO; | ||
2261 | if ((error = xfs_alloc_vextent(&args))) { | ||
2262 | XFS_BMBT_TRACE_CURSOR(cur, ERROR); | ||
2263 | return error; | ||
2264 | } | ||
2265 | if (args.fsbno == NULLFSBLOCK) { | ||
2266 | XFS_BMBT_TRACE_CURSOR(cur, EXIT); | ||
2267 | *stat = 0; | ||
2268 | return 0; | ||
2269 | } | ||
2270 | ASSERT(args.len == 1); | ||
2271 | cur->bc_private.b.firstblock = args.fsbno; | ||
2272 | cur->bc_private.b.allocated++; | ||
2273 | cur->bc_private.b.ip->i_d.di_nblocks++; | ||
2274 | XFS_TRANS_MOD_DQUOT_BYINO(args.mp, args.tp, cur->bc_private.b.ip, | ||
2275 | XFS_TRANS_DQ_BCOUNT, 1L); | ||
2276 | bp = xfs_btree_get_bufl(args.mp, cur->bc_tp, args.fsbno, 0); | ||
2277 | cblock = XFS_BUF_TO_BMBT_BLOCK(bp); | ||
2278 | *cblock = *block; | ||
2279 | be16_add_cpu(&block->bb_level, 1); | ||
2280 | block->bb_numrecs = cpu_to_be16(1); | ||
2281 | cur->bc_nlevels++; | ||
2282 | cur->bc_ptrs[level + 1] = 1; | ||
2283 | kp = XFS_BMAP_KEY_IADDR(block, 1, cur); | ||
2284 | ckp = XFS_BMAP_KEY_IADDR(cblock, 1, cur); | ||
2285 | memcpy(ckp, kp, be16_to_cpu(cblock->bb_numrecs) * sizeof(*kp)); | ||
2286 | cpp = XFS_BMAP_PTR_IADDR(cblock, 1, cur); | ||
2287 | #ifdef DEBUG | ||
2288 | for (i = 0; i < be16_to_cpu(cblock->bb_numrecs); i++) { | ||
2289 | if ((error = xfs_btree_check_lptr_disk(cur, pp[i], level))) { | ||
2290 | XFS_BMBT_TRACE_CURSOR(cur, ERROR); | ||
2291 | return error; | ||
2292 | } | ||
2293 | } | ||
2294 | #endif | ||
2295 | memcpy(cpp, pp, be16_to_cpu(cblock->bb_numrecs) * sizeof(*pp)); | ||
2296 | #ifdef DEBUG | ||
2297 | if ((error = xfs_btree_check_lptr(cur, args.fsbno, level))) { | ||
2298 | XFS_BMBT_TRACE_CURSOR(cur, ERROR); | ||
2299 | return error; | ||
2300 | } | ||
2301 | #endif | ||
2302 | *pp = cpu_to_be64(args.fsbno); | ||
2303 | xfs_iroot_realloc(cur->bc_private.b.ip, 1 - be16_to_cpu(cblock->bb_numrecs), | ||
2304 | cur->bc_private.b.whichfork); | ||
2305 | xfs_btree_setbuf(cur, level, bp); | ||
2306 | /* | ||
2307 | * Do all this logging at the end so that | ||
2308 | * the root is at the right level. | ||
2309 | */ | ||
2310 | xfs_bmbt_log_block(cur, bp, XFS_BB_ALL_BITS); | ||
2311 | xfs_bmbt_log_keys(cur, bp, 1, be16_to_cpu(cblock->bb_numrecs)); | ||
2312 | xfs_bmbt_log_ptrs(cur, bp, 1, be16_to_cpu(cblock->bb_numrecs)); | ||
2313 | XFS_BMBT_TRACE_CURSOR(cur, EXIT); | ||
2314 | *logflags |= | ||
2315 | XFS_ILOG_CORE | XFS_ILOG_FBROOT(cur->bc_private.b.whichfork); | ||
2316 | *stat = 1; | ||
2317 | return 0; | ||
2318 | } | ||
2319 | 236 | ||
2320 | /* | 237 | /* |
2321 | * Set all the fields in a bmap extent record from the arguments. | 238 | * Set all the fields in a bmap extent record from the arguments. |
@@ -2512,7 +429,8 @@ xfs_bmbt_set_state( | |||
2512 | */ | 429 | */ |
2513 | void | 430 | void |
2514 | xfs_bmbt_to_bmdr( | 431 | xfs_bmbt_to_bmdr( |
2515 | xfs_bmbt_block_t *rblock, | 432 | struct xfs_mount *mp, |
433 | struct xfs_btree_block *rblock, | ||
2516 | int rblocklen, | 434 | int rblocklen, |
2517 | xfs_bmdr_block_t *dblock, | 435 | xfs_bmdr_block_t *dblock, |
2518 | int dblocklen) | 436 | int dblocklen) |
@@ -2524,67 +442,22 @@ xfs_bmbt_to_bmdr( | |||
2524 | __be64 *tpp; | 442 | __be64 *tpp; |
2525 | 443 | ||
2526 | ASSERT(be32_to_cpu(rblock->bb_magic) == XFS_BMAP_MAGIC); | 444 | ASSERT(be32_to_cpu(rblock->bb_magic) == XFS_BMAP_MAGIC); |
2527 | ASSERT(be64_to_cpu(rblock->bb_leftsib) == NULLDFSBNO); | 445 | ASSERT(be64_to_cpu(rblock->bb_u.l.bb_leftsib) == NULLDFSBNO); |
2528 | ASSERT(be64_to_cpu(rblock->bb_rightsib) == NULLDFSBNO); | 446 | ASSERT(be64_to_cpu(rblock->bb_u.l.bb_rightsib) == NULLDFSBNO); |
2529 | ASSERT(be16_to_cpu(rblock->bb_level) > 0); | 447 | ASSERT(be16_to_cpu(rblock->bb_level) > 0); |
2530 | dblock->bb_level = rblock->bb_level; | 448 | dblock->bb_level = rblock->bb_level; |
2531 | dblock->bb_numrecs = rblock->bb_numrecs; | 449 | dblock->bb_numrecs = rblock->bb_numrecs; |
2532 | dmxr = (int)XFS_BTREE_BLOCK_MAXRECS(dblocklen, xfs_bmdr, 0); | 450 | dmxr = xfs_bmdr_maxrecs(mp, dblocklen, 0); |
2533 | fkp = XFS_BMAP_BROOT_KEY_ADDR(rblock, 1, rblocklen); | 451 | fkp = XFS_BMBT_KEY_ADDR(mp, rblock, 1); |
2534 | tkp = XFS_BTREE_KEY_ADDR(xfs_bmdr, dblock, 1); | 452 | tkp = XFS_BMDR_KEY_ADDR(dblock, 1); |
2535 | fpp = XFS_BMAP_BROOT_PTR_ADDR(rblock, 1, rblocklen); | 453 | fpp = XFS_BMAP_BROOT_PTR_ADDR(mp, rblock, 1, rblocklen); |
2536 | tpp = XFS_BTREE_PTR_ADDR(xfs_bmdr, dblock, 1, dmxr); | 454 | tpp = XFS_BMDR_PTR_ADDR(dblock, 1, dmxr); |
2537 | dmxr = be16_to_cpu(dblock->bb_numrecs); | 455 | dmxr = be16_to_cpu(dblock->bb_numrecs); |
2538 | memcpy(tkp, fkp, sizeof(*fkp) * dmxr); | 456 | memcpy(tkp, fkp, sizeof(*fkp) * dmxr); |
2539 | memcpy(tpp, fpp, sizeof(*fpp) * dmxr); | 457 | memcpy(tpp, fpp, sizeof(*fpp) * dmxr); |
2540 | } | 458 | } |
2541 | 459 | ||
2542 | /* | 460 | /* |
2543 | * Update the record to the passed values. | ||
2544 | */ | ||
2545 | int | ||
2546 | xfs_bmbt_update( | ||
2547 | xfs_btree_cur_t *cur, | ||
2548 | xfs_fileoff_t off, | ||
2549 | xfs_fsblock_t bno, | ||
2550 | xfs_filblks_t len, | ||
2551 | xfs_exntst_t state) | ||
2552 | { | ||
2553 | xfs_bmbt_block_t *block; | ||
2554 | xfs_buf_t *bp; | ||
2555 | int error; | ||
2556 | xfs_bmbt_key_t key; | ||
2557 | int ptr; | ||
2558 | xfs_bmbt_rec_t *rp; | ||
2559 | |||
2560 | XFS_BMBT_TRACE_CURSOR(cur, ENTRY); | ||
2561 | XFS_BMBT_TRACE_ARGFFFI(cur, (xfs_dfiloff_t)off, (xfs_dfsbno_t)bno, | ||
2562 | (xfs_dfilblks_t)len, (int)state); | ||
2563 | block = xfs_bmbt_get_block(cur, 0, &bp); | ||
2564 | #ifdef DEBUG | ||
2565 | if ((error = xfs_btree_check_lblock(cur, block, 0, bp))) { | ||
2566 | XFS_BMBT_TRACE_CURSOR(cur, ERROR); | ||
2567 | return error; | ||
2568 | } | ||
2569 | #endif | ||
2570 | ptr = cur->bc_ptrs[0]; | ||
2571 | rp = XFS_BMAP_REC_IADDR(block, ptr, cur); | ||
2572 | xfs_bmbt_disk_set_allf(rp, off, bno, len, state); | ||
2573 | xfs_bmbt_log_recs(cur, bp, ptr, ptr); | ||
2574 | if (ptr > 1) { | ||
2575 | XFS_BMBT_TRACE_CURSOR(cur, EXIT); | ||
2576 | return 0; | ||
2577 | } | ||
2578 | key.br_startoff = cpu_to_be64(off); | ||
2579 | if ((error = xfs_bmbt_updkey(cur, &key, 1))) { | ||
2580 | XFS_BMBT_TRACE_CURSOR(cur, ERROR); | ||
2581 | return error; | ||
2582 | } | ||
2583 | XFS_BMBT_TRACE_CURSOR(cur, EXIT); | ||
2584 | return 0; | ||
2585 | } | ||
2586 | |||
2587 | /* | ||
2588 | * Check extent records, which have just been read, for | 461 | * Check extent records, which have just been read, for |
2589 | * any bit in the extent flag field. ASSERT on debug | 462 | * any bit in the extent flag field. ASSERT on debug |
2590 | * kernels, as this condition should not occur. | 463 | * kernels, as this condition should not occur. |
@@ -2608,3 +481,451 @@ xfs_check_nostate_extents( | |||
2608 | } | 481 | } |
2609 | return 0; | 482 | return 0; |
2610 | } | 483 | } |
484 | |||
485 | |||
486 | STATIC struct xfs_btree_cur * | ||
487 | xfs_bmbt_dup_cursor( | ||
488 | struct xfs_btree_cur *cur) | ||
489 | { | ||
490 | struct xfs_btree_cur *new; | ||
491 | |||
492 | new = xfs_bmbt_init_cursor(cur->bc_mp, cur->bc_tp, | ||
493 | cur->bc_private.b.ip, cur->bc_private.b.whichfork); | ||
494 | |||
495 | /* | ||
496 | * Copy the firstblock, flist, and flags values, | ||
497 | * since init cursor doesn't get them. | ||
498 | */ | ||
499 | new->bc_private.b.firstblock = cur->bc_private.b.firstblock; | ||
500 | new->bc_private.b.flist = cur->bc_private.b.flist; | ||
501 | new->bc_private.b.flags = cur->bc_private.b.flags; | ||
502 | |||
503 | return new; | ||
504 | } | ||
505 | |||
506 | STATIC void | ||
507 | xfs_bmbt_update_cursor( | ||
508 | struct xfs_btree_cur *src, | ||
509 | struct xfs_btree_cur *dst) | ||
510 | { | ||
511 | ASSERT((dst->bc_private.b.firstblock != NULLFSBLOCK) || | ||
512 | (dst->bc_private.b.ip->i_d.di_flags & XFS_DIFLAG_REALTIME)); | ||
513 | ASSERT(dst->bc_private.b.flist == src->bc_private.b.flist); | ||
514 | |||
515 | dst->bc_private.b.allocated += src->bc_private.b.allocated; | ||
516 | dst->bc_private.b.firstblock = src->bc_private.b.firstblock; | ||
517 | |||
518 | src->bc_private.b.allocated = 0; | ||
519 | } | ||
520 | |||
521 | STATIC int | ||
522 | xfs_bmbt_alloc_block( | ||
523 | struct xfs_btree_cur *cur, | ||
524 | union xfs_btree_ptr *start, | ||
525 | union xfs_btree_ptr *new, | ||
526 | int length, | ||
527 | int *stat) | ||
528 | { | ||
529 | xfs_alloc_arg_t args; /* block allocation args */ | ||
530 | int error; /* error return value */ | ||
531 | |||
532 | memset(&args, 0, sizeof(args)); | ||
533 | args.tp = cur->bc_tp; | ||
534 | args.mp = cur->bc_mp; | ||
535 | args.fsbno = cur->bc_private.b.firstblock; | ||
536 | args.firstblock = args.fsbno; | ||
537 | |||
538 | if (args.fsbno == NULLFSBLOCK) { | ||
539 | args.fsbno = be64_to_cpu(start->l); | ||
540 | args.type = XFS_ALLOCTYPE_START_BNO; | ||
541 | /* | ||
542 | * Make sure there is sufficient room left in the AG to | ||
543 | * complete a full tree split for an extent insert. If | ||
544 | * we are converting the middle part of an extent then | ||
545 | * we may need space for two tree splits. | ||
546 | * | ||
547 | * We are relying on the caller to make the correct block | ||
548 | * reservation for this operation to succeed. If the | ||
549 | * reservation amount is insufficient then we may fail a | ||
550 | * block allocation here and corrupt the filesystem. | ||
551 | */ | ||
552 | args.minleft = xfs_trans_get_block_res(args.tp); | ||
553 | } else if (cur->bc_private.b.flist->xbf_low) { | ||
554 | args.type = XFS_ALLOCTYPE_START_BNO; | ||
555 | } else { | ||
556 | args.type = XFS_ALLOCTYPE_NEAR_BNO; | ||
557 | } | ||
558 | |||
559 | args.minlen = args.maxlen = args.prod = 1; | ||
560 | args.wasdel = cur->bc_private.b.flags & XFS_BTCUR_BPRV_WASDEL; | ||
561 | if (!args.wasdel && xfs_trans_get_block_res(args.tp) == 0) { | ||
562 | error = XFS_ERROR(ENOSPC); | ||
563 | goto error0; | ||
564 | } | ||
565 | error = xfs_alloc_vextent(&args); | ||
566 | if (error) | ||
567 | goto error0; | ||
568 | |||
569 | if (args.fsbno == NULLFSBLOCK && args.minleft) { | ||
570 | /* | ||
571 | * Could not find an AG with enough free space to satisfy | ||
572 | * a full btree split. Try again without minleft and if | ||
573 | * successful activate the lowspace algorithm. | ||
574 | */ | ||
575 | args.fsbno = 0; | ||
576 | args.type = XFS_ALLOCTYPE_FIRST_AG; | ||
577 | args.minleft = 0; | ||
578 | error = xfs_alloc_vextent(&args); | ||
579 | if (error) | ||
580 | goto error0; | ||
581 | cur->bc_private.b.flist->xbf_low = 1; | ||
582 | } | ||
583 | if (args.fsbno == NULLFSBLOCK) { | ||
584 | XFS_BTREE_TRACE_CURSOR(cur, XBT_EXIT); | ||
585 | *stat = 0; | ||
586 | return 0; | ||
587 | } | ||
588 | ASSERT(args.len == 1); | ||
589 | cur->bc_private.b.firstblock = args.fsbno; | ||
590 | cur->bc_private.b.allocated++; | ||
591 | cur->bc_private.b.ip->i_d.di_nblocks++; | ||
592 | xfs_trans_log_inode(args.tp, cur->bc_private.b.ip, XFS_ILOG_CORE); | ||
593 | XFS_TRANS_MOD_DQUOT_BYINO(args.mp, args.tp, cur->bc_private.b.ip, | ||
594 | XFS_TRANS_DQ_BCOUNT, 1L); | ||
595 | |||
596 | new->l = cpu_to_be64(args.fsbno); | ||
597 | |||
598 | XFS_BTREE_TRACE_CURSOR(cur, XBT_EXIT); | ||
599 | *stat = 1; | ||
600 | return 0; | ||
601 | |||
602 | error0: | ||
603 | XFS_BTREE_TRACE_CURSOR(cur, XBT_ERROR); | ||
604 | return error; | ||
605 | } | ||
606 | |||
607 | STATIC int | ||
608 | xfs_bmbt_free_block( | ||
609 | struct xfs_btree_cur *cur, | ||
610 | struct xfs_buf *bp) | ||
611 | { | ||
612 | struct xfs_mount *mp = cur->bc_mp; | ||
613 | struct xfs_inode *ip = cur->bc_private.b.ip; | ||
614 | struct xfs_trans *tp = cur->bc_tp; | ||
615 | xfs_fsblock_t fsbno = XFS_DADDR_TO_FSB(mp, XFS_BUF_ADDR(bp)); | ||
616 | |||
617 | xfs_bmap_add_free(fsbno, 1, cur->bc_private.b.flist, mp); | ||
618 | ip->i_d.di_nblocks--; | ||
619 | |||
620 | xfs_trans_log_inode(tp, ip, XFS_ILOG_CORE); | ||
621 | XFS_TRANS_MOD_DQUOT_BYINO(mp, tp, ip, XFS_TRANS_DQ_BCOUNT, -1L); | ||
622 | xfs_trans_binval(tp, bp); | ||
623 | return 0; | ||
624 | } | ||
625 | |||
626 | STATIC int | ||
627 | xfs_bmbt_get_minrecs( | ||
628 | struct xfs_btree_cur *cur, | ||
629 | int level) | ||
630 | { | ||
631 | if (level == cur->bc_nlevels - 1) { | ||
632 | struct xfs_ifork *ifp; | ||
633 | |||
634 | ifp = XFS_IFORK_PTR(cur->bc_private.b.ip, | ||
635 | cur->bc_private.b.whichfork); | ||
636 | |||
637 | return xfs_bmbt_maxrecs(cur->bc_mp, | ||
638 | ifp->if_broot_bytes, level == 0) / 2; | ||
639 | } | ||
640 | |||
641 | return cur->bc_mp->m_bmap_dmnr[level != 0]; | ||
642 | } | ||
643 | |||
644 | int | ||
645 | xfs_bmbt_get_maxrecs( | ||
646 | struct xfs_btree_cur *cur, | ||
647 | int level) | ||
648 | { | ||
649 | if (level == cur->bc_nlevels - 1) { | ||
650 | struct xfs_ifork *ifp; | ||
651 | |||
652 | ifp = XFS_IFORK_PTR(cur->bc_private.b.ip, | ||
653 | cur->bc_private.b.whichfork); | ||
654 | |||
655 | return xfs_bmbt_maxrecs(cur->bc_mp, | ||
656 | ifp->if_broot_bytes, level == 0); | ||
657 | } | ||
658 | |||
659 | return cur->bc_mp->m_bmap_dmxr[level != 0]; | ||
660 | |||
661 | } | ||
662 | |||
663 | /* | ||
664 | * Get the maximum records we could store in the on-disk format. | ||
665 | * | ||
666 | * For non-root nodes this is equivalent to xfs_bmbt_get_maxrecs, but | ||
667 | * for the root node this checks the available space in the dinode fork | ||
668 | * so that we can resize the in-memory buffer to match it. After a | ||
669 | * resize to the maximum size this function returns the same value | ||
670 | * as xfs_bmbt_get_maxrecs for the root node, too. | ||
671 | */ | ||
672 | STATIC int | ||
673 | xfs_bmbt_get_dmaxrecs( | ||
674 | struct xfs_btree_cur *cur, | ||
675 | int level) | ||
676 | { | ||
677 | if (level != cur->bc_nlevels - 1) | ||
678 | return cur->bc_mp->m_bmap_dmxr[level != 0]; | ||
679 | return xfs_bmdr_maxrecs(cur->bc_mp, cur->bc_private.b.forksize, | ||
680 | level == 0); | ||
681 | } | ||
682 | |||
683 | STATIC void | ||
684 | xfs_bmbt_init_key_from_rec( | ||
685 | union xfs_btree_key *key, | ||
686 | union xfs_btree_rec *rec) | ||
687 | { | ||
688 | key->bmbt.br_startoff = | ||
689 | cpu_to_be64(xfs_bmbt_disk_get_startoff(&rec->bmbt)); | ||
690 | } | ||
691 | |||
692 | STATIC void | ||
693 | xfs_bmbt_init_rec_from_key( | ||
694 | union xfs_btree_key *key, | ||
695 | union xfs_btree_rec *rec) | ||
696 | { | ||
697 | ASSERT(key->bmbt.br_startoff != 0); | ||
698 | |||
699 | xfs_bmbt_disk_set_allf(&rec->bmbt, be64_to_cpu(key->bmbt.br_startoff), | ||
700 | 0, 0, XFS_EXT_NORM); | ||
701 | } | ||
702 | |||
703 | STATIC void | ||
704 | xfs_bmbt_init_rec_from_cur( | ||
705 | struct xfs_btree_cur *cur, | ||
706 | union xfs_btree_rec *rec) | ||
707 | { | ||
708 | xfs_bmbt_disk_set_all(&rec->bmbt, &cur->bc_rec.b); | ||
709 | } | ||
710 | |||
711 | STATIC void | ||
712 | xfs_bmbt_init_ptr_from_cur( | ||
713 | struct xfs_btree_cur *cur, | ||
714 | union xfs_btree_ptr *ptr) | ||
715 | { | ||
716 | ptr->l = 0; | ||
717 | } | ||
718 | |||
719 | STATIC __int64_t | ||
720 | xfs_bmbt_key_diff( | ||
721 | struct xfs_btree_cur *cur, | ||
722 | union xfs_btree_key *key) | ||
723 | { | ||
724 | return (__int64_t)be64_to_cpu(key->bmbt.br_startoff) - | ||
725 | cur->bc_rec.b.br_startoff; | ||
726 | } | ||
727 | |||
728 | #ifdef DEBUG | ||
729 | STATIC int | ||
730 | xfs_bmbt_keys_inorder( | ||
731 | struct xfs_btree_cur *cur, | ||
732 | union xfs_btree_key *k1, | ||
733 | union xfs_btree_key *k2) | ||
734 | { | ||
735 | return be64_to_cpu(k1->bmbt.br_startoff) < | ||
736 | be64_to_cpu(k2->bmbt.br_startoff); | ||
737 | } | ||
738 | |||
739 | STATIC int | ||
740 | xfs_bmbt_recs_inorder( | ||
741 | struct xfs_btree_cur *cur, | ||
742 | union xfs_btree_rec *r1, | ||
743 | union xfs_btree_rec *r2) | ||
744 | { | ||
745 | return xfs_bmbt_disk_get_startoff(&r1->bmbt) + | ||
746 | xfs_bmbt_disk_get_blockcount(&r1->bmbt) <= | ||
747 | xfs_bmbt_disk_get_startoff(&r2->bmbt); | ||
748 | } | ||
749 | #endif /* DEBUG */ | ||
750 | |||
751 | #ifdef XFS_BTREE_TRACE | ||
752 | ktrace_t *xfs_bmbt_trace_buf; | ||
753 | |||
754 | STATIC void | ||
755 | xfs_bmbt_trace_enter( | ||
756 | struct xfs_btree_cur *cur, | ||
757 | const char *func, | ||
758 | char *s, | ||
759 | int type, | ||
760 | int line, | ||
761 | __psunsigned_t a0, | ||
762 | __psunsigned_t a1, | ||
763 | __psunsigned_t a2, | ||
764 | __psunsigned_t a3, | ||
765 | __psunsigned_t a4, | ||
766 | __psunsigned_t a5, | ||
767 | __psunsigned_t a6, | ||
768 | __psunsigned_t a7, | ||
769 | __psunsigned_t a8, | ||
770 | __psunsigned_t a9, | ||
771 | __psunsigned_t a10) | ||
772 | { | ||
773 | struct xfs_inode *ip = cur->bc_private.b.ip; | ||
774 | int whichfork = cur->bc_private.b.whichfork; | ||
775 | |||
776 | ktrace_enter(xfs_bmbt_trace_buf, | ||
777 | (void *)((__psint_t)type | (whichfork << 8) | (line << 16)), | ||
778 | (void *)func, (void *)s, (void *)ip, (void *)cur, | ||
779 | (void *)a0, (void *)a1, (void *)a2, (void *)a3, | ||
780 | (void *)a4, (void *)a5, (void *)a6, (void *)a7, | ||
781 | (void *)a8, (void *)a9, (void *)a10); | ||
782 | ktrace_enter(ip->i_btrace, | ||
783 | (void *)((__psint_t)type | (whichfork << 8) | (line << 16)), | ||
784 | (void *)func, (void *)s, (void *)ip, (void *)cur, | ||
785 | (void *)a0, (void *)a1, (void *)a2, (void *)a3, | ||
786 | (void *)a4, (void *)a5, (void *)a6, (void *)a7, | ||
787 | (void *)a8, (void *)a9, (void *)a10); | ||
788 | } | ||
789 | |||
790 | STATIC void | ||
791 | xfs_bmbt_trace_cursor( | ||
792 | struct xfs_btree_cur *cur, | ||
793 | __uint32_t *s0, | ||
794 | __uint64_t *l0, | ||
795 | __uint64_t *l1) | ||
796 | { | ||
797 | struct xfs_bmbt_rec_host r; | ||
798 | |||
799 | xfs_bmbt_set_all(&r, &cur->bc_rec.b); | ||
800 | |||
801 | *s0 = (cur->bc_nlevels << 24) | | ||
802 | (cur->bc_private.b.flags << 16) | | ||
803 | cur->bc_private.b.allocated; | ||
804 | *l0 = r.l0; | ||
805 | *l1 = r.l1; | ||
806 | } | ||
807 | |||
808 | STATIC void | ||
809 | xfs_bmbt_trace_key( | ||
810 | struct xfs_btree_cur *cur, | ||
811 | union xfs_btree_key *key, | ||
812 | __uint64_t *l0, | ||
813 | __uint64_t *l1) | ||
814 | { | ||
815 | *l0 = be64_to_cpu(key->bmbt.br_startoff); | ||
816 | *l1 = 0; | ||
817 | } | ||
818 | |||
819 | STATIC void | ||
820 | xfs_bmbt_trace_record( | ||
821 | struct xfs_btree_cur *cur, | ||
822 | union xfs_btree_rec *rec, | ||
823 | __uint64_t *l0, | ||
824 | __uint64_t *l1, | ||
825 | __uint64_t *l2) | ||
826 | { | ||
827 | struct xfs_bmbt_irec irec; | ||
828 | |||
829 | xfs_bmbt_disk_get_all(&rec->bmbt, &irec); | ||
830 | *l0 = irec.br_startoff; | ||
831 | *l1 = irec.br_startblock; | ||
832 | *l2 = irec.br_blockcount; | ||
833 | } | ||
834 | #endif /* XFS_BTREE_TRACE */ | ||
835 | |||
836 | static const struct xfs_btree_ops xfs_bmbt_ops = { | ||
837 | .rec_len = sizeof(xfs_bmbt_rec_t), | ||
838 | .key_len = sizeof(xfs_bmbt_key_t), | ||
839 | |||
840 | .dup_cursor = xfs_bmbt_dup_cursor, | ||
841 | .update_cursor = xfs_bmbt_update_cursor, | ||
842 | .alloc_block = xfs_bmbt_alloc_block, | ||
843 | .free_block = xfs_bmbt_free_block, | ||
844 | .get_maxrecs = xfs_bmbt_get_maxrecs, | ||
845 | .get_minrecs = xfs_bmbt_get_minrecs, | ||
846 | .get_dmaxrecs = xfs_bmbt_get_dmaxrecs, | ||
847 | .init_key_from_rec = xfs_bmbt_init_key_from_rec, | ||
848 | .init_rec_from_key = xfs_bmbt_init_rec_from_key, | ||
849 | .init_rec_from_cur = xfs_bmbt_init_rec_from_cur, | ||
850 | .init_ptr_from_cur = xfs_bmbt_init_ptr_from_cur, | ||
851 | .key_diff = xfs_bmbt_key_diff, | ||
852 | |||
853 | #ifdef DEBUG | ||
854 | .keys_inorder = xfs_bmbt_keys_inorder, | ||
855 | .recs_inorder = xfs_bmbt_recs_inorder, | ||
856 | #endif | ||
857 | |||
858 | #ifdef XFS_BTREE_TRACE | ||
859 | .trace_enter = xfs_bmbt_trace_enter, | ||
860 | .trace_cursor = xfs_bmbt_trace_cursor, | ||
861 | .trace_key = xfs_bmbt_trace_key, | ||
862 | .trace_record = xfs_bmbt_trace_record, | ||
863 | #endif | ||
864 | }; | ||
865 | |||
866 | /* | ||
867 | * Allocate a new bmap btree cursor. | ||
868 | */ | ||
869 | struct xfs_btree_cur * /* new bmap btree cursor */ | ||
870 | xfs_bmbt_init_cursor( | ||
871 | struct xfs_mount *mp, /* file system mount point */ | ||
872 | struct xfs_trans *tp, /* transaction pointer */ | ||
873 | struct xfs_inode *ip, /* inode owning the btree */ | ||
874 | int whichfork) /* data or attr fork */ | ||
875 | { | ||
876 | struct xfs_ifork *ifp = XFS_IFORK_PTR(ip, whichfork); | ||
877 | struct xfs_btree_cur *cur; | ||
878 | |||
879 | cur = kmem_zone_zalloc(xfs_btree_cur_zone, KM_SLEEP); | ||
880 | |||
881 | cur->bc_tp = tp; | ||
882 | cur->bc_mp = mp; | ||
883 | cur->bc_nlevels = be16_to_cpu(ifp->if_broot->bb_level) + 1; | ||
884 | cur->bc_btnum = XFS_BTNUM_BMAP; | ||
885 | cur->bc_blocklog = mp->m_sb.sb_blocklog; | ||
886 | |||
887 | cur->bc_ops = &xfs_bmbt_ops; | ||
888 | cur->bc_flags = XFS_BTREE_LONG_PTRS | XFS_BTREE_ROOT_IN_INODE; | ||
889 | |||
890 | cur->bc_private.b.forksize = XFS_IFORK_SIZE(ip, whichfork); | ||
891 | cur->bc_private.b.ip = ip; | ||
892 | cur->bc_private.b.firstblock = NULLFSBLOCK; | ||
893 | cur->bc_private.b.flist = NULL; | ||
894 | cur->bc_private.b.allocated = 0; | ||
895 | cur->bc_private.b.flags = 0; | ||
896 | cur->bc_private.b.whichfork = whichfork; | ||
897 | |||
898 | return cur; | ||
899 | } | ||
900 | |||
901 | /* | ||
902 | * Calculate number of records in a bmap btree block. | ||
903 | */ | ||
904 | int | ||
905 | xfs_bmbt_maxrecs( | ||
906 | struct xfs_mount *mp, | ||
907 | int blocklen, | ||
908 | int leaf) | ||
909 | { | ||
910 | blocklen -= XFS_BMBT_BLOCK_LEN(mp); | ||
911 | |||
912 | if (leaf) | ||
913 | return blocklen / sizeof(xfs_bmbt_rec_t); | ||
914 | return blocklen / (sizeof(xfs_bmbt_key_t) + sizeof(xfs_bmbt_ptr_t)); | ||
915 | } | ||
916 | |||
917 | /* | ||
918 | * Calculate number of records in a bmap btree inode root. | ||
919 | */ | ||
920 | int | ||
921 | xfs_bmdr_maxrecs( | ||
922 | struct xfs_mount *mp, | ||
923 | int blocklen, | ||
924 | int leaf) | ||
925 | { | ||
926 | blocklen -= sizeof(xfs_bmdr_block_t); | ||
927 | |||
928 | if (leaf) | ||
929 | return blocklen / sizeof(xfs_bmdr_rec_t); | ||
930 | return blocklen / (sizeof(xfs_bmdr_key_t) + sizeof(xfs_bmdr_ptr_t)); | ||
931 | } | ||