Pull error-inject into release branch
[linux-2.6] / fs / xfs / xfs_bmap_btree.c
1 /*
2  * Copyright (c) 2000-2003,2005 Silicon Graphics, Inc.
3  * All Rights Reserved.
4  *
5  * This program is free software; you can redistribute it and/or
6  * modify it under the terms of the GNU General Public License as
7  * published by the Free Software Foundation.
8  *
9  * This program is distributed in the hope that it would be useful,
10  * but WITHOUT ANY WARRANTY; without even the implied warranty of
11  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
12  * GNU General Public License for more details.
13  *
14  * You should have received a copy of the GNU General Public License
15  * along with this program; if not, write the Free Software Foundation,
16  * Inc.,  51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
17  */
18 #include "xfs.h"
19 #include "xfs_fs.h"
20 #include "xfs_types.h"
21 #include "xfs_bit.h"
22 #include "xfs_log.h"
23 #include "xfs_inum.h"
24 #include "xfs_trans.h"
25 #include "xfs_sb.h"
26 #include "xfs_ag.h"
27 #include "xfs_dir2.h"
28 #include "xfs_dmapi.h"
29 #include "xfs_mount.h"
30 #include "xfs_bmap_btree.h"
31 #include "xfs_alloc_btree.h"
32 #include "xfs_ialloc_btree.h"
33 #include "xfs_dir2_sf.h"
34 #include "xfs_attr_sf.h"
35 #include "xfs_dinode.h"
36 #include "xfs_inode.h"
37 #include "xfs_inode_item.h"
38 #include "xfs_alloc.h"
39 #include "xfs_btree.h"
40 #include "xfs_ialloc.h"
41 #include "xfs_itable.h"
42 #include "xfs_bmap.h"
43 #include "xfs_error.h"
44 #include "xfs_quota.h"
45
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         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         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         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         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         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         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         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         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         char            *func,
259         xfs_btree_cur_t *cur,
260         char            *s,
261         int             line)
262 {
263         xfs_bmbt_rec_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                 INT_GET(r.l0, ARCH_CONVERT) >> 32, (int)INT_GET(r.l0, ARCH_CONVERT), INT_GET(r.l1, ARCH_CONVERT) >> 32, (int)INT_GET(r.l1, ARCH_CONVERT),
270                 (unsigned long)cur->bc_bufs[0], (unsigned long)cur->bc_bufs[1],
271                 (unsigned long)cur->bc_bufs[2], (unsigned long)cur->bc_bufs[3],
272                 (cur->bc_ptrs[0] << 16) | cur->bc_ptrs[1],
273                 (cur->bc_ptrs[2] << 16) | cur->bc_ptrs[3]);
274 }
275
276 #define XFS_BMBT_TRACE_ARGBI(c,b,i)     \
277         xfs_bmbt_trace_argbi(fname, c, b, i, __LINE__)
278 #define XFS_BMBT_TRACE_ARGBII(c,b,i,j)  \
279         xfs_bmbt_trace_argbii(fname, c, b, i, j, __LINE__)
280 #define XFS_BMBT_TRACE_ARGFFFI(c,o,b,i,j)       \
281         xfs_bmbt_trace_argfffi(fname, c, o, b, i, j, __LINE__)
282 #define XFS_BMBT_TRACE_ARGI(c,i)        \
283         xfs_bmbt_trace_argi(fname, c, i, __LINE__)
284 #define XFS_BMBT_TRACE_ARGIFK(c,i,f,s)  \
285         xfs_bmbt_trace_argifk(fname, c, i, f, s, __LINE__)
286 #define XFS_BMBT_TRACE_ARGIFR(c,i,f,r)  \
287         xfs_bmbt_trace_argifr(fname, c, i, f, r, __LINE__)
288 #define XFS_BMBT_TRACE_ARGIK(c,i,k)     \
289         xfs_bmbt_trace_argik(fname, c, i, k, __LINE__)
290 #define XFS_BMBT_TRACE_CURSOR(c,s)      \
291         xfs_bmbt_trace_cursor(fname, c, s, __LINE__)
292 #else
293 #define XFS_BMBT_TRACE_ARGBI(c,b,i)
294 #define XFS_BMBT_TRACE_ARGBII(c,b,i,j)
295 #define XFS_BMBT_TRACE_ARGFFFI(c,o,b,i,j)
296 #define XFS_BMBT_TRACE_ARGI(c,i)
297 #define XFS_BMBT_TRACE_ARGIFK(c,i,f,s)
298 #define XFS_BMBT_TRACE_ARGIFR(c,i,f,r)
299 #define XFS_BMBT_TRACE_ARGIK(c,i,k)
300 #define XFS_BMBT_TRACE_CURSOR(c,s)
301 #endif  /* XFS_BMBT_TRACE */
302
303
304 /*
305  * Internal functions.
306  */
307
308 /*
309  * Delete record pointed to by cur/level.
310  */
311 STATIC int                                      /* error */
312 xfs_bmbt_delrec(
313         xfs_btree_cur_t         *cur,
314         int                     level,
315         int                     *stat)          /* success/failure */
316 {
317         xfs_bmbt_block_t        *block;         /* bmap btree block */
318         xfs_fsblock_t           bno;            /* fs-relative block number */
319         xfs_buf_t               *bp;            /* buffer for block */
320         int                     error;          /* error return value */
321 #ifdef XFS_BMBT_TRACE
322         static char             fname[] = "xfs_bmbt_delrec";
323 #endif
324         int                     i;              /* loop counter */
325         int                     j;              /* temp state */
326         xfs_bmbt_key_t          key;            /* bmap btree key */
327         xfs_bmbt_key_t          *kp=NULL;       /* pointer to bmap btree key */
328         xfs_fsblock_t           lbno;           /* left sibling block number */
329         xfs_buf_t               *lbp;           /* left buffer pointer */
330         xfs_bmbt_block_t        *left;          /* left btree block */
331         xfs_bmbt_key_t          *lkp;           /* left btree key */
332         xfs_bmbt_ptr_t          *lpp;           /* left address pointer */
333         int                     lrecs=0;        /* left record count */
334         xfs_bmbt_rec_t          *lrp;           /* left record pointer */
335         xfs_mount_t             *mp;            /* file system mount point */
336         xfs_bmbt_ptr_t          *pp;            /* pointer to bmap block addr */
337         int                     ptr;            /* key/record index */
338         xfs_fsblock_t           rbno;           /* right sibling block number */
339         xfs_buf_t               *rbp;           /* right buffer pointer */
340         xfs_bmbt_block_t        *right;         /* right btree block */
341         xfs_bmbt_key_t          *rkp;           /* right btree key */
342         xfs_bmbt_rec_t          *rp;            /* pointer to bmap btree rec */
343         xfs_bmbt_ptr_t          *rpp;           /* right address pointer */
344         xfs_bmbt_block_t        *rrblock;       /* right-right btree block */
345         xfs_buf_t               *rrbp;          /* right-right buffer pointer */
346         int                     rrecs=0;        /* right record count */
347         xfs_bmbt_rec_t          *rrp;           /* right record pointer */
348         xfs_btree_cur_t         *tcur;          /* temporary btree cursor */
349         int                     numrecs;        /* temporary numrec count */
350         int                     numlrecs, numrrecs;
351
352         XFS_BMBT_TRACE_CURSOR(cur, ENTRY);
353         XFS_BMBT_TRACE_ARGI(cur, level);
354         ptr = cur->bc_ptrs[level];
355         tcur = NULL;
356         if (ptr == 0) {
357                 XFS_BMBT_TRACE_CURSOR(cur, EXIT);
358                 *stat = 0;
359                 return 0;
360         }
361         block = xfs_bmbt_get_block(cur, level, &bp);
362         numrecs = be16_to_cpu(block->bb_numrecs);
363 #ifdef DEBUG
364         if ((error = xfs_btree_check_lblock(cur, block, level, bp))) {
365                 XFS_BMBT_TRACE_CURSOR(cur, ERROR);
366                 goto error0;
367         }
368 #endif
369         if (ptr > numrecs) {
370                 XFS_BMBT_TRACE_CURSOR(cur, EXIT);
371                 *stat = 0;
372                 return 0;
373         }
374         XFS_STATS_INC(xs_bmbt_delrec);
375         if (level > 0) {
376                 kp = XFS_BMAP_KEY_IADDR(block, 1, cur);
377                 pp = XFS_BMAP_PTR_IADDR(block, 1, cur);
378 #ifdef DEBUG
379                 for (i = ptr; i < numrecs; i++) {
380                         if ((error = xfs_btree_check_lptr_disk(cur, pp[i], level))) {
381                                 XFS_BMBT_TRACE_CURSOR(cur, ERROR);
382                                 goto error0;
383                         }
384                 }
385 #endif
386                 if (ptr < numrecs) {
387                         memmove(&kp[ptr - 1], &kp[ptr],
388                                 (numrecs - ptr) * sizeof(*kp));
389                         memmove(&pp[ptr - 1], &pp[ptr], /* INT_: direct copy */
390                                 (numrecs - ptr) * sizeof(*pp));
391                         xfs_bmbt_log_ptrs(cur, bp, ptr, numrecs - 1);
392                         xfs_bmbt_log_keys(cur, bp, ptr, numrecs - 1);
393                 }
394         } else {
395                 rp = XFS_BMAP_REC_IADDR(block, 1, cur);
396                 if (ptr < numrecs) {
397                         memmove(&rp[ptr - 1], &rp[ptr],
398                                 (numrecs - ptr) * sizeof(*rp));
399                         xfs_bmbt_log_recs(cur, bp, ptr, numrecs - 1);
400                 }
401                 if (ptr == 1) {
402                         key.br_startoff =
403                                 cpu_to_be64(xfs_bmbt_disk_get_startoff(rp));
404                         kp = &key;
405                 }
406         }
407         numrecs--;
408         block->bb_numrecs = cpu_to_be16(numrecs);
409         xfs_bmbt_log_block(cur, bp, XFS_BB_NUMRECS);
410         /*
411          * We're at the root level.
412          * First, shrink the root block in-memory.
413          * Try to get rid of the next level down.
414          * If we can't then there's nothing left to do.
415          */
416         if (level == cur->bc_nlevels - 1) {
417                 xfs_iroot_realloc(cur->bc_private.b.ip, -1,
418                         cur->bc_private.b.whichfork);
419                 if ((error = xfs_bmbt_killroot(cur))) {
420                         XFS_BMBT_TRACE_CURSOR(cur, ERROR);
421                         goto error0;
422                 }
423                 if (level > 0 && (error = xfs_bmbt_decrement(cur, level, &j))) {
424                         XFS_BMBT_TRACE_CURSOR(cur, ERROR);
425                         goto error0;
426                 }
427                 XFS_BMBT_TRACE_CURSOR(cur, EXIT);
428                 *stat = 1;
429                 return 0;
430         }
431         if (ptr == 1 && (error = xfs_bmbt_updkey(cur, kp, level + 1))) {
432                 XFS_BMBT_TRACE_CURSOR(cur, ERROR);
433                 goto error0;
434         }
435         if (numrecs >= XFS_BMAP_BLOCK_IMINRECS(level, cur)) {
436                 if (level > 0 && (error = xfs_bmbt_decrement(cur, level, &j))) {
437                         XFS_BMBT_TRACE_CURSOR(cur, ERROR);
438                         goto error0;
439                 }
440                 XFS_BMBT_TRACE_CURSOR(cur, EXIT);
441                 *stat = 1;
442                 return 0;
443         }
444         rbno = be64_to_cpu(block->bb_rightsib);
445         lbno = be64_to_cpu(block->bb_leftsib);
446         /*
447          * One child of root, need to get a chance to copy its contents
448          * into the root and delete it. Can't go up to next level,
449          * there's nothing to delete there.
450          */
451         if (lbno == NULLFSBLOCK && rbno == NULLFSBLOCK &&
452             level == cur->bc_nlevels - 2) {
453                 if ((error = xfs_bmbt_killroot(cur))) {
454                         XFS_BMBT_TRACE_CURSOR(cur, ERROR);
455                         goto error0;
456                 }
457                 if (level > 0 && (error = xfs_bmbt_decrement(cur, level, &i))) {
458                         XFS_BMBT_TRACE_CURSOR(cur, ERROR);
459                         goto error0;
460                 }
461                 XFS_BMBT_TRACE_CURSOR(cur, EXIT);
462                 *stat = 1;
463                 return 0;
464         }
465         ASSERT(rbno != NULLFSBLOCK || lbno != NULLFSBLOCK);
466         if ((error = xfs_btree_dup_cursor(cur, &tcur))) {
467                 XFS_BMBT_TRACE_CURSOR(cur, ERROR);
468                 goto error0;
469         }
470         bno = NULLFSBLOCK;
471         if (rbno != NULLFSBLOCK) {
472                 i = xfs_btree_lastrec(tcur, level);
473                 XFS_WANT_CORRUPTED_GOTO(i == 1, error0);
474                 if ((error = xfs_bmbt_increment(tcur, level, &i))) {
475                         XFS_BMBT_TRACE_CURSOR(cur, ERROR);
476                         goto error0;
477                 }
478                 XFS_WANT_CORRUPTED_GOTO(i == 1, error0);
479                 i = xfs_btree_lastrec(tcur, level);
480                 XFS_WANT_CORRUPTED_GOTO(i == 1, error0);
481                 rbp = tcur->bc_bufs[level];
482                 right = XFS_BUF_TO_BMBT_BLOCK(rbp);
483 #ifdef DEBUG
484                 if ((error = xfs_btree_check_lblock(cur, right, level, rbp))) {
485                         XFS_BMBT_TRACE_CURSOR(cur, ERROR);
486                         goto error0;
487                 }
488 #endif
489                 bno = be64_to_cpu(right->bb_leftsib);
490                 if (be16_to_cpu(right->bb_numrecs) - 1 >=
491                     XFS_BMAP_BLOCK_IMINRECS(level, cur)) {
492                         if ((error = xfs_bmbt_lshift(tcur, level, &i))) {
493                                 XFS_BMBT_TRACE_CURSOR(cur, ERROR);
494                                 goto error0;
495                         }
496                         if (i) {
497                                 ASSERT(be16_to_cpu(block->bb_numrecs) >=
498                                        XFS_BMAP_BLOCK_IMINRECS(level, tcur));
499                                 xfs_btree_del_cursor(tcur, XFS_BTREE_NOERROR);
500                                 tcur = NULL;
501                                 if (level > 0) {
502                                         if ((error = xfs_bmbt_decrement(cur,
503                                                         level, &i))) {
504                                                 XFS_BMBT_TRACE_CURSOR(cur,
505                                                         ERROR);
506                                                 goto error0;
507                                         }
508                                 }
509                                 XFS_BMBT_TRACE_CURSOR(cur, EXIT);
510                                 *stat = 1;
511                                 return 0;
512                         }
513                 }
514                 rrecs = be16_to_cpu(right->bb_numrecs);
515                 if (lbno != NULLFSBLOCK) {
516                         i = xfs_btree_firstrec(tcur, level);
517                         XFS_WANT_CORRUPTED_GOTO(i == 1, error0);
518                         if ((error = xfs_bmbt_decrement(tcur, level, &i))) {
519                                 XFS_BMBT_TRACE_CURSOR(cur, ERROR);
520                                 goto error0;
521                         }
522                         XFS_WANT_CORRUPTED_GOTO(i == 1, error0);
523                 }
524         }
525         if (lbno != NULLFSBLOCK) {
526                 i = xfs_btree_firstrec(tcur, level);
527                 XFS_WANT_CORRUPTED_GOTO(i == 1, error0);
528                 /*
529                  * decrement to last in block
530                  */
531                 if ((error = xfs_bmbt_decrement(tcur, level, &i))) {
532                         XFS_BMBT_TRACE_CURSOR(cur, ERROR);
533                         goto error0;
534                 }
535                 i = xfs_btree_firstrec(tcur, level);
536                 XFS_WANT_CORRUPTED_GOTO(i == 1, error0);
537                 lbp = tcur->bc_bufs[level];
538                 left = XFS_BUF_TO_BMBT_BLOCK(lbp);
539 #ifdef DEBUG
540                 if ((error = xfs_btree_check_lblock(cur, left, level, lbp))) {
541                         XFS_BMBT_TRACE_CURSOR(cur, ERROR);
542                         goto error0;
543                 }
544 #endif
545                 bno = be64_to_cpu(left->bb_rightsib);
546                 if (be16_to_cpu(left->bb_numrecs) - 1 >=
547                     XFS_BMAP_BLOCK_IMINRECS(level, cur)) {
548                         if ((error = xfs_bmbt_rshift(tcur, level, &i))) {
549                                 XFS_BMBT_TRACE_CURSOR(cur, ERROR);
550                                 goto error0;
551                         }
552                         if (i) {
553                                 ASSERT(be16_to_cpu(block->bb_numrecs) >=
554                                        XFS_BMAP_BLOCK_IMINRECS(level, tcur));
555                                 xfs_btree_del_cursor(tcur, XFS_BTREE_NOERROR);
556                                 tcur = NULL;
557                                 if (level == 0)
558                                         cur->bc_ptrs[0]++;
559                                 XFS_BMBT_TRACE_CURSOR(cur, EXIT);
560                                 *stat = 1;
561                                 return 0;
562                         }
563                 }
564                 lrecs = be16_to_cpu(left->bb_numrecs);
565         }
566         xfs_btree_del_cursor(tcur, XFS_BTREE_NOERROR);
567         tcur = NULL;
568         mp = cur->bc_mp;
569         ASSERT(bno != NULLFSBLOCK);
570         if (lbno != NULLFSBLOCK &&
571             lrecs + be16_to_cpu(block->bb_numrecs) <= XFS_BMAP_BLOCK_IMAXRECS(level, cur)) {
572                 rbno = bno;
573                 right = block;
574                 rbp = bp;
575                 if ((error = xfs_btree_read_bufl(mp, cur->bc_tp, lbno, 0, &lbp,
576                                 XFS_BMAP_BTREE_REF))) {
577                         XFS_BMBT_TRACE_CURSOR(cur, ERROR);
578                         goto error0;
579                 }
580                 left = XFS_BUF_TO_BMBT_BLOCK(lbp);
581                 if ((error = xfs_btree_check_lblock(cur, left, level, lbp))) {
582                         XFS_BMBT_TRACE_CURSOR(cur, ERROR);
583                         goto error0;
584                 }
585         } else if (rbno != NULLFSBLOCK &&
586                    rrecs + be16_to_cpu(block->bb_numrecs) <=
587                    XFS_BMAP_BLOCK_IMAXRECS(level, cur)) {
588                 lbno = bno;
589                 left = block;
590                 lbp = bp;
591                 if ((error = xfs_btree_read_bufl(mp, cur->bc_tp, rbno, 0, &rbp,
592                                 XFS_BMAP_BTREE_REF))) {
593                         XFS_BMBT_TRACE_CURSOR(cur, ERROR);
594                         goto error0;
595                 }
596                 right = XFS_BUF_TO_BMBT_BLOCK(rbp);
597                 if ((error = xfs_btree_check_lblock(cur, right, level, rbp))) {
598                         XFS_BMBT_TRACE_CURSOR(cur, ERROR);
599                         goto error0;
600                 }
601                 lrecs = be16_to_cpu(left->bb_numrecs);
602         } else {
603                 if (level > 0 && (error = xfs_bmbt_decrement(cur, level, &i))) {
604                         XFS_BMBT_TRACE_CURSOR(cur, ERROR);
605                         goto error0;
606                 }
607                 XFS_BMBT_TRACE_CURSOR(cur, EXIT);
608                 *stat = 1;
609                 return 0;
610         }
611         numlrecs = be16_to_cpu(left->bb_numrecs);
612         numrrecs = be16_to_cpu(right->bb_numrecs);
613         if (level > 0) {
614                 lkp = XFS_BMAP_KEY_IADDR(left, numlrecs + 1, cur);
615                 lpp = XFS_BMAP_PTR_IADDR(left, numlrecs + 1, cur);
616                 rkp = XFS_BMAP_KEY_IADDR(right, 1, cur);
617                 rpp = XFS_BMAP_PTR_IADDR(right, 1, cur);
618 #ifdef DEBUG
619                 for (i = 0; i < numrrecs; i++) {
620                         if ((error = xfs_btree_check_lptr_disk(cur, rpp[i], level))) {
621                                 XFS_BMBT_TRACE_CURSOR(cur, ERROR);
622                                 goto error0;
623                         }
624                 }
625 #endif
626                 memcpy(lkp, rkp, numrrecs * sizeof(*lkp));
627                 memcpy(lpp, rpp, numrrecs * sizeof(*lpp));
628                 xfs_bmbt_log_keys(cur, lbp, numlrecs + 1, numlrecs + numrrecs);
629                 xfs_bmbt_log_ptrs(cur, lbp, numlrecs + 1, numlrecs + numrrecs);
630         } else {
631                 lrp = XFS_BMAP_REC_IADDR(left, numlrecs + 1, cur);
632                 rrp = XFS_BMAP_REC_IADDR(right, 1, cur);
633                 memcpy(lrp, rrp, numrrecs * sizeof(*lrp));
634                 xfs_bmbt_log_recs(cur, lbp, numlrecs + 1, numlrecs + numrrecs);
635         }
636         be16_add(&left->bb_numrecs, numrrecs);
637         left->bb_rightsib = right->bb_rightsib;
638         xfs_bmbt_log_block(cur, lbp, XFS_BB_RIGHTSIB | XFS_BB_NUMRECS);
639         if (be64_to_cpu(left->bb_rightsib) != NULLDFSBNO) {
640                 if ((error = xfs_btree_read_bufl(mp, cur->bc_tp,
641                                 be64_to_cpu(left->bb_rightsib),
642                                 0, &rrbp, XFS_BMAP_BTREE_REF))) {
643                         XFS_BMBT_TRACE_CURSOR(cur, ERROR);
644                         goto error0;
645                 }
646                 rrblock = XFS_BUF_TO_BMBT_BLOCK(rrbp);
647                 if ((error = xfs_btree_check_lblock(cur, rrblock, level, rrbp))) {
648                         XFS_BMBT_TRACE_CURSOR(cur, ERROR);
649                         goto error0;
650                 }
651                 rrblock->bb_leftsib = cpu_to_be64(lbno);
652                 xfs_bmbt_log_block(cur, rrbp, XFS_BB_LEFTSIB);
653         }
654         xfs_bmap_add_free(XFS_DADDR_TO_FSB(mp, XFS_BUF_ADDR(rbp)), 1,
655                 cur->bc_private.b.flist, mp);
656         cur->bc_private.b.ip->i_d.di_nblocks--;
657         xfs_trans_log_inode(cur->bc_tp, cur->bc_private.b.ip, XFS_ILOG_CORE);
658         XFS_TRANS_MOD_DQUOT_BYINO(mp, cur->bc_tp, cur->bc_private.b.ip,
659                         XFS_TRANS_DQ_BCOUNT, -1L);
660         xfs_trans_binval(cur->bc_tp, rbp);
661         if (bp != lbp) {
662                 cur->bc_bufs[level] = lbp;
663                 cur->bc_ptrs[level] += lrecs;
664                 cur->bc_ra[level] = 0;
665         } else if ((error = xfs_bmbt_increment(cur, level + 1, &i))) {
666                 XFS_BMBT_TRACE_CURSOR(cur, ERROR);
667                 goto error0;
668         }
669         if (level > 0)
670                 cur->bc_ptrs[level]--;
671         XFS_BMBT_TRACE_CURSOR(cur, EXIT);
672         *stat = 2;
673         return 0;
674
675 error0:
676         if (tcur)
677                 xfs_btree_del_cursor(tcur, XFS_BTREE_ERROR);
678         return error;
679 }
680
681 /*
682  * Insert one record/level.  Return information to the caller
683  * allowing the next level up to proceed if necessary.
684  */
685 STATIC int                                      /* error */
686 xfs_bmbt_insrec(
687         xfs_btree_cur_t         *cur,
688         int                     level,
689         xfs_fsblock_t           *bnop,
690         xfs_bmbt_rec_t          *recp,
691         xfs_btree_cur_t         **curp,
692         int                     *stat)          /* no-go/done/continue */
693 {
694         xfs_bmbt_block_t        *block;         /* bmap btree block */
695         xfs_buf_t               *bp;            /* buffer for block */
696         int                     error;          /* error return value */
697 #ifdef XFS_BMBT_TRACE
698         static char             fname[] = "xfs_bmbt_insrec";
699 #endif
700         int                     i;              /* loop index */
701         xfs_bmbt_key_t          key;            /* bmap btree key */
702         xfs_bmbt_key_t          *kp=NULL;       /* pointer to bmap btree key */
703         int                     logflags;       /* inode logging flags */
704         xfs_fsblock_t           nbno;           /* new block number */
705         struct xfs_btree_cur    *ncur;          /* new btree cursor */
706         __uint64_t              startoff;       /* new btree key value */
707         xfs_bmbt_rec_t          nrec;           /* new record count */
708         int                     optr;           /* old key/record index */
709         xfs_bmbt_ptr_t          *pp;            /* pointer to bmap block addr */
710         int                     ptr;            /* key/record index */
711         xfs_bmbt_rec_t          *rp=NULL;       /* pointer to bmap btree rec */
712         int                     numrecs;
713
714         ASSERT(level < cur->bc_nlevels);
715         XFS_BMBT_TRACE_CURSOR(cur, ENTRY);
716         XFS_BMBT_TRACE_ARGIFR(cur, level, *bnop, recp);
717         ncur = NULL;
718         key.br_startoff = cpu_to_be64(xfs_bmbt_disk_get_startoff(recp));
719         optr = ptr = cur->bc_ptrs[level];
720         if (ptr == 0) {
721                 XFS_BMBT_TRACE_CURSOR(cur, EXIT);
722                 *stat = 0;
723                 return 0;
724         }
725         XFS_STATS_INC(xs_bmbt_insrec);
726         block = xfs_bmbt_get_block(cur, level, &bp);
727         numrecs = be16_to_cpu(block->bb_numrecs);
728 #ifdef DEBUG
729         if ((error = xfs_btree_check_lblock(cur, block, level, bp))) {
730                 XFS_BMBT_TRACE_CURSOR(cur, ERROR);
731                 return error;
732         }
733         if (ptr <= numrecs) {
734                 if (level == 0) {
735                         rp = XFS_BMAP_REC_IADDR(block, ptr, cur);
736                         xfs_btree_check_rec(XFS_BTNUM_BMAP, recp, rp);
737                 } else {
738                         kp = XFS_BMAP_KEY_IADDR(block, ptr, cur);
739                         xfs_btree_check_key(XFS_BTNUM_BMAP, &key, kp);
740                 }
741         }
742 #endif
743         nbno = NULLFSBLOCK;
744         if (numrecs == XFS_BMAP_BLOCK_IMAXRECS(level, cur)) {
745                 if (numrecs < XFS_BMAP_BLOCK_DMAXRECS(level, cur)) {
746                         /*
747                          * A root block, that can be made bigger.
748                          */
749                         xfs_iroot_realloc(cur->bc_private.b.ip, 1,
750                                 cur->bc_private.b.whichfork);
751                         block = xfs_bmbt_get_block(cur, level, &bp);
752                 } else if (level == cur->bc_nlevels - 1) {
753                         if ((error = xfs_bmbt_newroot(cur, &logflags, stat)) ||
754                             *stat == 0) {
755                                 XFS_BMBT_TRACE_CURSOR(cur, ERROR);
756                                 return error;
757                         }
758                         xfs_trans_log_inode(cur->bc_tp, cur->bc_private.b.ip,
759                                 logflags);
760                         block = xfs_bmbt_get_block(cur, level, &bp);
761                 } else {
762                         if ((error = xfs_bmbt_rshift(cur, level, &i))) {
763                                 XFS_BMBT_TRACE_CURSOR(cur, ERROR);
764                                 return error;
765                         }
766                         if (i) {
767                                 /* nothing */
768                         } else {
769                                 if ((error = xfs_bmbt_lshift(cur, level, &i))) {
770                                         XFS_BMBT_TRACE_CURSOR(cur, ERROR);
771                                         return error;
772                                 }
773                                 if (i) {
774                                         optr = ptr = cur->bc_ptrs[level];
775                                 } else {
776                                         if ((error = xfs_bmbt_split(cur, level,
777                                                         &nbno, &startoff, &ncur,
778                                                         &i))) {
779                                                 XFS_BMBT_TRACE_CURSOR(cur,
780                                                         ERROR);
781                                                 return error;
782                                         }
783                                         if (i) {
784                                                 block = xfs_bmbt_get_block(
785                                                             cur, level, &bp);
786 #ifdef DEBUG
787                                                 if ((error =
788                                                     xfs_btree_check_lblock(cur,
789                                                             block, level, bp))) {
790                                                         XFS_BMBT_TRACE_CURSOR(
791                                                                 cur, ERROR);
792                                                         return error;
793                                                 }
794 #endif
795                                                 ptr = cur->bc_ptrs[level];
796                                                 xfs_bmbt_disk_set_allf(&nrec,
797                                                         startoff, 0, 0,
798                                                         XFS_EXT_NORM);
799                                         } else {
800                                                 XFS_BMBT_TRACE_CURSOR(cur,
801                                                         EXIT);
802                                                 *stat = 0;
803                                                 return 0;
804                                         }
805                                 }
806                         }
807                 }
808         }
809         numrecs = be16_to_cpu(block->bb_numrecs);
810         if (level > 0) {
811                 kp = XFS_BMAP_KEY_IADDR(block, 1, cur);
812                 pp = XFS_BMAP_PTR_IADDR(block, 1, cur);
813 #ifdef DEBUG
814                 for (i = numrecs; i >= ptr; i--) {
815                         if ((error = xfs_btree_check_lptr_disk(cur, pp[i - 1],
816                                         level))) {
817                                 XFS_BMBT_TRACE_CURSOR(cur, ERROR);
818                                 return error;
819                         }
820                 }
821 #endif
822                 memmove(&kp[ptr], &kp[ptr - 1],
823                         (numrecs - ptr + 1) * sizeof(*kp));
824                 memmove(&pp[ptr], &pp[ptr - 1], /* INT_: direct copy */
825                         (numrecs - ptr + 1) * sizeof(*pp));
826 #ifdef DEBUG
827                 if ((error = xfs_btree_check_lptr(cur, *bnop, level))) {
828                         XFS_BMBT_TRACE_CURSOR(cur, ERROR);
829                         return error;
830                 }
831 #endif
832                 kp[ptr - 1] = key;
833                 pp[ptr - 1] = cpu_to_be64(*bnop);
834                 numrecs++;
835                 block->bb_numrecs = cpu_to_be16(numrecs);
836                 xfs_bmbt_log_keys(cur, bp, ptr, numrecs);
837                 xfs_bmbt_log_ptrs(cur, bp, ptr, numrecs);
838         } else {
839                 rp = XFS_BMAP_REC_IADDR(block, 1, cur);
840                 memmove(&rp[ptr], &rp[ptr - 1],
841                         (numrecs - ptr + 1) * sizeof(*rp));
842                 rp[ptr - 1] = *recp;
843                 numrecs++;
844                 block->bb_numrecs = cpu_to_be16(numrecs);
845                 xfs_bmbt_log_recs(cur, bp, ptr, numrecs);
846         }
847         xfs_bmbt_log_block(cur, bp, XFS_BB_NUMRECS);
848 #ifdef DEBUG
849         if (ptr < numrecs) {
850                 if (level == 0)
851                         xfs_btree_check_rec(XFS_BTNUM_BMAP, rp + ptr - 1,
852                                 rp + ptr);
853                 else
854                         xfs_btree_check_key(XFS_BTNUM_BMAP, kp + ptr - 1,
855                                 kp + ptr);
856         }
857 #endif
858         if (optr == 1 && (error = xfs_bmbt_updkey(cur, &key, level + 1))) {
859                 XFS_BMBT_TRACE_CURSOR(cur, ERROR);
860                 return error;
861         }
862         *bnop = nbno;
863         if (nbno != NULLFSBLOCK) {
864                 *recp = nrec;
865                 *curp = ncur;
866         }
867         XFS_BMBT_TRACE_CURSOR(cur, EXIT);
868         *stat = 1;
869         return 0;
870 }
871
872 STATIC int
873 xfs_bmbt_killroot(
874         xfs_btree_cur_t         *cur)
875 {
876         xfs_bmbt_block_t        *block;
877         xfs_bmbt_block_t        *cblock;
878         xfs_buf_t               *cbp;
879         xfs_bmbt_key_t          *ckp;
880         xfs_bmbt_ptr_t          *cpp;
881 #ifdef DEBUG
882         int                     error;
883 #endif
884 #ifdef XFS_BMBT_TRACE
885         static char             fname[] = "xfs_bmbt_killroot";
886 #endif
887         int                     i;
888         xfs_bmbt_key_t          *kp;
889         xfs_inode_t             *ip;
890         xfs_ifork_t             *ifp;
891         int                     level;
892         xfs_bmbt_ptr_t          *pp;
893
894         XFS_BMBT_TRACE_CURSOR(cur, ENTRY);
895         level = cur->bc_nlevels - 1;
896         ASSERT(level >= 1);
897         /*
898          * Don't deal with the root block needs to be a leaf case.
899          * We're just going to turn the thing back into extents anyway.
900          */
901         if (level == 1) {
902                 XFS_BMBT_TRACE_CURSOR(cur, EXIT);
903                 return 0;
904         }
905         block = xfs_bmbt_get_block(cur, level, &cbp);
906         /*
907          * Give up if the root has multiple children.
908          */
909         if (be16_to_cpu(block->bb_numrecs) != 1) {
910                 XFS_BMBT_TRACE_CURSOR(cur, EXIT);
911                 return 0;
912         }
913         /*
914          * Only do this if the next level will fit.
915          * Then the data must be copied up to the inode,
916          * instead of freeing the root you free the next level.
917          */
918         cbp = cur->bc_bufs[level - 1];
919         cblock = XFS_BUF_TO_BMBT_BLOCK(cbp);
920         if (be16_to_cpu(cblock->bb_numrecs) > XFS_BMAP_BLOCK_DMAXRECS(level, cur)) {
921                 XFS_BMBT_TRACE_CURSOR(cur, EXIT);
922                 return 0;
923         }
924         ASSERT(be64_to_cpu(cblock->bb_leftsib) == NULLDFSBNO);
925         ASSERT(be64_to_cpu(cblock->bb_rightsib) == NULLDFSBNO);
926         ip = cur->bc_private.b.ip;
927         ifp = XFS_IFORK_PTR(ip, cur->bc_private.b.whichfork);
928         ASSERT(XFS_BMAP_BLOCK_IMAXRECS(level, cur) ==
929                XFS_BMAP_BROOT_MAXRECS(ifp->if_broot_bytes));
930         i = (int)(be16_to_cpu(cblock->bb_numrecs) - XFS_BMAP_BLOCK_IMAXRECS(level, cur));
931         if (i) {
932                 xfs_iroot_realloc(ip, i, cur->bc_private.b.whichfork);
933                 block = ifp->if_broot;
934         }
935         be16_add(&block->bb_numrecs, i);
936         ASSERT(block->bb_numrecs == cblock->bb_numrecs);
937         kp = XFS_BMAP_KEY_IADDR(block, 1, cur);
938         ckp = XFS_BMAP_KEY_IADDR(cblock, 1, cur);
939         memcpy(kp, ckp, be16_to_cpu(block->bb_numrecs) * sizeof(*kp));
940         pp = XFS_BMAP_PTR_IADDR(block, 1, cur);
941         cpp = XFS_BMAP_PTR_IADDR(cblock, 1, cur);
942 #ifdef DEBUG
943         for (i = 0; i < be16_to_cpu(cblock->bb_numrecs); i++) {
944                 if ((error = xfs_btree_check_lptr_disk(cur, cpp[i], level - 1))) {
945                         XFS_BMBT_TRACE_CURSOR(cur, ERROR);
946                         return error;
947                 }
948         }
949 #endif
950         memcpy(pp, cpp, be16_to_cpu(block->bb_numrecs) * sizeof(*pp));
951         xfs_bmap_add_free(XFS_DADDR_TO_FSB(cur->bc_mp, XFS_BUF_ADDR(cbp)), 1,
952                         cur->bc_private.b.flist, cur->bc_mp);
953         ip->i_d.di_nblocks--;
954         XFS_TRANS_MOD_DQUOT_BYINO(cur->bc_mp, cur->bc_tp, ip,
955                         XFS_TRANS_DQ_BCOUNT, -1L);
956         xfs_trans_binval(cur->bc_tp, cbp);
957         cur->bc_bufs[level - 1] = NULL;
958         be16_add(&block->bb_level, -1);
959         xfs_trans_log_inode(cur->bc_tp, ip,
960                 XFS_ILOG_CORE | XFS_ILOG_FBROOT(cur->bc_private.b.whichfork));
961         cur->bc_nlevels--;
962         XFS_BMBT_TRACE_CURSOR(cur, EXIT);
963         return 0;
964 }
965
966 /*
967  * Log key values from the btree block.
968  */
969 STATIC void
970 xfs_bmbt_log_keys(
971         xfs_btree_cur_t *cur,
972         xfs_buf_t       *bp,
973         int             kfirst,
974         int             klast)
975 {
976 #ifdef XFS_BMBT_TRACE
977         static char     fname[] = "xfs_bmbt_log_keys";
978 #endif
979         xfs_trans_t     *tp;
980
981         XFS_BMBT_TRACE_CURSOR(cur, ENTRY);
982         XFS_BMBT_TRACE_ARGBII(cur, bp, kfirst, klast);
983         tp = cur->bc_tp;
984         if (bp) {
985                 xfs_bmbt_block_t        *block;
986                 int                     first;
987                 xfs_bmbt_key_t          *kp;
988                 int                     last;
989
990                 block = XFS_BUF_TO_BMBT_BLOCK(bp);
991                 kp = XFS_BMAP_KEY_DADDR(block, 1, cur);
992                 first = (int)((xfs_caddr_t)&kp[kfirst - 1] - (xfs_caddr_t)block);
993                 last = (int)(((xfs_caddr_t)&kp[klast] - 1) - (xfs_caddr_t)block);
994                 xfs_trans_log_buf(tp, bp, first, last);
995         } else {
996                 xfs_inode_t              *ip;
997
998                 ip = cur->bc_private.b.ip;
999                 xfs_trans_log_inode(tp, ip,
1000                         XFS_ILOG_FBROOT(cur->bc_private.b.whichfork));
1001         }
1002         XFS_BMBT_TRACE_CURSOR(cur, EXIT);
1003 }
1004
1005 /*
1006  * Log pointer values from the btree block.
1007  */
1008 STATIC void
1009 xfs_bmbt_log_ptrs(
1010         xfs_btree_cur_t *cur,
1011         xfs_buf_t       *bp,
1012         int             pfirst,
1013         int             plast)
1014 {
1015 #ifdef XFS_BMBT_TRACE
1016         static char     fname[] = "xfs_bmbt_log_ptrs";
1017 #endif
1018         xfs_trans_t     *tp;
1019
1020         XFS_BMBT_TRACE_CURSOR(cur, ENTRY);
1021         XFS_BMBT_TRACE_ARGBII(cur, bp, pfirst, plast);
1022         tp = cur->bc_tp;
1023         if (bp) {
1024                 xfs_bmbt_block_t        *block;
1025                 int                     first;
1026                 int                     last;
1027                 xfs_bmbt_ptr_t          *pp;
1028
1029                 block = XFS_BUF_TO_BMBT_BLOCK(bp);
1030                 pp = XFS_BMAP_PTR_DADDR(block, 1, cur);
1031                 first = (int)((xfs_caddr_t)&pp[pfirst - 1] - (xfs_caddr_t)block);
1032                 last = (int)(((xfs_caddr_t)&pp[plast] - 1) - (xfs_caddr_t)block);
1033                 xfs_trans_log_buf(tp, bp, first, last);
1034         } else {
1035                 xfs_inode_t             *ip;
1036
1037                 ip = cur->bc_private.b.ip;
1038                 xfs_trans_log_inode(tp, ip,
1039                         XFS_ILOG_FBROOT(cur->bc_private.b.whichfork));
1040         }
1041         XFS_BMBT_TRACE_CURSOR(cur, EXIT);
1042 }
1043
1044 /*
1045  * Lookup the record.  The cursor is made to point to it, based on dir.
1046  */
1047 STATIC int                              /* error */
1048 xfs_bmbt_lookup(
1049         xfs_btree_cur_t         *cur,
1050         xfs_lookup_t            dir,
1051         int                     *stat)          /* success/failure */
1052 {
1053         xfs_bmbt_block_t        *block=NULL;
1054         xfs_buf_t               *bp;
1055         xfs_daddr_t             d;
1056         xfs_sfiloff_t           diff;
1057         int                     error;          /* error return value */
1058 #ifdef XFS_BMBT_TRACE
1059         static char     fname[] = "xfs_bmbt_lookup";
1060 #endif
1061         xfs_fsblock_t           fsbno=0;
1062         int                     high;
1063         int                     i;
1064         int                     keyno=0;
1065         xfs_bmbt_key_t          *kkbase=NULL;
1066         xfs_bmbt_key_t          *kkp;
1067         xfs_bmbt_rec_t          *krbase=NULL;
1068         xfs_bmbt_rec_t          *krp;
1069         int                     level;
1070         int                     low;
1071         xfs_mount_t             *mp;
1072         xfs_bmbt_ptr_t          *pp;
1073         xfs_bmbt_irec_t         *rp;
1074         xfs_fileoff_t           startoff;
1075         xfs_trans_t             *tp;
1076
1077         XFS_STATS_INC(xs_bmbt_lookup);
1078         XFS_BMBT_TRACE_CURSOR(cur, ENTRY);
1079         XFS_BMBT_TRACE_ARGI(cur, (int)dir);
1080         tp = cur->bc_tp;
1081         mp = cur->bc_mp;
1082         rp = &cur->bc_rec.b;
1083         for (level = cur->bc_nlevels - 1, diff = 1; level >= 0; level--) {
1084                 if (level < cur->bc_nlevels - 1) {
1085                         d = XFS_FSB_TO_DADDR(mp, fsbno);
1086                         bp = cur->bc_bufs[level];
1087                         if (bp && XFS_BUF_ADDR(bp) != d)
1088                                 bp = NULL;
1089                         if (!bp) {
1090                                 if ((error = xfs_btree_read_bufl(mp, tp, fsbno,
1091                                                 0, &bp, XFS_BMAP_BTREE_REF))) {
1092                                         XFS_BMBT_TRACE_CURSOR(cur, ERROR);
1093                                         return error;
1094                                 }
1095                                 xfs_btree_setbuf(cur, level, bp);
1096                                 block = XFS_BUF_TO_BMBT_BLOCK(bp);
1097                                 if ((error = xfs_btree_check_lblock(cur, block,
1098                                                 level, bp))) {
1099                                         XFS_BMBT_TRACE_CURSOR(cur, ERROR);
1100                                         return error;
1101                                 }
1102                         } else
1103                                 block = XFS_BUF_TO_BMBT_BLOCK(bp);
1104                 } else
1105                         block = xfs_bmbt_get_block(cur, level, &bp);
1106                 if (diff == 0)
1107                         keyno = 1;
1108                 else {
1109                         if (level > 0)
1110                                 kkbase = XFS_BMAP_KEY_IADDR(block, 1, cur);
1111                         else
1112                                 krbase = XFS_BMAP_REC_IADDR(block, 1, cur);
1113                         low = 1;
1114                         if (!(high = be16_to_cpu(block->bb_numrecs))) {
1115                                 ASSERT(level == 0);
1116                                 cur->bc_ptrs[0] = dir != XFS_LOOKUP_LE;
1117                                 XFS_BMBT_TRACE_CURSOR(cur, EXIT);
1118                                 *stat = 0;
1119                                 return 0;
1120                         }
1121                         while (low <= high) {
1122                                 XFS_STATS_INC(xs_bmbt_compare);
1123                                 keyno = (low + high) >> 1;
1124                                 if (level > 0) {
1125                                         kkp = kkbase + keyno - 1;
1126                                         startoff = be64_to_cpu(kkp->br_startoff);
1127                                 } else {
1128                                         krp = krbase + keyno - 1;
1129                                         startoff = xfs_bmbt_disk_get_startoff(krp);
1130                                 }
1131                                 diff = (xfs_sfiloff_t)
1132                                                 (startoff - rp->br_startoff);
1133                                 if (diff < 0)
1134                                         low = keyno + 1;
1135                                 else if (diff > 0)
1136                                         high = keyno - 1;
1137                                 else
1138                                         break;
1139                         }
1140                 }
1141                 if (level > 0) {
1142                         if (diff > 0 && --keyno < 1)
1143                                 keyno = 1;
1144                         pp = XFS_BMAP_PTR_IADDR(block, keyno, cur);
1145                         fsbno = be64_to_cpu(*pp);
1146 #ifdef DEBUG
1147                         if ((error = xfs_btree_check_lptr(cur, fsbno, level))) {
1148                                 XFS_BMBT_TRACE_CURSOR(cur, ERROR);
1149                                 return error;
1150                         }
1151 #endif
1152                         cur->bc_ptrs[level] = keyno;
1153                 }
1154         }
1155         if (dir != XFS_LOOKUP_LE && diff < 0) {
1156                 keyno++;
1157                 /*
1158                  * If ge search and we went off the end of the block, but it's
1159                  * not the last block, we're in the wrong block.
1160                  */
1161                 if (dir == XFS_LOOKUP_GE && keyno > be16_to_cpu(block->bb_numrecs) &&
1162                     be64_to_cpu(block->bb_rightsib) != NULLDFSBNO) {
1163                         cur->bc_ptrs[0] = keyno;
1164                         if ((error = xfs_bmbt_increment(cur, 0, &i))) {
1165                                 XFS_BMBT_TRACE_CURSOR(cur, ERROR);
1166                                 return error;
1167                         }
1168                         XFS_WANT_CORRUPTED_RETURN(i == 1);
1169                         XFS_BMBT_TRACE_CURSOR(cur, EXIT);
1170                         *stat = 1;
1171                         return 0;
1172                 }
1173         }
1174         else if (dir == XFS_LOOKUP_LE && diff > 0)
1175                 keyno--;
1176         cur->bc_ptrs[0] = keyno;
1177         if (keyno == 0 || keyno > be16_to_cpu(block->bb_numrecs)) {
1178                 XFS_BMBT_TRACE_CURSOR(cur, EXIT);
1179                 *stat = 0;
1180         } else {
1181                 XFS_BMBT_TRACE_CURSOR(cur, EXIT);
1182                 *stat = ((dir != XFS_LOOKUP_EQ) || (diff == 0));
1183         }
1184         return 0;
1185 }
1186
1187 /*
1188  * Move 1 record left from cur/level if possible.
1189  * Update cur to reflect the new path.
1190  */
1191 STATIC int                                      /* error */
1192 xfs_bmbt_lshift(
1193         xfs_btree_cur_t         *cur,
1194         int                     level,
1195         int                     *stat)          /* success/failure */
1196 {
1197         int                     error;          /* error return value */
1198 #ifdef XFS_BMBT_TRACE
1199         static char             fname[] = "xfs_bmbt_lshift";
1200 #endif
1201 #ifdef DEBUG
1202         int                     i;              /* loop counter */
1203 #endif
1204         xfs_bmbt_key_t          key;            /* bmap btree key */
1205         xfs_buf_t               *lbp;           /* left buffer pointer */
1206         xfs_bmbt_block_t        *left;          /* left btree block */
1207         xfs_bmbt_key_t          *lkp=NULL;      /* left btree key */
1208         xfs_bmbt_ptr_t          *lpp;           /* left address pointer */
1209         int                     lrecs;          /* left record count */
1210         xfs_bmbt_rec_t          *lrp=NULL;      /* left record pointer */
1211         xfs_mount_t             *mp;            /* file system mount point */
1212         xfs_buf_t               *rbp;           /* right buffer pointer */
1213         xfs_bmbt_block_t        *right;         /* right btree block */
1214         xfs_bmbt_key_t          *rkp=NULL;      /* right btree key */
1215         xfs_bmbt_ptr_t          *rpp=NULL;      /* right address pointer */
1216         xfs_bmbt_rec_t          *rrp=NULL;      /* right record pointer */
1217         int                     rrecs;          /* right record count */
1218
1219         XFS_BMBT_TRACE_CURSOR(cur, ENTRY);
1220         XFS_BMBT_TRACE_ARGI(cur, level);
1221         if (level == cur->bc_nlevels - 1) {
1222                 XFS_BMBT_TRACE_CURSOR(cur, EXIT);
1223                 *stat = 0;
1224                 return 0;
1225         }
1226         rbp = cur->bc_bufs[level];
1227         right = XFS_BUF_TO_BMBT_BLOCK(rbp);
1228 #ifdef DEBUG
1229         if ((error = xfs_btree_check_lblock(cur, right, level, rbp))) {
1230                 XFS_BMBT_TRACE_CURSOR(cur, ERROR);
1231                 return error;
1232         }
1233 #endif
1234         if (be64_to_cpu(right->bb_leftsib) == NULLDFSBNO) {
1235                 XFS_BMBT_TRACE_CURSOR(cur, EXIT);
1236                 *stat = 0;
1237                 return 0;
1238         }
1239         if (cur->bc_ptrs[level] <= 1) {
1240                 XFS_BMBT_TRACE_CURSOR(cur, EXIT);
1241                 *stat = 0;
1242                 return 0;
1243         }
1244         mp = cur->bc_mp;
1245         if ((error = xfs_btree_read_bufl(mp, cur->bc_tp, be64_to_cpu(right->bb_leftsib), 0,
1246                         &lbp, XFS_BMAP_BTREE_REF))) {
1247                 XFS_BMBT_TRACE_CURSOR(cur, ERROR);
1248                 return error;
1249         }
1250         left = XFS_BUF_TO_BMBT_BLOCK(lbp);
1251         if ((error = xfs_btree_check_lblock(cur, left, level, lbp))) {
1252                 XFS_BMBT_TRACE_CURSOR(cur, ERROR);
1253                 return error;
1254         }
1255         if (be16_to_cpu(left->bb_numrecs) == XFS_BMAP_BLOCK_IMAXRECS(level, cur)) {
1256                 XFS_BMBT_TRACE_CURSOR(cur, EXIT);
1257                 *stat = 0;
1258                 return 0;
1259         }
1260         lrecs = be16_to_cpu(left->bb_numrecs) + 1;
1261         if (level > 0) {
1262                 lkp = XFS_BMAP_KEY_IADDR(left, lrecs, cur);
1263                 rkp = XFS_BMAP_KEY_IADDR(right, 1, cur);
1264                 *lkp = *rkp;
1265                 xfs_bmbt_log_keys(cur, lbp, lrecs, lrecs);
1266                 lpp = XFS_BMAP_PTR_IADDR(left, lrecs, cur);
1267                 rpp = XFS_BMAP_PTR_IADDR(right, 1, cur);
1268 #ifdef DEBUG
1269                 if ((error = xfs_btree_check_lptr_disk(cur, *rpp, level))) {
1270                         XFS_BMBT_TRACE_CURSOR(cur, ERROR);
1271                         return error;
1272                 }
1273 #endif
1274                 *lpp = *rpp; /* INT_: direct copy */
1275                 xfs_bmbt_log_ptrs(cur, lbp, lrecs, lrecs);
1276         } else {
1277                 lrp = XFS_BMAP_REC_IADDR(left, lrecs, cur);
1278                 rrp = XFS_BMAP_REC_IADDR(right, 1, cur);
1279                 *lrp = *rrp;
1280                 xfs_bmbt_log_recs(cur, lbp, lrecs, lrecs);
1281         }
1282         left->bb_numrecs = cpu_to_be16(lrecs);
1283         xfs_bmbt_log_block(cur, lbp, XFS_BB_NUMRECS);
1284 #ifdef DEBUG
1285         if (level > 0)
1286                 xfs_btree_check_key(XFS_BTNUM_BMAP, lkp - 1, lkp);
1287         else
1288                 xfs_btree_check_rec(XFS_BTNUM_BMAP, lrp - 1, lrp);
1289 #endif
1290         rrecs = be16_to_cpu(right->bb_numrecs) - 1;
1291         right->bb_numrecs = cpu_to_be16(rrecs);
1292         xfs_bmbt_log_block(cur, rbp, XFS_BB_NUMRECS);
1293         if (level > 0) {
1294 #ifdef DEBUG
1295                 for (i = 0; i < rrecs; i++) {
1296                         if ((error = xfs_btree_check_lptr_disk(cur, rpp[i + 1],
1297                                         level))) {
1298                                 XFS_BMBT_TRACE_CURSOR(cur, ERROR);
1299                                 return error;
1300                         }
1301                 }
1302 #endif
1303                 memmove(rkp, rkp + 1, rrecs * sizeof(*rkp));
1304                 memmove(rpp, rpp + 1, rrecs * sizeof(*rpp));
1305                 xfs_bmbt_log_keys(cur, rbp, 1, rrecs);
1306                 xfs_bmbt_log_ptrs(cur, rbp, 1, rrecs);
1307         } else {
1308                 memmove(rrp, rrp + 1, rrecs * sizeof(*rrp));
1309                 xfs_bmbt_log_recs(cur, rbp, 1, rrecs);
1310                 key.br_startoff = cpu_to_be64(xfs_bmbt_disk_get_startoff(rrp));
1311                 rkp = &key;
1312         }
1313         if ((error = xfs_bmbt_updkey(cur, rkp, level + 1))) {
1314                 XFS_BMBT_TRACE_CURSOR(cur, ERROR);
1315                 return error;
1316         }
1317         cur->bc_ptrs[level]--;
1318         XFS_BMBT_TRACE_CURSOR(cur, EXIT);
1319         *stat = 1;
1320         return 0;
1321 }
1322
1323 /*
1324  * Move 1 record right from cur/level if possible.
1325  * Update cur to reflect the new path.
1326  */
1327 STATIC int                                      /* error */
1328 xfs_bmbt_rshift(
1329         xfs_btree_cur_t         *cur,
1330         int                     level,
1331         int                     *stat)          /* success/failure */
1332 {
1333         int                     error;          /* error return value */
1334 #ifdef XFS_BMBT_TRACE
1335         static char             fname[] = "xfs_bmbt_rshift";
1336 #endif
1337         int                     i;              /* loop counter */
1338         xfs_bmbt_key_t          key;            /* bmap btree key */
1339         xfs_buf_t               *lbp;           /* left buffer pointer */
1340         xfs_bmbt_block_t        *left;          /* left btree block */
1341         xfs_bmbt_key_t          *lkp;           /* left btree key */
1342         xfs_bmbt_ptr_t          *lpp;           /* left address pointer */
1343         xfs_bmbt_rec_t          *lrp;           /* left record pointer */
1344         xfs_mount_t             *mp;            /* file system mount point */
1345         xfs_buf_t               *rbp;           /* right buffer pointer */
1346         xfs_bmbt_block_t        *right;         /* right btree block */
1347         xfs_bmbt_key_t          *rkp;           /* right btree key */
1348         xfs_bmbt_ptr_t          *rpp;           /* right address pointer */
1349         xfs_bmbt_rec_t          *rrp=NULL;      /* right record pointer */
1350         struct xfs_btree_cur    *tcur;          /* temporary btree cursor */
1351
1352         XFS_BMBT_TRACE_CURSOR(cur, ENTRY);
1353         XFS_BMBT_TRACE_ARGI(cur, level);
1354         if (level == cur->bc_nlevels - 1) {
1355                 XFS_BMBT_TRACE_CURSOR(cur, EXIT);
1356                 *stat = 0;
1357                 return 0;
1358         }
1359         lbp = cur->bc_bufs[level];
1360         left = XFS_BUF_TO_BMBT_BLOCK(lbp);
1361 #ifdef DEBUG
1362         if ((error = xfs_btree_check_lblock(cur, left, level, lbp))) {
1363                 XFS_BMBT_TRACE_CURSOR(cur, ERROR);
1364                 return error;
1365         }
1366 #endif
1367         if (be64_to_cpu(left->bb_rightsib) == NULLDFSBNO) {
1368                 XFS_BMBT_TRACE_CURSOR(cur, EXIT);
1369                 *stat = 0;
1370                 return 0;
1371         }
1372         if (cur->bc_ptrs[level] >= be16_to_cpu(left->bb_numrecs)) {
1373                 XFS_BMBT_TRACE_CURSOR(cur, EXIT);
1374                 *stat = 0;
1375                 return 0;
1376         }
1377         mp = cur->bc_mp;
1378         if ((error = xfs_btree_read_bufl(mp, cur->bc_tp, be64_to_cpu(left->bb_rightsib), 0,
1379                         &rbp, XFS_BMAP_BTREE_REF))) {
1380                 XFS_BMBT_TRACE_CURSOR(cur, ERROR);
1381                 return error;
1382         }
1383         right = XFS_BUF_TO_BMBT_BLOCK(rbp);
1384         if ((error = xfs_btree_check_lblock(cur, right, level, rbp))) {
1385                 XFS_BMBT_TRACE_CURSOR(cur, ERROR);
1386                 return error;
1387         }
1388         if (be16_to_cpu(right->bb_numrecs) == XFS_BMAP_BLOCK_IMAXRECS(level, cur)) {
1389                 XFS_BMBT_TRACE_CURSOR(cur, EXIT);
1390                 *stat = 0;
1391                 return 0;
1392         }
1393         if (level > 0) {
1394                 lkp = XFS_BMAP_KEY_IADDR(left, be16_to_cpu(left->bb_numrecs), cur);
1395                 lpp = XFS_BMAP_PTR_IADDR(left, be16_to_cpu(left->bb_numrecs), cur);
1396                 rkp = XFS_BMAP_KEY_IADDR(right, 1, cur);
1397                 rpp = XFS_BMAP_PTR_IADDR(right, 1, cur);
1398 #ifdef DEBUG
1399                 for (i = be16_to_cpu(right->bb_numrecs) - 1; i >= 0; i--) {
1400                         if ((error = xfs_btree_check_lptr_disk(cur, rpp[i], level))) {
1401                                 XFS_BMBT_TRACE_CURSOR(cur, ERROR);
1402                                 return error;
1403                         }
1404                 }
1405 #endif
1406                 memmove(rkp + 1, rkp, be16_to_cpu(right->bb_numrecs) * sizeof(*rkp));
1407                 memmove(rpp + 1, rpp, be16_to_cpu(right->bb_numrecs) * sizeof(*rpp));
1408 #ifdef DEBUG
1409                 if ((error = xfs_btree_check_lptr_disk(cur, *lpp, level))) {
1410                         XFS_BMBT_TRACE_CURSOR(cur, ERROR);
1411                         return error;
1412                 }
1413 #endif
1414                 *rkp = *lkp;
1415                 *rpp = *lpp; /* INT_: direct copy */
1416                 xfs_bmbt_log_keys(cur, rbp, 1, be16_to_cpu(right->bb_numrecs) + 1);
1417                 xfs_bmbt_log_ptrs(cur, rbp, 1, be16_to_cpu(right->bb_numrecs) + 1);
1418         } else {
1419                 lrp = XFS_BMAP_REC_IADDR(left, be16_to_cpu(left->bb_numrecs), cur);
1420                 rrp = XFS_BMAP_REC_IADDR(right, 1, cur);
1421                 memmove(rrp + 1, rrp, be16_to_cpu(right->bb_numrecs) * sizeof(*rrp));
1422                 *rrp = *lrp;
1423                 xfs_bmbt_log_recs(cur, rbp, 1, be16_to_cpu(right->bb_numrecs) + 1);
1424                 key.br_startoff = cpu_to_be64(xfs_bmbt_disk_get_startoff(rrp));
1425                 rkp = &key;
1426         }
1427         be16_add(&left->bb_numrecs, -1);
1428         xfs_bmbt_log_block(cur, lbp, XFS_BB_NUMRECS);
1429         be16_add(&right->bb_numrecs, 1);
1430 #ifdef DEBUG
1431         if (level > 0)
1432                 xfs_btree_check_key(XFS_BTNUM_BMAP, rkp, rkp + 1);
1433         else
1434                 xfs_btree_check_rec(XFS_BTNUM_BMAP, rrp, rrp + 1);
1435 #endif
1436         xfs_bmbt_log_block(cur, rbp, XFS_BB_NUMRECS);
1437         if ((error = xfs_btree_dup_cursor(cur, &tcur))) {
1438                 XFS_BMBT_TRACE_CURSOR(cur, ERROR);
1439                 return error;
1440         }
1441         i = xfs_btree_lastrec(tcur, level);
1442         XFS_WANT_CORRUPTED_GOTO(i == 1, error0);
1443         if ((error = xfs_bmbt_increment(tcur, level, &i))) {
1444                 XFS_BMBT_TRACE_CURSOR(tcur, ERROR);
1445                 goto error1;
1446         }
1447         XFS_WANT_CORRUPTED_GOTO(i == 1, error0);
1448         if ((error = xfs_bmbt_updkey(tcur, rkp, level + 1))) {
1449                 XFS_BMBT_TRACE_CURSOR(tcur, ERROR);
1450                 goto error1;
1451         }
1452         xfs_btree_del_cursor(tcur, XFS_BTREE_NOERROR);
1453         XFS_BMBT_TRACE_CURSOR(cur, EXIT);
1454         *stat = 1;
1455         return 0;
1456 error0:
1457         XFS_BMBT_TRACE_CURSOR(cur, ERROR);
1458 error1:
1459         xfs_btree_del_cursor(tcur, XFS_BTREE_ERROR);
1460         return error;
1461 }
1462
1463 /*
1464  * Determine the extent state.
1465  */
1466 /* ARGSUSED */
1467 STATIC xfs_exntst_t
1468 xfs_extent_state(
1469         xfs_filblks_t           blks,
1470         int                     extent_flag)
1471 {
1472         if (extent_flag) {
1473                 ASSERT(blks != 0);      /* saved for DMIG */
1474                 return XFS_EXT_UNWRITTEN;
1475         }
1476         return XFS_EXT_NORM;
1477 }
1478
1479
1480 /*
1481  * Split cur/level block in half.
1482  * Return new block number and its first record (to be inserted into parent).
1483  */
1484 STATIC int                                      /* error */
1485 xfs_bmbt_split(
1486         xfs_btree_cur_t         *cur,
1487         int                     level,
1488         xfs_fsblock_t           *bnop,
1489         __uint64_t              *startoff,
1490         xfs_btree_cur_t         **curp,
1491         int                     *stat)          /* success/failure */
1492 {
1493         xfs_alloc_arg_t         args;           /* block allocation args */
1494         int                     error;          /* error return value */
1495 #ifdef XFS_BMBT_TRACE
1496         static char             fname[] = "xfs_bmbt_split";
1497 #endif
1498         int                     i;              /* loop counter */
1499         xfs_fsblock_t           lbno;           /* left sibling block number */
1500         xfs_buf_t               *lbp;           /* left buffer pointer */
1501         xfs_bmbt_block_t        *left;          /* left btree block */
1502         xfs_bmbt_key_t          *lkp;           /* left btree key */
1503         xfs_bmbt_ptr_t          *lpp;           /* left address pointer */
1504         xfs_bmbt_rec_t          *lrp;           /* left record pointer */
1505         xfs_buf_t               *rbp;           /* right buffer pointer */
1506         xfs_bmbt_block_t        *right;         /* right btree block */
1507         xfs_bmbt_key_t          *rkp;           /* right btree key */
1508         xfs_bmbt_ptr_t          *rpp;           /* right address pointer */
1509         xfs_bmbt_block_t        *rrblock;       /* right-right btree block */
1510         xfs_buf_t               *rrbp;          /* right-right buffer pointer */
1511         xfs_bmbt_rec_t          *rrp;           /* right record pointer */
1512
1513         XFS_BMBT_TRACE_CURSOR(cur, ENTRY);
1514         XFS_BMBT_TRACE_ARGIFK(cur, level, *bnop, *startoff);
1515         args.tp = cur->bc_tp;
1516         args.mp = cur->bc_mp;
1517         lbp = cur->bc_bufs[level];
1518         lbno = XFS_DADDR_TO_FSB(args.mp, XFS_BUF_ADDR(lbp));
1519         left = XFS_BUF_TO_BMBT_BLOCK(lbp);
1520         args.fsbno = cur->bc_private.b.firstblock;
1521         args.firstblock = args.fsbno;
1522         if (args.fsbno == NULLFSBLOCK) {
1523                 args.fsbno = lbno;
1524                 args.type = XFS_ALLOCTYPE_START_BNO;
1525         } else
1526                 args.type = XFS_ALLOCTYPE_NEAR_BNO;
1527         args.mod = args.minleft = args.alignment = args.total = args.isfl =
1528                 args.userdata = args.minalignslop = 0;
1529         args.minlen = args.maxlen = args.prod = 1;
1530         args.wasdel = cur->bc_private.b.flags & XFS_BTCUR_BPRV_WASDEL;
1531         if (!args.wasdel && xfs_trans_get_block_res(args.tp) == 0) {
1532                 XFS_BMBT_TRACE_CURSOR(cur, ERROR);
1533                 return XFS_ERROR(ENOSPC);
1534         }
1535         if ((error = xfs_alloc_vextent(&args))) {
1536                 XFS_BMBT_TRACE_CURSOR(cur, ERROR);
1537                 return error;
1538         }
1539         if (args.fsbno == NULLFSBLOCK) {
1540                 XFS_BMBT_TRACE_CURSOR(cur, EXIT);
1541                 *stat = 0;
1542                 return 0;
1543         }
1544         ASSERT(args.len == 1);
1545         cur->bc_private.b.firstblock = args.fsbno;
1546         cur->bc_private.b.allocated++;
1547         cur->bc_private.b.ip->i_d.di_nblocks++;
1548         xfs_trans_log_inode(args.tp, cur->bc_private.b.ip, XFS_ILOG_CORE);
1549         XFS_TRANS_MOD_DQUOT_BYINO(args.mp, args.tp, cur->bc_private.b.ip,
1550                         XFS_TRANS_DQ_BCOUNT, 1L);
1551         rbp = xfs_btree_get_bufl(args.mp, args.tp, args.fsbno, 0);
1552         right = XFS_BUF_TO_BMBT_BLOCK(rbp);
1553 #ifdef DEBUG
1554         if ((error = xfs_btree_check_lblock(cur, left, level, rbp))) {
1555                 XFS_BMBT_TRACE_CURSOR(cur, ERROR);
1556                 return error;
1557         }
1558 #endif
1559         right->bb_magic = cpu_to_be32(XFS_BMAP_MAGIC);
1560         right->bb_level = left->bb_level;
1561         right->bb_numrecs = cpu_to_be16(be16_to_cpu(left->bb_numrecs) / 2);
1562         if ((be16_to_cpu(left->bb_numrecs) & 1) &&
1563             cur->bc_ptrs[level] <= be16_to_cpu(right->bb_numrecs) + 1)
1564                 be16_add(&right->bb_numrecs, 1);
1565         i = be16_to_cpu(left->bb_numrecs) - be16_to_cpu(right->bb_numrecs) + 1;
1566         if (level > 0) {
1567                 lkp = XFS_BMAP_KEY_IADDR(left, i, cur);
1568                 lpp = XFS_BMAP_PTR_IADDR(left, i, cur);
1569                 rkp = XFS_BMAP_KEY_IADDR(right, 1, cur);
1570                 rpp = XFS_BMAP_PTR_IADDR(right, 1, cur);
1571 #ifdef DEBUG
1572                 for (i = 0; i < be16_to_cpu(right->bb_numrecs); i++) {
1573                         if ((error = xfs_btree_check_lptr_disk(cur, lpp[i], level))) {
1574                                 XFS_BMBT_TRACE_CURSOR(cur, ERROR);
1575                                 return error;
1576                         }
1577                 }
1578 #endif
1579                 memcpy(rkp, lkp, be16_to_cpu(right->bb_numrecs) * sizeof(*rkp));
1580                 memcpy(rpp, lpp, be16_to_cpu(right->bb_numrecs) * sizeof(*rpp));
1581                 xfs_bmbt_log_keys(cur, rbp, 1, be16_to_cpu(right->bb_numrecs));
1582                 xfs_bmbt_log_ptrs(cur, rbp, 1, be16_to_cpu(right->bb_numrecs));
1583                 *startoff = be64_to_cpu(rkp->br_startoff);
1584         } else {
1585                 lrp = XFS_BMAP_REC_IADDR(left, i, cur);
1586                 rrp = XFS_BMAP_REC_IADDR(right, 1, cur);
1587                 memcpy(rrp, lrp, be16_to_cpu(right->bb_numrecs) * sizeof(*rrp));
1588                 xfs_bmbt_log_recs(cur, rbp, 1, be16_to_cpu(right->bb_numrecs));
1589                 *startoff = xfs_bmbt_disk_get_startoff(rrp);
1590         }
1591         be16_add(&left->bb_numrecs, -(be16_to_cpu(right->bb_numrecs)));
1592         right->bb_rightsib = left->bb_rightsib;
1593         left->bb_rightsib = cpu_to_be64(args.fsbno);
1594         right->bb_leftsib = cpu_to_be64(lbno);
1595         xfs_bmbt_log_block(cur, rbp, XFS_BB_ALL_BITS);
1596         xfs_bmbt_log_block(cur, lbp, XFS_BB_NUMRECS | XFS_BB_RIGHTSIB);
1597         if (be64_to_cpu(right->bb_rightsib) != NULLDFSBNO) {
1598                 if ((error = xfs_btree_read_bufl(args.mp, args.tp,
1599                                 be64_to_cpu(right->bb_rightsib), 0, &rrbp,
1600                                 XFS_BMAP_BTREE_REF))) {
1601                         XFS_BMBT_TRACE_CURSOR(cur, ERROR);
1602                         return error;
1603                 }
1604                 rrblock = XFS_BUF_TO_BMBT_BLOCK(rrbp);
1605                 if ((error = xfs_btree_check_lblock(cur, rrblock, level, rrbp))) {
1606                         XFS_BMBT_TRACE_CURSOR(cur, ERROR);
1607                         return error;
1608                 }
1609                 rrblock->bb_leftsib = cpu_to_be64(args.fsbno);
1610                 xfs_bmbt_log_block(cur, rrbp, XFS_BB_LEFTSIB);
1611         }
1612         if (cur->bc_ptrs[level] > be16_to_cpu(left->bb_numrecs) + 1) {
1613                 xfs_btree_setbuf(cur, level, rbp);
1614                 cur->bc_ptrs[level] -= be16_to_cpu(left->bb_numrecs);
1615         }
1616         if (level + 1 < cur->bc_nlevels) {
1617                 if ((error = xfs_btree_dup_cursor(cur, curp))) {
1618                         XFS_BMBT_TRACE_CURSOR(cur, ERROR);
1619                         return error;
1620                 }
1621                 (*curp)->bc_ptrs[level + 1]++;
1622         }
1623         *bnop = args.fsbno;
1624         XFS_BMBT_TRACE_CURSOR(cur, EXIT);
1625         *stat = 1;
1626         return 0;
1627 }
1628
1629
1630 /*
1631  * Update keys for the record.
1632  */
1633 STATIC int
1634 xfs_bmbt_updkey(
1635         xfs_btree_cur_t         *cur,
1636         xfs_bmbt_key_t          *keyp,  /* on-disk format */
1637         int                     level)
1638 {
1639         xfs_bmbt_block_t        *block;
1640         xfs_buf_t               *bp;
1641 #ifdef DEBUG
1642         int                     error;
1643 #endif
1644 #ifdef XFS_BMBT_TRACE
1645         static char             fname[] = "xfs_bmbt_updkey";
1646 #endif
1647         xfs_bmbt_key_t          *kp;
1648         int                     ptr;
1649
1650         ASSERT(level >= 1);
1651         XFS_BMBT_TRACE_CURSOR(cur, ENTRY);
1652         XFS_BMBT_TRACE_ARGIK(cur, level, keyp);
1653         for (ptr = 1; ptr == 1 && level < cur->bc_nlevels; level++) {
1654                 block = xfs_bmbt_get_block(cur, level, &bp);
1655 #ifdef DEBUG
1656                 if ((error = xfs_btree_check_lblock(cur, block, level, bp))) {
1657                         XFS_BMBT_TRACE_CURSOR(cur, ERROR);
1658                         return error;
1659                 }
1660 #endif
1661                 ptr = cur->bc_ptrs[level];
1662                 kp = XFS_BMAP_KEY_IADDR(block, ptr, cur);
1663                 *kp = *keyp;
1664                 xfs_bmbt_log_keys(cur, bp, ptr, ptr);
1665         }
1666         XFS_BMBT_TRACE_CURSOR(cur, EXIT);
1667         return 0;
1668 }
1669
1670 /*
1671  * Convert on-disk form of btree root to in-memory form.
1672  */
1673 void
1674 xfs_bmdr_to_bmbt(
1675         xfs_bmdr_block_t        *dblock,
1676         int                     dblocklen,
1677         xfs_bmbt_block_t        *rblock,
1678         int                     rblocklen)
1679 {
1680         int                     dmxr;
1681         xfs_bmbt_key_t          *fkp;
1682         __be64                  *fpp;
1683         xfs_bmbt_key_t          *tkp;
1684         __be64                  *tpp;
1685
1686         rblock->bb_magic = cpu_to_be32(XFS_BMAP_MAGIC);
1687         rblock->bb_level = dblock->bb_level;
1688         ASSERT(be16_to_cpu(rblock->bb_level) > 0);
1689         rblock->bb_numrecs = dblock->bb_numrecs;
1690         rblock->bb_leftsib = cpu_to_be64(NULLDFSBNO);
1691         rblock->bb_rightsib = cpu_to_be64(NULLDFSBNO);
1692         dmxr = (int)XFS_BTREE_BLOCK_MAXRECS(dblocklen, xfs_bmdr, 0);
1693         fkp = XFS_BTREE_KEY_ADDR(xfs_bmdr, dblock, 1);
1694         tkp = XFS_BMAP_BROOT_KEY_ADDR(rblock, 1, rblocklen);
1695         fpp = XFS_BTREE_PTR_ADDR(xfs_bmdr, dblock, 1, dmxr);
1696         tpp = XFS_BMAP_BROOT_PTR_ADDR(rblock, 1, rblocklen);
1697         dmxr = be16_to_cpu(dblock->bb_numrecs);
1698         memcpy(tkp, fkp, sizeof(*fkp) * dmxr);
1699         memcpy(tpp, fpp, sizeof(*fpp) * dmxr);
1700 }
1701
1702 /*
1703  * Decrement cursor by one record at the level.
1704  * For nonzero levels the leaf-ward information is untouched.
1705  */
1706 int                                             /* error */
1707 xfs_bmbt_decrement(
1708         xfs_btree_cur_t         *cur,
1709         int                     level,
1710         int                     *stat)          /* success/failure */
1711 {
1712         xfs_bmbt_block_t        *block;
1713         xfs_buf_t               *bp;
1714         int                     error;          /* error return value */
1715 #ifdef XFS_BMBT_TRACE
1716         static char             fname[] = "xfs_bmbt_decrement";
1717 #endif
1718         xfs_fsblock_t           fsbno;
1719         int                     lev;
1720         xfs_mount_t             *mp;
1721         xfs_trans_t             *tp;
1722
1723         XFS_BMBT_TRACE_CURSOR(cur, ENTRY);
1724         XFS_BMBT_TRACE_ARGI(cur, level);
1725         ASSERT(level < cur->bc_nlevels);
1726         if (level < cur->bc_nlevels - 1)
1727                 xfs_btree_readahead(cur, level, XFS_BTCUR_LEFTRA);
1728         if (--cur->bc_ptrs[level] > 0) {
1729                 XFS_BMBT_TRACE_CURSOR(cur, EXIT);
1730                 *stat = 1;
1731                 return 0;
1732         }
1733         block = xfs_bmbt_get_block(cur, level, &bp);
1734 #ifdef DEBUG
1735         if ((error = xfs_btree_check_lblock(cur, block, level, bp))) {
1736                 XFS_BMBT_TRACE_CURSOR(cur, ERROR);
1737                 return error;
1738         }
1739 #endif
1740         if (be64_to_cpu(block->bb_leftsib) == NULLDFSBNO) {
1741                 XFS_BMBT_TRACE_CURSOR(cur, EXIT);
1742                 *stat = 0;
1743                 return 0;
1744         }
1745         for (lev = level + 1; lev < cur->bc_nlevels; lev++) {
1746                 if (--cur->bc_ptrs[lev] > 0)
1747                         break;
1748                 if (lev < cur->bc_nlevels - 1)
1749                         xfs_btree_readahead(cur, lev, XFS_BTCUR_LEFTRA);
1750         }
1751         if (lev == cur->bc_nlevels) {
1752                 XFS_BMBT_TRACE_CURSOR(cur, EXIT);
1753                 *stat = 0;
1754                 return 0;
1755         }
1756         tp = cur->bc_tp;
1757         mp = cur->bc_mp;
1758         for (block = xfs_bmbt_get_block(cur, lev, &bp); lev > level; ) {
1759                 fsbno = be64_to_cpu(*XFS_BMAP_PTR_IADDR(block, cur->bc_ptrs[lev], cur));
1760                 if ((error = xfs_btree_read_bufl(mp, tp, fsbno, 0, &bp,
1761                                 XFS_BMAP_BTREE_REF))) {
1762                         XFS_BMBT_TRACE_CURSOR(cur, ERROR);
1763                         return error;
1764                 }
1765                 lev--;
1766                 xfs_btree_setbuf(cur, lev, bp);
1767                 block = XFS_BUF_TO_BMBT_BLOCK(bp);
1768                 if ((error = xfs_btree_check_lblock(cur, block, lev, bp))) {
1769                         XFS_BMBT_TRACE_CURSOR(cur, ERROR);
1770                         return error;
1771                 }
1772                 cur->bc_ptrs[lev] = be16_to_cpu(block->bb_numrecs);
1773         }
1774         XFS_BMBT_TRACE_CURSOR(cur, EXIT);
1775         *stat = 1;
1776         return 0;
1777 }
1778
1779 /*
1780  * Delete the record pointed to by cur.
1781  */
1782 int                                     /* error */
1783 xfs_bmbt_delete(
1784         xfs_btree_cur_t *cur,
1785         int             *stat)          /* success/failure */
1786 {
1787         int             error;          /* error return value */
1788 #ifdef XFS_BMBT_TRACE
1789         static char     fname[] = "xfs_bmbt_delete";
1790 #endif
1791         int             i;
1792         int             level;
1793
1794         XFS_BMBT_TRACE_CURSOR(cur, ENTRY);
1795         for (level = 0, i = 2; i == 2; level++) {
1796                 if ((error = xfs_bmbt_delrec(cur, level, &i))) {
1797                         XFS_BMBT_TRACE_CURSOR(cur, ERROR);
1798                         return error;
1799                 }
1800         }
1801         if (i == 0) {
1802                 for (level = 1; level < cur->bc_nlevels; level++) {
1803                         if (cur->bc_ptrs[level] == 0) {
1804                                 if ((error = xfs_bmbt_decrement(cur, level,
1805                                                 &i))) {
1806                                         XFS_BMBT_TRACE_CURSOR(cur, ERROR);
1807                                         return error;
1808                                 }
1809                                 break;
1810                         }
1811                 }
1812         }
1813         XFS_BMBT_TRACE_CURSOR(cur, EXIT);
1814         *stat = i;
1815         return 0;
1816 }
1817
1818 /*
1819  * Convert a compressed bmap extent record to an uncompressed form.
1820  * This code must be in sync with the routines xfs_bmbt_get_startoff,
1821  * xfs_bmbt_get_startblock, xfs_bmbt_get_blockcount and xfs_bmbt_get_state.
1822  */
1823
1824 STATIC_INLINE void
1825 __xfs_bmbt_get_all(
1826                 __uint64_t l0,
1827                 __uint64_t l1,
1828                 xfs_bmbt_irec_t *s)
1829 {
1830         int     ext_flag;
1831         xfs_exntst_t st;
1832
1833         ext_flag = (int)(l0 >> (64 - BMBT_EXNTFLAG_BITLEN));
1834         s->br_startoff = ((xfs_fileoff_t)l0 &
1835                            XFS_MASK64LO(64 - BMBT_EXNTFLAG_BITLEN)) >> 9;
1836 #if XFS_BIG_BLKNOS
1837         s->br_startblock = (((xfs_fsblock_t)l0 & XFS_MASK64LO(9)) << 43) |
1838                            (((xfs_fsblock_t)l1) >> 21);
1839 #else
1840 #ifdef DEBUG
1841         {
1842                 xfs_dfsbno_t    b;
1843
1844                 b = (((xfs_dfsbno_t)l0 & XFS_MASK64LO(9)) << 43) |
1845                     (((xfs_dfsbno_t)l1) >> 21);
1846                 ASSERT((b >> 32) == 0 || ISNULLDSTARTBLOCK(b));
1847                 s->br_startblock = (xfs_fsblock_t)b;
1848         }
1849 #else   /* !DEBUG */
1850         s->br_startblock = (xfs_fsblock_t)(((xfs_dfsbno_t)l1) >> 21);
1851 #endif  /* DEBUG */
1852 #endif  /* XFS_BIG_BLKNOS */
1853         s->br_blockcount = (xfs_filblks_t)(l1 & XFS_MASK64LO(21));
1854         /* This is xfs_extent_state() in-line */
1855         if (ext_flag) {
1856                 ASSERT(s->br_blockcount != 0);  /* saved for DMIG */
1857                 st = XFS_EXT_UNWRITTEN;
1858         } else
1859                 st = XFS_EXT_NORM;
1860         s->br_state = st;
1861 }
1862
1863 void
1864 xfs_bmbt_get_all(
1865         xfs_bmbt_rec_t  *r,
1866         xfs_bmbt_irec_t *s)
1867 {
1868         __xfs_bmbt_get_all(r->l0, r->l1, s);
1869 }
1870
1871 /*
1872  * Get the block pointer for the given level of the cursor.
1873  * Fill in the buffer pointer, if applicable.
1874  */
1875 xfs_bmbt_block_t *
1876 xfs_bmbt_get_block(
1877         xfs_btree_cur_t         *cur,
1878         int                     level,
1879         xfs_buf_t               **bpp)
1880 {
1881         xfs_ifork_t             *ifp;
1882         xfs_bmbt_block_t        *rval;
1883
1884         if (level < cur->bc_nlevels - 1) {
1885                 *bpp = cur->bc_bufs[level];
1886                 rval = XFS_BUF_TO_BMBT_BLOCK(*bpp);
1887         } else {
1888                 *bpp = NULL;
1889                 ifp = XFS_IFORK_PTR(cur->bc_private.b.ip,
1890                         cur->bc_private.b.whichfork);
1891                 rval = ifp->if_broot;
1892         }
1893         return rval;
1894 }
1895
1896 /*
1897  * Extract the blockcount field from an in memory bmap extent record.
1898  */
1899 xfs_filblks_t
1900 xfs_bmbt_get_blockcount(
1901         xfs_bmbt_rec_t  *r)
1902 {
1903         return (xfs_filblks_t)(r->l1 & XFS_MASK64LO(21));
1904 }
1905
1906 /*
1907  * Extract the startblock field from an in memory bmap extent record.
1908  */
1909 xfs_fsblock_t
1910 xfs_bmbt_get_startblock(
1911         xfs_bmbt_rec_t  *r)
1912 {
1913 #if XFS_BIG_BLKNOS
1914         return (((xfs_fsblock_t)r->l0 & XFS_MASK64LO(9)) << 43) |
1915                (((xfs_fsblock_t)r->l1) >> 21);
1916 #else
1917 #ifdef DEBUG
1918         xfs_dfsbno_t    b;
1919
1920         b = (((xfs_dfsbno_t)r->l0 & XFS_MASK64LO(9)) << 43) |
1921             (((xfs_dfsbno_t)r->l1) >> 21);
1922         ASSERT((b >> 32) == 0 || ISNULLDSTARTBLOCK(b));
1923         return (xfs_fsblock_t)b;
1924 #else   /* !DEBUG */
1925         return (xfs_fsblock_t)(((xfs_dfsbno_t)r->l1) >> 21);
1926 #endif  /* DEBUG */
1927 #endif  /* XFS_BIG_BLKNOS */
1928 }
1929
1930 /*
1931  * Extract the startoff field from an in memory bmap extent record.
1932  */
1933 xfs_fileoff_t
1934 xfs_bmbt_get_startoff(
1935         xfs_bmbt_rec_t  *r)
1936 {
1937         return ((xfs_fileoff_t)r->l0 &
1938                  XFS_MASK64LO(64 - BMBT_EXNTFLAG_BITLEN)) >> 9;
1939 }
1940
1941 xfs_exntst_t
1942 xfs_bmbt_get_state(
1943         xfs_bmbt_rec_t  *r)
1944 {
1945         int     ext_flag;
1946
1947         ext_flag = (int)((r->l0) >> (64 - BMBT_EXNTFLAG_BITLEN));
1948         return xfs_extent_state(xfs_bmbt_get_blockcount(r),
1949                                 ext_flag);
1950 }
1951
1952 #ifndef XFS_NATIVE_HOST
1953 /* Endian flipping versions of the bmbt extraction functions */
1954 void
1955 xfs_bmbt_disk_get_all(
1956         xfs_bmbt_rec_t  *r,
1957         xfs_bmbt_irec_t *s)
1958 {
1959         __uint64_t      l0, l1;
1960
1961         l0 = INT_GET(r->l0, ARCH_CONVERT);
1962         l1 = INT_GET(r->l1, ARCH_CONVERT);
1963
1964         __xfs_bmbt_get_all(l0, l1, s);
1965 }
1966
1967 /*
1968  * Extract the blockcount field from an on disk bmap extent record.
1969  */
1970 xfs_filblks_t
1971 xfs_bmbt_disk_get_blockcount(
1972         xfs_bmbt_rec_t  *r)
1973 {
1974         return (xfs_filblks_t)(INT_GET(r->l1, ARCH_CONVERT) & XFS_MASK64LO(21));
1975 }
1976
1977 /*
1978  * Extract the startoff field from a disk format bmap extent record.
1979  */
1980 xfs_fileoff_t
1981 xfs_bmbt_disk_get_startoff(
1982         xfs_bmbt_rec_t  *r)
1983 {
1984         return ((xfs_fileoff_t)INT_GET(r->l0, ARCH_CONVERT) &
1985                  XFS_MASK64LO(64 - BMBT_EXNTFLAG_BITLEN)) >> 9;
1986 }
1987 #endif /* XFS_NATIVE_HOST */
1988
1989
1990 /*
1991  * Increment cursor by one record at the level.
1992  * For nonzero levels the leaf-ward information is untouched.
1993  */
1994 int                                             /* error */
1995 xfs_bmbt_increment(
1996         xfs_btree_cur_t         *cur,
1997         int                     level,
1998         int                     *stat)          /* success/failure */
1999 {
2000         xfs_bmbt_block_t        *block;
2001         xfs_buf_t               *bp;
2002         int                     error;          /* error return value */
2003 #ifdef XFS_BMBT_TRACE
2004         static char             fname[] = "xfs_bmbt_increment";
2005 #endif
2006         xfs_fsblock_t           fsbno;
2007         int                     lev;
2008         xfs_mount_t             *mp;
2009         xfs_trans_t             *tp;
2010
2011         XFS_BMBT_TRACE_CURSOR(cur, ENTRY);
2012         XFS_BMBT_TRACE_ARGI(cur, level);
2013         ASSERT(level < cur->bc_nlevels);
2014         if (level < cur->bc_nlevels - 1)
2015                 xfs_btree_readahead(cur, level, XFS_BTCUR_RIGHTRA);
2016         block = xfs_bmbt_get_block(cur, level, &bp);
2017 #ifdef DEBUG
2018         if ((error = xfs_btree_check_lblock(cur, block, level, bp))) {
2019                 XFS_BMBT_TRACE_CURSOR(cur, ERROR);
2020                 return error;
2021         }
2022 #endif
2023         if (++cur->bc_ptrs[level] <= be16_to_cpu(block->bb_numrecs)) {
2024                 XFS_BMBT_TRACE_CURSOR(cur, EXIT);
2025                 *stat = 1;
2026                 return 0;
2027         }
2028         if (be64_to_cpu(block->bb_rightsib) == NULLDFSBNO) {
2029                 XFS_BMBT_TRACE_CURSOR(cur, EXIT);
2030                 *stat = 0;
2031                 return 0;
2032         }
2033         for (lev = level + 1; lev < cur->bc_nlevels; lev++) {
2034                 block = xfs_bmbt_get_block(cur, lev, &bp);
2035 #ifdef DEBUG
2036                 if ((error = xfs_btree_check_lblock(cur, block, lev, bp))) {
2037                         XFS_BMBT_TRACE_CURSOR(cur, ERROR);
2038                         return error;
2039                 }
2040 #endif
2041                 if (++cur->bc_ptrs[lev] <= be16_to_cpu(block->bb_numrecs))
2042                         break;
2043                 if (lev < cur->bc_nlevels - 1)
2044                         xfs_btree_readahead(cur, lev, XFS_BTCUR_RIGHTRA);
2045         }
2046         if (lev == cur->bc_nlevels) {
2047                 XFS_BMBT_TRACE_CURSOR(cur, EXIT);
2048                 *stat = 0;
2049                 return 0;
2050         }
2051         tp = cur->bc_tp;
2052         mp = cur->bc_mp;
2053         for (block = xfs_bmbt_get_block(cur, lev, &bp); lev > level; ) {
2054                 fsbno = be64_to_cpu(*XFS_BMAP_PTR_IADDR(block, cur->bc_ptrs[lev], cur));
2055                 if ((error = xfs_btree_read_bufl(mp, tp, fsbno, 0, &bp,
2056                                 XFS_BMAP_BTREE_REF))) {
2057                         XFS_BMBT_TRACE_CURSOR(cur, ERROR);
2058                         return error;
2059                 }
2060                 lev--;
2061                 xfs_btree_setbuf(cur, lev, bp);
2062                 block = XFS_BUF_TO_BMBT_BLOCK(bp);
2063                 if ((error = xfs_btree_check_lblock(cur, block, lev, bp))) {
2064                         XFS_BMBT_TRACE_CURSOR(cur, ERROR);
2065                         return error;
2066                 }
2067                 cur->bc_ptrs[lev] = 1;
2068         }
2069         XFS_BMBT_TRACE_CURSOR(cur, EXIT);
2070         *stat = 1;
2071         return 0;
2072 }
2073
2074 /*
2075  * Insert the current record at the point referenced by cur.
2076  */
2077 int                                     /* error */
2078 xfs_bmbt_insert(
2079         xfs_btree_cur_t *cur,
2080         int             *stat)          /* success/failure */
2081 {
2082         int             error;          /* error return value */
2083 #ifdef XFS_BMBT_TRACE
2084         static char     fname[] = "xfs_bmbt_insert";
2085 #endif
2086         int             i;
2087         int             level;
2088         xfs_fsblock_t   nbno;
2089         xfs_btree_cur_t *ncur;
2090         xfs_bmbt_rec_t  nrec;
2091         xfs_btree_cur_t *pcur;
2092
2093         XFS_BMBT_TRACE_CURSOR(cur, ENTRY);
2094         level = 0;
2095         nbno = NULLFSBLOCK;
2096         xfs_bmbt_disk_set_all(&nrec, &cur->bc_rec.b);
2097         ncur = NULL;
2098         pcur = cur;
2099         do {
2100                 if ((error = xfs_bmbt_insrec(pcur, level++, &nbno, &nrec, &ncur,
2101                                 &i))) {
2102                         if (pcur != cur)
2103                                 xfs_btree_del_cursor(pcur, XFS_BTREE_ERROR);
2104                         XFS_BMBT_TRACE_CURSOR(cur, ERROR);
2105                         return error;
2106                 }
2107                 XFS_WANT_CORRUPTED_GOTO(i == 1, error0);
2108                 if (pcur != cur && (ncur || nbno == NULLFSBLOCK)) {
2109                         cur->bc_nlevels = pcur->bc_nlevels;
2110                         cur->bc_private.b.allocated +=
2111                                 pcur->bc_private.b.allocated;
2112                         pcur->bc_private.b.allocated = 0;
2113                         ASSERT((cur->bc_private.b.firstblock != NULLFSBLOCK) ||
2114                                (cur->bc_private.b.ip->i_d.di_flags &
2115                                 XFS_DIFLAG_REALTIME));
2116                         cur->bc_private.b.firstblock =
2117                                 pcur->bc_private.b.firstblock;
2118                         ASSERT(cur->bc_private.b.flist ==
2119                                pcur->bc_private.b.flist);
2120                         xfs_btree_del_cursor(pcur, XFS_BTREE_NOERROR);
2121                 }
2122                 if (ncur) {
2123                         pcur = ncur;
2124                         ncur = NULL;
2125                 }
2126         } while (nbno != NULLFSBLOCK);
2127         XFS_BMBT_TRACE_CURSOR(cur, EXIT);
2128         *stat = i;
2129         return 0;
2130 error0:
2131         XFS_BMBT_TRACE_CURSOR(cur, ERROR);
2132         return error;
2133 }
2134
2135 /*
2136  * Log fields from the btree block header.
2137  */
2138 void
2139 xfs_bmbt_log_block(
2140         xfs_btree_cur_t         *cur,
2141         xfs_buf_t               *bp,
2142         int                     fields)
2143 {
2144         int                     first;
2145 #ifdef XFS_BMBT_TRACE
2146         static char             fname[] = "xfs_bmbt_log_block";
2147 #endif
2148         int                     last;
2149         xfs_trans_t             *tp;
2150         static const short      offsets[] = {
2151                 offsetof(xfs_bmbt_block_t, bb_magic),
2152                 offsetof(xfs_bmbt_block_t, bb_level),
2153                 offsetof(xfs_bmbt_block_t, bb_numrecs),
2154                 offsetof(xfs_bmbt_block_t, bb_leftsib),
2155                 offsetof(xfs_bmbt_block_t, bb_rightsib),
2156                 sizeof(xfs_bmbt_block_t)
2157         };
2158
2159         XFS_BMBT_TRACE_CURSOR(cur, ENTRY);
2160         XFS_BMBT_TRACE_ARGBI(cur, bp, fields);
2161         tp = cur->bc_tp;
2162         if (bp) {
2163                 xfs_btree_offsets(fields, offsets, XFS_BB_NUM_BITS, &first,
2164                                   &last);
2165                 xfs_trans_log_buf(tp, bp, first, last);
2166         } else
2167                 xfs_trans_log_inode(tp, cur->bc_private.b.ip,
2168                         XFS_ILOG_FBROOT(cur->bc_private.b.whichfork));
2169         XFS_BMBT_TRACE_CURSOR(cur, EXIT);
2170 }
2171
2172 /*
2173  * Log record values from the btree block.
2174  */
2175 void
2176 xfs_bmbt_log_recs(
2177         xfs_btree_cur_t         *cur,
2178         xfs_buf_t               *bp,
2179         int                     rfirst,
2180         int                     rlast)
2181 {
2182         xfs_bmbt_block_t        *block;
2183         int                     first;
2184 #ifdef XFS_BMBT_TRACE
2185         static char             fname[] = "xfs_bmbt_log_recs";
2186 #endif
2187         int                     last;
2188         xfs_bmbt_rec_t          *rp;
2189         xfs_trans_t             *tp;
2190
2191         XFS_BMBT_TRACE_CURSOR(cur, ENTRY);
2192         XFS_BMBT_TRACE_ARGBII(cur, bp, rfirst, rlast);
2193         ASSERT(bp);
2194         tp = cur->bc_tp;
2195         block = XFS_BUF_TO_BMBT_BLOCK(bp);
2196         rp = XFS_BMAP_REC_DADDR(block, 1, cur);
2197         first = (int)((xfs_caddr_t)&rp[rfirst - 1] - (xfs_caddr_t)block);
2198         last = (int)(((xfs_caddr_t)&rp[rlast] - 1) - (xfs_caddr_t)block);
2199         xfs_trans_log_buf(tp, bp, first, last);
2200         XFS_BMBT_TRACE_CURSOR(cur, EXIT);
2201 }
2202
2203 int                                     /* error */
2204 xfs_bmbt_lookup_eq(
2205         xfs_btree_cur_t *cur,
2206         xfs_fileoff_t   off,
2207         xfs_fsblock_t   bno,
2208         xfs_filblks_t   len,
2209         int             *stat)          /* success/failure */
2210 {
2211         cur->bc_rec.b.br_startoff = off;
2212         cur->bc_rec.b.br_startblock = bno;
2213         cur->bc_rec.b.br_blockcount = len;
2214         return xfs_bmbt_lookup(cur, XFS_LOOKUP_EQ, stat);
2215 }
2216
2217 int                                     /* error */
2218 xfs_bmbt_lookup_ge(
2219         xfs_btree_cur_t *cur,
2220         xfs_fileoff_t   off,
2221         xfs_fsblock_t   bno,
2222         xfs_filblks_t   len,
2223         int             *stat)          /* success/failure */
2224 {
2225         cur->bc_rec.b.br_startoff = off;
2226         cur->bc_rec.b.br_startblock = bno;
2227         cur->bc_rec.b.br_blockcount = len;
2228         return xfs_bmbt_lookup(cur, XFS_LOOKUP_GE, stat);
2229 }
2230
2231 /*
2232  * Give the bmap btree a new root block.  Copy the old broot contents
2233  * down into a real block and make the broot point to it.
2234  */
2235 int                                             /* error */
2236 xfs_bmbt_newroot(
2237         xfs_btree_cur_t         *cur,           /* btree cursor */
2238         int                     *logflags,      /* logging flags for inode */
2239         int                     *stat)          /* return status - 0 fail */
2240 {
2241         xfs_alloc_arg_t         args;           /* allocation arguments */
2242         xfs_bmbt_block_t        *block;         /* bmap btree block */
2243         xfs_buf_t               *bp;            /* buffer for block */
2244         xfs_bmbt_block_t        *cblock;        /* child btree block */
2245         xfs_bmbt_key_t          *ckp;           /* child key pointer */
2246         xfs_bmbt_ptr_t          *cpp;           /* child ptr pointer */
2247         int                     error;          /* error return code */
2248 #ifdef XFS_BMBT_TRACE
2249         static char             fname[] = "xfs_bmbt_newroot";
2250 #endif
2251 #ifdef DEBUG
2252         int                     i;              /* loop counter */
2253 #endif
2254         xfs_bmbt_key_t          *kp;            /* pointer to bmap btree key */
2255         int                     level;          /* btree level */
2256         xfs_bmbt_ptr_t          *pp;            /* pointer to bmap block addr */
2257
2258         XFS_BMBT_TRACE_CURSOR(cur, ENTRY);
2259         level = cur->bc_nlevels - 1;
2260         block = xfs_bmbt_get_block(cur, level, &bp);
2261         /*
2262          * Copy the root into a real block.
2263          */
2264         args.mp = cur->bc_mp;
2265         pp = XFS_BMAP_PTR_IADDR(block, 1, cur);
2266         args.tp = cur->bc_tp;
2267         args.fsbno = cur->bc_private.b.firstblock;
2268         args.mod = args.minleft = args.alignment = args.total = args.isfl =
2269                 args.userdata = args.minalignslop = 0;
2270         args.minlen = args.maxlen = args.prod = 1;
2271         args.wasdel = cur->bc_private.b.flags & XFS_BTCUR_BPRV_WASDEL;
2272         args.firstblock = args.fsbno;
2273         if (args.fsbno == NULLFSBLOCK) {
2274 #ifdef DEBUG
2275                 if ((error = xfs_btree_check_lptr_disk(cur, *pp, level))) {
2276                         XFS_BMBT_TRACE_CURSOR(cur, ERROR);
2277                         return error;
2278                 }
2279 #endif
2280                 args.fsbno = be64_to_cpu(*pp);
2281                 args.type = XFS_ALLOCTYPE_START_BNO;
2282         } else
2283                 args.type = XFS_ALLOCTYPE_NEAR_BNO;
2284         if ((error = xfs_alloc_vextent(&args))) {
2285                 XFS_BMBT_TRACE_CURSOR(cur, ERROR);
2286                 return error;
2287         }
2288         if (args.fsbno == NULLFSBLOCK) {
2289                 XFS_BMBT_TRACE_CURSOR(cur, EXIT);
2290                 *stat = 0;
2291                 return 0;
2292         }
2293         ASSERT(args.len == 1);
2294         cur->bc_private.b.firstblock = args.fsbno;
2295         cur->bc_private.b.allocated++;
2296         cur->bc_private.b.ip->i_d.di_nblocks++;
2297         XFS_TRANS_MOD_DQUOT_BYINO(args.mp, args.tp, cur->bc_private.b.ip,
2298                           XFS_TRANS_DQ_BCOUNT, 1L);
2299         bp = xfs_btree_get_bufl(args.mp, cur->bc_tp, args.fsbno, 0);
2300         cblock = XFS_BUF_TO_BMBT_BLOCK(bp);
2301         *cblock = *block;
2302         be16_add(&block->bb_level, 1);
2303         block->bb_numrecs = cpu_to_be16(1);
2304         cur->bc_nlevels++;
2305         cur->bc_ptrs[level + 1] = 1;
2306         kp = XFS_BMAP_KEY_IADDR(block, 1, cur);
2307         ckp = XFS_BMAP_KEY_IADDR(cblock, 1, cur);
2308         memcpy(ckp, kp, be16_to_cpu(cblock->bb_numrecs) * sizeof(*kp));
2309         cpp = XFS_BMAP_PTR_IADDR(cblock, 1, cur);
2310 #ifdef DEBUG
2311         for (i = 0; i < be16_to_cpu(cblock->bb_numrecs); i++) {
2312                 if ((error = xfs_btree_check_lptr_disk(cur, pp[i], level))) {
2313                         XFS_BMBT_TRACE_CURSOR(cur, ERROR);
2314                         return error;
2315                 }
2316         }
2317 #endif
2318         memcpy(cpp, pp, be16_to_cpu(cblock->bb_numrecs) * sizeof(*pp));
2319 #ifdef DEBUG
2320         if ((error = xfs_btree_check_lptr(cur, args.fsbno, level))) {
2321                 XFS_BMBT_TRACE_CURSOR(cur, ERROR);
2322                 return error;
2323         }
2324 #endif
2325         *pp = cpu_to_be64(args.fsbno);
2326         xfs_iroot_realloc(cur->bc_private.b.ip, 1 - be16_to_cpu(cblock->bb_numrecs),
2327                 cur->bc_private.b.whichfork);
2328         xfs_btree_setbuf(cur, level, bp);
2329         /*
2330          * Do all this logging at the end so that
2331          * the root is at the right level.
2332          */
2333         xfs_bmbt_log_block(cur, bp, XFS_BB_ALL_BITS);
2334         xfs_bmbt_log_keys(cur, bp, 1, be16_to_cpu(cblock->bb_numrecs));
2335         xfs_bmbt_log_ptrs(cur, bp, 1, be16_to_cpu(cblock->bb_numrecs));
2336         XFS_BMBT_TRACE_CURSOR(cur, EXIT);
2337         *logflags |=
2338                 XFS_ILOG_CORE | XFS_ILOG_FBROOT(cur->bc_private.b.whichfork);
2339         *stat = 1;
2340         return 0;
2341 }
2342
2343 /*
2344  * Set all the fields in a bmap extent record from the uncompressed form.
2345  */
2346 void
2347 xfs_bmbt_set_all(
2348         xfs_bmbt_rec_t  *r,
2349         xfs_bmbt_irec_t *s)
2350 {
2351         int     extent_flag;
2352
2353         ASSERT((s->br_state == XFS_EXT_NORM) ||
2354                 (s->br_state == XFS_EXT_UNWRITTEN));
2355         extent_flag = (s->br_state == XFS_EXT_NORM) ? 0 : 1;
2356         ASSERT((s->br_startoff & XFS_MASK64HI(9)) == 0);
2357         ASSERT((s->br_blockcount & XFS_MASK64HI(43)) == 0);
2358 #if XFS_BIG_BLKNOS
2359         ASSERT((s->br_startblock & XFS_MASK64HI(12)) == 0);
2360         r->l0 = ((xfs_bmbt_rec_base_t)extent_flag << 63) |
2361                  ((xfs_bmbt_rec_base_t)s->br_startoff << 9) |
2362                  ((xfs_bmbt_rec_base_t)s->br_startblock >> 43);
2363         r->l1 = ((xfs_bmbt_rec_base_t)s->br_startblock << 21) |
2364                  ((xfs_bmbt_rec_base_t)s->br_blockcount &
2365                  (xfs_bmbt_rec_base_t)XFS_MASK64LO(21));
2366 #else   /* !XFS_BIG_BLKNOS */
2367         if (ISNULLSTARTBLOCK(s->br_startblock)) {
2368                 r->l0 = ((xfs_bmbt_rec_base_t)extent_flag << 63) |
2369                         ((xfs_bmbt_rec_base_t)s->br_startoff << 9) |
2370                           (xfs_bmbt_rec_base_t)XFS_MASK64LO(9);
2371                 r->l1 = XFS_MASK64HI(11) |
2372                           ((xfs_bmbt_rec_base_t)s->br_startblock << 21) |
2373                           ((xfs_bmbt_rec_base_t)s->br_blockcount &
2374                            (xfs_bmbt_rec_base_t)XFS_MASK64LO(21));
2375         } else {
2376                 r->l0 = ((xfs_bmbt_rec_base_t)extent_flag << 63) |
2377                         ((xfs_bmbt_rec_base_t)s->br_startoff << 9);
2378                 r->l1 = ((xfs_bmbt_rec_base_t)s->br_startblock << 21) |
2379                           ((xfs_bmbt_rec_base_t)s->br_blockcount &
2380                            (xfs_bmbt_rec_base_t)XFS_MASK64LO(21));
2381         }
2382 #endif  /* XFS_BIG_BLKNOS */
2383 }
2384
2385 /*
2386  * Set all the fields in a bmap extent record from the arguments.
2387  */
2388 void
2389 xfs_bmbt_set_allf(
2390         xfs_bmbt_rec_t  *r,
2391         xfs_fileoff_t   o,
2392         xfs_fsblock_t   b,
2393         xfs_filblks_t   c,
2394         xfs_exntst_t    v)
2395 {
2396         int     extent_flag;
2397
2398         ASSERT((v == XFS_EXT_NORM) || (v == XFS_EXT_UNWRITTEN));
2399         extent_flag = (v == XFS_EXT_NORM) ? 0 : 1;
2400         ASSERT((o & XFS_MASK64HI(64-BMBT_STARTOFF_BITLEN)) == 0);
2401         ASSERT((c & XFS_MASK64HI(64-BMBT_BLOCKCOUNT_BITLEN)) == 0);
2402 #if XFS_BIG_BLKNOS
2403         ASSERT((b & XFS_MASK64HI(64-BMBT_STARTBLOCK_BITLEN)) == 0);
2404         r->l0 = ((xfs_bmbt_rec_base_t)extent_flag << 63) |
2405                 ((xfs_bmbt_rec_base_t)o << 9) |
2406                 ((xfs_bmbt_rec_base_t)b >> 43);
2407         r->l1 = ((xfs_bmbt_rec_base_t)b << 21) |
2408                 ((xfs_bmbt_rec_base_t)c &
2409                 (xfs_bmbt_rec_base_t)XFS_MASK64LO(21));
2410 #else   /* !XFS_BIG_BLKNOS */
2411         if (ISNULLSTARTBLOCK(b)) {
2412                 r->l0 = ((xfs_bmbt_rec_base_t)extent_flag << 63) |
2413                         ((xfs_bmbt_rec_base_t)o << 9) |
2414                          (xfs_bmbt_rec_base_t)XFS_MASK64LO(9);
2415                 r->l1 = XFS_MASK64HI(11) |
2416                           ((xfs_bmbt_rec_base_t)b << 21) |
2417                           ((xfs_bmbt_rec_base_t)c &
2418                            (xfs_bmbt_rec_base_t)XFS_MASK64LO(21));
2419         } else {
2420                 r->l0 = ((xfs_bmbt_rec_base_t)extent_flag << 63) |
2421                         ((xfs_bmbt_rec_base_t)o << 9);
2422                 r->l1 = ((xfs_bmbt_rec_base_t)b << 21) |
2423                          ((xfs_bmbt_rec_base_t)c &
2424                          (xfs_bmbt_rec_base_t)XFS_MASK64LO(21));
2425         }
2426 #endif  /* XFS_BIG_BLKNOS */
2427 }
2428
2429 #ifndef XFS_NATIVE_HOST
2430 /*
2431  * Set all the fields in a bmap extent record from the uncompressed form.
2432  */
2433 void
2434 xfs_bmbt_disk_set_all(
2435         xfs_bmbt_rec_t  *r,
2436         xfs_bmbt_irec_t *s)
2437 {
2438         int     extent_flag;
2439
2440         ASSERT((s->br_state == XFS_EXT_NORM) ||
2441                 (s->br_state == XFS_EXT_UNWRITTEN));
2442         extent_flag = (s->br_state == XFS_EXT_NORM) ? 0 : 1;
2443         ASSERT((s->br_startoff & XFS_MASK64HI(9)) == 0);
2444         ASSERT((s->br_blockcount & XFS_MASK64HI(43)) == 0);
2445 #if XFS_BIG_BLKNOS
2446         ASSERT((s->br_startblock & XFS_MASK64HI(12)) == 0);
2447         INT_SET(r->l0, ARCH_CONVERT, ((xfs_bmbt_rec_base_t)extent_flag << 63) |
2448                   ((xfs_bmbt_rec_base_t)s->br_startoff << 9) |
2449                   ((xfs_bmbt_rec_base_t)s->br_startblock >> 43));
2450         INT_SET(r->l1, ARCH_CONVERT, ((xfs_bmbt_rec_base_t)s->br_startblock << 21) |
2451                   ((xfs_bmbt_rec_base_t)s->br_blockcount &
2452                    (xfs_bmbt_rec_base_t)XFS_MASK64LO(21)));
2453 #else   /* !XFS_BIG_BLKNOS */
2454         if (ISNULLSTARTBLOCK(s->br_startblock)) {
2455                 INT_SET(r->l0, ARCH_CONVERT, ((xfs_bmbt_rec_base_t)extent_flag << 63) |
2456                         ((xfs_bmbt_rec_base_t)s->br_startoff << 9) |
2457                           (xfs_bmbt_rec_base_t)XFS_MASK64LO(9));
2458                 INT_SET(r->l1, ARCH_CONVERT, XFS_MASK64HI(11) |
2459                           ((xfs_bmbt_rec_base_t)s->br_startblock << 21) |
2460                           ((xfs_bmbt_rec_base_t)s->br_blockcount &
2461                            (xfs_bmbt_rec_base_t)XFS_MASK64LO(21)));
2462         } else {
2463                 INT_SET(r->l0, ARCH_CONVERT, ((xfs_bmbt_rec_base_t)extent_flag << 63) |
2464                         ((xfs_bmbt_rec_base_t)s->br_startoff << 9));
2465                 INT_SET(r->l1, ARCH_CONVERT, ((xfs_bmbt_rec_base_t)s->br_startblock << 21) |
2466                           ((xfs_bmbt_rec_base_t)s->br_blockcount &
2467                            (xfs_bmbt_rec_base_t)XFS_MASK64LO(21)));
2468         }
2469 #endif  /* XFS_BIG_BLKNOS */
2470 }
2471
2472 /*
2473  * Set all the fields in a disk format bmap extent record from the arguments.
2474  */
2475 void
2476 xfs_bmbt_disk_set_allf(
2477         xfs_bmbt_rec_t  *r,
2478         xfs_fileoff_t   o,
2479         xfs_fsblock_t   b,
2480         xfs_filblks_t   c,
2481         xfs_exntst_t    v)
2482 {
2483         int     extent_flag;
2484
2485         ASSERT((v == XFS_EXT_NORM) || (v == XFS_EXT_UNWRITTEN));
2486         extent_flag = (v == XFS_EXT_NORM) ? 0 : 1;
2487         ASSERT((o & XFS_MASK64HI(64-BMBT_STARTOFF_BITLEN)) == 0);
2488         ASSERT((c & XFS_MASK64HI(64-BMBT_BLOCKCOUNT_BITLEN)) == 0);
2489 #if XFS_BIG_BLKNOS
2490         ASSERT((b & XFS_MASK64HI(64-BMBT_STARTBLOCK_BITLEN)) == 0);
2491         INT_SET(r->l0, ARCH_CONVERT, ((xfs_bmbt_rec_base_t)extent_flag << 63) |
2492                 ((xfs_bmbt_rec_base_t)o << 9) |
2493                 ((xfs_bmbt_rec_base_t)b >> 43));
2494         INT_SET(r->l1, ARCH_CONVERT, ((xfs_bmbt_rec_base_t)b << 21) |
2495                   ((xfs_bmbt_rec_base_t)c &
2496                    (xfs_bmbt_rec_base_t)XFS_MASK64LO(21)));
2497 #else   /* !XFS_BIG_BLKNOS */
2498         if (ISNULLSTARTBLOCK(b)) {
2499                 INT_SET(r->l0, ARCH_CONVERT, ((xfs_bmbt_rec_base_t)extent_flag << 63) |
2500                         ((xfs_bmbt_rec_base_t)o << 9) |
2501                          (xfs_bmbt_rec_base_t)XFS_MASK64LO(9));
2502                 INT_SET(r->l1, ARCH_CONVERT, XFS_MASK64HI(11) |
2503                           ((xfs_bmbt_rec_base_t)b << 21) |
2504                           ((xfs_bmbt_rec_base_t)c &
2505                            (xfs_bmbt_rec_base_t)XFS_MASK64LO(21)));
2506         } else {
2507                 INT_SET(r->l0, ARCH_CONVERT, ((xfs_bmbt_rec_base_t)extent_flag << 63) |
2508                         ((xfs_bmbt_rec_base_t)o << 9));
2509                 INT_SET(r->l1, ARCH_CONVERT, ((xfs_bmbt_rec_base_t)b << 21) |
2510                           ((xfs_bmbt_rec_base_t)c &
2511                            (xfs_bmbt_rec_base_t)XFS_MASK64LO(21)));
2512         }
2513 #endif  /* XFS_BIG_BLKNOS */
2514 }
2515 #endif /* XFS_NATIVE_HOST */
2516
2517 /*
2518  * Set the blockcount field in a bmap extent record.
2519  */
2520 void
2521 xfs_bmbt_set_blockcount(
2522         xfs_bmbt_rec_t  *r,
2523         xfs_filblks_t   v)
2524 {
2525         ASSERT((v & XFS_MASK64HI(43)) == 0);
2526         r->l1 = (r->l1 & (xfs_bmbt_rec_base_t)XFS_MASK64HI(43)) |
2527                   (xfs_bmbt_rec_base_t)(v & XFS_MASK64LO(21));
2528 }
2529
2530 /*
2531  * Set the startblock field in a bmap extent record.
2532  */
2533 void
2534 xfs_bmbt_set_startblock(
2535         xfs_bmbt_rec_t  *r,
2536         xfs_fsblock_t   v)
2537 {
2538 #if XFS_BIG_BLKNOS
2539         ASSERT((v & XFS_MASK64HI(12)) == 0);
2540         r->l0 = (r->l0 & (xfs_bmbt_rec_base_t)XFS_MASK64HI(55)) |
2541                   (xfs_bmbt_rec_base_t)(v >> 43);
2542         r->l1 = (r->l1 & (xfs_bmbt_rec_base_t)XFS_MASK64LO(21)) |
2543                   (xfs_bmbt_rec_base_t)(v << 21);
2544 #else   /* !XFS_BIG_BLKNOS */
2545         if (ISNULLSTARTBLOCK(v)) {
2546                 r->l0 |= (xfs_bmbt_rec_base_t)XFS_MASK64LO(9);
2547                 r->l1 = (xfs_bmbt_rec_base_t)XFS_MASK64HI(11) |
2548                           ((xfs_bmbt_rec_base_t)v << 21) |
2549                           (r->l1 & (xfs_bmbt_rec_base_t)XFS_MASK64LO(21));
2550         } else {
2551                 r->l0 &= ~(xfs_bmbt_rec_base_t)XFS_MASK64LO(9);
2552                 r->l1 = ((xfs_bmbt_rec_base_t)v << 21) |
2553                           (r->l1 & (xfs_bmbt_rec_base_t)XFS_MASK64LO(21));
2554         }
2555 #endif  /* XFS_BIG_BLKNOS */
2556 }
2557
2558 /*
2559  * Set the startoff field in a bmap extent record.
2560  */
2561 void
2562 xfs_bmbt_set_startoff(
2563         xfs_bmbt_rec_t  *r,
2564         xfs_fileoff_t   v)
2565 {
2566         ASSERT((v & XFS_MASK64HI(9)) == 0);
2567         r->l0 = (r->l0 & (xfs_bmbt_rec_base_t) XFS_MASK64HI(1)) |
2568                 ((xfs_bmbt_rec_base_t)v << 9) |
2569                   (r->l0 & (xfs_bmbt_rec_base_t)XFS_MASK64LO(9));
2570 }
2571
2572 /*
2573  * Set the extent state field in a bmap extent record.
2574  */
2575 void
2576 xfs_bmbt_set_state(
2577         xfs_bmbt_rec_t  *r,
2578         xfs_exntst_t    v)
2579 {
2580         ASSERT(v == XFS_EXT_NORM || v == XFS_EXT_UNWRITTEN);
2581         if (v == XFS_EXT_NORM)
2582                 r->l0 &= XFS_MASK64LO(64 - BMBT_EXNTFLAG_BITLEN);
2583         else
2584                 r->l0 |= XFS_MASK64HI(BMBT_EXNTFLAG_BITLEN);
2585 }
2586
2587 /*
2588  * Convert in-memory form of btree root to on-disk form.
2589  */
2590 void
2591 xfs_bmbt_to_bmdr(
2592         xfs_bmbt_block_t        *rblock,
2593         int                     rblocklen,
2594         xfs_bmdr_block_t        *dblock,
2595         int                     dblocklen)
2596 {
2597         int                     dmxr;
2598         xfs_bmbt_key_t          *fkp;
2599         __be64                  *fpp;
2600         xfs_bmbt_key_t          *tkp;
2601         __be64                  *tpp;
2602
2603         ASSERT(be32_to_cpu(rblock->bb_magic) == XFS_BMAP_MAGIC);
2604         ASSERT(be64_to_cpu(rblock->bb_leftsib) == NULLDFSBNO);
2605         ASSERT(be64_to_cpu(rblock->bb_rightsib) == NULLDFSBNO);
2606         ASSERT(be16_to_cpu(rblock->bb_level) > 0);
2607         dblock->bb_level = rblock->bb_level;
2608         dblock->bb_numrecs = rblock->bb_numrecs;
2609         dmxr = (int)XFS_BTREE_BLOCK_MAXRECS(dblocklen, xfs_bmdr, 0);
2610         fkp = XFS_BMAP_BROOT_KEY_ADDR(rblock, 1, rblocklen);
2611         tkp = XFS_BTREE_KEY_ADDR(xfs_bmdr, dblock, 1);
2612         fpp = XFS_BMAP_BROOT_PTR_ADDR(rblock, 1, rblocklen);
2613         tpp = XFS_BTREE_PTR_ADDR(xfs_bmdr, dblock, 1, dmxr);
2614         dmxr = be16_to_cpu(dblock->bb_numrecs);
2615         memcpy(tkp, fkp, sizeof(*fkp) * dmxr);
2616         memcpy(tpp, fpp, sizeof(*fpp) * dmxr);
2617 }
2618
2619 /*
2620  * Update the record to the passed values.
2621  */
2622 int
2623 xfs_bmbt_update(
2624         xfs_btree_cur_t         *cur,
2625         xfs_fileoff_t           off,
2626         xfs_fsblock_t           bno,
2627         xfs_filblks_t           len,
2628         xfs_exntst_t            state)
2629 {
2630         xfs_bmbt_block_t        *block;
2631         xfs_buf_t               *bp;
2632         int                     error;
2633 #ifdef XFS_BMBT_TRACE
2634         static char             fname[] = "xfs_bmbt_update";
2635 #endif
2636         xfs_bmbt_key_t          key;
2637         int                     ptr;
2638         xfs_bmbt_rec_t          *rp;
2639
2640         XFS_BMBT_TRACE_CURSOR(cur, ENTRY);
2641         XFS_BMBT_TRACE_ARGFFFI(cur, (xfs_dfiloff_t)off, (xfs_dfsbno_t)bno,
2642                 (xfs_dfilblks_t)len, (int)state);
2643         block = xfs_bmbt_get_block(cur, 0, &bp);
2644 #ifdef DEBUG
2645         if ((error = xfs_btree_check_lblock(cur, block, 0, bp))) {
2646                 XFS_BMBT_TRACE_CURSOR(cur, ERROR);
2647                 return error;
2648         }
2649 #endif
2650         ptr = cur->bc_ptrs[0];
2651         rp = XFS_BMAP_REC_IADDR(block, ptr, cur);
2652         xfs_bmbt_disk_set_allf(rp, off, bno, len, state);
2653         xfs_bmbt_log_recs(cur, bp, ptr, ptr);
2654         if (ptr > 1) {
2655                 XFS_BMBT_TRACE_CURSOR(cur, EXIT);
2656                 return 0;
2657         }
2658         key.br_startoff = cpu_to_be64(off);
2659         if ((error = xfs_bmbt_updkey(cur, &key, 1))) {
2660                 XFS_BMBT_TRACE_CURSOR(cur, ERROR);
2661                 return error;
2662         }
2663         XFS_BMBT_TRACE_CURSOR(cur, EXIT);
2664         return 0;
2665 }
2666
2667 /*
2668  * Check extent records, which have just been read, for
2669  * any bit in the extent flag field. ASSERT on debug
2670  * kernels, as this condition should not occur.
2671  * Return an error condition (1) if any flags found,
2672  * otherwise return 0.
2673  */
2674
2675 int
2676 xfs_check_nostate_extents(
2677         xfs_ifork_t             *ifp,
2678         xfs_extnum_t            idx,
2679         xfs_extnum_t            num)
2680 {
2681         xfs_bmbt_rec_t          *ep;
2682
2683         for (; num > 0; num--, idx++) {
2684                 ep = xfs_iext_get_ext(ifp, idx);
2685                 if ((ep->l0 >>
2686                      (64 - BMBT_EXNTFLAG_BITLEN)) != 0) {
2687                         ASSERT(0);
2688                         return 1;
2689                 }
2690         }
2691         return 0;
2692 }