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