~ubuntu-branches/ubuntu/utopic/xfsprogs/utopic-proposed

« back to all changes in this revision

Viewing changes to libxfs/xfs_alloc_btree.c

  • Committer: Bazaar Package Importer
  • Author(s): Nathan Scott
  • Date: 2002-04-13 09:45:06 UTC
  • Revision ID: james.westby@ubuntu.com-20020413094506-t8dhemv41gkeg4kx
Tags: 2.0.3-1
New upstream bugfix release

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
/*
 
2
 * Copyright (c) 2000 Silicon Graphics, Inc.  All Rights Reserved.
 
3
 * 
 
4
 * This program is free software; you can redistribute it and/or modify it
 
5
 * under the terms of version 2 of the GNU General Public License as
 
6
 * published by the Free Software Foundation.
 
7
 * 
 
8
 * This program is distributed in the hope that it would be useful, but
 
9
 * WITHOUT ANY WARRANTY; without even the implied warranty of
 
10
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
 
11
 * 
 
12
 * Further, this software is distributed without any warranty that it is
 
13
 * free of the rightful claim of any third person regarding infringement
 
14
 * or the like.  Any license provided herein, whether implied or
 
15
 * otherwise, applies only to this software file.  Patent licenses, if
 
16
 * any, provided herein do not apply to combinations of this program with
 
17
 * other software, or any other product whatsoever.
 
18
 * 
 
19
 * You should have received a copy of the GNU General Public License along
 
20
 * with this program; if not, write the Free Software Foundation, Inc., 59
 
21
 * Temple Place - Suite 330, Boston MA 02111-1307, USA.
 
22
 * 
 
23
 * Contact information: Silicon Graphics, Inc., 1600 Amphitheatre Pkwy,
 
24
 * Mountain View, CA  94043, or:
 
25
 * 
 
26
 * http://www.sgi.com 
 
27
 * 
 
28
 * For further information regarding this notice, see: 
 
29
 * 
 
30
 * http://oss.sgi.com/projects/GenInfo/SGIGPLNoticeExplan/
 
31
 */
 
32
 
 
33
/*
 
34
 * Free space allocation for XFS.
 
35
 */
 
36
 
 
37
#include <xfs.h>
 
38
 
 
39
/*
 
40
 * Single level of the xfs_alloc_delete record deletion routine.
 
41
 * Delete record pointed to by cur/level.
 
42
 * Remove the record from its block then rebalance the tree.
 
43
 * Return 0 for error, 1 for done, 2 to go on to the next level.
 
44
 */
 
45
STATIC int                              /* error */
 
46
xfs_alloc_delrec(
 
47
        xfs_btree_cur_t         *cur,   /* btree cursor */
 
48
        int                     level,  /* level removing record from */
 
49
        int                     *stat)  /* fail/done/go-on */
 
50
{
 
51
        xfs_agf_t               *agf;   /* allocation group freelist header */
 
52
        xfs_alloc_block_t       *block; /* btree block record/key lives in */
 
53
        xfs_agblock_t           bno;    /* btree block number */
 
54
        xfs_buf_t               *bp;    /* buffer for block */
 
55
        int                     error;  /* error return value */
 
56
        int                     i;      /* loop index */
 
57
        xfs_alloc_key_t         key;    /* kp points here if block is level 0 */
 
58
        xfs_agblock_t           lbno;   /* left block's block number */
 
59
        xfs_buf_t               *lbp;   /* left block's buffer pointer */
 
60
        xfs_alloc_block_t       *left;  /* left btree block */
 
61
        xfs_alloc_key_t         *lkp=NULL;      /* left block key pointer */
 
62
        xfs_alloc_ptr_t         *lpp=NULL;      /* left block address pointer */
 
63
        int                     lrecs=0;        /* number of records in left block */
 
64
        xfs_alloc_rec_t         *lrp;   /* left block record pointer */
 
65
        xfs_mount_t             *mp;    /* mount structure */
 
66
        int                     ptr;    /* index in btree block for this rec */
 
67
        xfs_agblock_t           rbno;   /* right block's block number */
 
68
        xfs_buf_t               *rbp;   /* right block's buffer pointer */
 
69
        xfs_alloc_block_t       *right; /* right btree block */
 
70
        xfs_alloc_key_t         *rkp;   /* right block key pointer */
 
71
        xfs_alloc_ptr_t         *rpp;   /* right block address pointer */
 
72
        int                     rrecs=0;        /* number of records in right block */
 
73
        xfs_alloc_rec_t         *rrp;   /* right block record pointer */
 
74
        xfs_btree_cur_t         *tcur;  /* temporary btree cursor */
 
75
 
 
76
        /*
 
77
         * Get the index of the entry being deleted, check for nothing there.
 
78
         */
 
79
        ptr = cur->bc_ptrs[level];
 
80
        if (ptr == 0) {
 
81
                *stat = 0;
 
82
                return 0;
 
83
        }
 
84
        /*
 
85
         * Get the buffer & block containing the record or key/ptr.
 
86
         */
 
87
        bp = cur->bc_bufs[level];
 
88
        block = XFS_BUF_TO_ALLOC_BLOCK(bp);
 
89
#ifdef DEBUG
 
90
        if ((error = xfs_btree_check_sblock(cur, block, level, bp)))
 
91
                return error;
 
92
#endif
 
93
        /*
 
94
         * Fail if we're off the end of the block.
 
95
         */
 
96
        if (ptr > INT_GET(block->bb_numrecs, ARCH_CONVERT)) {
 
97
                *stat = 0;
 
98
                return 0;
 
99
        }
 
100
        XFS_STATS_INC(xfsstats.xs_abt_delrec);
 
101
        /*
 
102
         * It's a nonleaf.  Excise the key and ptr being deleted, by
 
103
         * sliding the entries past them down one.
 
104
         * Log the changed areas of the block.
 
105
         */
 
106
        if (level > 0) {
 
107
                lkp = XFS_ALLOC_KEY_ADDR(block, 1, cur);
 
108
                lpp = XFS_ALLOC_PTR_ADDR(block, 1, cur);
 
109
#ifdef DEBUG
 
110
                for (i = ptr; i < INT_GET(block->bb_numrecs, ARCH_CONVERT); i++) {
 
111
                        if ((error = xfs_btree_check_sptr(cur, INT_GET(lpp[i], ARCH_CONVERT), level)))
 
112
                                return error;
 
113
                }
 
114
#endif
 
115
                if (ptr < INT_GET(block->bb_numrecs, ARCH_CONVERT)) {
 
116
                        ovbcopy(&lkp[ptr], &lkp[ptr - 1],
 
117
                                (INT_GET(block->bb_numrecs, ARCH_CONVERT) - ptr) * sizeof(*lkp)); /* INT_: mem copy */
 
118
                        ovbcopy(&lpp[ptr], &lpp[ptr - 1],
 
119
                                (INT_GET(block->bb_numrecs, ARCH_CONVERT) - ptr) * sizeof(*lpp)); /* INT_: mem copy */
 
120
                        xfs_alloc_log_ptrs(cur, bp, ptr, INT_GET(block->bb_numrecs, ARCH_CONVERT) - 1);
 
121
                        xfs_alloc_log_keys(cur, bp, ptr, INT_GET(block->bb_numrecs, ARCH_CONVERT) - 1);
 
122
                }
 
123
        }
 
124
        /*
 
125
         * It's a leaf.  Excise the record being deleted, by sliding the
 
126
         * entries past it down one.  Log the changed areas of the block.
 
127
         */
 
128
        else {
 
129
                lrp = XFS_ALLOC_REC_ADDR(block, 1, cur);
 
130
                if (ptr < INT_GET(block->bb_numrecs, ARCH_CONVERT)) {
 
131
                        ovbcopy(&lrp[ptr], &lrp[ptr - 1],
 
132
                                (INT_GET(block->bb_numrecs, ARCH_CONVERT) - ptr) * sizeof(*lrp));
 
133
                        xfs_alloc_log_recs(cur, bp, ptr, INT_GET(block->bb_numrecs, ARCH_CONVERT) - 1);
 
134
                }
 
135
                /*
 
136
                 * If it's the first record in the block, we'll need a key
 
137
                 * structure to pass up to the next level (updkey).
 
138
                 */
 
139
                if (ptr == 1) {
 
140
                        key.ar_startblock = lrp->ar_startblock; /* INT_: direct copy */
 
141
                        key.ar_blockcount = lrp->ar_blockcount; /* INT_: direct copy */
 
142
                        lkp = &key;
 
143
                }
 
144
        }
 
145
        /*
 
146
         * Decrement and log the number of entries in the block.
 
147
         */
 
148
        INT_MOD(block->bb_numrecs, ARCH_CONVERT, -1);
 
149
        xfs_alloc_log_block(cur->bc_tp, bp, XFS_BB_NUMRECS);
 
150
        /*
 
151
         * See if the longest free extent in the allocation group was
 
152
         * changed by this operation.  True if it's the by-size btree, and
 
153
         * this is the leaf level, and there is no right sibling block,
 
154
         * and this was the last record.
 
155
         */
 
156
        agf = XFS_BUF_TO_AGF(cur->bc_private.a.agbp);
 
157
        mp = cur->bc_mp;
 
158
 
 
159
        if (level == 0 &&
 
160
            cur->bc_btnum == XFS_BTNUM_CNT &&
 
161
            INT_GET(block->bb_rightsib, ARCH_CONVERT) == NULLAGBLOCK &&
 
162
            ptr > INT_GET(block->bb_numrecs, ARCH_CONVERT)) {
 
163
                ASSERT(ptr == INT_GET(block->bb_numrecs, ARCH_CONVERT) + 1);
 
164
                /*
 
165
                 * There are still records in the block.  Grab the size
 
166
                 * from the last one.
 
167
                 */
 
168
                if (INT_GET(block->bb_numrecs, ARCH_CONVERT)) {
 
169
                        rrp = XFS_ALLOC_REC_ADDR(block, INT_GET(block->bb_numrecs, ARCH_CONVERT), cur);
 
170
                        INT_COPY(agf->agf_longest, rrp->ar_blockcount, ARCH_CONVERT);
 
171
                }
 
172
                /*
 
173
                 * No free extents left.
 
174
                 */
 
175
                else
 
176
                        INT_ZERO(agf->agf_longest, ARCH_CONVERT);
 
177
                mp->m_perag[INT_GET(agf->agf_seqno, ARCH_CONVERT)].pagf_longest =
 
178
                        INT_GET(agf->agf_longest, ARCH_CONVERT);
 
179
                xfs_alloc_log_agf(cur->bc_tp, cur->bc_private.a.agbp,
 
180
                        XFS_AGF_LONGEST);
 
181
        }
 
182
        /*
 
183
         * Is this the root level?  If so, we're almost done.
 
184
         */
 
185
        if (level == cur->bc_nlevels - 1) {
 
186
                /*
 
187
                 * If this is the root level,
 
188
                 * and there's only one entry left,
 
189
                 * and it's NOT the leaf level,
 
190
                 * then we can get rid of this level.
 
191
                 */
 
192
                if (INT_GET(block->bb_numrecs, ARCH_CONVERT) == 1 && level > 0) {
 
193
                        /*
 
194
                         * lpp is still set to the first pointer in the block.
 
195
                         * Make it the new root of the btree.
 
196
                         */
 
197
                        bno = INT_GET(agf->agf_roots[cur->bc_btnum], ARCH_CONVERT);
 
198
                        INT_COPY(agf->agf_roots[cur->bc_btnum], *lpp, ARCH_CONVERT);
 
199
                        INT_MOD(agf->agf_levels[cur->bc_btnum], ARCH_CONVERT, -1);
 
200
                        mp->m_perag[INT_GET(agf->agf_seqno, ARCH_CONVERT)].pagf_levels[cur->bc_btnum]--;
 
201
                        /*
 
202
                         * Put this buffer/block on the ag's freelist.
 
203
                         */
 
204
                        if ((error = xfs_alloc_put_freelist(cur->bc_tp,
 
205
                                        cur->bc_private.a.agbp, NULL, bno)))
 
206
                                return error;
 
207
                        xfs_trans_agbtree_delta(cur->bc_tp, -1);
 
208
                        xfs_alloc_log_agf(cur->bc_tp, cur->bc_private.a.agbp,
 
209
                                XFS_AGF_ROOTS | XFS_AGF_LEVELS);
 
210
                        /*
 
211
                         * Update the cursor so there's one fewer level.
 
212
                         */
 
213
                        xfs_btree_setbuf(cur, level, 0);
 
214
                        cur->bc_nlevels--;
 
215
                } else if (level > 0 &&
 
216
                           (error = xfs_alloc_decrement(cur, level, &i)))
 
217
                        return error;
 
218
                *stat = 1;
 
219
                return 0;
 
220
        }
 
221
        /*
 
222
         * If we deleted the leftmost entry in the block, update the
 
223
         * key values above us in the tree.
 
224
         */
 
225
        if (ptr == 1 && (error = xfs_alloc_updkey(cur, lkp, level + 1)))
 
226
                return error;
 
227
        /*
 
228
         * If the number of records remaining in the block is at least
 
229
         * the minimum, we're done.
 
230
         */
 
231
        if (INT_GET(block->bb_numrecs, ARCH_CONVERT) >= XFS_ALLOC_BLOCK_MINRECS(level, cur)) {
 
232
                if (level > 0 && (error = xfs_alloc_decrement(cur, level, &i)))
 
233
                        return error;
 
234
                *stat = 1;
 
235
                return 0;
 
236
        }
 
237
        /*
 
238
         * Otherwise, we have to move some records around to keep the
 
239
         * tree balanced.  Look at the left and right sibling blocks to
 
240
         * see if we can re-balance by moving only one record.
 
241
         */
 
242
        rbno = INT_GET(block->bb_rightsib, ARCH_CONVERT);
 
243
        lbno = INT_GET(block->bb_leftsib, ARCH_CONVERT);
 
244
        bno = NULLAGBLOCK;
 
245
        ASSERT(rbno != NULLAGBLOCK || lbno != NULLAGBLOCK);
 
246
        /*
 
247
         * Duplicate the cursor so our btree manipulations here won't
 
248
         * disrupt the next level up.
 
249
         */
 
250
        if ((error = xfs_btree_dup_cursor(cur, &tcur)))
 
251
                return error;
 
252
        /*
 
253
         * If there's a right sibling, see if it's ok to shift an entry
 
254
         * out of it.
 
255
         */
 
256
        if (rbno != NULLAGBLOCK) {
 
257
                /*
 
258
                 * Move the temp cursor to the last entry in the next block.
 
259
                 * Actually any entry but the first would suffice.
 
260
                 */
 
261
                i = xfs_btree_lastrec(tcur, level);
 
262
                XFS_WANT_CORRUPTED_GOTO(i == 1, error0);
 
263
                if ((error = xfs_alloc_increment(tcur, level, &i)))
 
264
                        goto error0;
 
265
                XFS_WANT_CORRUPTED_GOTO(i == 1, error0);
 
266
                i = xfs_btree_lastrec(tcur, level);
 
267
                XFS_WANT_CORRUPTED_GOTO(i == 1, error0);
 
268
                /*
 
269
                 * Grab a pointer to the block.
 
270
                 */
 
271
                rbp = tcur->bc_bufs[level];
 
272
                right = XFS_BUF_TO_ALLOC_BLOCK(rbp);
 
273
#ifdef DEBUG
 
274
                if ((error = xfs_btree_check_sblock(cur, right, level, rbp)))
 
275
                        goto error0;
 
276
#endif
 
277
                /*
 
278
                 * Grab the current block number, for future use.
 
279
                 */
 
280
                bno = INT_GET(right->bb_leftsib, ARCH_CONVERT);
 
281
                /*
 
282
                 * If right block is full enough so that removing one entry
 
283
                 * won't make it too empty, and left-shifting an entry out
 
284
                 * of right to us works, we're done.
 
285
                 */
 
286
                if (INT_GET(right->bb_numrecs, ARCH_CONVERT) - 1 >=
 
287
                     XFS_ALLOC_BLOCK_MINRECS(level, cur)) {
 
288
                        if ((error = xfs_alloc_lshift(tcur, level, &i)))
 
289
                                goto error0;
 
290
                        if (i) {
 
291
                                ASSERT(INT_GET(block->bb_numrecs, ARCH_CONVERT) >=
 
292
                                       XFS_ALLOC_BLOCK_MINRECS(level, cur));
 
293
                                xfs_btree_del_cursor(tcur,
 
294
                                                     XFS_BTREE_NOERROR);
 
295
                                if (level > 0 &&
 
296
                                    (error = xfs_alloc_decrement(cur, level,
 
297
                                            &i)))
 
298
                                        return error;
 
299
                                *stat = 1;
 
300
                                return 0;
 
301
                        }
 
302
                }
 
303
                /*
 
304
                 * Otherwise, grab the number of records in right for
 
305
                 * future reference, and fix up the temp cursor to point 
 
306
                 * to our block again (last record).
 
307
                 */
 
308
                rrecs = INT_GET(right->bb_numrecs, ARCH_CONVERT);
 
309
                if (lbno != NULLAGBLOCK) {
 
310
                        i = xfs_btree_firstrec(tcur, level);
 
311
                        XFS_WANT_CORRUPTED_GOTO(i == 1, error0);
 
312
                        if ((error = xfs_alloc_decrement(tcur, level, &i)))
 
313
                                goto error0;
 
314
                        XFS_WANT_CORRUPTED_GOTO(i == 1, error0);
 
315
                }
 
316
        }
 
317
        /*
 
318
         * If there's a left sibling, see if it's ok to shift an entry
 
319
         * out of it.
 
320
         */
 
321
        if (lbno != NULLAGBLOCK) {
 
322
                /*
 
323
                 * Move the temp cursor to the first entry in the
 
324
                 * previous block.
 
325
                 */
 
326
                i = xfs_btree_firstrec(tcur, level);
 
327
                XFS_WANT_CORRUPTED_GOTO(i == 1, error0);
 
328
                if ((error = xfs_alloc_decrement(tcur, level, &i)))
 
329
                        goto error0;
 
330
                XFS_WANT_CORRUPTED_GOTO(i == 1, error0);
 
331
                xfs_btree_firstrec(tcur, level);
 
332
                /*
 
333
                 * Grab a pointer to the block.
 
334
                 */
 
335
                lbp = tcur->bc_bufs[level];
 
336
                left = XFS_BUF_TO_ALLOC_BLOCK(lbp);
 
337
#ifdef DEBUG
 
338
                if ((error = xfs_btree_check_sblock(cur, left, level, lbp)))
 
339
                        goto error0;
 
340
#endif
 
341
                /*
 
342
                 * Grab the current block number, for future use.
 
343
                 */
 
344
                bno = INT_GET(left->bb_rightsib, ARCH_CONVERT);
 
345
                /*
 
346
                 * If left block is full enough so that removing one entry
 
347
                 * won't make it too empty, and right-shifting an entry out
 
348
                 * of left to us works, we're done.
 
349
                 */
 
350
                if (INT_GET(left->bb_numrecs, ARCH_CONVERT) - 1 >=
 
351
                     XFS_ALLOC_BLOCK_MINRECS(level, cur)) {
 
352
                        if ((error = xfs_alloc_rshift(tcur, level, &i)))
 
353
                                goto error0;
 
354
                        if (i) {
 
355
                                ASSERT(INT_GET(block->bb_numrecs, ARCH_CONVERT) >=
 
356
                                       XFS_ALLOC_BLOCK_MINRECS(level, cur));
 
357
                                xfs_btree_del_cursor(tcur,
 
358
                                                     XFS_BTREE_NOERROR);
 
359
                                if (level == 0)
 
360
                                        cur->bc_ptrs[0]++;
 
361
                                *stat = 1;
 
362
                                return 0;
 
363
                        }
 
364
                }
 
365
                /*
 
366
                 * Otherwise, grab the number of records in right for
 
367
                 * future reference.
 
368
                 */
 
369
                lrecs = INT_GET(left->bb_numrecs, ARCH_CONVERT);
 
370
        }
 
371
        /*
 
372
         * Delete the temp cursor, we're done with it.
 
373
         */
 
374
        xfs_btree_del_cursor(tcur, XFS_BTREE_NOERROR);
 
375
        /*
 
376
         * If here, we need to do a join to keep the tree balanced.
 
377
         */
 
378
        ASSERT(bno != NULLAGBLOCK);
 
379
        /*
 
380
         * See if we can join with the left neighbor block.
 
381
         */
 
382
        if (lbno != NULLAGBLOCK &&
 
383
            lrecs + INT_GET(block->bb_numrecs, ARCH_CONVERT) <= XFS_ALLOC_BLOCK_MAXRECS(level, cur)) {
 
384
                /*
 
385
                 * Set "right" to be the starting block,
 
386
                 * "left" to be the left neighbor.
 
387
                 */
 
388
                rbno = bno;
 
389
                right = block;
 
390
                rbp = bp;
 
391
                if ((error = xfs_btree_read_bufs(mp, cur->bc_tp,
 
392
                                cur->bc_private.a.agno, lbno, 0, &lbp,
 
393
                                XFS_ALLOC_BTREE_REF)))
 
394
                        return error;
 
395
                left = XFS_BUF_TO_ALLOC_BLOCK(lbp);
 
396
                if ((error = xfs_btree_check_sblock(cur, left, level, lbp)))
 
397
                        return error;
 
398
        }
 
399
        /*
 
400
         * If that won't work, see if we can join with the right neighbor block.
 
401
         */
 
402
        else if (rbno != NULLAGBLOCK &&
 
403
                 rrecs + INT_GET(block->bb_numrecs, ARCH_CONVERT) <=
 
404
                  XFS_ALLOC_BLOCK_MAXRECS(level, cur)) {
 
405
                /*
 
406
                 * Set "left" to be the starting block,
 
407
                 * "right" to be the right neighbor.
 
408
                 */
 
409
                lbno = bno;
 
410
                left = block;
 
411
                lbp = bp;
 
412
                if ((error = xfs_btree_read_bufs(mp, cur->bc_tp,
 
413
                                cur->bc_private.a.agno, rbno, 0, &rbp,
 
414
                                XFS_ALLOC_BTREE_REF)))
 
415
                        return error;
 
416
                right = XFS_BUF_TO_ALLOC_BLOCK(rbp);
 
417
                if ((error = xfs_btree_check_sblock(cur, right, level, rbp)))
 
418
                        return error;
 
419
        }
 
420
        /*
 
421
         * Otherwise, we can't fix the imbalance.
 
422
         * Just return.  This is probably a logic error, but it's not fatal.
 
423
         */
 
424
        else {
 
425
                if (level > 0 && (error = xfs_alloc_decrement(cur, level, &i)))
 
426
                        return error;
 
427
                *stat = 1;
 
428
                return 0;
 
429
        }
 
430
        /*
 
431
         * We're now going to join "left" and "right" by moving all the stuff
 
432
         * in "right" to "left" and deleting "right".
 
433
         */
 
434
        if (level > 0) {
 
435
                /*
 
436
                 * It's a non-leaf.  Move keys and pointers.
 
437
                 */
 
438
                lkp = XFS_ALLOC_KEY_ADDR(left, INT_GET(left->bb_numrecs, ARCH_CONVERT) + 1, cur);
 
439
                lpp = XFS_ALLOC_PTR_ADDR(left, INT_GET(left->bb_numrecs, ARCH_CONVERT) + 1, cur);
 
440
                rkp = XFS_ALLOC_KEY_ADDR(right, 1, cur);
 
441
                rpp = XFS_ALLOC_PTR_ADDR(right, 1, cur);
 
442
#ifdef DEBUG
 
443
                for (i = 0; i < INT_GET(right->bb_numrecs, ARCH_CONVERT); i++) {
 
444
                        if ((error = xfs_btree_check_sptr(cur, INT_GET(rpp[i], ARCH_CONVERT), level)))
 
445
                                return error;
 
446
                }
 
447
#endif
 
448
                bcopy(rkp, lkp, INT_GET(right->bb_numrecs, ARCH_CONVERT) * sizeof(*lkp)); /* INT_: structure copy */
 
449
                bcopy(rpp, lpp, INT_GET(right->bb_numrecs, ARCH_CONVERT) * sizeof(*lpp)); /* INT_: structure copy */
 
450
                xfs_alloc_log_keys(cur, lbp, INT_GET(left->bb_numrecs, ARCH_CONVERT) + 1,
 
451
                                   INT_GET(left->bb_numrecs, ARCH_CONVERT) + INT_GET(right->bb_numrecs, ARCH_CONVERT));
 
452
                xfs_alloc_log_ptrs(cur, lbp, INT_GET(left->bb_numrecs, ARCH_CONVERT) + 1,
 
453
                                   INT_GET(left->bb_numrecs, ARCH_CONVERT) + INT_GET(right->bb_numrecs, ARCH_CONVERT));
 
454
        } else {
 
455
                /*
 
456
                 * It's a leaf.  Move records.
 
457
                 */
 
458
                lrp = XFS_ALLOC_REC_ADDR(left, INT_GET(left->bb_numrecs, ARCH_CONVERT) + 1, cur);
 
459
                rrp = XFS_ALLOC_REC_ADDR(right, 1, cur);
 
460
                bcopy(rrp, lrp, INT_GET(right->bb_numrecs, ARCH_CONVERT) * sizeof(*lrp));
 
461
                xfs_alloc_log_recs(cur, lbp, INT_GET(left->bb_numrecs, ARCH_CONVERT) + 1,
 
462
                                   INT_GET(left->bb_numrecs, ARCH_CONVERT) + INT_GET(right->bb_numrecs, ARCH_CONVERT));
 
463
        }
 
464
        /*
 
465
         * If we joined with the left neighbor, set the buffer in the
 
466
         * cursor to the left block, and fix up the index.
 
467
         */
 
468
        if (bp != lbp) {
 
469
                xfs_btree_setbuf(cur, level, lbp);
 
470
                cur->bc_ptrs[level] += INT_GET(left->bb_numrecs, ARCH_CONVERT);
 
471
        }
 
472
        /*
 
473
         * If we joined with the right neighbor and there's a level above
 
474
         * us, increment the cursor at that level.
 
475
         */
 
476
        else if (level + 1 < cur->bc_nlevels &&
 
477
                 (error = xfs_alloc_increment(cur, level + 1, &i)))
 
478
                return error;
 
479
        /*
 
480
         * Fix up the number of records in the surviving block.
 
481
         */
 
482
        INT_MOD(left->bb_numrecs, ARCH_CONVERT, INT_GET(right->bb_numrecs, ARCH_CONVERT));
 
483
        /*
 
484
         * Fix up the right block pointer in the surviving block, and log it.
 
485
         */
 
486
        left->bb_rightsib = right->bb_rightsib; /* INT_: direct copy */
 
487
        xfs_alloc_log_block(cur->bc_tp, lbp, XFS_BB_NUMRECS | XFS_BB_RIGHTSIB);
 
488
        /*
 
489
         * If there is a right sibling now, make it point to the 
 
490
         * remaining block.
 
491
         */
 
492
        if (INT_GET(left->bb_rightsib, ARCH_CONVERT) != NULLAGBLOCK) {
 
493
                xfs_alloc_block_t       *rrblock;
 
494
                xfs_buf_t               *rrbp;
 
495
 
 
496
                if ((error = xfs_btree_read_bufs(mp, cur->bc_tp,
 
497
                                cur->bc_private.a.agno, INT_GET(left->bb_rightsib, ARCH_CONVERT), 0,
 
498
                                &rrbp, XFS_ALLOC_BTREE_REF)))
 
499
                        return error;
 
500
                rrblock = XFS_BUF_TO_ALLOC_BLOCK(rrbp);
 
501
                if ((error = xfs_btree_check_sblock(cur, rrblock, level, rrbp)))
 
502
                        return error;
 
503
                INT_SET(rrblock->bb_leftsib, ARCH_CONVERT, lbno);
 
504
                xfs_alloc_log_block(cur->bc_tp, rrbp, XFS_BB_LEFTSIB);
 
505
        }
 
506
        /*
 
507
         * Free the deleting block by putting it on the freelist.
 
508
         */
 
509
        if ((error = xfs_alloc_put_freelist(cur->bc_tp, cur->bc_private.a.agbp,
 
510
                        NULL, rbno)))
 
511
                return error;
 
512
        xfs_trans_agbtree_delta(cur->bc_tp, -1);
 
513
        /*
 
514
         * Adjust the current level's cursor so that we're left referring
 
515
         * to the right node, after we're done.
 
516
         * If this leaves the ptr value 0 our caller will fix it up.
 
517
         */
 
518
        if (level > 0)
 
519
                cur->bc_ptrs[level]--;
 
520
        /* 
 
521
         * Return value means the next level up has something to do.
 
522
         */
 
523
        *stat = 2;
 
524
        return 0;
 
525
 
 
526
error0:
 
527
        xfs_btree_del_cursor(tcur, XFS_BTREE_ERROR);
 
528
        return error;
 
529
}
 
530
 
 
531
/*
 
532
 * Insert one record/level.  Return information to the caller
 
533
 * allowing the next level up to proceed if necessary.
 
534
 */
 
535
STATIC int                              /* error */
 
536
xfs_alloc_insrec(
 
537
        xfs_btree_cur_t         *cur,   /* btree cursor */
 
538
        int                     level,  /* level to insert record at */
 
539
        xfs_agblock_t           *bnop,  /* i/o: block number inserted */
 
540
        xfs_alloc_rec_t         *recp,  /* i/o: record data inserted */
 
541
        xfs_btree_cur_t         **curp, /* output: new cursor replacing cur */
 
542
        int                     *stat)  /* output: success/failure */
 
543
{
 
544
        xfs_agf_t               *agf;   /* allocation group freelist header */
 
545
        xfs_alloc_block_t       *block; /* btree block record/key lives in */
 
546
        xfs_buf_t               *bp;    /* buffer for block */
 
547
        int                     error;  /* error return value */
 
548
        int                     i;      /* loop index */
 
549
        xfs_alloc_key_t         key;    /* key value being inserted */
 
550
        xfs_alloc_key_t         *kp;    /* pointer to btree keys */
 
551
        xfs_agblock_t           nbno;   /* block number of allocated block */
 
552
        xfs_btree_cur_t         *ncur;  /* new cursor to be used at next lvl */
 
553
        xfs_alloc_key_t         nkey;   /* new key value, from split */
 
554
        xfs_alloc_rec_t         nrec;   /* new record value, for caller */
 
555
        int                     optr;   /* old ptr value */
 
556
        xfs_alloc_ptr_t         *pp;    /* pointer to btree addresses */
 
557
        int                     ptr;    /* index in btree block for this rec */
 
558
        xfs_alloc_rec_t         *rp;    /* pointer to btree records */
 
559
 
 
560
        ASSERT(INT_GET(recp->ar_blockcount, ARCH_CONVERT) > 0);
 
561
        /*
 
562
         * If we made it to the root level, allocate a new root block
 
563
         * and we're done.
 
564
         */
 
565
        if (level >= cur->bc_nlevels) {
 
566
                XFS_STATS_INC(xfsstats.xs_abt_insrec);
 
567
                if ((error = xfs_alloc_newroot(cur, &i)))
 
568
                        return error;
 
569
                *bnop = NULLAGBLOCK;
 
570
                *stat = i;
 
571
                return 0;
 
572
        }
 
573
        /*
 
574
         * Make a key out of the record data to be inserted, and save it.
 
575
         */
 
576
        key.ar_startblock = recp->ar_startblock; /* INT_: direct copy */
 
577
        key.ar_blockcount = recp->ar_blockcount; /* INT_: direct copy */
 
578
        optr = ptr = cur->bc_ptrs[level];
 
579
        /*
 
580
         * If we're off the left edge, return failure.
 
581
         */
 
582
        if (ptr == 0) {
 
583
                *stat = 0;
 
584
                return 0;
 
585
        }
 
586
        XFS_STATS_INC(xfsstats.xs_abt_insrec);
 
587
        /*
 
588
         * Get pointers to the btree buffer and block.
 
589
         */
 
590
        bp = cur->bc_bufs[level];
 
591
        block = XFS_BUF_TO_ALLOC_BLOCK(bp);
 
592
#ifdef DEBUG
 
593
        if ((error = xfs_btree_check_sblock(cur, block, level, bp)))
 
594
                return error;
 
595
        /* 
 
596
         * Check that the new entry is being inserted in the right place.
 
597
         */
 
598
        if (ptr <= INT_GET(block->bb_numrecs, ARCH_CONVERT)) {
 
599
                if (level == 0) {
 
600
                        rp = XFS_ALLOC_REC_ADDR(block, ptr, cur);
 
601
                        xfs_btree_check_rec(cur->bc_btnum, recp, rp);
 
602
                } else {
 
603
                        kp = XFS_ALLOC_KEY_ADDR(block, ptr, cur);
 
604
                        xfs_btree_check_key(cur->bc_btnum, &key, kp);
 
605
                }
 
606
        }
 
607
#endif
 
608
        nbno = NULLAGBLOCK;
 
609
        ncur = (xfs_btree_cur_t *)0;
 
610
        /*
 
611
         * If the block is full, we can't insert the new entry until we
 
612
         * make the block un-full.
 
613
         */
 
614
        if (INT_GET(block->bb_numrecs, ARCH_CONVERT) == XFS_ALLOC_BLOCK_MAXRECS(level, cur)) {
 
615
                /*
 
616
                 * First, try shifting an entry to the right neighbor.
 
617
                 */
 
618
                if ((error = xfs_alloc_rshift(cur, level, &i)))
 
619
                        return error;
 
620
                if (i) {
 
621
                        /* nothing */
 
622
                }
 
623
                /*
 
624
                 * Next, try shifting an entry to the left neighbor.
 
625
                 */
 
626
                else {
 
627
                        if ((error = xfs_alloc_lshift(cur, level, &i)))
 
628
                                return error;
 
629
                        if (i)
 
630
                                optr = ptr = cur->bc_ptrs[level];
 
631
                        else {
 
632
                                /*
 
633
                                 * Next, try splitting the current block in
 
634
                                 * half. If this works we have to re-set our
 
635
                                 * variables because we could be in a
 
636
                                 * different block now.
 
637
                                 */
 
638
                                if ((error = xfs_alloc_split(cur, level, &nbno,
 
639
                                                &nkey, &ncur, &i)))
 
640
                                        return error;
 
641
                                if (i) {
 
642
                                        bp = cur->bc_bufs[level];
 
643
                                        block = XFS_BUF_TO_ALLOC_BLOCK(bp);
 
644
#ifdef DEBUG
 
645
                                        if ((error =
 
646
                                                xfs_btree_check_sblock(cur,
 
647
                                                        block, level, bp)))
 
648
                                                return error;
 
649
#endif
 
650
                                        ptr = cur->bc_ptrs[level];
 
651
                                        nrec.ar_startblock = nkey.ar_startblock; /* INT_: direct copy */
 
652
                                        nrec.ar_blockcount = nkey.ar_blockcount; /* INT_: direct copy */
 
653
                                }
 
654
                                /*
 
655
                                 * Otherwise the insert fails.
 
656
                                 */
 
657
                                else {
 
658
                                        *stat = 0;
 
659
                                        return 0;
 
660
                                }
 
661
                        }
 
662
                }
 
663
        }
 
664
        /*
 
665
         * At this point we know there's room for our new entry in the block
 
666
         * we're pointing at.
 
667
         */
 
668
        if (level > 0) {
 
669
                /*
 
670
                 * It's a non-leaf entry.  Make a hole for the new data
 
671
                 * in the key and ptr regions of the block.
 
672
                 */
 
673
                kp = XFS_ALLOC_KEY_ADDR(block, 1, cur);
 
674
                pp = XFS_ALLOC_PTR_ADDR(block, 1, cur);
 
675
#ifdef DEBUG
 
676
                for (i = INT_GET(block->bb_numrecs, ARCH_CONVERT); i >= ptr; i--) {
 
677
                        if ((error = xfs_btree_check_sptr(cur, INT_GET(pp[i - 1], ARCH_CONVERT), level)))
 
678
                                return error;
 
679
                }
 
680
#endif
 
681
                ovbcopy(&kp[ptr - 1], &kp[ptr],
 
682
                        (INT_GET(block->bb_numrecs, ARCH_CONVERT) - ptr + 1) * sizeof(*kp)); /* INT_: copy */
 
683
                ovbcopy(&pp[ptr - 1], &pp[ptr],
 
684
                        (INT_GET(block->bb_numrecs, ARCH_CONVERT) - ptr + 1) * sizeof(*pp)); /* INT_: copy */
 
685
#ifdef DEBUG
 
686
                if ((error = xfs_btree_check_sptr(cur, *bnop, level)))
 
687
                        return error;
 
688
#endif
 
689
                /*
 
690
                 * Now stuff the new data in, bump numrecs and log the new data.
 
691
                 */
 
692
                kp[ptr - 1] = key;
 
693
                INT_SET(pp[ptr - 1], ARCH_CONVERT, *bnop);
 
694
                INT_MOD(block->bb_numrecs, ARCH_CONVERT, +1);
 
695
                xfs_alloc_log_keys(cur, bp, ptr, INT_GET(block->bb_numrecs, ARCH_CONVERT));
 
696
                xfs_alloc_log_ptrs(cur, bp, ptr, INT_GET(block->bb_numrecs, ARCH_CONVERT));
 
697
#ifdef DEBUG
 
698
                if (ptr < INT_GET(block->bb_numrecs, ARCH_CONVERT))
 
699
                        xfs_btree_check_key(cur->bc_btnum, kp + ptr - 1,
 
700
                                kp + ptr);
 
701
#endif
 
702
        } else {
 
703
                /*
 
704
                 * It's a leaf entry.  Make a hole for the new record.
 
705
                 */
 
706
                rp = XFS_ALLOC_REC_ADDR(block, 1, cur);
 
707
                ovbcopy(&rp[ptr - 1], &rp[ptr],
 
708
                        (INT_GET(block->bb_numrecs, ARCH_CONVERT) - ptr + 1) * sizeof(*rp));
 
709
                /*
 
710
                 * Now stuff the new record in, bump numrecs
 
711
                 * and log the new data.
 
712
                 */
 
713
                rp[ptr - 1] = *recp; /* INT_: struct copy */
 
714
                INT_MOD(block->bb_numrecs, ARCH_CONVERT, +1);
 
715
                xfs_alloc_log_recs(cur, bp, ptr, INT_GET(block->bb_numrecs, ARCH_CONVERT));
 
716
#ifdef DEBUG
 
717
                if (ptr < INT_GET(block->bb_numrecs, ARCH_CONVERT))
 
718
                        xfs_btree_check_rec(cur->bc_btnum, rp + ptr - 1,
 
719
                                rp + ptr);
 
720
#endif
 
721
        }
 
722
        /*
 
723
         * Log the new number of records in the btree header.
 
724
         */
 
725
        xfs_alloc_log_block(cur->bc_tp, bp, XFS_BB_NUMRECS);
 
726
        /*
 
727
         * If we inserted at the start of a block, update the parents' keys.
 
728
         */
 
729
        if (optr == 1 && (error = xfs_alloc_updkey(cur, &key, level + 1)))
 
730
                return error;
 
731
        /*
 
732
         * Look to see if the longest extent in the allocation group
 
733
         * needs to be updated.
 
734
         */
 
735
 
 
736
        agf = XFS_BUF_TO_AGF(cur->bc_private.a.agbp);
 
737
        if (level == 0 &&
 
738
            cur->bc_btnum == XFS_BTNUM_CNT &&
 
739
            INT_GET(block->bb_rightsib, ARCH_CONVERT) == NULLAGBLOCK &&
 
740
            INT_GET(recp->ar_blockcount, ARCH_CONVERT) > INT_GET(agf->agf_longest, ARCH_CONVERT)) {
 
741
                /*
 
742
                 * If this is a leaf in the by-size btree and there
 
743
                 * is no right sibling block and this block is bigger
 
744
                 * than the previous longest block, update it.
 
745
                 */
 
746
                INT_COPY(agf->agf_longest, recp->ar_blockcount, ARCH_CONVERT);
 
747
                cur->bc_mp->m_perag[INT_GET(agf->agf_seqno, ARCH_CONVERT)].pagf_longest
 
748
                        = INT_GET(recp->ar_blockcount, ARCH_CONVERT);
 
749
                xfs_alloc_log_agf(cur->bc_tp, cur->bc_private.a.agbp,
 
750
                        XFS_AGF_LONGEST);
 
751
        }
 
752
        /*
 
753
         * Return the new block number, if any.
 
754
         * If there is one, give back a record value and a cursor too.
 
755
         */
 
756
        *bnop = nbno;
 
757
        if (nbno != NULLAGBLOCK) {
 
758
                *recp = nrec; /* INT_: struct copy */
 
759
                *curp = ncur; /* INT_: struct copy */
 
760
        }
 
761
        *stat = 1;
 
762
        return 0;
 
763
}
 
764
 
 
765
/*
 
766
 * Log header fields from a btree block.
 
767
 */
 
768
STATIC void
 
769
xfs_alloc_log_block(
 
770
        xfs_trans_t             *tp,    /* transaction pointer */
 
771
        xfs_buf_t               *bp,    /* buffer containing btree block */
 
772
        int                     fields) /* mask of fields: XFS_BB_... */
 
773
{
 
774
        int                     first;  /* first byte offset logged */
 
775
        int                     last;   /* last byte offset logged */
 
776
        static const short      offsets[] = {   /* table of offsets */
 
777
                offsetof(xfs_alloc_block_t, bb_magic),
 
778
                offsetof(xfs_alloc_block_t, bb_level),
 
779
                offsetof(xfs_alloc_block_t, bb_numrecs),
 
780
                offsetof(xfs_alloc_block_t, bb_leftsib),
 
781
                offsetof(xfs_alloc_block_t, bb_rightsib),
 
782
                sizeof(xfs_alloc_block_t)
 
783
        };
 
784
 
 
785
        xfs_btree_offsets(fields, offsets, XFS_BB_NUM_BITS, &first, &last);
 
786
        xfs_trans_log_buf(tp, bp, first, last);
 
787
}
 
788
 
 
789
/*
 
790
 * Log keys from a btree block (nonleaf).
 
791
 */
 
792
STATIC void
 
793
xfs_alloc_log_keys(
 
794
        xfs_btree_cur_t         *cur,   /* btree cursor */
 
795
        xfs_buf_t                       *bp,    /* buffer containing btree block */
 
796
        int                     kfirst, /* index of first key to log */
 
797
        int                     klast)  /* index of last key to log */
 
798
{
 
799
        xfs_alloc_block_t       *block; /* btree block to log from */
 
800
        int                     first;  /* first byte offset logged */
 
801
        xfs_alloc_key_t         *kp;    /* key pointer in btree block */
 
802
        int                     last;   /* last byte offset logged */
 
803
 
 
804
        block = XFS_BUF_TO_ALLOC_BLOCK(bp);
 
805
        kp = XFS_ALLOC_KEY_ADDR(block, 1, cur);
 
806
        first = (int)((xfs_caddr_t)&kp[kfirst - 1] - (xfs_caddr_t)block);
 
807
        last = (int)(((xfs_caddr_t)&kp[klast] - 1) - (xfs_caddr_t)block);
 
808
        xfs_trans_log_buf(cur->bc_tp, bp, first, last);
 
809
}
 
810
 
 
811
/*
 
812
 * Log block pointer fields from a btree block (nonleaf).
 
813
 */
 
814
STATIC void
 
815
xfs_alloc_log_ptrs(
 
816
        xfs_btree_cur_t         *cur,   /* btree cursor */
 
817
        xfs_buf_t                       *bp,    /* buffer containing btree block */
 
818
        int                     pfirst, /* index of first pointer to log */
 
819
        int                     plast)  /* index of last pointer to log */
 
820
{
 
821
        xfs_alloc_block_t       *block; /* btree block to log from */
 
822
        int                     first;  /* first byte offset logged */
 
823
        int                     last;   /* last byte offset logged */
 
824
        xfs_alloc_ptr_t         *pp;    /* block-pointer pointer in btree blk */
 
825
 
 
826
        block = XFS_BUF_TO_ALLOC_BLOCK(bp);
 
827
        pp = XFS_ALLOC_PTR_ADDR(block, 1, cur);
 
828
        first = (int)((xfs_caddr_t)&pp[pfirst - 1] - (xfs_caddr_t)block);
 
829
        last = (int)(((xfs_caddr_t)&pp[plast] - 1) - (xfs_caddr_t)block);
 
830
        xfs_trans_log_buf(cur->bc_tp, bp, first, last);
 
831
}
 
832
 
 
833
/*
 
834
 * Log records from a btree block (leaf).
 
835
 */
 
836
STATIC void
 
837
xfs_alloc_log_recs(
 
838
        xfs_btree_cur_t         *cur,   /* btree cursor */
 
839
        xfs_buf_t               *bp,    /* buffer containing btree block */
 
840
        int                     rfirst, /* index of first record to log */
 
841
        int                     rlast)  /* index of last record to log */
 
842
{
 
843
        xfs_alloc_block_t       *block; /* btree block to log from */
 
844
        int                     first;  /* first byte offset logged */
 
845
        int                     last;   /* last byte offset logged */
 
846
        xfs_alloc_rec_t         *rp;    /* record pointer for btree block */
 
847
 
 
848
 
 
849
        block = XFS_BUF_TO_ALLOC_BLOCK(bp);
 
850
        rp = XFS_ALLOC_REC_ADDR(block, 1, cur);
 
851
#ifdef DEBUG
 
852
        {
 
853
                xfs_agf_t       *agf;
 
854
                xfs_alloc_rec_t *p;
 
855
 
 
856
                agf = XFS_BUF_TO_AGF(cur->bc_private.a.agbp);
 
857
                for (p = &rp[rfirst - 1]; p <= &rp[rlast - 1]; p++)
 
858
                        ASSERT(INT_GET(p->ar_startblock, ARCH_CONVERT) + INT_GET(p->ar_blockcount, ARCH_CONVERT) <=
 
859
                               INT_GET(agf->agf_length, ARCH_CONVERT));
 
860
        }
 
861
#endif
 
862
        first = (int)((xfs_caddr_t)&rp[rfirst - 1] - (xfs_caddr_t)block);
 
863
        last = (int)(((xfs_caddr_t)&rp[rlast] - 1) - (xfs_caddr_t)block);
 
864
        xfs_trans_log_buf(cur->bc_tp, bp, first, last);
 
865
}
 
866
 
 
867
/*
 
868
 * Lookup the record.  The cursor is made to point to it, based on dir.
 
869
 * Return 0 if can't find any such record, 1 for success.
 
870
 */
 
871
STATIC int                              /* error */
 
872
xfs_alloc_lookup(
 
873
        xfs_btree_cur_t         *cur,   /* btree cursor */
 
874
        xfs_lookup_t            dir,    /* <=, ==, or >= */
 
875
        int                     *stat)  /* success/failure */
 
876
{
 
877
        xfs_agblock_t           agbno;  /* a.g. relative btree block number */
 
878
        xfs_agnumber_t          agno;   /* allocation group number */
 
879
        xfs_alloc_block_t       *block=NULL;    /* current btree block */
 
880
        int                     diff;   /* difference for the current key */
 
881
        int                     error;  /* error return value */
 
882
        int                     keyno=0;        /* current key number */
 
883
        int                     level;  /* level in the btree */
 
884
        xfs_mount_t             *mp;    /* file system mount point */
 
885
 
 
886
        XFS_STATS_INC(xfsstats.xs_abt_lookup);
 
887
        /*
 
888
         * Get the allocation group header, and the root block number.
 
889
         */
 
890
        mp = cur->bc_mp;
 
891
 
 
892
        {
 
893
                xfs_agf_t       *agf;   /* a.g. freespace header */
 
894
 
 
895
                agf = XFS_BUF_TO_AGF(cur->bc_private.a.agbp);
 
896
                agno = INT_GET(agf->agf_seqno, ARCH_CONVERT);
 
897
                agbno = INT_GET(agf->agf_roots[cur->bc_btnum], ARCH_CONVERT);
 
898
        }
 
899
        /*
 
900
         * Iterate over each level in the btree, starting at the root.
 
901
         * For each level above the leaves, find the key we need, based
 
902
         * on the lookup record, then follow the corresponding block
 
903
         * pointer down to the next level.
 
904
         */
 
905
        for (level = cur->bc_nlevels - 1, diff = 1; level >= 0; level--) {
 
906
                xfs_buf_t       *bp;    /* buffer pointer for btree block */
 
907
                xfs_daddr_t     d;      /* disk address of btree block */
 
908
 
 
909
                /*
 
910
                 * Get the disk address we're looking for.
 
911
                 */
 
912
                d = XFS_AGB_TO_DADDR(mp, agno, agbno);
 
913
                /*
 
914
                 * If the old buffer at this level is for a different block,
 
915
                 * throw it away, otherwise just use it.
 
916
                 */
 
917
                bp = cur->bc_bufs[level];
 
918
                if (bp && XFS_BUF_ADDR(bp) != d)
 
919
                        bp = (xfs_buf_t *)0;
 
920
                if (!bp) {
 
921
                        /*
 
922
                         * Need to get a new buffer.  Read it, then 
 
923
                         * set it in the cursor, releasing the old one.
 
924
                         */
 
925
                        if ((error = xfs_btree_read_bufs(mp, cur->bc_tp, agno,
 
926
                                        agbno, 0, &bp, XFS_ALLOC_BTREE_REF)))
 
927
                                return error;
 
928
                        xfs_btree_setbuf(cur, level, bp);
 
929
                        /*
 
930
                         * Point to the btree block, now that we have the buffer
 
931
                         */
 
932
                        block = XFS_BUF_TO_ALLOC_BLOCK(bp);
 
933
                        if ((error = xfs_btree_check_sblock(cur, block, level,
 
934
                                        bp)))
 
935
                                return error;
 
936
                } else
 
937
                        block = XFS_BUF_TO_ALLOC_BLOCK(bp);
 
938
                /*
 
939
                 * If we already had a key match at a higher level, we know
 
940
                 * we need to use the first entry in this block.
 
941
                 */
 
942
                if (diff == 0)
 
943
                        keyno = 1;
 
944
                /*
 
945
                 * Otherwise we need to search this block.  Do a binary search.
 
946
                 */
 
947
                else {
 
948
                        int             high;   /* high entry number */
 
949
                        xfs_alloc_key_t *kkbase=NULL;/* base of keys in block */
 
950
                        xfs_alloc_rec_t *krbase=NULL;/* base of records in block */
 
951
                        int             low;    /* low entry number */
 
952
 
 
953
                        /*
 
954
                         * Get a pointer to keys or records.
 
955
                         */
 
956
                        if (level > 0)
 
957
                                kkbase = XFS_ALLOC_KEY_ADDR(block, 1, cur);
 
958
                        else
 
959
                                krbase = XFS_ALLOC_REC_ADDR(block, 1, cur);
 
960
                        /*
 
961
                         * Set low and high entry numbers, 1-based.
 
962
                         */
 
963
                        low = 1;
 
964
                        if (!(high = INT_GET(block->bb_numrecs, ARCH_CONVERT))) {
 
965
                                /*
 
966
                                 * If the block is empty, the tree must
 
967
                                 * be an empty leaf.
 
968
                                 */
 
969
                                ASSERT(level == 0 && cur->bc_nlevels == 1);
 
970
                                cur->bc_ptrs[0] = dir != XFS_LOOKUP_LE;
 
971
                                *stat = 0;
 
972
                                return 0;
 
973
                        }
 
974
                        /*
 
975
                         * Binary search the block.
 
976
                         */
 
977
                        while (low <= high) {
 
978
                                xfs_extlen_t    blockcount;     /* key value */
 
979
                                xfs_agblock_t   startblock;     /* key value */
 
980
 
 
981
                                XFS_STATS_INC(xfsstats.xs_abt_compare);
 
982
                                /*
 
983
                                 * keyno is average of low and high.
 
984
                                 */
 
985
                                keyno = (low + high) >> 1;
 
986
                                /*
 
987
                                 * Get startblock & blockcount.
 
988
                                 */
 
989
                                if (level > 0) {
 
990
                                        xfs_alloc_key_t *kkp;
 
991
 
 
992
                                        kkp = kkbase + keyno - 1;
 
993
                                        startblock = INT_GET(kkp->ar_startblock, ARCH_CONVERT);
 
994
                                        blockcount = INT_GET(kkp->ar_blockcount, ARCH_CONVERT);
 
995
                                } else {
 
996
                                        xfs_alloc_rec_t *krp;
 
997
 
 
998
                                        krp = krbase + keyno - 1;
 
999
                                        startblock = INT_GET(krp->ar_startblock, ARCH_CONVERT);
 
1000
                                        blockcount = INT_GET(krp->ar_blockcount, ARCH_CONVERT);
 
1001
                                }
 
1002
                                /*
 
1003
                                 * Compute difference to get next direction.
 
1004
                                 */
 
1005
                                if (cur->bc_btnum == XFS_BTNUM_BNO)
 
1006
                                        diff = (int)startblock -
 
1007
                                               (int)cur->bc_rec.a.ar_startblock;
 
1008
                                else if (!(diff = (int)blockcount -
 
1009
                                            (int)cur->bc_rec.a.ar_blockcount))
 
1010
                                        diff = (int)startblock -
 
1011
                                            (int)cur->bc_rec.a.ar_startblock;
 
1012
                                /*
 
1013
                                 * Less than, move right.
 
1014
                                 */
 
1015
                                if (diff < 0)
 
1016
                                        low = keyno + 1;
 
1017
                                /*
 
1018
                                 * Greater than, move left.
 
1019
                                 */
 
1020
                                else if (diff > 0)
 
1021
                                        high = keyno - 1;
 
1022
                                /*
 
1023
                                 * Equal, we're done.
 
1024
                                 */
 
1025
                                else
 
1026
                                        break;
 
1027
                        }
 
1028
                }
 
1029
                /*
 
1030
                 * If there are more levels, set up for the next level
 
1031
                 * by getting the block number and filling in the cursor.
 
1032
                 */
 
1033
                if (level > 0) {
 
1034
                        /*
 
1035
                         * If we moved left, need the previous key number,
 
1036
                         * unless there isn't one.
 
1037
                         */
 
1038
                        if (diff > 0 && --keyno < 1)
 
1039
                                keyno = 1;
 
1040
                        agbno = INT_GET(*XFS_ALLOC_PTR_ADDR(block, keyno, cur), ARCH_CONVERT);
 
1041
#ifdef DEBUG
 
1042
                        if ((error = xfs_btree_check_sptr(cur, agbno, level)))
 
1043
                                return error;
 
1044
#endif
 
1045
                        cur->bc_ptrs[level] = keyno;
 
1046
                }
 
1047
        }
 
1048
        /*
 
1049
         * Done with the search.
 
1050
         * See if we need to adjust the results.
 
1051
         */
 
1052
        if (dir != XFS_LOOKUP_LE && diff < 0) {
 
1053
                keyno++;
 
1054
                /*
 
1055
                 * If ge search and we went off the end of the block, but it's
 
1056
                 * not the last block, we're in the wrong block.
 
1057
                 */
 
1058
                if (dir == XFS_LOOKUP_GE &&
 
1059
                    keyno > INT_GET(block->bb_numrecs, ARCH_CONVERT) &&
 
1060
                    INT_GET(block->bb_rightsib, ARCH_CONVERT) != NULLAGBLOCK) {
 
1061
                        int     i;
 
1062
 
 
1063
                        cur->bc_ptrs[0] = keyno;
 
1064
                        if ((error = xfs_alloc_increment(cur, 0, &i)))
 
1065
                                return error;
 
1066
                        XFS_WANT_CORRUPTED_RETURN(i == 1);
 
1067
                        *stat = 1;
 
1068
                        return 0;
 
1069
                }
 
1070
        }
 
1071
        else if (dir == XFS_LOOKUP_LE && diff > 0)
 
1072
                keyno--;
 
1073
        cur->bc_ptrs[0] = keyno;
 
1074
        /*
 
1075
         * Return if we succeeded or not.
 
1076
         */
 
1077
        if (keyno == 0 || keyno > INT_GET(block->bb_numrecs, ARCH_CONVERT))
 
1078
                *stat = 0;
 
1079
        else
 
1080
                *stat = ((dir != XFS_LOOKUP_EQ) || (diff == 0));
 
1081
        return 0;
 
1082
}
 
1083
 
 
1084
/*
 
1085
 * Move 1 record left from cur/level if possible.
 
1086
 * Update cur to reflect the new path.
 
1087
 */
 
1088
STATIC int                              /* error */
 
1089
xfs_alloc_lshift(
 
1090
        xfs_btree_cur_t         *cur,   /* btree cursor */
 
1091
        int                     level,  /* level to shift record on */
 
1092
        int                     *stat)  /* success/failure */
 
1093
{
 
1094
        int                     error;  /* error return value */
 
1095
#ifdef DEBUG
 
1096
        int                     i;      /* loop index */
 
1097
#endif
 
1098
        xfs_alloc_key_t         key;    /* key value for leaf level upward */
 
1099
        xfs_buf_t               *lbp;   /* buffer for left neighbor block */
 
1100
        xfs_alloc_block_t       *left;  /* left neighbor btree block */
 
1101
        int                     nrec;   /* new number of left block entries */
 
1102
        xfs_buf_t               *rbp;   /* buffer for right (current) block */
 
1103
        xfs_alloc_block_t       *right; /* right (current) btree block */
 
1104
        xfs_alloc_key_t         *rkp=NULL;      /* key pointer for right block */
 
1105
        xfs_alloc_ptr_t         *rpp=NULL;      /* address pointer for right block */
 
1106
        xfs_alloc_rec_t         *rrp=NULL;      /* record pointer for right block */
 
1107
 
 
1108
        /*
 
1109
         * Set up variables for this block as "right".
 
1110
         */
 
1111
        rbp = cur->bc_bufs[level];
 
1112
        right = XFS_BUF_TO_ALLOC_BLOCK(rbp);
 
1113
#ifdef DEBUG
 
1114
        if ((error = xfs_btree_check_sblock(cur, right, level, rbp)))
 
1115
                return error;
 
1116
#endif
 
1117
        /*
 
1118
         * If we've got no left sibling then we can't shift an entry left.
 
1119
         */
 
1120
        if (INT_GET(right->bb_leftsib, ARCH_CONVERT) == NULLAGBLOCK) {
 
1121
                *stat = 0;
 
1122
                return 0;
 
1123
        }
 
1124
        /*
 
1125
         * If the cursor entry is the one that would be moved, don't 
 
1126
         * do it... it's too complicated.
 
1127
         */
 
1128
        if (cur->bc_ptrs[level] <= 1) {
 
1129
                *stat = 0;
 
1130
                return 0;
 
1131
        }
 
1132
        /*
 
1133
         * Set up the left neighbor as "left".
 
1134
         */
 
1135
        if ((error = xfs_btree_read_bufs(cur->bc_mp, cur->bc_tp,
 
1136
                        cur->bc_private.a.agno, INT_GET(right->bb_leftsib, ARCH_CONVERT), 0, &lbp,
 
1137
                        XFS_ALLOC_BTREE_REF)))
 
1138
                return error;
 
1139
        left = XFS_BUF_TO_ALLOC_BLOCK(lbp);
 
1140
        if ((error = xfs_btree_check_sblock(cur, left, level, lbp)))
 
1141
                return error;
 
1142
        /*
 
1143
         * If it's full, it can't take another entry.
 
1144
         */
 
1145
        if (INT_GET(left->bb_numrecs, ARCH_CONVERT) == XFS_ALLOC_BLOCK_MAXRECS(level, cur)) {
 
1146
                *stat = 0;
 
1147
                return 0;
 
1148
        }
 
1149
        nrec = INT_GET(left->bb_numrecs, ARCH_CONVERT) + 1;
 
1150
        /*
 
1151
         * If non-leaf, copy a key and a ptr to the left block.
 
1152
         */
 
1153
        if (level > 0) {
 
1154
                xfs_alloc_key_t *lkp;   /* key pointer for left block */
 
1155
                xfs_alloc_ptr_t *lpp;   /* address pointer for left block */
 
1156
 
 
1157
                lkp = XFS_ALLOC_KEY_ADDR(left, nrec, cur);
 
1158
                rkp = XFS_ALLOC_KEY_ADDR(right, 1, cur);
 
1159
                *lkp = *rkp;
 
1160
                xfs_alloc_log_keys(cur, lbp, nrec, nrec);
 
1161
                lpp = XFS_ALLOC_PTR_ADDR(left, nrec, cur);
 
1162
                rpp = XFS_ALLOC_PTR_ADDR(right, 1, cur);
 
1163
#ifdef DEBUG
 
1164
                if ((error = xfs_btree_check_sptr(cur, INT_GET(*rpp, ARCH_CONVERT), level)))
 
1165
                        return error;
 
1166
#endif
 
1167
                *lpp = *rpp; /* INT_: copy */
 
1168
                xfs_alloc_log_ptrs(cur, lbp, nrec, nrec);
 
1169
                xfs_btree_check_key(cur->bc_btnum, lkp - 1, lkp);
 
1170
        }
 
1171
        /*
 
1172
         * If leaf, copy a record to the left block.
 
1173
         */
 
1174
        else {
 
1175
                xfs_alloc_rec_t *lrp;   /* record pointer for left block */
 
1176
 
 
1177
                lrp = XFS_ALLOC_REC_ADDR(left, nrec, cur);
 
1178
                rrp = XFS_ALLOC_REC_ADDR(right, 1, cur);
 
1179
                *lrp = *rrp;
 
1180
                xfs_alloc_log_recs(cur, lbp, nrec, nrec);
 
1181
                xfs_btree_check_rec(cur->bc_btnum, lrp - 1, lrp);
 
1182
        }
 
1183
        /*
 
1184
         * Bump and log left's numrecs, decrement and log right's numrecs.
 
1185
         */
 
1186
        INT_MOD(left->bb_numrecs, ARCH_CONVERT, +1);
 
1187
        xfs_alloc_log_block(cur->bc_tp, lbp, XFS_BB_NUMRECS);
 
1188
        INT_MOD(right->bb_numrecs, ARCH_CONVERT, -1);
 
1189
        xfs_alloc_log_block(cur->bc_tp, rbp, XFS_BB_NUMRECS);
 
1190
        /*
 
1191
         * Slide the contents of right down one entry.
 
1192
         */
 
1193
        if (level > 0) {
 
1194
#ifdef DEBUG
 
1195
                for (i = 0; i < INT_GET(right->bb_numrecs, ARCH_CONVERT); i++) {
 
1196
                        if ((error = xfs_btree_check_sptr(cur, INT_GET(rpp[i + 1], ARCH_CONVERT),
 
1197
                                        level)))
 
1198
                                return error;
 
1199
                }
 
1200
#endif
 
1201
                ovbcopy(rkp + 1, rkp, INT_GET(right->bb_numrecs, ARCH_CONVERT) * sizeof(*rkp));
 
1202
                ovbcopy(rpp + 1, rpp, INT_GET(right->bb_numrecs, ARCH_CONVERT) * sizeof(*rpp));
 
1203
                xfs_alloc_log_keys(cur, rbp, 1, INT_GET(right->bb_numrecs, ARCH_CONVERT));
 
1204
                xfs_alloc_log_ptrs(cur, rbp, 1, INT_GET(right->bb_numrecs, ARCH_CONVERT));
 
1205
        } else {
 
1206
                ovbcopy(rrp + 1, rrp, INT_GET(right->bb_numrecs, ARCH_CONVERT) * sizeof(*rrp));
 
1207
                xfs_alloc_log_recs(cur, rbp, 1, INT_GET(right->bb_numrecs, ARCH_CONVERT));
 
1208
                key.ar_startblock = rrp->ar_startblock; /* INT_: direct copy */
 
1209
                key.ar_blockcount = rrp->ar_blockcount; /* INT_: direct copy */
 
1210
                rkp = &key;
 
1211
        }
 
1212
        /*
 
1213
         * Update the parent key values of right.
 
1214
         */
 
1215
        if ((error = xfs_alloc_updkey(cur, rkp, level + 1)))
 
1216
                return error;
 
1217
        /*
 
1218
         * Slide the cursor value left one.
 
1219
         */
 
1220
        cur->bc_ptrs[level]--;
 
1221
        *stat = 1;
 
1222
        return 0;
 
1223
}
 
1224
 
 
1225
/*
 
1226
 * Allocate a new root block, fill it in.
 
1227
 */
 
1228
STATIC int                              /* error */
 
1229
xfs_alloc_newroot(
 
1230
        xfs_btree_cur_t         *cur,   /* btree cursor */
 
1231
        int                     *stat)  /* success/failure */
 
1232
{
 
1233
        int                     error;  /* error return value */
 
1234
        xfs_agblock_t           lbno;   /* left block number */
 
1235
        xfs_buf_t               *lbp;   /* left btree buffer */
 
1236
        xfs_alloc_block_t       *left;  /* left btree block */
 
1237
        xfs_mount_t             *mp;    /* mount structure */
 
1238
        xfs_agblock_t           nbno;   /* new block number */
 
1239
        xfs_buf_t               *nbp;   /* new (root) buffer */
 
1240
        xfs_alloc_block_t       *new;   /* new (root) btree block */
 
1241
        int                     nptr;   /* new value for key index, 1 or 2 */
 
1242
        xfs_agblock_t           rbno;   /* right block number */
 
1243
        xfs_buf_t               *rbp;   /* right btree buffer */
 
1244
        xfs_alloc_block_t       *right; /* right btree block */
 
1245
 
 
1246
        mp = cur->bc_mp;
 
1247
 
 
1248
        ASSERT(cur->bc_nlevels < XFS_AG_MAXLEVELS(mp));
 
1249
        /*
 
1250
         * Get a buffer from the freelist blocks, for the new root.
 
1251
         */
 
1252
        if ((error = xfs_alloc_get_freelist(cur->bc_tp, cur->bc_private.a.agbp,
 
1253
                        &nbno)))
 
1254
                return error;
 
1255
        /*
 
1256
         * None available, we fail.
 
1257
         */
 
1258
        if (nbno == NULLAGBLOCK) {
 
1259
                *stat = 0;
 
1260
                return 0;
 
1261
        }
 
1262
        xfs_trans_agbtree_delta(cur->bc_tp, 1);
 
1263
        nbp = xfs_btree_get_bufs(mp, cur->bc_tp, cur->bc_private.a.agno, nbno,
 
1264
                0);
 
1265
        new = XFS_BUF_TO_ALLOC_BLOCK(nbp);
 
1266
        /*
 
1267
         * Set the root data in the a.g. freespace structure.
 
1268
         */
 
1269
        {
 
1270
                xfs_agf_t       *agf;   /* a.g. freespace header */
 
1271
                xfs_agnumber_t  seqno;
 
1272
 
 
1273
                agf = XFS_BUF_TO_AGF(cur->bc_private.a.agbp);
 
1274
                INT_SET(agf->agf_roots[cur->bc_btnum], ARCH_CONVERT, nbno);
 
1275
                INT_MOD(agf->agf_levels[cur->bc_btnum], ARCH_CONVERT, 1);
 
1276
                seqno = INT_GET(agf->agf_seqno, ARCH_CONVERT);
 
1277
                mp->m_perag[seqno].pagf_levels[cur->bc_btnum]++;
 
1278
                xfs_alloc_log_agf(cur->bc_tp, cur->bc_private.a.agbp,
 
1279
                        XFS_AGF_ROOTS | XFS_AGF_LEVELS);
 
1280
        }
 
1281
        /*
 
1282
         * At the previous root level there are now two blocks: the old
 
1283
         * root, and the new block generated when it was split.
 
1284
         * We don't know which one the cursor is pointing at, so we
 
1285
         * set up variables "left" and "right" for each case.
 
1286
         */
 
1287
        lbp = cur->bc_bufs[cur->bc_nlevels - 1];
 
1288
        left = XFS_BUF_TO_ALLOC_BLOCK(lbp);
 
1289
#ifdef DEBUG
 
1290
        if ((error = xfs_btree_check_sblock(cur, left, cur->bc_nlevels - 1, lbp)))
 
1291
                return error;
 
1292
#endif
 
1293
        if (INT_GET(left->bb_rightsib, ARCH_CONVERT) != NULLAGBLOCK) {
 
1294
                /*
 
1295
                 * Our block is left, pick up the right block.
 
1296
                 */
 
1297
                lbno = XFS_DADDR_TO_AGBNO(mp, XFS_BUF_ADDR(lbp));
 
1298
                rbno = INT_GET(left->bb_rightsib, ARCH_CONVERT);
 
1299
                if ((error = xfs_btree_read_bufs(mp, cur->bc_tp,
 
1300
                                cur->bc_private.a.agno, rbno, 0, &rbp,
 
1301
                                XFS_ALLOC_BTREE_REF)))
 
1302
                        return error;
 
1303
                right = XFS_BUF_TO_ALLOC_BLOCK(rbp);
 
1304
                if ((error = xfs_btree_check_sblock(cur, right,
 
1305
                                cur->bc_nlevels - 1, rbp)))
 
1306
                        return error;
 
1307
                nptr = 1;
 
1308
        } else {
 
1309
                /*
 
1310
                 * Our block is right, pick up the left block.
 
1311
                 */
 
1312
                rbp = lbp;
 
1313
                right = left;
 
1314
                rbno = XFS_DADDR_TO_AGBNO(mp, XFS_BUF_ADDR(rbp));
 
1315
                lbno = INT_GET(right->bb_leftsib, ARCH_CONVERT);
 
1316
                if ((error = xfs_btree_read_bufs(mp, cur->bc_tp,
 
1317
                                cur->bc_private.a.agno, lbno, 0, &lbp,
 
1318
                                XFS_ALLOC_BTREE_REF)))
 
1319
                        return error;
 
1320
                left = XFS_BUF_TO_ALLOC_BLOCK(lbp);
 
1321
                if ((error = xfs_btree_check_sblock(cur, left,
 
1322
                                cur->bc_nlevels - 1, lbp)))
 
1323
                        return error;
 
1324
                nptr = 2;
 
1325
        }
 
1326
        /*
 
1327
         * Fill in the new block's btree header and log it.
 
1328
         */
 
1329
        INT_SET(new->bb_magic, ARCH_CONVERT, xfs_magics[cur->bc_btnum]);
 
1330
        INT_SET(new->bb_level, ARCH_CONVERT, (__uint16_t)cur->bc_nlevels);
 
1331
        INT_SET(new->bb_numrecs, ARCH_CONVERT, 2);
 
1332
        INT_SET(new->bb_leftsib, ARCH_CONVERT, NULLAGBLOCK);
 
1333
        INT_SET(new->bb_rightsib, ARCH_CONVERT, NULLAGBLOCK);
 
1334
        xfs_alloc_log_block(cur->bc_tp, nbp, XFS_BB_ALL_BITS);
 
1335
        ASSERT(lbno != NULLAGBLOCK && rbno != NULLAGBLOCK);
 
1336
        /*
 
1337
         * Fill in the key data in the new root.
 
1338
         */
 
1339
        {
 
1340
                xfs_alloc_key_t         *kp;    /* btree key pointer */
 
1341
 
 
1342
                kp = XFS_ALLOC_KEY_ADDR(new, 1, cur);
 
1343
                if (INT_GET(left->bb_level, ARCH_CONVERT) > 0) {
 
1344
                        kp[0] = *XFS_ALLOC_KEY_ADDR(left, 1, cur); /* INT_: structure copy */
 
1345
                        kp[1] = *XFS_ALLOC_KEY_ADDR(right, 1, cur);/* INT_: structure copy */
 
1346
                } else {
 
1347
                        xfs_alloc_rec_t *rp;    /* btree record pointer */
 
1348
 
 
1349
                        rp = XFS_ALLOC_REC_ADDR(left, 1, cur);
 
1350
                        kp[0].ar_startblock = rp->ar_startblock; /* INT_: direct copy */
 
1351
                        kp[0].ar_blockcount = rp->ar_blockcount; /* INT_: direct copy */
 
1352
                        rp = XFS_ALLOC_REC_ADDR(right, 1, cur);
 
1353
                        kp[1].ar_startblock = rp->ar_startblock; /* INT_: direct copy */
 
1354
                        kp[1].ar_blockcount = rp->ar_blockcount; /* INT_: direct copy */
 
1355
                }
 
1356
        }
 
1357
        xfs_alloc_log_keys(cur, nbp, 1, 2);
 
1358
        /*
 
1359
         * Fill in the pointer data in the new root.
 
1360
         */
 
1361
        {
 
1362
                xfs_alloc_ptr_t         *pp;    /* btree address pointer */
 
1363
 
 
1364
                pp = XFS_ALLOC_PTR_ADDR(new, 1, cur);
 
1365
                INT_SET(pp[0], ARCH_CONVERT, lbno);
 
1366
                INT_SET(pp[1], ARCH_CONVERT, rbno);
 
1367
        }
 
1368
        xfs_alloc_log_ptrs(cur, nbp, 1, 2);
 
1369
        /*
 
1370
         * Fix up the cursor.
 
1371
         */
 
1372
        xfs_btree_setbuf(cur, cur->bc_nlevels, nbp);
 
1373
        cur->bc_ptrs[cur->bc_nlevels] = nptr;
 
1374
        cur->bc_nlevels++;
 
1375
        *stat = 1;
 
1376
        return 0;
 
1377
}
 
1378
 
 
1379
/*
 
1380
 * Move 1 record right from cur/level if possible.
 
1381
 * Update cur to reflect the new path.
 
1382
 */
 
1383
STATIC int                              /* error */
 
1384
xfs_alloc_rshift(
 
1385
        xfs_btree_cur_t         *cur,   /* btree cursor */
 
1386
        int                     level,  /* level to shift record on */
 
1387
        int                     *stat)  /* success/failure */
 
1388
{
 
1389
        int                     error;  /* error return value */
 
1390
        int                     i;      /* loop index */
 
1391
        xfs_alloc_key_t         key;    /* key value for leaf level upward */
 
1392
        xfs_buf_t               *lbp;   /* buffer for left (current) block */
 
1393
        xfs_alloc_block_t       *left;  /* left (current) btree block */
 
1394
        xfs_buf_t               *rbp;   /* buffer for right neighbor block */
 
1395
        xfs_alloc_block_t       *right; /* right neighbor btree block */
 
1396
        xfs_alloc_key_t         *rkp;   /* key pointer for right block */
 
1397
        xfs_btree_cur_t         *tcur;  /* temporary cursor */
 
1398
 
 
1399
        /*
 
1400
         * Set up variables for this block as "left".
 
1401
         */
 
1402
        lbp = cur->bc_bufs[level];
 
1403
        left = XFS_BUF_TO_ALLOC_BLOCK(lbp);
 
1404
#ifdef DEBUG
 
1405
        if ((error = xfs_btree_check_sblock(cur, left, level, lbp)))
 
1406
                return error;
 
1407
#endif
 
1408
        /*
 
1409
         * If we've got no right sibling then we can't shift an entry right.
 
1410
         */
 
1411
        if (INT_GET(left->bb_rightsib, ARCH_CONVERT) == NULLAGBLOCK) {
 
1412
                *stat = 0;
 
1413
                return 0;
 
1414
        }
 
1415
        /*
 
1416
         * If the cursor entry is the one that would be moved, don't
 
1417
         * do it... it's too complicated.
 
1418
         */
 
1419
        if (cur->bc_ptrs[level] >= INT_GET(left->bb_numrecs, ARCH_CONVERT)) {
 
1420
                *stat = 0;
 
1421
                return 0;
 
1422
        }
 
1423
        /*
 
1424
         * Set up the right neighbor as "right".
 
1425
         */
 
1426
        if ((error = xfs_btree_read_bufs(cur->bc_mp, cur->bc_tp,
 
1427
                        cur->bc_private.a.agno, INT_GET(left->bb_rightsib, ARCH_CONVERT), 0, &rbp,
 
1428
                        XFS_ALLOC_BTREE_REF)))
 
1429
                return error;
 
1430
        right = XFS_BUF_TO_ALLOC_BLOCK(rbp);
 
1431
        if ((error = xfs_btree_check_sblock(cur, right, level, rbp)))
 
1432
                return error;
 
1433
        /*
 
1434
         * If it's full, it can't take another entry.
 
1435
         */
 
1436
        if (INT_GET(right->bb_numrecs, ARCH_CONVERT) == XFS_ALLOC_BLOCK_MAXRECS(level, cur)) {
 
1437
                *stat = 0;
 
1438
                return 0;
 
1439
        }
 
1440
        /*
 
1441
         * Make a hole at the start of the right neighbor block, then
 
1442
         * copy the last left block entry to the hole.
 
1443
         */
 
1444
        if (level > 0) {
 
1445
                xfs_alloc_key_t *lkp;   /* key pointer for left block */
 
1446
                xfs_alloc_ptr_t *lpp;   /* address pointer for left block */
 
1447
                xfs_alloc_ptr_t *rpp;   /* address pointer for right block */
 
1448
 
 
1449
                lkp = XFS_ALLOC_KEY_ADDR(left, INT_GET(left->bb_numrecs, ARCH_CONVERT), cur);
 
1450
                lpp = XFS_ALLOC_PTR_ADDR(left, INT_GET(left->bb_numrecs, ARCH_CONVERT), cur);
 
1451
                rkp = XFS_ALLOC_KEY_ADDR(right, 1, cur);
 
1452
                rpp = XFS_ALLOC_PTR_ADDR(right, 1, cur);
 
1453
#ifdef DEBUG
 
1454
                for (i = INT_GET(right->bb_numrecs, ARCH_CONVERT) - 1; i >= 0; i--) {
 
1455
                        if ((error = xfs_btree_check_sptr(cur, INT_GET(rpp[i], ARCH_CONVERT), level)))
 
1456
                                return error;
 
1457
                }
 
1458
#endif
 
1459
                ovbcopy(rkp, rkp + 1, INT_GET(right->bb_numrecs, ARCH_CONVERT) * sizeof(*rkp));
 
1460
                ovbcopy(rpp, rpp + 1, INT_GET(right->bb_numrecs, ARCH_CONVERT) * sizeof(*rpp));
 
1461
#ifdef DEBUG
 
1462
                if ((error = xfs_btree_check_sptr(cur, INT_GET(*lpp, ARCH_CONVERT), level)))
 
1463
                        return error;
 
1464
#endif
 
1465
                *rkp = *lkp; /* INT_: copy */
 
1466
                *rpp = *lpp; /* INT_: copy */
 
1467
                xfs_alloc_log_keys(cur, rbp, 1, INT_GET(right->bb_numrecs, ARCH_CONVERT) + 1);
 
1468
                xfs_alloc_log_ptrs(cur, rbp, 1, INT_GET(right->bb_numrecs, ARCH_CONVERT) + 1);
 
1469
                xfs_btree_check_key(cur->bc_btnum, rkp, rkp + 1);
 
1470
        } else {
 
1471
                xfs_alloc_rec_t *lrp;   /* record pointer for left block */
 
1472
                xfs_alloc_rec_t *rrp;   /* record pointer for right block */
 
1473
 
 
1474
                lrp = XFS_ALLOC_REC_ADDR(left, INT_GET(left->bb_numrecs, ARCH_CONVERT), cur);
 
1475
                rrp = XFS_ALLOC_REC_ADDR(right, 1, cur);
 
1476
                ovbcopy(rrp, rrp + 1, INT_GET(right->bb_numrecs, ARCH_CONVERT) * sizeof(*rrp));
 
1477
                *rrp = *lrp;
 
1478
                xfs_alloc_log_recs(cur, rbp, 1, INT_GET(right->bb_numrecs, ARCH_CONVERT) + 1);
 
1479
                key.ar_startblock = rrp->ar_startblock; /* INT_: direct copy */
 
1480
                key.ar_blockcount = rrp->ar_blockcount; /* INT_: direct copy */
 
1481
                rkp = &key;
 
1482
                xfs_btree_check_rec(cur->bc_btnum, rrp, rrp + 1);
 
1483
        }
 
1484
        /*
 
1485
         * Decrement and log left's numrecs, bump and log right's numrecs.
 
1486
         */
 
1487
        INT_MOD(left->bb_numrecs, ARCH_CONVERT, -1);
 
1488
        xfs_alloc_log_block(cur->bc_tp, lbp, XFS_BB_NUMRECS);
 
1489
        INT_MOD(right->bb_numrecs, ARCH_CONVERT, +1);
 
1490
        xfs_alloc_log_block(cur->bc_tp, rbp, XFS_BB_NUMRECS);
 
1491
        /*
 
1492
         * Using a temporary cursor, update the parent key values of the
 
1493
         * block on the right.
 
1494
         */
 
1495
        if ((error = xfs_btree_dup_cursor(cur, &tcur)))
 
1496
                return error;
 
1497
        i = xfs_btree_lastrec(tcur, level);
 
1498
        XFS_WANT_CORRUPTED_GOTO(i == 1, error0);
 
1499
        if ((error = xfs_alloc_increment(tcur, level, &i)) ||
 
1500
            (error = xfs_alloc_updkey(tcur, rkp, level + 1)))
 
1501
                goto error0;
 
1502
        xfs_btree_del_cursor(tcur, XFS_BTREE_NOERROR);
 
1503
        *stat = 1;
 
1504
        return 0;
 
1505
error0:
 
1506
        xfs_btree_del_cursor(tcur, XFS_BTREE_ERROR);
 
1507
        return error;
 
1508
}
 
1509
 
 
1510
/*
 
1511
 * Split cur/level block in half.
 
1512
 * Return new block number and its first record (to be inserted into parent).
 
1513
 */
 
1514
STATIC int                              /* error */
 
1515
xfs_alloc_split(
 
1516
        xfs_btree_cur_t         *cur,   /* btree cursor */
 
1517
        int                     level,  /* level to split */
 
1518
        xfs_agblock_t           *bnop,  /* output: block number allocated */
 
1519
        xfs_alloc_key_t         *keyp,  /* output: first key of new block */
 
1520
        xfs_btree_cur_t         **curp, /* output: new cursor */
 
1521
        int                     *stat)  /* success/failure */
 
1522
{
 
1523
        int                     error;  /* error return value */
 
1524
        int                     i;      /* loop index/record number */
 
1525
        xfs_agblock_t           lbno;   /* left (current) block number */
 
1526
        xfs_buf_t               *lbp;   /* buffer for left block */
 
1527
        xfs_alloc_block_t       *left;  /* left (current) btree block */
 
1528
        xfs_agblock_t           rbno;   /* right (new) block number */
 
1529
        xfs_buf_t               *rbp;   /* buffer for right block */
 
1530
        xfs_alloc_block_t       *right; /* right (new) btree block */
 
1531
 
 
1532
        /*
 
1533
         * Allocate the new block from the freelist.
 
1534
         * If we can't do it, we're toast.  Give up.
 
1535
         */
 
1536
        if ((error = xfs_alloc_get_freelist(cur->bc_tp, cur->bc_private.a.agbp,
 
1537
                        &rbno)))
 
1538
                return error;
 
1539
        if (rbno == NULLAGBLOCK) {
 
1540
                *stat = 0;
 
1541
                return 0;
 
1542
        }
 
1543
        xfs_trans_agbtree_delta(cur->bc_tp, 1);
 
1544
        rbp = xfs_btree_get_bufs(cur->bc_mp, cur->bc_tp, cur->bc_private.a.agno,
 
1545
                rbno, 0);
 
1546
        /*
 
1547
         * Set up the new block as "right".
 
1548
         */
 
1549
        right = XFS_BUF_TO_ALLOC_BLOCK(rbp);
 
1550
        /*
 
1551
         * "Left" is the current (according to the cursor) block.
 
1552
         */
 
1553
        lbp = cur->bc_bufs[level];
 
1554
        left = XFS_BUF_TO_ALLOC_BLOCK(lbp);
 
1555
#ifdef DEBUG
 
1556
        if ((error = xfs_btree_check_sblock(cur, left, level, lbp)))
 
1557
                return error;
 
1558
#endif
 
1559
        /*
 
1560
         * Fill in the btree header for the new block.
 
1561
         */
 
1562
        INT_SET(right->bb_magic, ARCH_CONVERT, xfs_magics[cur->bc_btnum]);
 
1563
        right->bb_level = left->bb_level; /* INT_: direct copy */
 
1564
        INT_SET(right->bb_numrecs, ARCH_CONVERT, (__uint16_t)(INT_GET(left->bb_numrecs, ARCH_CONVERT) / 2));
 
1565
        /*
 
1566
         * Make sure that if there's an odd number of entries now, that
 
1567
         * each new block will have the same number of entries.
 
1568
         */
 
1569
        if ((INT_GET(left->bb_numrecs, ARCH_CONVERT) & 1) &&
 
1570
            cur->bc_ptrs[level] <= INT_GET(right->bb_numrecs, ARCH_CONVERT) + 1)
 
1571
                INT_MOD(right->bb_numrecs, ARCH_CONVERT, +1);
 
1572
        i = INT_GET(left->bb_numrecs, ARCH_CONVERT) - INT_GET(right->bb_numrecs, ARCH_CONVERT) + 1;
 
1573
        /*
 
1574
         * For non-leaf blocks, copy keys and addresses over to the new block.
 
1575
         */
 
1576
        if (level > 0) {
 
1577
                xfs_alloc_key_t *lkp;   /* left btree key pointer */
 
1578
                xfs_alloc_ptr_t *lpp;   /* left btree address pointer */
 
1579
                xfs_alloc_key_t *rkp;   /* right btree key pointer */
 
1580
                xfs_alloc_ptr_t *rpp;   /* right btree address pointer */
 
1581
 
 
1582
                lkp = XFS_ALLOC_KEY_ADDR(left, i, cur);
 
1583
                lpp = XFS_ALLOC_PTR_ADDR(left, i, cur);
 
1584
                rkp = XFS_ALLOC_KEY_ADDR(right, 1, cur);
 
1585
                rpp = XFS_ALLOC_PTR_ADDR(right, 1, cur);
 
1586
#ifdef DEBUG
 
1587
                for (i = 0; i < INT_GET(right->bb_numrecs, ARCH_CONVERT); i++) {
 
1588
                        if ((error = xfs_btree_check_sptr(cur, INT_GET(lpp[i], ARCH_CONVERT), level)))
 
1589
                                return error;
 
1590
                }
 
1591
#endif
 
1592
                bcopy(lkp, rkp, INT_GET(right->bb_numrecs, ARCH_CONVERT) * sizeof(*rkp)); /* INT_: copy */
 
1593
                bcopy(lpp, rpp, INT_GET(right->bb_numrecs, ARCH_CONVERT) * sizeof(*rpp));/* INT_: copy */
 
1594
                xfs_alloc_log_keys(cur, rbp, 1, INT_GET(right->bb_numrecs, ARCH_CONVERT));
 
1595
                xfs_alloc_log_ptrs(cur, rbp, 1, INT_GET(right->bb_numrecs, ARCH_CONVERT));
 
1596
                *keyp = *rkp;
 
1597
        }
 
1598
        /*
 
1599
         * For leaf blocks, copy records over to the new block.
 
1600
         */
 
1601
        else {
 
1602
                xfs_alloc_rec_t *lrp;   /* left btree record pointer */
 
1603
                xfs_alloc_rec_t *rrp;   /* right btree record pointer */
 
1604
 
 
1605
                lrp = XFS_ALLOC_REC_ADDR(left, i, cur);
 
1606
                rrp = XFS_ALLOC_REC_ADDR(right, 1, cur);
 
1607
                bcopy(lrp, rrp, INT_GET(right->bb_numrecs, ARCH_CONVERT) * sizeof(*rrp));
 
1608
                xfs_alloc_log_recs(cur, rbp, 1, INT_GET(right->bb_numrecs, ARCH_CONVERT));
 
1609
                keyp->ar_startblock = rrp->ar_startblock; /* INT_: direct copy */
 
1610
                keyp->ar_blockcount = rrp->ar_blockcount; /* INT_: direct copy */
 
1611
        }
 
1612
        /*
 
1613
         * Find the left block number by looking in the buffer.
 
1614
         * Adjust numrecs, sibling pointers.
 
1615
         */
 
1616
        lbno = XFS_DADDR_TO_AGBNO(cur->bc_mp, XFS_BUF_ADDR(lbp));
 
1617
        INT_MOD(left->bb_numrecs, ARCH_CONVERT, -(INT_GET(right->bb_numrecs, ARCH_CONVERT)));
 
1618
        right->bb_rightsib = left->bb_rightsib; /* INT_: direct copy */
 
1619
        INT_SET(left->bb_rightsib, ARCH_CONVERT, rbno);
 
1620
        INT_SET(right->bb_leftsib, ARCH_CONVERT, lbno);
 
1621
        xfs_alloc_log_block(cur->bc_tp, rbp, XFS_BB_ALL_BITS);
 
1622
        xfs_alloc_log_block(cur->bc_tp, lbp, XFS_BB_NUMRECS | XFS_BB_RIGHTSIB);
 
1623
        /*
 
1624
         * If there's a block to the new block's right, make that block
 
1625
         * point back to right instead of to left.
 
1626
         */
 
1627
        if (INT_GET(right->bb_rightsib, ARCH_CONVERT) != NULLAGBLOCK) {
 
1628
                xfs_alloc_block_t       *rrblock;       /* rr btree block */
 
1629
                xfs_buf_t               *rrbp;          /* buffer for rrblock */
 
1630
 
 
1631
                if ((error = xfs_btree_read_bufs(cur->bc_mp, cur->bc_tp,
 
1632
                                cur->bc_private.a.agno, INT_GET(right->bb_rightsib, ARCH_CONVERT), 0,
 
1633
                                &rrbp, XFS_ALLOC_BTREE_REF)))
 
1634
                        return error;
 
1635
                rrblock = XFS_BUF_TO_ALLOC_BLOCK(rrbp);
 
1636
                if ((error = xfs_btree_check_sblock(cur, rrblock, level, rrbp)))
 
1637
                        return error;
 
1638
                INT_SET(rrblock->bb_leftsib, ARCH_CONVERT, rbno);
 
1639
                xfs_alloc_log_block(cur->bc_tp, rrbp, XFS_BB_LEFTSIB);
 
1640
        }
 
1641
        /*
 
1642
         * If the cursor is really in the right block, move it there.
 
1643
         * If it's just pointing past the last entry in left, then we'll
 
1644
         * insert there, so don't change anything in that case.
 
1645
         */
 
1646
        if (cur->bc_ptrs[level] > INT_GET(left->bb_numrecs, ARCH_CONVERT) + 1) {
 
1647
                xfs_btree_setbuf(cur, level, rbp);
 
1648
                cur->bc_ptrs[level] -= INT_GET(left->bb_numrecs, ARCH_CONVERT);
 
1649
        }
 
1650
        /*
 
1651
         * If there are more levels, we'll need another cursor which refers to
 
1652
         * the right block, no matter where this cursor was.
 
1653
         */
 
1654
        if (level + 1 < cur->bc_nlevels) {
 
1655
                if ((error = xfs_btree_dup_cursor(cur, curp)))
 
1656
                        return error;
 
1657
                (*curp)->bc_ptrs[level + 1]++;
 
1658
        }
 
1659
        *bnop = rbno;
 
1660
        *stat = 1;
 
1661
        return 0;
 
1662
}
 
1663
 
 
1664
/*
 
1665
 * Update keys at all levels from here to the root along the cursor's path.
 
1666
 */
 
1667
STATIC int                              /* error */
 
1668
xfs_alloc_updkey(
 
1669
        xfs_btree_cur_t         *cur,   /* btree cursor */
 
1670
        xfs_alloc_key_t         *keyp,  /* new key value to update to */
 
1671
        int                     level)  /* starting level for update */
 
1672
{
 
1673
        int                     ptr;    /* index of key in block */
 
1674
 
 
1675
        /*
 
1676
         * Go up the tree from this level toward the root.
 
1677
         * At each level, update the key value to the value input.
 
1678
         * Stop when we reach a level where the cursor isn't pointing
 
1679
         * at the first entry in the block.
 
1680
         */
 
1681
        for (ptr = 1; ptr == 1 && level < cur->bc_nlevels; level++) {
 
1682
                xfs_alloc_block_t       *block; /* btree block */
 
1683
                xfs_buf_t               *bp;    /* buffer for block */
 
1684
#ifdef DEBUG
 
1685
                int                     error;  /* error return value */
 
1686
#endif
 
1687
                xfs_alloc_key_t         *kp;    /* ptr to btree block keys */
 
1688
 
 
1689
                bp = cur->bc_bufs[level];
 
1690
                block = XFS_BUF_TO_ALLOC_BLOCK(bp);
 
1691
#ifdef DEBUG
 
1692
                if ((error = xfs_btree_check_sblock(cur, block, level, bp)))
 
1693
                        return error;
 
1694
#endif
 
1695
                ptr = cur->bc_ptrs[level];
 
1696
                kp = XFS_ALLOC_KEY_ADDR(block, ptr, cur);
 
1697
                *kp = *keyp;
 
1698
                xfs_alloc_log_keys(cur, bp, ptr, ptr);
 
1699
        }
 
1700
        return 0;
 
1701
}
 
1702
 
 
1703
/*
 
1704
 * Externally visible routines.
 
1705
 */
 
1706
 
 
1707
/*
 
1708
 * Decrement cursor by one record at the level.
 
1709
 * For nonzero levels the leaf-ward information is untouched.
 
1710
 */
 
1711
int                                     /* error */
 
1712
xfs_alloc_decrement(
 
1713
        xfs_btree_cur_t         *cur,   /* btree cursor */
 
1714
        int                     level,  /* level in btree, 0 is leaf */
 
1715
        int                     *stat)  /* success/failure */
 
1716
{
 
1717
        xfs_alloc_block_t       *block; /* btree block */
 
1718
        int                     error;  /* error return value */
 
1719
        int                     lev;    /* btree level */
 
1720
 
 
1721
        ASSERT(level < cur->bc_nlevels);
 
1722
        /*
 
1723
         * Read-ahead to the left at this level.
 
1724
         */
 
1725
        xfs_btree_readahead(cur, level, XFS_BTCUR_LEFTRA);
 
1726
        /*
 
1727
         * Decrement the ptr at this level.  If we're still in the block
 
1728
         * then we're done.
 
1729
         */
 
1730
        if (--cur->bc_ptrs[level] > 0) {
 
1731
                *stat = 1;
 
1732
                return 0;
 
1733
        }
 
1734
        /*
 
1735
         * Get a pointer to the btree block.
 
1736
         */
 
1737
        block = XFS_BUF_TO_ALLOC_BLOCK(cur->bc_bufs[level]);
 
1738
#ifdef DEBUG
 
1739
        if ((error = xfs_btree_check_sblock(cur, block, level,
 
1740
                        cur->bc_bufs[level])))
 
1741
                return error;
 
1742
#endif
 
1743
        /*
 
1744
         * If we just went off the left edge of the tree, return failure.
 
1745
         */
 
1746
        if (INT_GET(block->bb_leftsib, ARCH_CONVERT) == NULLAGBLOCK) {
 
1747
                *stat = 0;
 
1748
                return 0;
 
1749
        }
 
1750
        /*
 
1751
         * March up the tree decrementing pointers.
 
1752
         * Stop when we don't go off the left edge of a block.
 
1753
         */
 
1754
        for (lev = level + 1; lev < cur->bc_nlevels; lev++) {
 
1755
                if (--cur->bc_ptrs[lev] > 0)
 
1756
                        break;
 
1757
                /*
 
1758
                 * Read-ahead the left block, we're going to read it 
 
1759
                 * in the next loop.
 
1760
                 */
 
1761
                xfs_btree_readahead(cur, lev, XFS_BTCUR_LEFTRA);
 
1762
        }
 
1763
        /*
 
1764
         * If we went off the root then we are seriously confused.
 
1765
         */
 
1766
        ASSERT(lev < cur->bc_nlevels);
 
1767
        /*
 
1768
         * Now walk back down the tree, fixing up the cursor's buffer
 
1769
         * pointers and key numbers.
 
1770
         */
 
1771
        for (block = XFS_BUF_TO_ALLOC_BLOCK(cur->bc_bufs[lev]); lev > level; ) {
 
1772
                xfs_agblock_t   agbno;  /* block number of btree block */
 
1773
                xfs_buf_t       *bp;    /* buffer pointer for block */
 
1774
 
 
1775
                agbno = INT_GET(*XFS_ALLOC_PTR_ADDR(block, cur->bc_ptrs[lev], cur), ARCH_CONVERT);
 
1776
                if ((error = xfs_btree_read_bufs(cur->bc_mp, cur->bc_tp,
 
1777
                                cur->bc_private.a.agno, agbno, 0, &bp,
 
1778
                                XFS_ALLOC_BTREE_REF)))
 
1779
                        return error;
 
1780
                lev--;
 
1781
                xfs_btree_setbuf(cur, lev, bp);
 
1782
                block = XFS_BUF_TO_ALLOC_BLOCK(bp);
 
1783
                if ((error = xfs_btree_check_sblock(cur, block, lev, bp)))
 
1784
                        return error;
 
1785
                cur->bc_ptrs[lev] = INT_GET(block->bb_numrecs, ARCH_CONVERT);
 
1786
        }
 
1787
        *stat = 1;
 
1788
        return 0;
 
1789
}
 
1790
 
 
1791
/*
 
1792
 * Delete the record pointed to by cur.
 
1793
 * The cursor refers to the place where the record was (could be inserted)
 
1794
 * when the operation returns.
 
1795
 */
 
1796
int                                     /* error */
 
1797
xfs_alloc_delete(
 
1798
        xfs_btree_cur_t *cur,           /* btree cursor */
 
1799
        int             *stat)          /* success/failure */
 
1800
{
 
1801
        int             error;          /* error return value */
 
1802
        int             i;              /* result code */
 
1803
        int             level;          /* btree level */
 
1804
 
 
1805
        /*
 
1806
         * Go up the tree, starting at leaf level.
 
1807
         * If 2 is returned then a join was done; go to the next level.
 
1808
         * Otherwise we are done.
 
1809
         */
 
1810
        for (level = 0, i = 2; i == 2; level++) {
 
1811
                if ((error = xfs_alloc_delrec(cur, level, &i)))
 
1812
                        return error;
 
1813
        }
 
1814
        if (i == 0) {
 
1815
                for (level = 1; level < cur->bc_nlevels; level++) {
 
1816
                        if (cur->bc_ptrs[level] == 0) {
 
1817
                                if ((error = xfs_alloc_decrement(cur, level, &i)))
 
1818
                                        return error;
 
1819
                                break;
 
1820
                        }
 
1821
                }
 
1822
        }
 
1823
        *stat = i;
 
1824
        return 0;
 
1825
}
 
1826
 
 
1827
/* 
 
1828
 * Get the data from the pointed-to record.
 
1829
 */
 
1830
int                                     /* error */
 
1831
xfs_alloc_get_rec(
 
1832
        xfs_btree_cur_t         *cur,   /* btree cursor */
 
1833
        xfs_agblock_t           *bno,   /* output: starting block of extent */
 
1834
        xfs_extlen_t            *len,   /* output: length of extent */
 
1835
        int                     *stat)  /* output: success/failure */
 
1836
{
 
1837
        xfs_alloc_block_t       *block; /* btree block */
 
1838
#ifdef DEBUG
 
1839
        int                     error;  /* error return value */
 
1840
#endif
 
1841
        int                     ptr;    /* record number */
 
1842
 
 
1843
        ptr = cur->bc_ptrs[0];
 
1844
        block = XFS_BUF_TO_ALLOC_BLOCK(cur->bc_bufs[0]);
 
1845
#ifdef DEBUG
 
1846
        if ((error = xfs_btree_check_sblock(cur, block, 0, cur->bc_bufs[0])))
 
1847
                return error;
 
1848
#endif
 
1849
        /*
 
1850
         * Off the right end or left end, return failure.
 
1851
         */
 
1852
        if (ptr > INT_GET(block->bb_numrecs, ARCH_CONVERT) || ptr <= 0) {
 
1853
                *stat = 0;
 
1854
                return 0;
 
1855
        }
 
1856
        /*
 
1857
         * Point to the record and extract its data.
 
1858
         */
 
1859
        {
 
1860
                xfs_alloc_rec_t         *rec;   /* record data */
 
1861
 
 
1862
                rec = XFS_ALLOC_REC_ADDR(block, ptr, cur);
 
1863
                *bno = INT_GET(rec->ar_startblock, ARCH_CONVERT);
 
1864
                *len = INT_GET(rec->ar_blockcount, ARCH_CONVERT);
 
1865
        }
 
1866
        *stat = 1;
 
1867
        return 0;
 
1868
}
 
1869
 
 
1870
/*
 
1871
 * Increment cursor by one record at the level.
 
1872
 * For nonzero levels the leaf-ward information is untouched.
 
1873
 */
 
1874
int                                     /* error */
 
1875
xfs_alloc_increment(
 
1876
        xfs_btree_cur_t         *cur,   /* btree cursor */
 
1877
        int                     level,  /* level in btree, 0 is leaf */
 
1878
        int                     *stat)  /* success/failure */
 
1879
{
 
1880
        xfs_alloc_block_t       *block; /* btree block */
 
1881
        xfs_buf_t               *bp;    /* tree block buffer */
 
1882
        int                     error;  /* error return value */
 
1883
        int                     lev;    /* btree level */
 
1884
 
 
1885
        ASSERT(level < cur->bc_nlevels);
 
1886
        /*
 
1887
         * Read-ahead to the right at this level.
 
1888
         */
 
1889
        xfs_btree_readahead(cur, level, XFS_BTCUR_RIGHTRA);
 
1890
        /*
 
1891
         * Get a pointer to the btree block.
 
1892
         */
 
1893
        bp = cur->bc_bufs[level];
 
1894
        block = XFS_BUF_TO_ALLOC_BLOCK(bp);
 
1895
#ifdef DEBUG
 
1896
        if ((error = xfs_btree_check_sblock(cur, block, level, bp)))
 
1897
                return error;
 
1898
#endif
 
1899
        /*
 
1900
         * Increment the ptr at this level.  If we're still in the block
 
1901
         * then we're done.
 
1902
         */
 
1903
        if (++cur->bc_ptrs[level] <= INT_GET(block->bb_numrecs, ARCH_CONVERT)) {
 
1904
                *stat = 1;
 
1905
                return 0;
 
1906
        }
 
1907
        /*
 
1908
         * If we just went off the right edge of the tree, return failure.
 
1909
         */
 
1910
        if (INT_GET(block->bb_rightsib, ARCH_CONVERT) == NULLAGBLOCK) {
 
1911
                *stat = 0;
 
1912
                return 0;
 
1913
        }
 
1914
        /*
 
1915
         * March up the tree incrementing pointers.
 
1916
         * Stop when we don't go off the right edge of a block.
 
1917
         */
 
1918
        for (lev = level + 1; lev < cur->bc_nlevels; lev++) {
 
1919
                bp = cur->bc_bufs[lev];
 
1920
                block = XFS_BUF_TO_ALLOC_BLOCK(bp);
 
1921
#ifdef DEBUG
 
1922
                if ((error = xfs_btree_check_sblock(cur, block, lev, bp)))
 
1923
                        return error;
 
1924
#endif
 
1925
                if (++cur->bc_ptrs[lev] <= INT_GET(block->bb_numrecs, ARCH_CONVERT))
 
1926
                        break;
 
1927
                /*
 
1928
                 * Read-ahead the right block, we're going to read it 
 
1929
                 * in the next loop.
 
1930
                 */
 
1931
                xfs_btree_readahead(cur, lev, XFS_BTCUR_RIGHTRA);
 
1932
        }
 
1933
        /*
 
1934
         * If we went off the root then we are seriously confused.
 
1935
         */
 
1936
        ASSERT(lev < cur->bc_nlevels);
 
1937
        /*
 
1938
         * Now walk back down the tree, fixing up the cursor's buffer
 
1939
         * pointers and key numbers.
 
1940
         */
 
1941
        for (bp = cur->bc_bufs[lev], block = XFS_BUF_TO_ALLOC_BLOCK(bp);
 
1942
             lev > level; ) {
 
1943
                xfs_agblock_t   agbno;  /* block number of btree block */
 
1944
 
 
1945
                agbno = INT_GET(*XFS_ALLOC_PTR_ADDR(block, cur->bc_ptrs[lev], cur), ARCH_CONVERT);
 
1946
                if ((error = xfs_btree_read_bufs(cur->bc_mp, cur->bc_tp,
 
1947
                                cur->bc_private.a.agno, agbno, 0, &bp,
 
1948
                                XFS_ALLOC_BTREE_REF)))
 
1949
                        return error;
 
1950
                lev--;
 
1951
                xfs_btree_setbuf(cur, lev, bp);
 
1952
                block = XFS_BUF_TO_ALLOC_BLOCK(bp);
 
1953
                if ((error = xfs_btree_check_sblock(cur, block, lev, bp)))
 
1954
                        return error;
 
1955
                cur->bc_ptrs[lev] = 1;
 
1956
        }
 
1957
        *stat = 1;
 
1958
        return 0;
 
1959
}
 
1960
 
 
1961
/*
 
1962
 * Insert the current record at the point referenced by cur.
 
1963
 * The cursor may be inconsistent on return if splits have been done.
 
1964
 */
 
1965
int                                     /* error */
 
1966
xfs_alloc_insert(
 
1967
        xfs_btree_cur_t *cur,           /* btree cursor */
 
1968
        int             *stat)          /* success/failure */
 
1969
{
 
1970
        int             error;          /* error return value */
 
1971
        int             i;              /* result value, 0 for failure */
 
1972
        int             level;          /* current level number in btree */
 
1973
        xfs_agblock_t   nbno;           /* new block number (split result) */
 
1974
        xfs_btree_cur_t *ncur;          /* new cursor (split result) */
 
1975
        xfs_alloc_rec_t nrec;           /* record being inserted this level */
 
1976
        xfs_btree_cur_t *pcur;          /* previous level's cursor */
 
1977
 
 
1978
        level = 0;
 
1979
        nbno = NULLAGBLOCK;
 
1980
        INT_SET(nrec.ar_startblock, ARCH_CONVERT, cur->bc_rec.a.ar_startblock);
 
1981
        INT_SET(nrec.ar_blockcount, ARCH_CONVERT, cur->bc_rec.a.ar_blockcount);
 
1982
        ncur = (xfs_btree_cur_t *)0;
 
1983
        pcur = cur;
 
1984
        /*
 
1985
         * Loop going up the tree, starting at the leaf level.
 
1986
         * Stop when we don't get a split block, that must mean that
 
1987
         * the insert is finished with this level.
 
1988
         */
 
1989
        do {
 
1990
                /*
 
1991
                 * Insert nrec/nbno into this level of the tree.
 
1992
                 * Note if we fail, nbno will be null.
 
1993
                 */
 
1994
                if ((error = xfs_alloc_insrec(pcur, level++, &nbno, &nrec, &ncur,
 
1995
                                &i))) {
 
1996
                        if (pcur != cur)
 
1997
                                xfs_btree_del_cursor(pcur, XFS_BTREE_ERROR);
 
1998
                        return error;
 
1999
                }
 
2000
                /*
 
2001
                 * See if the cursor we just used is trash.
 
2002
                 * Can't trash the caller's cursor, but otherwise we should
 
2003
                 * if ncur is a new cursor or we're about to be done.
 
2004
                 */
 
2005
                if (pcur != cur && (ncur || nbno == NULLAGBLOCK)) {
 
2006
                        cur->bc_nlevels = pcur->bc_nlevels;
 
2007
                        xfs_btree_del_cursor(pcur, XFS_BTREE_NOERROR);
 
2008
                }
 
2009
                /*
 
2010
                 * If we got a new cursor, switch to it.
 
2011
                 */
 
2012
                if (ncur) {
 
2013
                        pcur = ncur;
 
2014
                        ncur = (xfs_btree_cur_t *)0;
 
2015
                }
 
2016
        } while (nbno != NULLAGBLOCK);
 
2017
        *stat = i;
 
2018
        return 0;
 
2019
}
 
2020
 
 
2021
/*
 
2022
 * Lookup the record equal to [bno, len] in the btree given by cur.
 
2023
 */
 
2024
int                                     /* error */
 
2025
xfs_alloc_lookup_eq(
 
2026
        xfs_btree_cur_t *cur,           /* btree cursor */
 
2027
        xfs_agblock_t   bno,            /* starting block of extent */
 
2028
        xfs_extlen_t    len,            /* length of extent */
 
2029
        int             *stat)          /* success/failure */
 
2030
{
 
2031
        cur->bc_rec.a.ar_startblock = bno;
 
2032
        cur->bc_rec.a.ar_blockcount = len;
 
2033
        return xfs_alloc_lookup(cur, XFS_LOOKUP_EQ, stat);
 
2034
}
 
2035
 
 
2036
/*
 
2037
 * Lookup the first record greater than or equal to [bno, len]
 
2038
 * in the btree given by cur.
 
2039
 */
 
2040
int                                     /* error */
 
2041
xfs_alloc_lookup_ge(
 
2042
        xfs_btree_cur_t *cur,           /* btree cursor */
 
2043
        xfs_agblock_t   bno,            /* starting block of extent */
 
2044
        xfs_extlen_t    len,            /* length of extent */
 
2045
        int             *stat)          /* success/failure */
 
2046
{
 
2047
        cur->bc_rec.a.ar_startblock = bno;
 
2048
        cur->bc_rec.a.ar_blockcount = len;
 
2049
        return xfs_alloc_lookup(cur, XFS_LOOKUP_GE, stat);
 
2050
}
 
2051
 
 
2052
/*
 
2053
 * Lookup the first record less than or equal to [bno, len]
 
2054
 * in the btree given by cur.
 
2055
 */
 
2056
int                                     /* error */
 
2057
xfs_alloc_lookup_le(
 
2058
        xfs_btree_cur_t *cur,           /* btree cursor */
 
2059
        xfs_agblock_t   bno,            /* starting block of extent */
 
2060
        xfs_extlen_t    len,            /* length of extent */
 
2061
        int             *stat)          /* success/failure */
 
2062
{
 
2063
        cur->bc_rec.a.ar_startblock = bno;
 
2064
        cur->bc_rec.a.ar_blockcount = len;
 
2065
        return xfs_alloc_lookup(cur, XFS_LOOKUP_LE, stat);
 
2066
}
 
2067
 
 
2068
/*
 
2069
 * Update the record referred to by cur, to the value given by [bno, len].
 
2070
 * This either works (return 0) or gets an EFSCORRUPTED error.
 
2071
 */
 
2072
int                                     /* error */
 
2073
xfs_alloc_update(
 
2074
        xfs_btree_cur_t         *cur,   /* btree cursor */
 
2075
        xfs_agblock_t           bno,    /* starting block of extent */
 
2076
        xfs_extlen_t            len)    /* length of extent */
 
2077
{
 
2078
        xfs_alloc_block_t       *block; /* btree block to update */
 
2079
        int                     error;  /* error return value */
 
2080
        int                     ptr;    /* current record number (updating) */
 
2081
 
 
2082
        ASSERT(len > 0);
 
2083
        /*
 
2084
         * Pick up the a.g. freelist struct and the current block.
 
2085
         */
 
2086
        block = XFS_BUF_TO_ALLOC_BLOCK(cur->bc_bufs[0]);
 
2087
#ifdef DEBUG
 
2088
        if ((error = xfs_btree_check_sblock(cur, block, 0, cur->bc_bufs[0])))
 
2089
                return error;
 
2090
#endif
 
2091
        /*
 
2092
         * Get the address of the rec to be updated.
 
2093
         */
 
2094
        ptr = cur->bc_ptrs[0];
 
2095
        {
 
2096
                xfs_alloc_rec_t         *rp;    /* pointer to updated record */
 
2097
 
 
2098
                rp = XFS_ALLOC_REC_ADDR(block, ptr, cur);
 
2099
                /*
 
2100
                 * Fill in the new contents and log them.
 
2101
                 */
 
2102
                INT_SET(rp->ar_startblock, ARCH_CONVERT, bno);
 
2103
                INT_SET(rp->ar_blockcount, ARCH_CONVERT, len);
 
2104
                xfs_alloc_log_recs(cur, cur->bc_bufs[0], ptr, ptr);
 
2105
        }
 
2106
        /*
 
2107
         * If it's the by-size btree and it's the last leaf block and
 
2108
         * it's the last record... then update the size of the longest
 
2109
         * extent in the a.g., which we cache in the a.g. freelist header.
 
2110
         */
 
2111
        if (cur->bc_btnum == XFS_BTNUM_CNT &&
 
2112
            INT_GET(block->bb_rightsib, ARCH_CONVERT) == NULLAGBLOCK &&
 
2113
            ptr == INT_GET(block->bb_numrecs, ARCH_CONVERT)) {
 
2114
                xfs_agf_t       *agf;   /* a.g. freespace header */
 
2115
                xfs_agnumber_t  seqno;
 
2116
 
 
2117
                agf = XFS_BUF_TO_AGF(cur->bc_private.a.agbp);
 
2118
                seqno = INT_GET(agf->agf_seqno, ARCH_CONVERT);
 
2119
                cur->bc_mp->m_perag[seqno].pagf_longest = len;
 
2120
                INT_SET(agf->agf_longest, ARCH_CONVERT, len);
 
2121
                xfs_alloc_log_agf(cur->bc_tp, cur->bc_private.a.agbp,
 
2122
                        XFS_AGF_LONGEST);
 
2123
        }
 
2124
        /*
 
2125
         * Updating first record in leaf. Pass new key value up to our parent.
 
2126
         */
 
2127
        if (ptr == 1) {
 
2128
                xfs_alloc_key_t key;    /* key containing [bno, len] */
 
2129
 
 
2130
                INT_SET(key.ar_startblock, ARCH_CONVERT, bno);
 
2131
                INT_SET(key.ar_blockcount, ARCH_CONVERT, len);
 
2132
                if ((error = xfs_alloc_updkey(cur, &key, 1)))
 
2133
                        return error;
 
2134
        }
 
2135
        return 0;
 
2136
}