[XFS] move xfs_bmbt_killroot to common code
[safe/jmp/linux-2.6] / fs / xfs / xfs_ialloc_btree.c
1 /*
2  * Copyright (c) 2000-2001,2005 Silicon Graphics, Inc.
3  * All Rights Reserved.
4  *
5  * This program is free software; you can redistribute it and/or
6  * modify it under the terms of the GNU General Public License as
7  * published by the Free Software Foundation.
8  *
9  * This program is distributed in the hope that it would be useful,
10  * but WITHOUT ANY WARRANTY; without even the implied warranty of
11  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
12  * GNU General Public License for more details.
13  *
14  * You should have received a copy of the GNU General Public License
15  * along with this program; if not, write the Free Software Foundation,
16  * Inc.,  51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
17  */
18 #include "xfs.h"
19 #include "xfs_fs.h"
20 #include "xfs_types.h"
21 #include "xfs_bit.h"
22 #include "xfs_log.h"
23 #include "xfs_inum.h"
24 #include "xfs_trans.h"
25 #include "xfs_sb.h"
26 #include "xfs_ag.h"
27 #include "xfs_dir2.h"
28 #include "xfs_dmapi.h"
29 #include "xfs_mount.h"
30 #include "xfs_bmap_btree.h"
31 #include "xfs_alloc_btree.h"
32 #include "xfs_ialloc_btree.h"
33 #include "xfs_dir2_sf.h"
34 #include "xfs_attr_sf.h"
35 #include "xfs_dinode.h"
36 #include "xfs_inode.h"
37 #include "xfs_btree.h"
38 #include "xfs_btree_trace.h"
39 #include "xfs_ialloc.h"
40 #include "xfs_alloc.h"
41 #include "xfs_error.h"
42
43 STATIC void xfs_inobt_log_block(xfs_trans_t *, xfs_buf_t *, int);
44 STATIC void xfs_inobt_log_keys(xfs_btree_cur_t *, xfs_buf_t *, int, int);
45 STATIC void xfs_inobt_log_ptrs(xfs_btree_cur_t *, xfs_buf_t *, int, int);
46 STATIC void xfs_inobt_log_recs(xfs_btree_cur_t *, xfs_buf_t *, int, int);
47
48 /*
49  * Single level of the xfs_inobt_delete record deletion routine.
50  * Delete record pointed to by cur/level.
51  * Remove the record from its block then rebalance the tree.
52  * Return 0 for error, 1 for done, 2 to go on to the next level.
53  */
54 STATIC int                              /* error */
55 xfs_inobt_delrec(
56         xfs_btree_cur_t         *cur,   /* btree cursor */
57         int                     level,  /* level removing record from */
58         int                     *stat)  /* fail/done/go-on */
59 {
60         xfs_buf_t               *agbp;  /* buffer for a.g. inode header */
61         xfs_mount_t             *mp;    /* mount structure */
62         xfs_agi_t               *agi;   /* allocation group inode header */
63         xfs_inobt_block_t       *block; /* btree block record/key lives in */
64         xfs_agblock_t           bno;    /* btree block number */
65         xfs_buf_t               *bp;    /* buffer for block */
66         int                     error;  /* error return value */
67         int                     i;      /* loop index */
68         xfs_inobt_key_t         key;    /* kp points here if block is level 0 */
69         xfs_inobt_key_t         *kp = NULL;     /* pointer to btree keys */
70         xfs_agblock_t           lbno;   /* left block's block number */
71         xfs_buf_t               *lbp;   /* left block's buffer pointer */
72         xfs_inobt_block_t       *left;  /* left btree block */
73         xfs_inobt_key_t         *lkp;   /* left block key pointer */
74         xfs_inobt_ptr_t         *lpp;   /* left block address pointer */
75         int                     lrecs = 0;      /* number of records in left block */
76         xfs_inobt_rec_t         *lrp;   /* left block record pointer */
77         xfs_inobt_ptr_t         *pp = NULL;     /* pointer to btree addresses */
78         int                     ptr;    /* index in btree block for this rec */
79         xfs_agblock_t           rbno;   /* right block's block number */
80         xfs_buf_t               *rbp;   /* right block's buffer pointer */
81         xfs_inobt_block_t       *right; /* right btree block */
82         xfs_inobt_key_t         *rkp;   /* right block key pointer */
83         xfs_inobt_rec_t         *rp;    /* pointer to btree records */
84         xfs_inobt_ptr_t         *rpp;   /* right block address pointer */
85         int                     rrecs = 0;      /* number of records in right block */
86         int                     numrecs;
87         xfs_inobt_rec_t         *rrp;   /* right block record pointer */
88         xfs_btree_cur_t         *tcur;  /* temporary btree cursor */
89
90         mp = cur->bc_mp;
91
92         /*
93          * Get the index of the entry being deleted, check for nothing there.
94          */
95         ptr = cur->bc_ptrs[level];
96         if (ptr == 0) {
97                 *stat = 0;
98                 return 0;
99         }
100
101         /*
102          * Get the buffer & block containing the record or key/ptr.
103          */
104         bp = cur->bc_bufs[level];
105         block = XFS_BUF_TO_INOBT_BLOCK(bp);
106 #ifdef DEBUG
107         if ((error = xfs_btree_check_sblock(cur, block, level, bp)))
108                 return error;
109 #endif
110         /*
111          * Fail if we're off the end of the block.
112          */
113
114         numrecs = be16_to_cpu(block->bb_numrecs);
115         if (ptr > numrecs) {
116                 *stat = 0;
117                 return 0;
118         }
119         /*
120          * It's a nonleaf.  Excise the key and ptr being deleted, by
121          * sliding the entries past them down one.
122          * Log the changed areas of the block.
123          */
124         if (level > 0) {
125                 kp = XFS_INOBT_KEY_ADDR(block, 1, cur);
126                 pp = XFS_INOBT_PTR_ADDR(block, 1, cur);
127 #ifdef DEBUG
128                 for (i = ptr; i < numrecs; i++) {
129                         if ((error = xfs_btree_check_sptr(cur, be32_to_cpu(pp[i]), level)))
130                                 return error;
131                 }
132 #endif
133                 if (ptr < numrecs) {
134                         memmove(&kp[ptr - 1], &kp[ptr],
135                                 (numrecs - ptr) * sizeof(*kp));
136                         memmove(&pp[ptr - 1], &pp[ptr],
137                                 (numrecs - ptr) * sizeof(*kp));
138                         xfs_inobt_log_keys(cur, bp, ptr, numrecs - 1);
139                         xfs_inobt_log_ptrs(cur, bp, ptr, numrecs - 1);
140                 }
141         }
142         /*
143          * It's a leaf.  Excise the record being deleted, by sliding the
144          * entries past it down one.  Log the changed areas of the block.
145          */
146         else {
147                 rp = XFS_INOBT_REC_ADDR(block, 1, cur);
148                 if (ptr < numrecs) {
149                         memmove(&rp[ptr - 1], &rp[ptr],
150                                 (numrecs - ptr) * sizeof(*rp));
151                         xfs_inobt_log_recs(cur, bp, ptr, numrecs - 1);
152                 }
153                 /*
154                  * If it's the first record in the block, we'll need a key
155                  * structure to pass up to the next level (updkey).
156                  */
157                 if (ptr == 1) {
158                         key.ir_startino = rp->ir_startino;
159                         kp = &key;
160                 }
161         }
162         /*
163          * Decrement and log the number of entries in the block.
164          */
165         numrecs--;
166         block->bb_numrecs = cpu_to_be16(numrecs);
167         xfs_inobt_log_block(cur->bc_tp, bp, XFS_BB_NUMRECS);
168         /*
169          * Is this the root level?  If so, we're almost done.
170          */
171         if (level == cur->bc_nlevels - 1) {
172                 /*
173                  * If this is the root level,
174                  * and there's only one entry left,
175                  * and it's NOT the leaf level,
176                  * then we can get rid of this level.
177                  */
178                 if (numrecs == 1 && level > 0) {
179                         agbp = cur->bc_private.a.agbp;
180                         agi = XFS_BUF_TO_AGI(agbp);
181                         /*
182                          * pp is still set to the first pointer in the block.
183                          * Make it the new root of the btree.
184                          */
185                         bno = be32_to_cpu(agi->agi_root);
186                         agi->agi_root = *pp;
187                         be32_add_cpu(&agi->agi_level, -1);
188                         /*
189                          * Free the block.
190                          */
191                         if ((error = xfs_free_extent(cur->bc_tp,
192                                 XFS_AGB_TO_FSB(mp, cur->bc_private.a.agno, bno), 1)))
193                                 return error;
194                         xfs_trans_binval(cur->bc_tp, bp);
195                         xfs_ialloc_log_agi(cur->bc_tp, agbp,
196                                 XFS_AGI_ROOT | XFS_AGI_LEVEL);
197                         /*
198                          * Update the cursor so there's one fewer level.
199                          */
200                         cur->bc_bufs[level] = NULL;
201                         cur->bc_nlevels--;
202                 } else if (level > 0 &&
203                            (error = xfs_btree_decrement(cur, level, &i)))
204                         return error;
205                 *stat = 1;
206                 return 0;
207         }
208         /*
209          * If we deleted the leftmost entry in the block, update the
210          * key values above us in the tree.
211          */
212         if (ptr == 1 && (error = xfs_btree_updkey(cur, (union xfs_btree_key *)kp, level + 1)))
213                 return error;
214         /*
215          * If the number of records remaining in the block is at least
216          * the minimum, we're done.
217          */
218         if (numrecs >= XFS_INOBT_BLOCK_MINRECS(level, cur)) {
219                 if (level > 0 &&
220                     (error = xfs_btree_decrement(cur, level, &i)))
221                         return error;
222                 *stat = 1;
223                 return 0;
224         }
225         /*
226          * Otherwise, we have to move some records around to keep the
227          * tree balanced.  Look at the left and right sibling blocks to
228          * see if we can re-balance by moving only one record.
229          */
230         rbno = be32_to_cpu(block->bb_rightsib);
231         lbno = be32_to_cpu(block->bb_leftsib);
232         bno = NULLAGBLOCK;
233         ASSERT(rbno != NULLAGBLOCK || lbno != NULLAGBLOCK);
234         /*
235          * Duplicate the cursor so our btree manipulations here won't
236          * disrupt the next level up.
237          */
238         if ((error = xfs_btree_dup_cursor(cur, &tcur)))
239                 return error;
240         /*
241          * If there's a right sibling, see if it's ok to shift an entry
242          * out of it.
243          */
244         if (rbno != NULLAGBLOCK) {
245                 /*
246                  * Move the temp cursor to the last entry in the next block.
247                  * Actually any entry but the first would suffice.
248                  */
249                 i = xfs_btree_lastrec(tcur, level);
250                 XFS_WANT_CORRUPTED_GOTO(i == 1, error0);
251                 if ((error = xfs_btree_increment(tcur, level, &i)))
252                         goto error0;
253                 XFS_WANT_CORRUPTED_GOTO(i == 1, error0);
254                 i = xfs_btree_lastrec(tcur, level);
255                 XFS_WANT_CORRUPTED_GOTO(i == 1, error0);
256                 /*
257                  * Grab a pointer to the block.
258                  */
259                 rbp = tcur->bc_bufs[level];
260                 right = XFS_BUF_TO_INOBT_BLOCK(rbp);
261 #ifdef DEBUG
262                 if ((error = xfs_btree_check_sblock(cur, right, level, rbp)))
263                         goto error0;
264 #endif
265                 /*
266                  * Grab the current block number, for future use.
267                  */
268                 bno = be32_to_cpu(right->bb_leftsib);
269                 /*
270                  * If right block is full enough so that removing one entry
271                  * won't make it too empty, and left-shifting an entry out
272                  * of right to us works, we're done.
273                  */
274                 if (be16_to_cpu(right->bb_numrecs) - 1 >=
275                      XFS_INOBT_BLOCK_MINRECS(level, cur)) {
276                         if ((error = xfs_btree_lshift(tcur, level, &i)))
277                                 goto error0;
278                         if (i) {
279                                 ASSERT(be16_to_cpu(block->bb_numrecs) >=
280                                        XFS_INOBT_BLOCK_MINRECS(level, cur));
281                                 xfs_btree_del_cursor(tcur,
282                                                      XFS_BTREE_NOERROR);
283                                 if (level > 0 &&
284                                     (error = xfs_btree_decrement(cur, level,
285                                                 &i)))
286                                         return error;
287                                 *stat = 1;
288                                 return 0;
289                         }
290                 }
291                 /*
292                  * Otherwise, grab the number of records in right for
293                  * future reference, and fix up the temp cursor to point
294                  * to our block again (last record).
295                  */
296                 rrecs = be16_to_cpu(right->bb_numrecs);
297                 if (lbno != NULLAGBLOCK) {
298                         xfs_btree_firstrec(tcur, level);
299                         if ((error = xfs_btree_decrement(tcur, level, &i)))
300                                 goto error0;
301                 }
302         }
303         /*
304          * If there's a left sibling, see if it's ok to shift an entry
305          * out of it.
306          */
307         if (lbno != NULLAGBLOCK) {
308                 /*
309                  * Move the temp cursor to the first entry in the
310                  * previous block.
311                  */
312                 xfs_btree_firstrec(tcur, level);
313                 if ((error = xfs_btree_decrement(tcur, level, &i)))
314                         goto error0;
315                 xfs_btree_firstrec(tcur, level);
316                 /*
317                  * Grab a pointer to the block.
318                  */
319                 lbp = tcur->bc_bufs[level];
320                 left = XFS_BUF_TO_INOBT_BLOCK(lbp);
321 #ifdef DEBUG
322                 if ((error = xfs_btree_check_sblock(cur, left, level, lbp)))
323                         goto error0;
324 #endif
325                 /*
326                  * Grab the current block number, for future use.
327                  */
328                 bno = be32_to_cpu(left->bb_rightsib);
329                 /*
330                  * If left block is full enough so that removing one entry
331                  * won't make it too empty, and right-shifting an entry out
332                  * of left to us works, we're done.
333                  */
334                 if (be16_to_cpu(left->bb_numrecs) - 1 >=
335                      XFS_INOBT_BLOCK_MINRECS(level, cur)) {
336                         if ((error = xfs_btree_rshift(tcur, level, &i)))
337                                 goto error0;
338                         if (i) {
339                                 ASSERT(be16_to_cpu(block->bb_numrecs) >=
340                                        XFS_INOBT_BLOCK_MINRECS(level, cur));
341                                 xfs_btree_del_cursor(tcur,
342                                                      XFS_BTREE_NOERROR);
343                                 if (level == 0)
344                                         cur->bc_ptrs[0]++;
345                                 *stat = 1;
346                                 return 0;
347                         }
348                 }
349                 /*
350                  * Otherwise, grab the number of records in right for
351                  * future reference.
352                  */
353                 lrecs = be16_to_cpu(left->bb_numrecs);
354         }
355         /*
356          * Delete the temp cursor, we're done with it.
357          */
358         xfs_btree_del_cursor(tcur, XFS_BTREE_NOERROR);
359         /*
360          * If here, we need to do a join to keep the tree balanced.
361          */
362         ASSERT(bno != NULLAGBLOCK);
363         /*
364          * See if we can join with the left neighbor block.
365          */
366         if (lbno != NULLAGBLOCK &&
367             lrecs + numrecs <= XFS_INOBT_BLOCK_MAXRECS(level, cur)) {
368                 /*
369                  * Set "right" to be the starting block,
370                  * "left" to be the left neighbor.
371                  */
372                 rbno = bno;
373                 right = block;
374                 rrecs = be16_to_cpu(right->bb_numrecs);
375                 rbp = bp;
376                 if ((error = xfs_btree_read_bufs(mp, cur->bc_tp,
377                                 cur->bc_private.a.agno, lbno, 0, &lbp,
378                                 XFS_INO_BTREE_REF)))
379                         return error;
380                 left = XFS_BUF_TO_INOBT_BLOCK(lbp);
381                 lrecs = be16_to_cpu(left->bb_numrecs);
382                 if ((error = xfs_btree_check_sblock(cur, left, level, lbp)))
383                         return error;
384         }
385         /*
386          * If that won't work, see if we can join with the right neighbor block.
387          */
388         else if (rbno != NULLAGBLOCK &&
389                  rrecs + numrecs <= XFS_INOBT_BLOCK_MAXRECS(level, cur)) {
390                 /*
391                  * Set "left" to be the starting block,
392                  * "right" to be the right neighbor.
393                  */
394                 lbno = bno;
395                 left = block;
396                 lrecs = be16_to_cpu(left->bb_numrecs);
397                 lbp = bp;
398                 if ((error = xfs_btree_read_bufs(mp, cur->bc_tp,
399                                 cur->bc_private.a.agno, rbno, 0, &rbp,
400                                 XFS_INO_BTREE_REF)))
401                         return error;
402                 right = XFS_BUF_TO_INOBT_BLOCK(rbp);
403                 rrecs = be16_to_cpu(right->bb_numrecs);
404                 if ((error = xfs_btree_check_sblock(cur, right, level, rbp)))
405                         return error;
406         }
407         /*
408          * Otherwise, we can't fix the imbalance.
409          * Just return.  This is probably a logic error, but it's not fatal.
410          */
411         else {
412                 if (level > 0 && (error = xfs_btree_decrement(cur, level, &i)))
413                         return error;
414                 *stat = 1;
415                 return 0;
416         }
417         /*
418          * We're now going to join "left" and "right" by moving all the stuff
419          * in "right" to "left" and deleting "right".
420          */
421         if (level > 0) {
422                 /*
423                  * It's a non-leaf.  Move keys and pointers.
424                  */
425                 lkp = XFS_INOBT_KEY_ADDR(left, lrecs + 1, cur);
426                 lpp = XFS_INOBT_PTR_ADDR(left, lrecs + 1, cur);
427                 rkp = XFS_INOBT_KEY_ADDR(right, 1, cur);
428                 rpp = XFS_INOBT_PTR_ADDR(right, 1, cur);
429 #ifdef DEBUG
430                 for (i = 0; i < rrecs; i++) {
431                         if ((error = xfs_btree_check_sptr(cur, be32_to_cpu(rpp[i]), level)))
432                                 return error;
433                 }
434 #endif
435                 memcpy(lkp, rkp, rrecs * sizeof(*lkp));
436                 memcpy(lpp, rpp, rrecs * sizeof(*lpp));
437                 xfs_inobt_log_keys(cur, lbp, lrecs + 1, lrecs + rrecs);
438                 xfs_inobt_log_ptrs(cur, lbp, lrecs + 1, lrecs + rrecs);
439         } else {
440                 /*
441                  * It's a leaf.  Move records.
442                  */
443                 lrp = XFS_INOBT_REC_ADDR(left, lrecs + 1, cur);
444                 rrp = XFS_INOBT_REC_ADDR(right, 1, cur);
445                 memcpy(lrp, rrp, rrecs * sizeof(*lrp));
446                 xfs_inobt_log_recs(cur, lbp, lrecs + 1, lrecs + rrecs);
447         }
448         /*
449          * If we joined with the left neighbor, set the buffer in the
450          * cursor to the left block, and fix up the index.
451          */
452         if (bp != lbp) {
453                 xfs_btree_setbuf(cur, level, lbp);
454                 cur->bc_ptrs[level] += lrecs;
455         }
456         /*
457          * If we joined with the right neighbor and there's a level above
458          * us, increment the cursor at that level.
459          */
460         else if (level + 1 < cur->bc_nlevels &&
461                  (error = xfs_btree_increment(cur, level + 1, &i)))
462                 return error;
463         /*
464          * Fix up the number of records in the surviving block.
465          */
466         lrecs += rrecs;
467         left->bb_numrecs = cpu_to_be16(lrecs);
468         /*
469          * Fix up the right block pointer in the surviving block, and log it.
470          */
471         left->bb_rightsib = right->bb_rightsib;
472         xfs_inobt_log_block(cur->bc_tp, lbp, XFS_BB_NUMRECS | XFS_BB_RIGHTSIB);
473         /*
474          * If there is a right sibling now, make it point to the
475          * remaining block.
476          */
477         if (be32_to_cpu(left->bb_rightsib) != NULLAGBLOCK) {
478                 xfs_inobt_block_t       *rrblock;
479                 xfs_buf_t               *rrbp;
480
481                 if ((error = xfs_btree_read_bufs(mp, cur->bc_tp,
482                                 cur->bc_private.a.agno, be32_to_cpu(left->bb_rightsib), 0,
483                                 &rrbp, XFS_INO_BTREE_REF)))
484                         return error;
485                 rrblock = XFS_BUF_TO_INOBT_BLOCK(rrbp);
486                 if ((error = xfs_btree_check_sblock(cur, rrblock, level, rrbp)))
487                         return error;
488                 rrblock->bb_leftsib = cpu_to_be32(lbno);
489                 xfs_inobt_log_block(cur->bc_tp, rrbp, XFS_BB_LEFTSIB);
490         }
491         /*
492          * Free the deleting block.
493          */
494         if ((error = xfs_free_extent(cur->bc_tp, XFS_AGB_TO_FSB(mp,
495                                      cur->bc_private.a.agno, rbno), 1)))
496                 return error;
497         xfs_trans_binval(cur->bc_tp, rbp);
498         /*
499          * Readjust the ptr at this level if it's not a leaf, since it's
500          * still pointing at the deletion point, which makes the cursor
501          * inconsistent.  If this makes the ptr 0, the caller fixes it up.
502          * We can't use decrement because it would change the next level up.
503          */
504         if (level > 0)
505                 cur->bc_ptrs[level]--;
506         /*
507          * Return value means the next level up has something to do.
508          */
509         *stat = 2;
510         return 0;
511
512 error0:
513         xfs_btree_del_cursor(tcur, XFS_BTREE_ERROR);
514         return error;
515 }
516
517 /*
518  * Log header fields from a btree block.
519  */
520 STATIC void
521 xfs_inobt_log_block(
522         xfs_trans_t             *tp,    /* transaction pointer */
523         xfs_buf_t               *bp,    /* buffer containing btree block */
524         int                     fields) /* mask of fields: XFS_BB_... */
525 {
526         int                     first;  /* first byte offset logged */
527         int                     last;   /* last byte offset logged */
528         static const short      offsets[] = {   /* table of offsets */
529                 offsetof(xfs_inobt_block_t, bb_magic),
530                 offsetof(xfs_inobt_block_t, bb_level),
531                 offsetof(xfs_inobt_block_t, bb_numrecs),
532                 offsetof(xfs_inobt_block_t, bb_leftsib),
533                 offsetof(xfs_inobt_block_t, bb_rightsib),
534                 sizeof(xfs_inobt_block_t)
535         };
536
537         xfs_btree_offsets(fields, offsets, XFS_BB_NUM_BITS, &first, &last);
538         xfs_trans_log_buf(tp, bp, first, last);
539 }
540
541 /*
542  * Log keys from a btree block (nonleaf).
543  */
544 STATIC void
545 xfs_inobt_log_keys(
546         xfs_btree_cur_t         *cur,   /* btree cursor */
547         xfs_buf_t               *bp,    /* buffer containing btree block */
548         int                     kfirst, /* index of first key to log */
549         int                     klast)  /* index of last key to log */
550 {
551         xfs_inobt_block_t       *block; /* btree block to log from */
552         int                     first;  /* first byte offset logged */
553         xfs_inobt_key_t         *kp;    /* key pointer in btree block */
554         int                     last;   /* last byte offset logged */
555
556         block = XFS_BUF_TO_INOBT_BLOCK(bp);
557         kp = XFS_INOBT_KEY_ADDR(block, 1, cur);
558         first = (int)((xfs_caddr_t)&kp[kfirst - 1] - (xfs_caddr_t)block);
559         last = (int)(((xfs_caddr_t)&kp[klast] - 1) - (xfs_caddr_t)block);
560         xfs_trans_log_buf(cur->bc_tp, bp, first, last);
561 }
562
563 /*
564  * Log block pointer fields from a btree block (nonleaf).
565  */
566 STATIC void
567 xfs_inobt_log_ptrs(
568         xfs_btree_cur_t         *cur,   /* btree cursor */
569         xfs_buf_t               *bp,    /* buffer containing btree block */
570         int                     pfirst, /* index of first pointer to log */
571         int                     plast)  /* index of last pointer to log */
572 {
573         xfs_inobt_block_t       *block; /* btree block to log from */
574         int                     first;  /* first byte offset logged */
575         int                     last;   /* last byte offset logged */
576         xfs_inobt_ptr_t         *pp;    /* block-pointer pointer in btree blk */
577
578         block = XFS_BUF_TO_INOBT_BLOCK(bp);
579         pp = XFS_INOBT_PTR_ADDR(block, 1, cur);
580         first = (int)((xfs_caddr_t)&pp[pfirst - 1] - (xfs_caddr_t)block);
581         last = (int)(((xfs_caddr_t)&pp[plast] - 1) - (xfs_caddr_t)block);
582         xfs_trans_log_buf(cur->bc_tp, bp, first, last);
583 }
584
585 /*
586  * Log records from a btree block (leaf).
587  */
588 STATIC void
589 xfs_inobt_log_recs(
590         xfs_btree_cur_t         *cur,   /* btree cursor */
591         xfs_buf_t               *bp,    /* buffer containing btree block */
592         int                     rfirst, /* index of first record to log */
593         int                     rlast)  /* index of last record to log */
594 {
595         xfs_inobt_block_t       *block; /* btree block to log from */
596         int                     first;  /* first byte offset logged */
597         int                     last;   /* last byte offset logged */
598         xfs_inobt_rec_t         *rp;    /* record pointer for btree block */
599
600         block = XFS_BUF_TO_INOBT_BLOCK(bp);
601         rp = XFS_INOBT_REC_ADDR(block, 1, cur);
602         first = (int)((xfs_caddr_t)&rp[rfirst - 1] - (xfs_caddr_t)block);
603         last = (int)(((xfs_caddr_t)&rp[rlast] - 1) - (xfs_caddr_t)block);
604         xfs_trans_log_buf(cur->bc_tp, bp, first, last);
605 }
606
607
608 /*
609  * Externally visible routines.
610  */
611
612 /*
613  * Delete the record pointed to by cur.
614  * The cursor refers to the place where the record was (could be inserted)
615  * when the operation returns.
616  */
617 int                                     /* error */
618 xfs_inobt_delete(
619         xfs_btree_cur_t *cur,           /* btree cursor */
620         int             *stat)          /* success/failure */
621 {
622         int             error;
623         int             i;              /* result code */
624         int             level;          /* btree level */
625
626         /*
627          * Go up the tree, starting at leaf level.
628          * If 2 is returned then a join was done; go to the next level.
629          * Otherwise we are done.
630          */
631         for (level = 0, i = 2; i == 2; level++) {
632                 if ((error = xfs_inobt_delrec(cur, level, &i)))
633                         return error;
634         }
635         if (i == 0) {
636                 for (level = 1; level < cur->bc_nlevels; level++) {
637                         if (cur->bc_ptrs[level] == 0) {
638                                 if ((error = xfs_btree_decrement(cur, level, &i)))
639                                         return error;
640                                 break;
641                         }
642                 }
643         }
644         *stat = i;
645         return 0;
646 }
647
648
649 /*
650  * Get the data from the pointed-to record.
651  */
652 int                                     /* error */
653 xfs_inobt_get_rec(
654         xfs_btree_cur_t         *cur,   /* btree cursor */
655         xfs_agino_t             *ino,   /* output: starting inode of chunk */
656         __int32_t               *fcnt,  /* output: number of free inodes */
657         xfs_inofree_t           *free,  /* output: free inode mask */
658         int                     *stat)  /* output: success/failure */
659 {
660         xfs_inobt_block_t       *block; /* btree block */
661         xfs_buf_t               *bp;    /* buffer containing btree block */
662 #ifdef DEBUG
663         int                     error;  /* error return value */
664 #endif
665         int                     ptr;    /* record number */
666         xfs_inobt_rec_t         *rec;   /* record data */
667
668         bp = cur->bc_bufs[0];
669         ptr = cur->bc_ptrs[0];
670         block = XFS_BUF_TO_INOBT_BLOCK(bp);
671 #ifdef DEBUG
672         if ((error = xfs_btree_check_sblock(cur, block, 0, bp)))
673                 return error;
674 #endif
675         /*
676          * Off the right end or left end, return failure.
677          */
678         if (ptr > be16_to_cpu(block->bb_numrecs) || ptr <= 0) {
679                 *stat = 0;
680                 return 0;
681         }
682         /*
683          * Point to the record and extract its data.
684          */
685         rec = XFS_INOBT_REC_ADDR(block, ptr, cur);
686         *ino = be32_to_cpu(rec->ir_startino);
687         *fcnt = be32_to_cpu(rec->ir_freecount);
688         *free = be64_to_cpu(rec->ir_free);
689         *stat = 1;
690         return 0;
691 }
692
693
694 STATIC struct xfs_btree_cur *
695 xfs_inobt_dup_cursor(
696         struct xfs_btree_cur    *cur)
697 {
698         return xfs_inobt_init_cursor(cur->bc_mp, cur->bc_tp,
699                         cur->bc_private.a.agbp, cur->bc_private.a.agno);
700 }
701
702 STATIC void
703 xfs_inobt_set_root(
704         struct xfs_btree_cur    *cur,
705         union xfs_btree_ptr     *nptr,
706         int                     inc)    /* level change */
707 {
708         struct xfs_buf          *agbp = cur->bc_private.a.agbp;
709         struct xfs_agi          *agi = XFS_BUF_TO_AGI(agbp);
710
711         agi->agi_root = nptr->s;
712         be32_add_cpu(&agi->agi_level, inc);
713         xfs_ialloc_log_agi(cur->bc_tp, agbp, XFS_AGI_ROOT | XFS_AGI_LEVEL);
714 }
715
716 STATIC int
717 xfs_inobt_alloc_block(
718         struct xfs_btree_cur    *cur,
719         union xfs_btree_ptr     *start,
720         union xfs_btree_ptr     *new,
721         int                     length,
722         int                     *stat)
723 {
724         xfs_alloc_arg_t         args;           /* block allocation args */
725         int                     error;          /* error return value */
726         xfs_agblock_t           sbno = be32_to_cpu(start->s);
727
728         XFS_BTREE_TRACE_CURSOR(cur, XBT_ENTRY);
729
730         memset(&args, 0, sizeof(args));
731         args.tp = cur->bc_tp;
732         args.mp = cur->bc_mp;
733         args.fsbno = XFS_AGB_TO_FSB(args.mp, cur->bc_private.a.agno, sbno);
734         args.minlen = 1;
735         args.maxlen = 1;
736         args.prod = 1;
737         args.type = XFS_ALLOCTYPE_NEAR_BNO;
738
739         error = xfs_alloc_vextent(&args);
740         if (error) {
741                 XFS_BTREE_TRACE_CURSOR(cur, XBT_ERROR);
742                 return error;
743         }
744         if (args.fsbno == NULLFSBLOCK) {
745                 XFS_BTREE_TRACE_CURSOR(cur, XBT_EXIT);
746                 *stat = 0;
747                 return 0;
748         }
749         ASSERT(args.len == 1);
750         XFS_BTREE_TRACE_CURSOR(cur, XBT_EXIT);
751
752         new->s = cpu_to_be32(XFS_FSB_TO_AGBNO(args.mp, args.fsbno));
753         *stat = 1;
754         return 0;
755 }
756
757 STATIC int
758 xfs_inobt_free_block(
759         struct xfs_btree_cur    *cur,
760         struct xfs_buf          *bp)
761 {
762         xfs_fsblock_t           fsbno;
763         int                     error;
764
765         fsbno = XFS_DADDR_TO_FSB(cur->bc_mp, XFS_BUF_ADDR(bp));
766         error = xfs_free_extent(cur->bc_tp, fsbno, 1);
767         if (error)
768                 return error;
769
770         xfs_trans_binval(cur->bc_tp, bp);
771         return error;
772 }
773
774 STATIC int
775 xfs_inobt_get_maxrecs(
776         struct xfs_btree_cur    *cur,
777         int                     level)
778 {
779         return cur->bc_mp->m_inobt_mxr[level != 0];
780 }
781
782 STATIC void
783 xfs_inobt_init_key_from_rec(
784         union xfs_btree_key     *key,
785         union xfs_btree_rec     *rec)
786 {
787         key->inobt.ir_startino = rec->inobt.ir_startino;
788 }
789
790 STATIC void
791 xfs_inobt_init_rec_from_key(
792         union xfs_btree_key     *key,
793         union xfs_btree_rec     *rec)
794 {
795         rec->inobt.ir_startino = key->inobt.ir_startino;
796 }
797
798 STATIC void
799 xfs_inobt_init_rec_from_cur(
800         struct xfs_btree_cur    *cur,
801         union xfs_btree_rec     *rec)
802 {
803         rec->inobt.ir_startino = cpu_to_be32(cur->bc_rec.i.ir_startino);
804         rec->inobt.ir_freecount = cpu_to_be32(cur->bc_rec.i.ir_freecount);
805         rec->inobt.ir_free = cpu_to_be64(cur->bc_rec.i.ir_free);
806 }
807
808 /*
809  * intial value of ptr for lookup
810  */
811 STATIC void
812 xfs_inobt_init_ptr_from_cur(
813         struct xfs_btree_cur    *cur,
814         union xfs_btree_ptr     *ptr)
815 {
816         struct xfs_agi          *agi = XFS_BUF_TO_AGI(cur->bc_private.a.agbp);
817
818         ASSERT(cur->bc_private.a.agno == be32_to_cpu(agi->agi_seqno));
819
820         ptr->s = agi->agi_root;
821 }
822
823 STATIC __int64_t
824 xfs_inobt_key_diff(
825         struct xfs_btree_cur    *cur,
826         union xfs_btree_key     *key)
827 {
828         return (__int64_t)be32_to_cpu(key->inobt.ir_startino) -
829                           cur->bc_rec.i.ir_startino;
830 }
831
832 #ifdef XFS_BTREE_TRACE
833 ktrace_t        *xfs_inobt_trace_buf;
834
835 STATIC void
836 xfs_inobt_trace_enter(
837         struct xfs_btree_cur    *cur,
838         const char              *func,
839         char                    *s,
840         int                     type,
841         int                     line,
842         __psunsigned_t          a0,
843         __psunsigned_t          a1,
844         __psunsigned_t          a2,
845         __psunsigned_t          a3,
846         __psunsigned_t          a4,
847         __psunsigned_t          a5,
848         __psunsigned_t          a6,
849         __psunsigned_t          a7,
850         __psunsigned_t          a8,
851         __psunsigned_t          a9,
852         __psunsigned_t          a10)
853 {
854         ktrace_enter(xfs_inobt_trace_buf, (void *)(__psint_t)type,
855                 (void *)func, (void *)s, NULL, (void *)cur,
856                 (void *)a0, (void *)a1, (void *)a2, (void *)a3,
857                 (void *)a4, (void *)a5, (void *)a6, (void *)a7,
858                 (void *)a8, (void *)a9, (void *)a10);
859 }
860
861 STATIC void
862 xfs_inobt_trace_cursor(
863         struct xfs_btree_cur    *cur,
864         __uint32_t              *s0,
865         __uint64_t              *l0,
866         __uint64_t              *l1)
867 {
868         *s0 = cur->bc_private.a.agno;
869         *l0 = cur->bc_rec.i.ir_startino;
870         *l1 = cur->bc_rec.i.ir_free;
871 }
872
873 STATIC void
874 xfs_inobt_trace_key(
875         struct xfs_btree_cur    *cur,
876         union xfs_btree_key     *key,
877         __uint64_t              *l0,
878         __uint64_t              *l1)
879 {
880         *l0 = be32_to_cpu(key->inobt.ir_startino);
881         *l1 = 0;
882 }
883
884 STATIC void
885 xfs_inobt_trace_record(
886         struct xfs_btree_cur    *cur,
887         union xfs_btree_rec     *rec,
888         __uint64_t              *l0,
889         __uint64_t              *l1,
890         __uint64_t              *l2)
891 {
892         *l0 = be32_to_cpu(rec->inobt.ir_startino);
893         *l1 = be32_to_cpu(rec->inobt.ir_freecount);
894         *l2 = be64_to_cpu(rec->inobt.ir_free);
895 }
896 #endif /* XFS_BTREE_TRACE */
897
898 static const struct xfs_btree_ops xfs_inobt_ops = {
899         .rec_len                = sizeof(xfs_inobt_rec_t),
900         .key_len                = sizeof(xfs_inobt_key_t),
901
902         .dup_cursor             = xfs_inobt_dup_cursor,
903         .set_root               = xfs_inobt_set_root,
904         .alloc_block            = xfs_inobt_alloc_block,
905         .free_block             = xfs_inobt_free_block,
906         .get_maxrecs            = xfs_inobt_get_maxrecs,
907         .init_key_from_rec      = xfs_inobt_init_key_from_rec,
908         .init_rec_from_key      = xfs_inobt_init_rec_from_key,
909         .init_rec_from_cur      = xfs_inobt_init_rec_from_cur,
910         .init_ptr_from_cur      = xfs_inobt_init_ptr_from_cur,
911         .key_diff               = xfs_inobt_key_diff,
912
913 #ifdef XFS_BTREE_TRACE
914         .trace_enter            = xfs_inobt_trace_enter,
915         .trace_cursor           = xfs_inobt_trace_cursor,
916         .trace_key              = xfs_inobt_trace_key,
917         .trace_record           = xfs_inobt_trace_record,
918 #endif
919 };
920
921 /*
922  * Allocate a new inode btree cursor.
923  */
924 struct xfs_btree_cur *                          /* new inode btree cursor */
925 xfs_inobt_init_cursor(
926         struct xfs_mount        *mp,            /* file system mount point */
927         struct xfs_trans        *tp,            /* transaction pointer */
928         struct xfs_buf          *agbp,          /* buffer for agi structure */
929         xfs_agnumber_t          agno)           /* allocation group number */
930 {
931         struct xfs_agi          *agi = XFS_BUF_TO_AGI(agbp);
932         struct xfs_btree_cur    *cur;
933
934         cur = kmem_zone_zalloc(xfs_btree_cur_zone, KM_SLEEP);
935
936         cur->bc_tp = tp;
937         cur->bc_mp = mp;
938         cur->bc_nlevels = be32_to_cpu(agi->agi_level);
939         cur->bc_btnum = XFS_BTNUM_INO;
940         cur->bc_blocklog = mp->m_sb.sb_blocklog;
941
942         cur->bc_ops = &xfs_inobt_ops;
943
944         cur->bc_private.a.agbp = agbp;
945         cur->bc_private.a.agno = agno;
946
947         return cur;
948 }