OpenCores
URL https://opencores.org/ocsvn/or1k/or1k/trunk

Subversion Repositories or1k

[/] [or1k/] [trunk/] [linux/] [linux-2.4/] [fs/] [xfs/] [xfs_da_btree.c] - Blame information for rev 1765

Details | Compare with Previous | View Log

Line No. Rev Author Line
1 1275 phoenix
/*
2
 * Copyright (c) 2000-2003 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
#include "xfs.h"
34
 
35
#include "xfs_macros.h"
36
#include "xfs_types.h"
37
#include "xfs_inum.h"
38
#include "xfs_log.h"
39
#include "xfs_trans.h"
40
#include "xfs_sb.h"
41
#include "xfs_ag.h"
42
#include "xfs_dir.h"
43
#include "xfs_dir2.h"
44
#include "xfs_dmapi.h"
45
#include "xfs_mount.h"
46
#include "xfs_alloc_btree.h"
47
#include "xfs_bmap_btree.h"
48
#include "xfs_ialloc_btree.h"
49
#include "xfs_alloc.h"
50
#include "xfs_btree.h"
51
#include "xfs_attr_sf.h"
52
#include "xfs_dir_sf.h"
53
#include "xfs_dir2_sf.h"
54
#include "xfs_dinode.h"
55
#include "xfs_inode_item.h"
56
#include "xfs_inode.h"
57
#include "xfs_bmap.h"
58
#include "xfs_da_btree.h"
59
#include "xfs_attr.h"
60
#include "xfs_attr_leaf.h"
61
#include "xfs_dir_leaf.h"
62
#include "xfs_dir2_data.h"
63
#include "xfs_dir2_leaf.h"
64
#include "xfs_dir2_block.h"
65
#include "xfs_dir2_node.h"
66
#include "xfs_error.h"
67
#include "xfs_bit.h"
68
 
69
/*
70
 * xfs_da_btree.c
71
 *
72
 * Routines to implement directories as Btrees of hashed names.
73
 */
74
 
75
/*========================================================================
76
 * Function prototypes for the kernel.
77
 *========================================================================*/
78
 
79
/*
80
 * Routines used for growing the Btree.
81
 */
82
STATIC int xfs_da_root_split(xfs_da_state_t *state,
83
                                            xfs_da_state_blk_t *existing_root,
84
                                            xfs_da_state_blk_t *new_child);
85
STATIC int xfs_da_node_split(xfs_da_state_t *state,
86
                                            xfs_da_state_blk_t *existing_blk,
87
                                            xfs_da_state_blk_t *split_blk,
88
                                            xfs_da_state_blk_t *blk_to_add,
89
                                            int treelevel,
90
                                            int *result);
91
STATIC void xfs_da_node_rebalance(xfs_da_state_t *state,
92
                                         xfs_da_state_blk_t *node_blk_1,
93
                                         xfs_da_state_blk_t *node_blk_2);
94
STATIC void xfs_da_node_add(xfs_da_state_t *state,
95
                                   xfs_da_state_blk_t *old_node_blk,
96
                                   xfs_da_state_blk_t *new_node_blk);
97
 
98
/*
99
 * Routines used for shrinking the Btree.
100
 */
101
STATIC int xfs_da_root_join(xfs_da_state_t *state,
102
                                           xfs_da_state_blk_t *root_blk);
103
STATIC int xfs_da_node_toosmall(xfs_da_state_t *state, int *retval);
104
STATIC void xfs_da_node_remove(xfs_da_state_t *state,
105
                                              xfs_da_state_blk_t *drop_blk);
106
STATIC void xfs_da_node_unbalance(xfs_da_state_t *state,
107
                                         xfs_da_state_blk_t *src_node_blk,
108
                                         xfs_da_state_blk_t *dst_node_blk);
109
 
110
/*
111
 * Utility routines.
112
 */
113
STATIC uint     xfs_da_node_lasthash(xfs_dabuf_t *bp, int *count);
114
STATIC int      xfs_da_node_order(xfs_dabuf_t *node1_bp, xfs_dabuf_t *node2_bp);
115
STATIC xfs_dabuf_t *xfs_da_buf_make(int nbuf, xfs_buf_t **bps, inst_t *ra);
116
 
117
 
118
/*========================================================================
119
 * Routines used for growing the Btree.
120
 *========================================================================*/
121
 
122
/*
123
 * Create the initial contents of an intermediate node.
124
 */
125
int
126
xfs_da_node_create(xfs_da_args_t *args, xfs_dablk_t blkno, int level,
127
                                 xfs_dabuf_t **bpp, int whichfork)
128
{
129
        xfs_da_intnode_t *node;
130
        xfs_dabuf_t *bp;
131
        int error;
132
        xfs_trans_t *tp;
133
 
134
        tp = args->trans;
135
        error = xfs_da_get_buf(tp, args->dp, blkno, -1, &bp, whichfork);
136
        if (error)
137
                return(error);
138
        ASSERT(bp != NULL);
139
        node = bp->data;
140
        INT_ZERO(node->hdr.info.forw, ARCH_CONVERT);
141
        INT_ZERO(node->hdr.info.back, ARCH_CONVERT);
142
        INT_SET(node->hdr.info.magic, ARCH_CONVERT, XFS_DA_NODE_MAGIC);
143
        INT_ZERO(node->hdr.info.pad, ARCH_CONVERT);
144
        INT_ZERO(node->hdr.count, ARCH_CONVERT);
145
        INT_SET(node->hdr.level, ARCH_CONVERT, level);
146
 
147
        xfs_da_log_buf(tp, bp,
148
                XFS_DA_LOGRANGE(node, &node->hdr, sizeof(node->hdr)));
149
 
150
        *bpp = bp;
151
        return(0);
152
}
153
 
154
/*
155
 * Split a leaf node, rebalance, then possibly split
156
 * intermediate nodes, rebalance, etc.
157
 */
158
int                                                     /* error */
159
xfs_da_split(xfs_da_state_t *state)
160
{
161
        xfs_da_state_blk_t *oldblk, *newblk, *addblk;
162
        xfs_da_intnode_t *node;
163
        xfs_dabuf_t *bp;
164
        int max, action, error, i;
165
 
166
        /*
167
         * Walk back up the tree splitting/inserting/adjusting as necessary.
168
         * If we need to insert and there isn't room, split the node, then
169
         * decide which fragment to insert the new block from below into.
170
         * Note that we may split the root this way, but we need more fixup.
171
         */
172
        max = state->path.active - 1;
173
        ASSERT((max >= 0) && (max < XFS_DA_NODE_MAXDEPTH));
174
        ASSERT(state->path.blk[max].magic == XFS_ATTR_LEAF_MAGIC ||
175
               state->path.blk[max].magic == XFS_DIRX_LEAF_MAGIC(state->mp));
176
 
177
        addblk = &state->path.blk[max];         /* initial dummy value */
178
        for (i = max; (i >= 0) && addblk; state->path.active--, i--) {
179
                oldblk = &state->path.blk[i];
180
                newblk = &state->altpath.blk[i];
181
 
182
                /*
183
                 * If a leaf node then
184
                 *     Allocate a new leaf node, then rebalance across them.
185
                 * else if an intermediate node then
186
                 *     We split on the last layer, must we split the node?
187
                 */
188
                switch (oldblk->magic) {
189
                case XFS_ATTR_LEAF_MAGIC:
190
#ifndef __KERNEL__
191
                        return(ENOTTY);
192
#else
193
                        error = xfs_attr_leaf_split(state, oldblk, newblk);
194
                        if ((error != 0) && (error != ENOSPC)) {
195
                                return(error);  /* GROT: attr is inconsistent */
196
                        }
197
                        if (!error) {
198
                                addblk = newblk;
199
                                break;
200
                        }
201
                        /*
202
                         * Entry wouldn't fit, split the leaf again.
203
                         */
204
                        state->extravalid = 1;
205
                        if (state->inleaf) {
206
                                state->extraafter = 0;   /* before newblk */
207
                                error = xfs_attr_leaf_split(state, oldblk,
208
                                                            &state->extrablk);
209
                        } else {
210
                                state->extraafter = 1;  /* after newblk */
211
                                error = xfs_attr_leaf_split(state, newblk,
212
                                                            &state->extrablk);
213
                        }
214
                        if (error)
215
                                return(error);  /* GROT: attr inconsistent */
216
                        addblk = newblk;
217
                        break;
218
#endif
219
                case XFS_DIR_LEAF_MAGIC:
220
                        ASSERT(XFS_DIR_IS_V1(state->mp));
221
                        error = xfs_dir_leaf_split(state, oldblk, newblk);
222
                        if ((error != 0) && (error != ENOSPC)) {
223
                                return(error);  /* GROT: dir is inconsistent */
224
                        }
225
                        if (!error) {
226
                                addblk = newblk;
227
                                break;
228
                        }
229
                        /*
230
                         * Entry wouldn't fit, split the leaf again.
231
                         */
232
                        state->extravalid = 1;
233
                        if (state->inleaf) {
234
                                state->extraafter = 0;   /* before newblk */
235
                                error = xfs_dir_leaf_split(state, oldblk,
236
                                                           &state->extrablk);
237
                                if (error)
238
                                        return(error);  /* GROT: dir incon. */
239
                                addblk = newblk;
240
                        } else {
241
                                state->extraafter = 1;  /* after newblk */
242
                                error = xfs_dir_leaf_split(state, newblk,
243
                                                           &state->extrablk);
244
                                if (error)
245
                                        return(error);  /* GROT: dir incon. */
246
                                addblk = newblk;
247
                        }
248
                        break;
249
                case XFS_DIR2_LEAFN_MAGIC:
250
                        ASSERT(XFS_DIR_IS_V2(state->mp));
251
                        error = xfs_dir2_leafn_split(state, oldblk, newblk);
252
                        if (error)
253
                                return error;
254
                        addblk = newblk;
255
                        break;
256
                case XFS_DA_NODE_MAGIC:
257
                        error = xfs_da_node_split(state, oldblk, newblk, addblk,
258
                                                         max - i, &action);
259
                        xfs_da_buf_done(addblk->bp);
260
                        addblk->bp = NULL;
261
                        if (error)
262
                                return(error);  /* GROT: dir is inconsistent */
263
                        /*
264
                         * Record the newly split block for the next time thru?
265
                         */
266
                        if (action)
267
                                addblk = newblk;
268
                        else
269
                                addblk = NULL;
270
                        break;
271
                }
272
 
273
                /*
274
                 * Update the btree to show the new hashval for this child.
275
                 */
276
                xfs_da_fixhashpath(state, &state->path);
277
                /*
278
                 * If we won't need this block again, it's getting dropped
279
                 * from the active path by the loop control, so we need
280
                 * to mark it done now.
281
                 */
282
                if (i > 0 || !addblk)
283
                        xfs_da_buf_done(oldblk->bp);
284
        }
285
        if (!addblk)
286
                return(0);
287
 
288
        /*
289
         * Split the root node.
290
         */
291
        ASSERT(state->path.active == 0);
292
        oldblk = &state->path.blk[0];
293
        error = xfs_da_root_split(state, oldblk, addblk);
294
        if (error) {
295
                xfs_da_buf_done(oldblk->bp);
296
                xfs_da_buf_done(addblk->bp);
297
                addblk->bp = NULL;
298
                return(error);  /* GROT: dir is inconsistent */
299
        }
300
 
301
        /*
302
         * Update pointers to the node which used to be block 0 and
303
         * just got bumped because of the addition of a new root node.
304
         * There might be three blocks involved if a double split occurred,
305
         * and the original block 0 could be at any position in the list.
306
         */
307
 
308
        node = oldblk->bp->data;
309
        if (!INT_ISZERO(node->hdr.info.forw, ARCH_CONVERT)) {
310
                if (INT_GET(node->hdr.info.forw, ARCH_CONVERT) == addblk->blkno) {
311
                        bp = addblk->bp;
312
                } else {
313
                        ASSERT(state->extravalid);
314
                        bp = state->extrablk.bp;
315
                }
316
                node = bp->data;
317
                INT_SET(node->hdr.info.back, ARCH_CONVERT, oldblk->blkno);
318
                xfs_da_log_buf(state->args->trans, bp,
319
                    XFS_DA_LOGRANGE(node, &node->hdr.info,
320
                    sizeof(node->hdr.info)));
321
        }
322
        node = oldblk->bp->data;
323
        if (INT_GET(node->hdr.info.back, ARCH_CONVERT)) {
324
                if (INT_GET(node->hdr.info.back, ARCH_CONVERT) == addblk->blkno) {
325
                        bp = addblk->bp;
326
                } else {
327
                        ASSERT(state->extravalid);
328
                        bp = state->extrablk.bp;
329
                }
330
                node = bp->data;
331
                INT_SET(node->hdr.info.forw, ARCH_CONVERT, oldblk->blkno);
332
                xfs_da_log_buf(state->args->trans, bp,
333
                    XFS_DA_LOGRANGE(node, &node->hdr.info,
334
                    sizeof(node->hdr.info)));
335
        }
336
        xfs_da_buf_done(oldblk->bp);
337
        xfs_da_buf_done(addblk->bp);
338
        addblk->bp = NULL;
339
        return(0);
340
}
341
 
342
/*
343
 * Split the root.  We have to create a new root and point to the two
344
 * parts (the split old root) that we just created.  Copy block zero to
345
 * the EOF, extending the inode in process.
346
 */
347
STATIC int                                              /* error */
348
xfs_da_root_split(xfs_da_state_t *state, xfs_da_state_blk_t *blk1,
349
                                 xfs_da_state_blk_t *blk2)
350
{
351
        xfs_da_intnode_t *node, *oldroot;
352
        xfs_da_args_t *args;
353
        xfs_dablk_t blkno;
354
        xfs_dabuf_t *bp;
355
        int error, size;
356
        xfs_inode_t *dp;
357
        xfs_trans_t *tp;
358
        xfs_mount_t *mp;
359
        xfs_dir2_leaf_t *leaf;
360
 
361
        /*
362
         * Copy the existing (incorrect) block from the root node position
363
         * to a free space somewhere.
364
         */
365
        args = state->args;
366
        ASSERT(args != NULL);
367
        error = xfs_da_grow_inode(args, &blkno);
368
        if (error)
369
                return(error);
370
        dp = args->dp;
371
        tp = args->trans;
372
        mp = state->mp;
373
        error = xfs_da_get_buf(tp, dp, blkno, -1, &bp, args->whichfork);
374
        if (error)
375
                return(error);
376
        ASSERT(bp != NULL);
377
        node = bp->data;
378
        oldroot = blk1->bp->data;
379
        if (INT_GET(oldroot->hdr.info.magic, ARCH_CONVERT) == XFS_DA_NODE_MAGIC) {
380
                size = (int)((char *)&oldroot->btree[INT_GET(oldroot->hdr.count, ARCH_CONVERT)] -
381
                             (char *)oldroot);
382
        } else {
383
                ASSERT(XFS_DIR_IS_V2(mp));
384
                ASSERT(INT_GET(oldroot->hdr.info.magic, ARCH_CONVERT) == XFS_DIR2_LEAFN_MAGIC);
385
                leaf = (xfs_dir2_leaf_t *)oldroot;
386
                size = (int)((char *)&leaf->ents[INT_GET(leaf->hdr.count, ARCH_CONVERT)] -
387
                             (char *)leaf);
388
        }
389
        memcpy(node, oldroot, size);
390
        xfs_da_log_buf(tp, bp, 0, size - 1);
391
        xfs_da_buf_done(blk1->bp);
392
        blk1->bp = bp;
393
        blk1->blkno = blkno;
394
 
395
        /*
396
         * Set up the new root node.
397
         */
398
        error = xfs_da_node_create(args,
399
                args->whichfork == XFS_DATA_FORK &&
400
                XFS_DIR_IS_V2(mp) ? mp->m_dirleafblk : 0,
401
                INT_GET(node->hdr.level, ARCH_CONVERT) + 1, &bp, args->whichfork);
402
        if (error)
403
                return(error);
404
        node = bp->data;
405
        INT_SET(node->btree[0].hashval, ARCH_CONVERT, blk1->hashval);
406
        INT_SET(node->btree[0].before, ARCH_CONVERT, blk1->blkno);
407
        INT_SET(node->btree[1].hashval, ARCH_CONVERT, blk2->hashval);
408
        INT_SET(node->btree[1].before, ARCH_CONVERT, blk2->blkno);
409
        INT_SET(node->hdr.count, ARCH_CONVERT, 2);
410
 
411
#ifdef DEBUG
412
        if (INT_GET(oldroot->hdr.info.magic, ARCH_CONVERT) == XFS_DIR2_LEAFN_MAGIC) {
413
                ASSERT(blk1->blkno >= mp->m_dirleafblk &&
414
                       blk1->blkno < mp->m_dirfreeblk);
415
                ASSERT(blk2->blkno >= mp->m_dirleafblk &&
416
                       blk2->blkno < mp->m_dirfreeblk);
417
        }
418
#endif
419
 
420
        /* Header is already logged by xfs_da_node_create */
421
        xfs_da_log_buf(tp, bp,
422
                XFS_DA_LOGRANGE(node, node->btree,
423
                        sizeof(xfs_da_node_entry_t) * 2));
424
        xfs_da_buf_done(bp);
425
 
426
        return(0);
427
}
428
 
429
/*
430
 * Split the node, rebalance, then add the new entry.
431
 */
432
STATIC int                                              /* error */
433
xfs_da_node_split(xfs_da_state_t *state, xfs_da_state_blk_t *oldblk,
434
                                 xfs_da_state_blk_t *newblk,
435
                                 xfs_da_state_blk_t *addblk,
436
                                 int treelevel, int *result)
437
{
438
        xfs_da_intnode_t *node;
439
        xfs_dablk_t blkno;
440
        int newcount, error;
441
        int useextra;
442
 
443
        node = oldblk->bp->data;
444
        ASSERT(INT_GET(node->hdr.info.magic, ARCH_CONVERT) == XFS_DA_NODE_MAGIC);
445
 
446
        /*
447
         * With V2 the extra block is data or freespace.
448
         */
449
        useextra = state->extravalid && XFS_DIR_IS_V1(state->mp);
450
        newcount = 1 + useextra;
451
        /*
452
         * Do we have to split the node?
453
         */
454
        if ((INT_GET(node->hdr.count, ARCH_CONVERT) + newcount) > state->node_ents) {
455
                /*
456
                 * Allocate a new node, add to the doubly linked chain of
457
                 * nodes, then move some of our excess entries into it.
458
                 */
459
                error = xfs_da_grow_inode(state->args, &blkno);
460
                if (error)
461
                        return(error);  /* GROT: dir is inconsistent */
462
 
463
                error = xfs_da_node_create(state->args, blkno, treelevel,
464
                                           &newblk->bp, state->args->whichfork);
465
                if (error)
466
                        return(error);  /* GROT: dir is inconsistent */
467
                newblk->blkno = blkno;
468
                newblk->magic = XFS_DA_NODE_MAGIC;
469
                xfs_da_node_rebalance(state, oldblk, newblk);
470
                error = xfs_da_blk_link(state, oldblk, newblk);
471
                if (error)
472
                        return(error);
473
                *result = 1;
474
        } else {
475
                *result = 0;
476
        }
477
 
478
        /*
479
         * Insert the new entry(s) into the correct block
480
         * (updating last hashval in the process).
481
         *
482
         * xfs_da_node_add() inserts BEFORE the given index,
483
         * and as a result of using node_lookup_int() we always
484
         * point to a valid entry (not after one), but a split
485
         * operation always results in a new block whose hashvals
486
         * FOLLOW the current block.
487
         *
488
         * If we had double-split op below us, then add the extra block too.
489
         */
490
        node = oldblk->bp->data;
491
        if (oldblk->index <= INT_GET(node->hdr.count, ARCH_CONVERT)) {
492
                oldblk->index++;
493
                xfs_da_node_add(state, oldblk, addblk);
494
                if (useextra) {
495
                        if (state->extraafter)
496
                                oldblk->index++;
497
                        xfs_da_node_add(state, oldblk, &state->extrablk);
498
                        state->extravalid = 0;
499
                }
500
        } else {
501
                newblk->index++;
502
                xfs_da_node_add(state, newblk, addblk);
503
                if (useextra) {
504
                        if (state->extraafter)
505
                                newblk->index++;
506
                        xfs_da_node_add(state, newblk, &state->extrablk);
507
                        state->extravalid = 0;
508
                }
509
        }
510
 
511
        return(0);
512
}
513
 
514
/*
515
 * Balance the btree elements between two intermediate nodes,
516
 * usually one full and one empty.
517
 *
518
 * NOTE: if blk2 is empty, then it will get the upper half of blk1.
519
 */
520
STATIC void
521
xfs_da_node_rebalance(xfs_da_state_t *state, xfs_da_state_blk_t *blk1,
522
                                     xfs_da_state_blk_t *blk2)
523
{
524
        xfs_da_intnode_t *node1, *node2, *tmpnode;
525
        xfs_da_node_entry_t *btree_s, *btree_d;
526
        int count, tmp;
527
        xfs_trans_t *tp;
528
 
529
        node1 = blk1->bp->data;
530
        node2 = blk2->bp->data;
531
        /*
532
         * Figure out how many entries need to move, and in which direction.
533
         * Swap the nodes around if that makes it simpler.
534
         */
535
        if ((INT_GET(node1->hdr.count, ARCH_CONVERT) > 0) && (INT_GET(node2->hdr.count, ARCH_CONVERT) > 0) &&
536
            ((INT_GET(node2->btree[ 0 ].hashval, ARCH_CONVERT) < INT_GET(node1->btree[ 0 ].hashval, ARCH_CONVERT)) ||
537
             (INT_GET(node2->btree[ INT_GET(node2->hdr.count, ARCH_CONVERT)-1 ].hashval, ARCH_CONVERT) <
538
              INT_GET(node1->btree[ INT_GET(node1->hdr.count, ARCH_CONVERT)-1 ].hashval, ARCH_CONVERT)))) {
539
                tmpnode = node1;
540
                node1 = node2;
541
                node2 = tmpnode;
542
        }
543
        ASSERT(INT_GET(node1->hdr.info.magic, ARCH_CONVERT) == XFS_DA_NODE_MAGIC);
544
        ASSERT(INT_GET(node2->hdr.info.magic, ARCH_CONVERT) == XFS_DA_NODE_MAGIC);
545
        count = (INT_GET(node1->hdr.count, ARCH_CONVERT) - INT_GET(node2->hdr.count, ARCH_CONVERT)) / 2;
546
        if (count == 0)
547
                return;
548
        tp = state->args->trans;
549
        /*
550
         * Two cases: high-to-low and low-to-high.
551
         */
552
        if (count > 0) {
553
                /*
554
                 * Move elements in node2 up to make a hole.
555
                 */
556
                if ((tmp = INT_GET(node2->hdr.count, ARCH_CONVERT)) > 0) {
557
                        tmp *= (uint)sizeof(xfs_da_node_entry_t);
558
                        btree_s = &node2->btree[0];
559
                        btree_d = &node2->btree[count];
560
                        memmove(btree_d, btree_s, tmp);
561
                }
562
 
563
                /*
564
                 * Move the req'd B-tree elements from high in node1 to
565
                 * low in node2.
566
                 */
567
                INT_MOD(node2->hdr.count, ARCH_CONVERT, count);
568
                tmp = count * (uint)sizeof(xfs_da_node_entry_t);
569
                btree_s = &node1->btree[INT_GET(node1->hdr.count, ARCH_CONVERT) - count];
570
                btree_d = &node2->btree[0];
571
                memcpy(btree_d, btree_s, tmp);
572
                INT_MOD(node1->hdr.count, ARCH_CONVERT, -(count));
573
 
574
        } else {
575
                /*
576
                 * Move the req'd B-tree elements from low in node2 to
577
                 * high in node1.
578
                 */
579
                count = -count;
580
                tmp = count * (uint)sizeof(xfs_da_node_entry_t);
581
                btree_s = &node2->btree[0];
582
                btree_d = &node1->btree[INT_GET(node1->hdr.count, ARCH_CONVERT)];
583
                memcpy(btree_d, btree_s, tmp);
584
                INT_MOD(node1->hdr.count, ARCH_CONVERT, count);
585
                xfs_da_log_buf(tp, blk1->bp,
586
                        XFS_DA_LOGRANGE(node1, btree_d, tmp));
587
 
588
                /*
589
                 * Move elements in node2 down to fill the hole.
590
                 */
591
                tmp  = INT_GET(node2->hdr.count, ARCH_CONVERT) - count;
592
                tmp *= (uint)sizeof(xfs_da_node_entry_t);
593
                btree_s = &node2->btree[count];
594
                btree_d = &node2->btree[0];
595
                memmove(btree_d, btree_s, tmp);
596
                INT_MOD(node2->hdr.count, ARCH_CONVERT, -(count));
597
        }
598
 
599
        /*
600
         * Log header of node 1 and all current bits of node 2.
601
         */
602
        xfs_da_log_buf(tp, blk1->bp,
603
                XFS_DA_LOGRANGE(node1, &node1->hdr, sizeof(node1->hdr)));
604
        xfs_da_log_buf(tp, blk2->bp,
605
                XFS_DA_LOGRANGE(node2, &node2->hdr,
606
                        sizeof(node2->hdr) +
607
                        sizeof(node2->btree[0]) * INT_GET(node2->hdr.count, ARCH_CONVERT)));
608
 
609
        /*
610
         * Record the last hashval from each block for upward propagation.
611
         * (note: don't use the swapped node pointers)
612
         */
613
        node1 = blk1->bp->data;
614
        node2 = blk2->bp->data;
615
        blk1->hashval = INT_GET(node1->btree[ INT_GET(node1->hdr.count, ARCH_CONVERT)-1 ].hashval, ARCH_CONVERT);
616
        blk2->hashval = INT_GET(node2->btree[ INT_GET(node2->hdr.count, ARCH_CONVERT)-1 ].hashval, ARCH_CONVERT);
617
 
618
        /*
619
         * Adjust the expected index for insertion.
620
         */
621
        if (blk1->index >= INT_GET(node1->hdr.count, ARCH_CONVERT)) {
622
                blk2->index = blk1->index - INT_GET(node1->hdr.count, ARCH_CONVERT);
623
                blk1->index = INT_GET(node1->hdr.count, ARCH_CONVERT) + 1;      /* make it invalid */
624
        }
625
}
626
 
627
/*
628
 * Add a new entry to an intermediate node.
629
 */
630
STATIC void
631
xfs_da_node_add(xfs_da_state_t *state, xfs_da_state_blk_t *oldblk,
632
                               xfs_da_state_blk_t *newblk)
633
{
634
        xfs_da_intnode_t *node;
635
        xfs_da_node_entry_t *btree;
636
        int tmp;
637
        xfs_mount_t *mp;
638
 
639
        node = oldblk->bp->data;
640
        mp = state->mp;
641
        ASSERT(INT_GET(node->hdr.info.magic, ARCH_CONVERT) == XFS_DA_NODE_MAGIC);
642
        ASSERT((oldblk->index >= 0) && (oldblk->index <= INT_GET(node->hdr.count, ARCH_CONVERT)));
643
        ASSERT(newblk->blkno != 0);
644
        if (state->args->whichfork == XFS_DATA_FORK && XFS_DIR_IS_V2(mp))
645
                ASSERT(newblk->blkno >= mp->m_dirleafblk &&
646
                       newblk->blkno < mp->m_dirfreeblk);
647
 
648
        /*
649
         * We may need to make some room before we insert the new node.
650
         */
651
        tmp = 0;
652
        btree = &node->btree[ oldblk->index ];
653
        if (oldblk->index < INT_GET(node->hdr.count, ARCH_CONVERT)) {
654
                tmp = (INT_GET(node->hdr.count, ARCH_CONVERT) - oldblk->index) * (uint)sizeof(*btree);
655
                memmove(btree + 1, btree, tmp);
656
        }
657
        INT_SET(btree->hashval, ARCH_CONVERT, newblk->hashval);
658
        INT_SET(btree->before, ARCH_CONVERT, newblk->blkno);
659
        xfs_da_log_buf(state->args->trans, oldblk->bp,
660
                XFS_DA_LOGRANGE(node, btree, tmp + sizeof(*btree)));
661
        INT_MOD(node->hdr.count, ARCH_CONVERT, +1);
662
        xfs_da_log_buf(state->args->trans, oldblk->bp,
663
                XFS_DA_LOGRANGE(node, &node->hdr, sizeof(node->hdr)));
664
 
665
        /*
666
         * Copy the last hash value from the oldblk to propagate upwards.
667
         */
668
        oldblk->hashval = INT_GET(node->btree[ INT_GET(node->hdr.count, ARCH_CONVERT)-1 ].hashval, ARCH_CONVERT);
669
}
670
 
671
/*========================================================================
672
 * Routines used for shrinking the Btree.
673
 *========================================================================*/
674
 
675
/*
676
 * Deallocate an empty leaf node, remove it from its parent,
677
 * possibly deallocating that block, etc...
678
 */
679
int
680
xfs_da_join(xfs_da_state_t *state)
681
{
682
        xfs_da_state_blk_t *drop_blk, *save_blk;
683
        int action, error;
684
 
685
        action = 0;
686
        drop_blk = &state->path.blk[ state->path.active-1 ];
687
        save_blk = &state->altpath.blk[ state->path.active-1 ];
688
        ASSERT(state->path.blk[0].magic == XFS_DA_NODE_MAGIC);
689
        ASSERT(drop_blk->magic == XFS_ATTR_LEAF_MAGIC ||
690
               drop_blk->magic == XFS_DIRX_LEAF_MAGIC(state->mp));
691
 
692
        /*
693
         * Walk back up the tree joining/deallocating as necessary.
694
         * When we stop dropping blocks, break out.
695
         */
696
        for (  ; state->path.active >= 2; drop_blk--, save_blk--,
697
                 state->path.active--) {
698
                /*
699
                 * See if we can combine the block with a neighbor.
700
                 *   (action == 0) => no options, just leave
701
                 *   (action == 1) => coalesce, then unlink
702
                 *   (action == 2) => block empty, unlink it
703
                 */
704
                switch (drop_blk->magic) {
705
                case XFS_ATTR_LEAF_MAGIC:
706
#ifndef __KERNEL__
707
                        error = ENOTTY;
708
#else
709
                        error = xfs_attr_leaf_toosmall(state, &action);
710
#endif
711
                        if (error)
712
                                return(error);
713
                        if (action == 0)
714
                                return(0);
715
#ifdef __KERNEL__
716
                        xfs_attr_leaf_unbalance(state, drop_blk, save_blk);
717
#endif
718
                        break;
719
                case XFS_DIR_LEAF_MAGIC:
720
                        ASSERT(XFS_DIR_IS_V1(state->mp));
721
                        error = xfs_dir_leaf_toosmall(state, &action);
722
                        if (error)
723
                                return(error);
724
                        if (action == 0)
725
                                return(0);
726
                        xfs_dir_leaf_unbalance(state, drop_blk, save_blk);
727
                        break;
728
                case XFS_DIR2_LEAFN_MAGIC:
729
                        ASSERT(XFS_DIR_IS_V2(state->mp));
730
                        error = xfs_dir2_leafn_toosmall(state, &action);
731
                        if (error)
732
                                return error;
733
                        if (action == 0)
734
                                return 0;
735
                        xfs_dir2_leafn_unbalance(state, drop_blk, save_blk);
736
                        break;
737
                case XFS_DA_NODE_MAGIC:
738
                        /*
739
                         * Remove the offending node, fixup hashvals,
740
                         * check for a toosmall neighbor.
741
                         */
742
                        xfs_da_node_remove(state, drop_blk);
743
                        xfs_da_fixhashpath(state, &state->path);
744
                        error = xfs_da_node_toosmall(state, &action);
745
                        if (error)
746
                                return(error);
747
                        if (action == 0)
748
                                return 0;
749
                        xfs_da_node_unbalance(state, drop_blk, save_blk);
750
                        break;
751
                }
752
                xfs_da_fixhashpath(state, &state->altpath);
753
                error = xfs_da_blk_unlink(state, drop_blk, save_blk);
754
                xfs_da_state_kill_altpath(state);
755
                if (error)
756
                        return(error);
757
                error = xfs_da_shrink_inode(state->args, drop_blk->blkno,
758
                                                         drop_blk->bp);
759
                drop_blk->bp = NULL;
760
                if (error)
761
                        return(error);
762
        }
763
        /*
764
         * We joined all the way to the top.  If it turns out that
765
         * we only have one entry in the root, make the child block
766
         * the new root.
767
         */
768
        xfs_da_node_remove(state, drop_blk);
769
        xfs_da_fixhashpath(state, &state->path);
770
        error = xfs_da_root_join(state, &state->path.blk[0]);
771
        return(error);
772
}
773
 
774
/*
775
 * We have only one entry in the root.  Copy the only remaining child of
776
 * the old root to block 0 as the new root node.
777
 */
778
STATIC int
779
xfs_da_root_join(xfs_da_state_t *state, xfs_da_state_blk_t *root_blk)
780
{
781
        xfs_da_intnode_t *oldroot;
782
        /* REFERENCED */
783
        xfs_da_blkinfo_t *blkinfo;
784
        xfs_da_args_t *args;
785
        xfs_dablk_t child;
786
        xfs_dabuf_t *bp;
787
        int error;
788
 
789
        args = state->args;
790
        ASSERT(args != NULL);
791
        ASSERT(root_blk->magic == XFS_DA_NODE_MAGIC);
792
        oldroot = root_blk->bp->data;
793
        ASSERT(INT_GET(oldroot->hdr.info.magic, ARCH_CONVERT) == XFS_DA_NODE_MAGIC);
794
        ASSERT(INT_ISZERO(oldroot->hdr.info.forw, ARCH_CONVERT));
795
        ASSERT(INT_ISZERO(oldroot->hdr.info.back, ARCH_CONVERT));
796
 
797
        /*
798
         * If the root has more than one child, then don't do anything.
799
         */
800
        if (INT_GET(oldroot->hdr.count, ARCH_CONVERT) > 1)
801
                return(0);
802
 
803
        /*
804
         * Read in the (only) child block, then copy those bytes into
805
         * the root block's buffer and free the original child block.
806
         */
807
        child = INT_GET(oldroot->btree[ 0 ].before, ARCH_CONVERT);
808
        ASSERT(child != 0);
809
        error = xfs_da_read_buf(args->trans, args->dp, child, -1, &bp,
810
                                             args->whichfork);
811
        if (error)
812
                return(error);
813
        ASSERT(bp != NULL);
814
        blkinfo = bp->data;
815
        if (INT_GET(oldroot->hdr.level, ARCH_CONVERT) == 1) {
816
                ASSERT(INT_GET(blkinfo->magic, ARCH_CONVERT) == XFS_DIRX_LEAF_MAGIC(state->mp) ||
817
                       INT_GET(blkinfo->magic, ARCH_CONVERT) == XFS_ATTR_LEAF_MAGIC);
818
        } else {
819
                ASSERT(INT_GET(blkinfo->magic, ARCH_CONVERT) == XFS_DA_NODE_MAGIC);
820
        }
821
        ASSERT(INT_ISZERO(blkinfo->forw, ARCH_CONVERT));
822
        ASSERT(INT_ISZERO(blkinfo->back, ARCH_CONVERT));
823
        memcpy(root_blk->bp->data, bp->data, state->blocksize);
824
        xfs_da_log_buf(args->trans, root_blk->bp, 0, state->blocksize - 1);
825
        error = xfs_da_shrink_inode(args, child, bp);
826
        return(error);
827
}
828
 
829
/*
830
 * Check a node block and its neighbors to see if the block should be
831
 * collapsed into one or the other neighbor.  Always keep the block
832
 * with the smaller block number.
833
 * If the current block is over 50% full, don't try to join it, return 0.
834
 * If the block is empty, fill in the state structure and return 2.
835
 * If it can be collapsed, fill in the state structure and return 1.
836
 * If nothing can be done, return 0.
837
 */
838
STATIC int
839
xfs_da_node_toosmall(xfs_da_state_t *state, int *action)
840
{
841
        xfs_da_intnode_t *node;
842
        xfs_da_state_blk_t *blk;
843
        xfs_da_blkinfo_t *info;
844
        int count, forward, error, retval, i;
845
        xfs_dablk_t blkno;
846
        xfs_dabuf_t *bp;
847
 
848
        /*
849
         * Check for the degenerate case of the block being over 50% full.
850
         * If so, it's not worth even looking to see if we might be able
851
         * to coalesce with a sibling.
852
         */
853
        blk = &state->path.blk[ state->path.active-1 ];
854
        info = blk->bp->data;
855
        ASSERT(INT_GET(info->magic, ARCH_CONVERT) == XFS_DA_NODE_MAGIC);
856
        node = (xfs_da_intnode_t *)info;
857
        count = INT_GET(node->hdr.count, ARCH_CONVERT);
858
        if (count > (state->node_ents >> 1)) {
859
                *action = 0;     /* blk over 50%, don't try to join */
860
                return(0);       /* blk over 50%, don't try to join */
861
        }
862
 
863
        /*
864
         * Check for the degenerate case of the block being empty.
865
         * If the block is empty, we'll simply delete it, no need to
866
         * coalesce it with a sibling block.  We choose (aribtrarily)
867
         * to merge with the forward block unless it is NULL.
868
         */
869
        if (count == 0) {
870
                /*
871
                 * Make altpath point to the block we want to keep and
872
                 * path point to the block we want to drop (this one).
873
                 */
874
                forward = (!INT_ISZERO(info->forw, ARCH_CONVERT));
875
                memcpy(&state->altpath, &state->path, sizeof(state->path));
876
                error = xfs_da_path_shift(state, &state->altpath, forward,
877
                                                 0, &retval);
878
                if (error)
879
                        return(error);
880
                if (retval) {
881
                        *action = 0;
882
                } else {
883
                        *action = 2;
884
                }
885
                return(0);
886
        }
887
 
888
        /*
889
         * Examine each sibling block to see if we can coalesce with
890
         * at least 25% free space to spare.  We need to figure out
891
         * whether to merge with the forward or the backward block.
892
         * We prefer coalescing with the lower numbered sibling so as
893
         * to shrink a directory over time.
894
         */
895
        /* start with smaller blk num */
896
        forward = (INT_GET(info->forw, ARCH_CONVERT)
897
                                < INT_GET(info->back, ARCH_CONVERT));
898
        for (i = 0; i < 2; forward = !forward, i++) {
899
                if (forward)
900
                        blkno = INT_GET(info->forw, ARCH_CONVERT);
901
                else
902
                        blkno = INT_GET(info->back, ARCH_CONVERT);
903
                if (blkno == 0)
904
                        continue;
905
                error = xfs_da_read_buf(state->args->trans, state->args->dp,
906
                                        blkno, -1, &bp, state->args->whichfork);
907
                if (error)
908
                        return(error);
909
                ASSERT(bp != NULL);
910
 
911
                node = (xfs_da_intnode_t *)info;
912
                count  = state->node_ents;
913
                count -= state->node_ents >> 2;
914
                count -= INT_GET(node->hdr.count, ARCH_CONVERT);
915
                node = bp->data;
916
                ASSERT(INT_GET(node->hdr.info.magic, ARCH_CONVERT) == XFS_DA_NODE_MAGIC);
917
                count -= INT_GET(node->hdr.count, ARCH_CONVERT);
918
                xfs_da_brelse(state->args->trans, bp);
919
                if (count >= 0)
920
                        break;  /* fits with at least 25% to spare */
921
        }
922
        if (i >= 2) {
923
                *action = 0;
924
                return(0);
925
        }
926
 
927
        /*
928
         * Make altpath point to the block we want to keep (the lower
929
         * numbered block) and path point to the block we want to drop.
930
         */
931
        memcpy(&state->altpath, &state->path, sizeof(state->path));
932
        if (blkno < blk->blkno) {
933
                error = xfs_da_path_shift(state, &state->altpath, forward,
934
                                                 0, &retval);
935
                if (error) {
936
                        return(error);
937
                }
938
                if (retval) {
939
                        *action = 0;
940
                        return(0);
941
                }
942
        } else {
943
                error = xfs_da_path_shift(state, &state->path, forward,
944
                                                 0, &retval);
945
                if (error) {
946
                        return(error);
947
                }
948
                if (retval) {
949
                        *action = 0;
950
                        return(0);
951
                }
952
        }
953
        *action = 1;
954
        return(0);
955
}
956
 
957
/*
958
 * Walk back up the tree adjusting hash values as necessary,
959
 * when we stop making changes, return.
960
 */
961
void
962
xfs_da_fixhashpath(xfs_da_state_t *state, xfs_da_state_path_t *path)
963
{
964
        xfs_da_state_blk_t *blk;
965
        xfs_da_intnode_t *node;
966
        xfs_da_node_entry_t *btree;
967
        xfs_dahash_t lasthash=0;
968
        int level, count;
969
 
970
        level = path->active-1;
971
        blk = &path->blk[ level ];
972
        switch (blk->magic) {
973
#ifdef __KERNEL__
974
        case XFS_ATTR_LEAF_MAGIC:
975
                lasthash = xfs_attr_leaf_lasthash(blk->bp, &count);
976
                if (count == 0)
977
                        return;
978
                break;
979
#endif
980
        case XFS_DIR_LEAF_MAGIC:
981
                ASSERT(XFS_DIR_IS_V1(state->mp));
982
                lasthash = xfs_dir_leaf_lasthash(blk->bp, &count);
983
                if (count == 0)
984
                        return;
985
                break;
986
        case XFS_DIR2_LEAFN_MAGIC:
987
                ASSERT(XFS_DIR_IS_V2(state->mp));
988
                lasthash = xfs_dir2_leafn_lasthash(blk->bp, &count);
989
                if (count == 0)
990
                        return;
991
                break;
992
        case XFS_DA_NODE_MAGIC:
993
                lasthash = xfs_da_node_lasthash(blk->bp, &count);
994
                if (count == 0)
995
                        return;
996
                break;
997
        }
998
        for (blk--, level--; level >= 0; blk--, level--) {
999
                node = blk->bp->data;
1000
                ASSERT(INT_GET(node->hdr.info.magic, ARCH_CONVERT) == XFS_DA_NODE_MAGIC);
1001
                btree = &node->btree[ blk->index ];
1002
                if (INT_GET(btree->hashval, ARCH_CONVERT) == lasthash)
1003
                        break;
1004
                blk->hashval = lasthash;
1005
                INT_SET(btree->hashval, ARCH_CONVERT, lasthash);
1006
                xfs_da_log_buf(state->args->trans, blk->bp,
1007
                                  XFS_DA_LOGRANGE(node, btree, sizeof(*btree)));
1008
 
1009
                lasthash = INT_GET(node->btree[ INT_GET(node->hdr.count, ARCH_CONVERT)-1 ].hashval, ARCH_CONVERT);
1010
        }
1011
}
1012
 
1013
/*
1014
 * Remove an entry from an intermediate node.
1015
 */
1016
STATIC void
1017
xfs_da_node_remove(xfs_da_state_t *state, xfs_da_state_blk_t *drop_blk)
1018
{
1019
        xfs_da_intnode_t *node;
1020
        xfs_da_node_entry_t *btree;
1021
        int tmp;
1022
 
1023
        node = drop_blk->bp->data;
1024
        ASSERT(drop_blk->index < INT_GET(node->hdr.count, ARCH_CONVERT));
1025
        ASSERT(drop_blk->index >= 0);
1026
 
1027
        /*
1028
         * Copy over the offending entry, or just zero it out.
1029
         */
1030
        btree = &node->btree[drop_blk->index];
1031
        if (drop_blk->index < (INT_GET(node->hdr.count, ARCH_CONVERT)-1)) {
1032
                tmp  = INT_GET(node->hdr.count, ARCH_CONVERT) - drop_blk->index - 1;
1033
                tmp *= (uint)sizeof(xfs_da_node_entry_t);
1034
                memmove(btree, btree + 1, tmp);
1035
                xfs_da_log_buf(state->args->trans, drop_blk->bp,
1036
                    XFS_DA_LOGRANGE(node, btree, tmp));
1037
                btree = &node->btree[ INT_GET(node->hdr.count, ARCH_CONVERT)-1 ];
1038
        }
1039
        memset((char *)btree, 0, sizeof(xfs_da_node_entry_t));
1040
        xfs_da_log_buf(state->args->trans, drop_blk->bp,
1041
            XFS_DA_LOGRANGE(node, btree, sizeof(*btree)));
1042
        INT_MOD(node->hdr.count, ARCH_CONVERT, -1);
1043
        xfs_da_log_buf(state->args->trans, drop_blk->bp,
1044
            XFS_DA_LOGRANGE(node, &node->hdr, sizeof(node->hdr)));
1045
 
1046
        /*
1047
         * Copy the last hash value from the block to propagate upwards.
1048
         */
1049
        btree--;
1050
        drop_blk->hashval = INT_GET(btree->hashval, ARCH_CONVERT);
1051
}
1052
 
1053
/*
1054
 * Unbalance the btree elements between two intermediate nodes,
1055
 * move all Btree elements from one node into another.
1056
 */
1057
STATIC void
1058
xfs_da_node_unbalance(xfs_da_state_t *state, xfs_da_state_blk_t *drop_blk,
1059
                                     xfs_da_state_blk_t *save_blk)
1060
{
1061
        xfs_da_intnode_t *drop_node, *save_node;
1062
        xfs_da_node_entry_t *btree;
1063
        int tmp;
1064
        xfs_trans_t *tp;
1065
 
1066
        drop_node = drop_blk->bp->data;
1067
        save_node = save_blk->bp->data;
1068
        ASSERT(INT_GET(drop_node->hdr.info.magic, ARCH_CONVERT) == XFS_DA_NODE_MAGIC);
1069
        ASSERT(INT_GET(save_node->hdr.info.magic, ARCH_CONVERT) == XFS_DA_NODE_MAGIC);
1070
        tp = state->args->trans;
1071
 
1072
        /*
1073
         * If the dying block has lower hashvals, then move all the
1074
         * elements in the remaining block up to make a hole.
1075
         */
1076
        if ((INT_GET(drop_node->btree[ 0 ].hashval, ARCH_CONVERT) < INT_GET(save_node->btree[ 0 ].hashval, ARCH_CONVERT)) ||
1077
            (INT_GET(drop_node->btree[ INT_GET(drop_node->hdr.count, ARCH_CONVERT)-1 ].hashval, ARCH_CONVERT) <
1078
             INT_GET(save_node->btree[ INT_GET(save_node->hdr.count, ARCH_CONVERT)-1 ].hashval, ARCH_CONVERT)))
1079
        {
1080
                btree = &save_node->btree[ INT_GET(drop_node->hdr.count, ARCH_CONVERT) ];
1081
                tmp = INT_GET(save_node->hdr.count, ARCH_CONVERT) * (uint)sizeof(xfs_da_node_entry_t);
1082
                memmove(btree, &save_node->btree[0], tmp);
1083
                btree = &save_node->btree[0];
1084
                xfs_da_log_buf(tp, save_blk->bp,
1085
                        XFS_DA_LOGRANGE(save_node, btree,
1086
                                (INT_GET(save_node->hdr.count, ARCH_CONVERT) + INT_GET(drop_node->hdr.count, ARCH_CONVERT)) *
1087
                                sizeof(xfs_da_node_entry_t)));
1088
        } else {
1089
                btree = &save_node->btree[ INT_GET(save_node->hdr.count, ARCH_CONVERT) ];
1090
                xfs_da_log_buf(tp, save_blk->bp,
1091
                        XFS_DA_LOGRANGE(save_node, btree,
1092
                                INT_GET(drop_node->hdr.count, ARCH_CONVERT) *
1093
                                sizeof(xfs_da_node_entry_t)));
1094
        }
1095
 
1096
        /*
1097
         * Move all the B-tree elements from drop_blk to save_blk.
1098
         */
1099
        tmp = INT_GET(drop_node->hdr.count, ARCH_CONVERT) * (uint)sizeof(xfs_da_node_entry_t);
1100
        memcpy(btree, &drop_node->btree[0], tmp);
1101
        INT_MOD(save_node->hdr.count, ARCH_CONVERT, INT_GET(drop_node->hdr.count, ARCH_CONVERT));
1102
 
1103
        xfs_da_log_buf(tp, save_blk->bp,
1104
                XFS_DA_LOGRANGE(save_node, &save_node->hdr,
1105
                        sizeof(save_node->hdr)));
1106
 
1107
        /*
1108
         * Save the last hashval in the remaining block for upward propagation.
1109
         */
1110
        save_blk->hashval = INT_GET(save_node->btree[ INT_GET(save_node->hdr.count, ARCH_CONVERT)-1 ].hashval, ARCH_CONVERT);
1111
}
1112
 
1113
/*========================================================================
1114
 * Routines used for finding things in the Btree.
1115
 *========================================================================*/
1116
 
1117
/*
1118
 * Walk down the Btree looking for a particular filename, filling
1119
 * in the state structure as we go.
1120
 *
1121
 * We will set the state structure to point to each of the elements
1122
 * in each of the nodes where either the hashval is or should be.
1123
 *
1124
 * We support duplicate hashval's so for each entry in the current
1125
 * node that could contain the desired hashval, descend.  This is a
1126
 * pruned depth-first tree search.
1127
 */
1128
int                                                     /* error */
1129
xfs_da_node_lookup_int(xfs_da_state_t *state, int *result)
1130
{
1131
        xfs_da_state_blk_t *blk;
1132
        xfs_da_blkinfo_t *curr;
1133
        xfs_da_intnode_t *node;
1134
        xfs_da_node_entry_t *btree;
1135
        xfs_dablk_t blkno;
1136
        int probe, span, max, error, retval;
1137
        xfs_dahash_t hashval;
1138
        xfs_da_args_t *args;
1139
 
1140
        args = state->args;
1141
 
1142
        /*
1143
         * Descend thru the B-tree searching each level for the right
1144
         * node to use, until the right hashval is found.
1145
         */
1146
        if (args->whichfork == XFS_DATA_FORK && XFS_DIR_IS_V2(state->mp))
1147
                blkno = state->mp->m_dirleafblk;
1148
        else
1149
                blkno = 0;
1150
        for (blk = &state->path.blk[0], state->path.active = 1;
1151
                         state->path.active <= XFS_DA_NODE_MAXDEPTH;
1152
                         blk++, state->path.active++) {
1153
                /*
1154
                 * Read the next node down in the tree.
1155
                 */
1156
                blk->blkno = blkno;
1157
                error = xfs_da_read_buf(args->trans, args->dp, blkno,
1158
                                        -1, &blk->bp, args->whichfork);
1159
                if (error) {
1160
                        blk->blkno = 0;
1161
                        state->path.active--;
1162
                        return(error);
1163
                }
1164
                curr = blk->bp->data;
1165
                ASSERT(INT_GET(curr->magic, ARCH_CONVERT) == XFS_DA_NODE_MAGIC ||
1166
                       INT_GET(curr->magic, ARCH_CONVERT) == XFS_DIRX_LEAF_MAGIC(state->mp) ||
1167
                       INT_GET(curr->magic, ARCH_CONVERT) == XFS_ATTR_LEAF_MAGIC);
1168
 
1169
                /*
1170
                 * Search an intermediate node for a match.
1171
                 */
1172
                blk->magic = INT_GET(curr->magic, ARCH_CONVERT);
1173
                if (INT_GET(curr->magic, ARCH_CONVERT) == XFS_DA_NODE_MAGIC) {
1174
                        node = blk->bp->data;
1175
                        blk->hashval = INT_GET(node->btree[ INT_GET(node->hdr.count, ARCH_CONVERT)-1 ].hashval, ARCH_CONVERT);
1176
 
1177
                        /*
1178
                         * Binary search.  (note: small blocks will skip loop)
1179
                         */
1180
                        max = INT_GET(node->hdr.count, ARCH_CONVERT);
1181
                        probe = span = max / 2;
1182
                        hashval = args->hashval;
1183
                        for (btree = &node->btree[probe]; span > 4;
1184
                                   btree = &node->btree[probe]) {
1185
                                span /= 2;
1186
                                if (INT_GET(btree->hashval, ARCH_CONVERT) < hashval)
1187
                                        probe += span;
1188
                                else if (INT_GET(btree->hashval, ARCH_CONVERT) > hashval)
1189
                                        probe -= span;
1190
                                else
1191
                                        break;
1192
                        }
1193
                        ASSERT((probe >= 0) && (probe < max));
1194
                        ASSERT((span <= 4) || (INT_GET(btree->hashval, ARCH_CONVERT) == hashval));
1195
 
1196
                        /*
1197
                         * Since we may have duplicate hashval's, find the first
1198
                         * matching hashval in the node.
1199
                         */
1200
                        while ((probe > 0) && (INT_GET(btree->hashval, ARCH_CONVERT) >= hashval)) {
1201
                                btree--;
1202
                                probe--;
1203
                        }
1204
                        while ((probe < max) && (INT_GET(btree->hashval, ARCH_CONVERT) < hashval)) {
1205
                                btree++;
1206
                                probe++;
1207
                        }
1208
 
1209
                        /*
1210
                         * Pick the right block to descend on.
1211
                         */
1212
                        if (probe == max) {
1213
                                blk->index = max-1;
1214
                                blkno = INT_GET(node->btree[ max-1 ].before, ARCH_CONVERT);
1215
                        } else {
1216
                                blk->index = probe;
1217
                                blkno = INT_GET(btree->before, ARCH_CONVERT);
1218
                        }
1219
                }
1220
#ifdef __KERNEL__
1221
                else if (INT_GET(curr->magic, ARCH_CONVERT) == XFS_ATTR_LEAF_MAGIC) {
1222
                        blk->hashval = xfs_attr_leaf_lasthash(blk->bp, NULL);
1223
                        break;
1224
                }
1225
#endif
1226
                else if (INT_GET(curr->magic, ARCH_CONVERT) == XFS_DIR_LEAF_MAGIC) {
1227
                        blk->hashval = xfs_dir_leaf_lasthash(blk->bp, NULL);
1228
                        break;
1229
                }
1230
                else if (INT_GET(curr->magic, ARCH_CONVERT) == XFS_DIR2_LEAFN_MAGIC) {
1231
                        blk->hashval = xfs_dir2_leafn_lasthash(blk->bp, NULL);
1232
                        break;
1233
                }
1234
        }
1235
 
1236
        /*
1237
         * A leaf block that ends in the hashval that we are interested in
1238
         * (final hashval == search hashval) means that the next block may
1239
         * contain more entries with the same hashval, shift upward to the
1240
         * next leaf and keep searching.
1241
         */
1242
        for (;;) {
1243
                if (blk->magic == XFS_DIR_LEAF_MAGIC) {
1244
                        ASSERT(XFS_DIR_IS_V1(state->mp));
1245
                        retval = xfs_dir_leaf_lookup_int(blk->bp, args,
1246
                                                                  &blk->index);
1247
                } else if (blk->magic == XFS_DIR2_LEAFN_MAGIC) {
1248
                        ASSERT(XFS_DIR_IS_V2(state->mp));
1249
                        retval = xfs_dir2_leafn_lookup_int(blk->bp, args,
1250
                                                        &blk->index, state);
1251
                }
1252
#ifdef __KERNEL__
1253
                else if (blk->magic == XFS_ATTR_LEAF_MAGIC) {
1254
                        retval = xfs_attr_leaf_lookup_int(blk->bp, args);
1255
                        blk->index = args->index;
1256
                        args->blkno = blk->blkno;
1257
                }
1258
#endif
1259
                if (((retval == ENOENT) || (retval == ENOATTR)) &&
1260
                    (blk->hashval == args->hashval)) {
1261
                        error = xfs_da_path_shift(state, &state->path, 1, 1,
1262
                                                         &retval);
1263
                        if (error)
1264
                                return(error);
1265
                        if (retval == 0) {
1266
                                continue;
1267
                        }
1268
#ifdef __KERNEL__
1269
                        else if (blk->magic == XFS_ATTR_LEAF_MAGIC) {
1270
                                /* path_shift() gives ENOENT */
1271
                                retval = XFS_ERROR(ENOATTR);
1272
                        }
1273
#endif
1274
                }
1275
                break;
1276
        }
1277
        *result = retval;
1278
        return(0);
1279
}
1280
 
1281
/*========================================================================
1282
 * Utility routines.
1283
 *========================================================================*/
1284
 
1285
/*
1286
 * Link a new block into a doubly linked list of blocks (of whatever type).
1287
 */
1288
int                                                     /* error */
1289
xfs_da_blk_link(xfs_da_state_t *state, xfs_da_state_blk_t *old_blk,
1290
                               xfs_da_state_blk_t *new_blk)
1291
{
1292
        xfs_da_blkinfo_t *old_info, *new_info, *tmp_info;
1293
        xfs_da_args_t *args;
1294
        int before=0, error;
1295
        xfs_dabuf_t *bp;
1296
 
1297
        /*
1298
         * Set up environment.
1299
         */
1300
        args = state->args;
1301
        ASSERT(args != NULL);
1302
        old_info = old_blk->bp->data;
1303
        new_info = new_blk->bp->data;
1304
        ASSERT(old_blk->magic == XFS_DA_NODE_MAGIC ||
1305
               old_blk->magic == XFS_DIRX_LEAF_MAGIC(state->mp) ||
1306
               old_blk->magic == XFS_ATTR_LEAF_MAGIC);
1307
        ASSERT(old_blk->magic == INT_GET(old_info->magic, ARCH_CONVERT));
1308
        ASSERT(new_blk->magic == INT_GET(new_info->magic, ARCH_CONVERT));
1309
        ASSERT(old_blk->magic == new_blk->magic);
1310
 
1311
        switch (old_blk->magic) {
1312
#ifdef __KERNEL__
1313
        case XFS_ATTR_LEAF_MAGIC:
1314
                before = xfs_attr_leaf_order(old_blk->bp, new_blk->bp);
1315
                break;
1316
#endif
1317
        case XFS_DIR_LEAF_MAGIC:
1318
                ASSERT(XFS_DIR_IS_V1(state->mp));
1319
                before = xfs_dir_leaf_order(old_blk->bp, new_blk->bp);
1320
                break;
1321
        case XFS_DIR2_LEAFN_MAGIC:
1322
                ASSERT(XFS_DIR_IS_V2(state->mp));
1323
                before = xfs_dir2_leafn_order(old_blk->bp, new_blk->bp);
1324
                break;
1325
        case XFS_DA_NODE_MAGIC:
1326
                before = xfs_da_node_order(old_blk->bp, new_blk->bp);
1327
                break;
1328
        }
1329
 
1330
        /*
1331
         * Link blocks in appropriate order.
1332
         */
1333
        if (before) {
1334
                /*
1335
                 * Link new block in before existing block.
1336
                 */
1337
                INT_SET(new_info->forw, ARCH_CONVERT, old_blk->blkno);
1338
                new_info->back = old_info->back; /* INT_: direct copy */
1339
                if (INT_GET(old_info->back, ARCH_CONVERT)) {
1340
                        error = xfs_da_read_buf(args->trans, args->dp,
1341
                                                INT_GET(old_info->back,
1342
                                                        ARCH_CONVERT), -1, &bp,
1343
                                                args->whichfork);
1344
                        if (error)
1345
                                return(error);
1346
                        ASSERT(bp != NULL);
1347
                        tmp_info = bp->data;
1348
                        ASSERT(INT_GET(tmp_info->magic, ARCH_CONVERT) == INT_GET(old_info->magic, ARCH_CONVERT));
1349
                        ASSERT(INT_GET(tmp_info->forw, ARCH_CONVERT) == old_blk->blkno);
1350
                        INT_SET(tmp_info->forw, ARCH_CONVERT, new_blk->blkno);
1351
                        xfs_da_log_buf(args->trans, bp, 0, sizeof(*tmp_info)-1);
1352
                        xfs_da_buf_done(bp);
1353
                }
1354
                INT_SET(old_info->back, ARCH_CONVERT, new_blk->blkno);
1355
        } else {
1356
                /*
1357
                 * Link new block in after existing block.
1358
                 */
1359
                new_info->forw = old_info->forw; /* INT_: direct copy */
1360
                INT_SET(new_info->back, ARCH_CONVERT, old_blk->blkno);
1361
                if (INT_GET(old_info->forw, ARCH_CONVERT)) {
1362
                        error = xfs_da_read_buf(args->trans, args->dp,
1363
                                                INT_GET(old_info->forw, ARCH_CONVERT), -1, &bp,
1364
                                                args->whichfork);
1365
                        if (error)
1366
                                return(error);
1367
                        ASSERT(bp != NULL);
1368
                        tmp_info = bp->data;
1369
                        ASSERT(INT_GET(tmp_info->magic, ARCH_CONVERT)
1370
                                    == INT_GET(old_info->magic, ARCH_CONVERT));
1371
                        ASSERT(INT_GET(tmp_info->back, ARCH_CONVERT)
1372
                                    == old_blk->blkno);
1373
                        INT_SET(tmp_info->back, ARCH_CONVERT, new_blk->blkno);
1374
                        xfs_da_log_buf(args->trans, bp, 0, sizeof(*tmp_info)-1);
1375
                        xfs_da_buf_done(bp);
1376
                }
1377
                INT_SET(old_info->forw, ARCH_CONVERT, new_blk->blkno);
1378
        }
1379
 
1380
        xfs_da_log_buf(args->trans, old_blk->bp, 0, sizeof(*tmp_info) - 1);
1381
        xfs_da_log_buf(args->trans, new_blk->bp, 0, sizeof(*tmp_info) - 1);
1382
        return(0);
1383
}
1384
 
1385
/*
1386
 * Compare two intermediate nodes for "order".
1387
 */
1388
STATIC int
1389
xfs_da_node_order(xfs_dabuf_t *node1_bp, xfs_dabuf_t *node2_bp)
1390
{
1391
        xfs_da_intnode_t *node1, *node2;
1392
 
1393
        node1 = node1_bp->data;
1394
        node2 = node2_bp->data;
1395
        ASSERT((INT_GET(node1->hdr.info.magic, ARCH_CONVERT) == XFS_DA_NODE_MAGIC) &&
1396
               (INT_GET(node2->hdr.info.magic, ARCH_CONVERT) == XFS_DA_NODE_MAGIC));
1397
        if ((INT_GET(node1->hdr.count, ARCH_CONVERT) > 0) && (INT_GET(node2->hdr.count, ARCH_CONVERT) > 0) &&
1398
            ((INT_GET(node2->btree[ 0 ].hashval, ARCH_CONVERT) <
1399
              INT_GET(node1->btree[ 0 ].hashval, ARCH_CONVERT)) ||
1400
             (INT_GET(node2->btree[ INT_GET(node2->hdr.count, ARCH_CONVERT)-1 ].hashval, ARCH_CONVERT) <
1401
              INT_GET(node1->btree[ INT_GET(node1->hdr.count, ARCH_CONVERT)-1 ].hashval, ARCH_CONVERT)))) {
1402
                return(1);
1403
        }
1404
        return(0);
1405
}
1406
 
1407
/*
1408
 * Pick up the last hashvalue from an intermediate node.
1409
 */
1410
STATIC uint
1411
xfs_da_node_lasthash(xfs_dabuf_t *bp, int *count)
1412
{
1413
        xfs_da_intnode_t *node;
1414
 
1415
        node = bp->data;
1416
        ASSERT(INT_GET(node->hdr.info.magic, ARCH_CONVERT) == XFS_DA_NODE_MAGIC);
1417
        if (count)
1418
                *count = INT_GET(node->hdr.count, ARCH_CONVERT);
1419
        if (INT_ISZERO(node->hdr.count, ARCH_CONVERT))
1420
                return(0);
1421
        return(INT_GET(node->btree[ INT_GET(node->hdr.count, ARCH_CONVERT)-1 ].hashval, ARCH_CONVERT));
1422
}
1423
 
1424
/*
1425
 * Unlink a block from a doubly linked list of blocks.
1426
 */
1427
int                                                     /* error */
1428
xfs_da_blk_unlink(xfs_da_state_t *state, xfs_da_state_blk_t *drop_blk,
1429
                                 xfs_da_state_blk_t *save_blk)
1430
{
1431
        xfs_da_blkinfo_t *drop_info, *save_info, *tmp_info;
1432
        xfs_da_args_t *args;
1433
        xfs_dabuf_t *bp;
1434
        int error;
1435
 
1436
        /*
1437
         * Set up environment.
1438
         */
1439
        args = state->args;
1440
        ASSERT(args != NULL);
1441
        save_info = save_blk->bp->data;
1442
        drop_info = drop_blk->bp->data;
1443
        ASSERT(save_blk->magic == XFS_DA_NODE_MAGIC ||
1444
               save_blk->magic == XFS_DIRX_LEAF_MAGIC(state->mp) ||
1445
               save_blk->magic == XFS_ATTR_LEAF_MAGIC);
1446
        ASSERT(save_blk->magic == INT_GET(save_info->magic, ARCH_CONVERT));
1447
        ASSERT(drop_blk->magic == INT_GET(drop_info->magic, ARCH_CONVERT));
1448
        ASSERT(save_blk->magic == drop_blk->magic);
1449
        ASSERT((INT_GET(save_info->forw, ARCH_CONVERT) == drop_blk->blkno) ||
1450
               (INT_GET(save_info->back, ARCH_CONVERT) == drop_blk->blkno));
1451
        ASSERT((INT_GET(drop_info->forw, ARCH_CONVERT) == save_blk->blkno) ||
1452
               (INT_GET(drop_info->back, ARCH_CONVERT) == save_blk->blkno));
1453
 
1454
        /*
1455
         * Unlink the leaf block from the doubly linked chain of leaves.
1456
         */
1457
        if (INT_GET(save_info->back, ARCH_CONVERT) == drop_blk->blkno) {
1458
                save_info->back = drop_info->back; /* INT_: direct copy */
1459
                if (INT_GET(drop_info->back, ARCH_CONVERT)) {
1460
                        error = xfs_da_read_buf(args->trans, args->dp,
1461
                                                INT_GET(drop_info->back,
1462
                                                        ARCH_CONVERT), -1, &bp,
1463
                                                args->whichfork);
1464
                        if (error)
1465
                                return(error);
1466
                        ASSERT(bp != NULL);
1467
                        tmp_info = bp->data;
1468
                        ASSERT(INT_GET(tmp_info->magic, ARCH_CONVERT) == INT_GET(save_info->magic, ARCH_CONVERT));
1469
                        ASSERT(INT_GET(tmp_info->forw, ARCH_CONVERT) == drop_blk->blkno);
1470
                        INT_SET(tmp_info->forw, ARCH_CONVERT, save_blk->blkno);
1471
                        xfs_da_log_buf(args->trans, bp, 0,
1472
                                                    sizeof(*tmp_info) - 1);
1473
                        xfs_da_buf_done(bp);
1474
                }
1475
        } else {
1476
                save_info->forw = drop_info->forw; /* INT_: direct copy */
1477
                if (INT_GET(drop_info->forw, ARCH_CONVERT)) {
1478
                        error = xfs_da_read_buf(args->trans, args->dp,
1479
                                                INT_GET(drop_info->forw, ARCH_CONVERT), -1, &bp,
1480
                                                args->whichfork);
1481
                        if (error)
1482
                                return(error);
1483
                        ASSERT(bp != NULL);
1484
                        tmp_info = bp->data;
1485
                        ASSERT(INT_GET(tmp_info->magic, ARCH_CONVERT)
1486
                                    == INT_GET(save_info->magic, ARCH_CONVERT));
1487
                        ASSERT(INT_GET(tmp_info->back, ARCH_CONVERT)
1488
                                    == drop_blk->blkno);
1489
                        INT_SET(tmp_info->back, ARCH_CONVERT, save_blk->blkno);
1490
                        xfs_da_log_buf(args->trans, bp, 0,
1491
                                                    sizeof(*tmp_info) - 1);
1492
                        xfs_da_buf_done(bp);
1493
                }
1494
        }
1495
 
1496
        xfs_da_log_buf(args->trans, save_blk->bp, 0, sizeof(*save_info) - 1);
1497
        return(0);
1498
}
1499
 
1500
/*
1501
 * Move a path "forward" or "!forward" one block at the current level.
1502
 *
1503
 * This routine will adjust a "path" to point to the next block
1504
 * "forward" (higher hashvalues) or "!forward" (lower hashvals) in the
1505
 * Btree, including updating pointers to the intermediate nodes between
1506
 * the new bottom and the root.
1507
 */
1508
int                                                     /* error */
1509
xfs_da_path_shift(xfs_da_state_t *state, xfs_da_state_path_t *path,
1510
                                 int forward, int release, int *result)
1511
{
1512
        xfs_da_state_blk_t *blk;
1513
        xfs_da_blkinfo_t *info;
1514
        xfs_da_intnode_t *node;
1515
        xfs_da_args_t *args;
1516
        xfs_dablk_t blkno=0;
1517
        int level, error;
1518
 
1519
        /*
1520
         * Roll up the Btree looking for the first block where our
1521
         * current index is not at the edge of the block.  Note that
1522
         * we skip the bottom layer because we want the sibling block.
1523
         */
1524
        args = state->args;
1525
        ASSERT(args != NULL);
1526
        ASSERT(path != NULL);
1527
        ASSERT((path->active > 0) && (path->active < XFS_DA_NODE_MAXDEPTH));
1528
        level = (path->active-1) - 1;   /* skip bottom layer in path */
1529
        for (blk = &path->blk[level]; level >= 0; blk--, level--) {
1530
                ASSERT(blk->bp != NULL);
1531
                node = blk->bp->data;
1532
                ASSERT(INT_GET(node->hdr.info.magic, ARCH_CONVERT) == XFS_DA_NODE_MAGIC);
1533
                if (forward && (blk->index < INT_GET(node->hdr.count, ARCH_CONVERT)-1)) {
1534
                        blk->index++;
1535
                        blkno = INT_GET(node->btree[ blk->index ].before, ARCH_CONVERT);
1536
                        break;
1537
                } else if (!forward && (blk->index > 0)) {
1538
                        blk->index--;
1539
                        blkno = INT_GET(node->btree[ blk->index ].before, ARCH_CONVERT);
1540
                        break;
1541
                }
1542
        }
1543
        if (level < 0) {
1544
                *result = XFS_ERROR(ENOENT);    /* we're out of our tree */
1545
                ASSERT(args->oknoent);
1546
                return(0);
1547
        }
1548
 
1549
        /*
1550
         * Roll down the edge of the subtree until we reach the
1551
         * same depth we were at originally.
1552
         */
1553
        for (blk++, level++; level < path->active; blk++, level++) {
1554
                /*
1555
                 * Release the old block.
1556
                 * (if it's dirty, trans won't actually let go)
1557
                 */
1558
                if (release)
1559
                        xfs_da_brelse(args->trans, blk->bp);
1560
 
1561
                /*
1562
                 * Read the next child block.
1563
                 */
1564
                blk->blkno = blkno;
1565
                error = xfs_da_read_buf(args->trans, args->dp, blkno, -1,
1566
                                                     &blk->bp, args->whichfork);
1567
                if (error)
1568
                        return(error);
1569
                ASSERT(blk->bp != NULL);
1570
                info = blk->bp->data;
1571
                ASSERT(INT_GET(info->magic, ARCH_CONVERT) == XFS_DA_NODE_MAGIC ||
1572
                       INT_GET(info->magic, ARCH_CONVERT) == XFS_DIRX_LEAF_MAGIC(state->mp) ||
1573
                       INT_GET(info->magic, ARCH_CONVERT) == XFS_ATTR_LEAF_MAGIC);
1574
                blk->magic = INT_GET(info->magic, ARCH_CONVERT);
1575
                if (INT_GET(info->magic, ARCH_CONVERT) == XFS_DA_NODE_MAGIC) {
1576
                        node = (xfs_da_intnode_t *)info;
1577
                        blk->hashval = INT_GET(node->btree[ INT_GET(node->hdr.count, ARCH_CONVERT)-1 ].hashval, ARCH_CONVERT);
1578
                        if (forward)
1579
                                blk->index = 0;
1580
                        else
1581
                                blk->index = INT_GET(node->hdr.count, ARCH_CONVERT)-1;
1582
                        blkno = INT_GET(node->btree[ blk->index ].before, ARCH_CONVERT);
1583
                } else {
1584
                        ASSERT(level == path->active-1);
1585
                        blk->index = 0;
1586
                        switch(blk->magic) {
1587
#ifdef __KERNEL__
1588
                        case XFS_ATTR_LEAF_MAGIC:
1589
                                blk->hashval = xfs_attr_leaf_lasthash(blk->bp,
1590
                                                                      NULL);
1591
                                break;
1592
#endif
1593
                        case XFS_DIR_LEAF_MAGIC:
1594
                                ASSERT(XFS_DIR_IS_V1(state->mp));
1595
                                blk->hashval = xfs_dir_leaf_lasthash(blk->bp,
1596
                                                                     NULL);
1597
                                break;
1598
                        case XFS_DIR2_LEAFN_MAGIC:
1599
                                ASSERT(XFS_DIR_IS_V2(state->mp));
1600
                                blk->hashval = xfs_dir2_leafn_lasthash(blk->bp,
1601
                                                                       NULL);
1602
                                break;
1603
                        default:
1604
                                ASSERT(blk->magic == XFS_ATTR_LEAF_MAGIC ||
1605
                                       blk->magic ==
1606
                                       XFS_DIRX_LEAF_MAGIC(state->mp));
1607
                                break;
1608
                        }
1609
                }
1610
        }
1611
        *result = 0;
1612
        return(0);
1613
}
1614
 
1615
 
1616
/*========================================================================
1617
 * Utility routines.
1618
 *========================================================================*/
1619
 
1620
/*
1621
 * Implement a simple hash on a character string.
1622
 * Rotate the hash value by 7 bits, then XOR each character in.
1623
 * This is implemented with some source-level loop unrolling.
1624
 */
1625
xfs_dahash_t
1626
xfs_da_hashname(uchar_t *name, int namelen)
1627
{
1628
        xfs_dahash_t hash;
1629
 
1630
#define ROTL(x,y)       (((x) << (y)) | ((x) >> (32 - (y))))
1631
#ifdef SLOWVERSION
1632
        /*
1633
         * This is the old one-byte-at-a-time version.
1634
         */
1635
        for (hash = 0; namelen > 0; namelen--) {
1636
                hash = *name++ ^ ROTL(hash, 7);
1637
        }
1638
        return(hash);
1639
#else
1640
        /*
1641
         * Do four characters at a time as long as we can.
1642
         */
1643
        for (hash = 0; namelen >= 4; namelen -= 4, name += 4) {
1644
                hash = (name[0] << 21) ^ (name[1] << 14) ^ (name[2] << 7) ^
1645
                       (name[3] << 0) ^ ROTL(hash, 7 * 4);
1646
        }
1647
        /*
1648
         * Now do the rest of the characters.
1649
         */
1650
        switch (namelen) {
1651
        case 3:
1652
                return (name[0] << 14) ^ (name[1] << 7) ^ (name[2] << 0) ^
1653
                       ROTL(hash, 7 * 3);
1654
        case 2:
1655
                return (name[0] << 7) ^ (name[1] << 0) ^ ROTL(hash, 7 * 2);
1656
        case 1:
1657
                return (name[0] << 0) ^ ROTL(hash, 7 * 1);
1658
        case 0:
1659
                return hash;
1660
        }
1661
        /* NOTREACHED */
1662
#endif
1663
#undef ROTL
1664
        return 0; /* keep gcc happy */
1665
}
1666
 
1667
/*
1668
 * Add a block to the btree ahead of the file.
1669
 * Return the new block number to the caller.
1670
 */
1671
int
1672
xfs_da_grow_inode(xfs_da_args_t *args, xfs_dablk_t *new_blkno)
1673
{
1674
        xfs_fileoff_t bno, b;
1675
        xfs_bmbt_irec_t map;
1676
        xfs_bmbt_irec_t *mapp;
1677
        xfs_inode_t *dp;
1678
        int nmap, error, w, count, c, got, i, mapi;
1679
        xfs_fsize_t size;
1680
        xfs_trans_t *tp;
1681
        xfs_mount_t *mp;
1682
 
1683
        dp = args->dp;
1684
        mp = dp->i_mount;
1685
        w = args->whichfork;
1686
        tp = args->trans;
1687
        /*
1688
         * For new directories adjust the file offset and block count.
1689
         */
1690
        if (w == XFS_DATA_FORK && XFS_DIR_IS_V2(mp)) {
1691
                bno = mp->m_dirleafblk;
1692
                count = mp->m_dirblkfsbs;
1693
        } else {
1694
                bno = 0;
1695
                count = 1;
1696
        }
1697
        /*
1698
         * Find a spot in the file space to put the new block.
1699
         */
1700
        if ((error = xfs_bmap_first_unused(tp, dp, count, &bno, w))) {
1701
                return error;
1702
        }
1703
        if (w == XFS_DATA_FORK && XFS_DIR_IS_V2(mp))
1704
                ASSERT(bno >= mp->m_dirleafblk && bno < mp->m_dirfreeblk);
1705
        /*
1706
         * Try mapping it in one filesystem block.
1707
         */
1708
        nmap = 1;
1709
        ASSERT(args->firstblock != NULL);
1710
        if ((error = xfs_bmapi(tp, dp, bno, count,
1711
                        XFS_BMAPI_AFLAG(w)|XFS_BMAPI_WRITE|XFS_BMAPI_METADATA|
1712
                        XFS_BMAPI_CONTIG,
1713
                        args->firstblock, args->total, &map, &nmap,
1714
                        args->flist))) {
1715
                return error;
1716
        }
1717
        ASSERT(nmap <= 1);
1718
        if (nmap == 1) {
1719
                mapp = &map;
1720
                mapi = 1;
1721
        }
1722
        /*
1723
         * If we didn't get it and the block might work if fragmented,
1724
         * try without the CONTIG flag.  Loop until we get it all.
1725
         */
1726
        else if (nmap == 0 && count > 1) {
1727
                mapp = kmem_alloc(sizeof(*mapp) * count, KM_SLEEP);
1728
                for (b = bno, mapi = 0; b < bno + count; ) {
1729
                        nmap = MIN(XFS_BMAP_MAX_NMAP, count);
1730
                        c = (int)(bno + count - b);
1731
                        if ((error = xfs_bmapi(tp, dp, b, c,
1732
                                        XFS_BMAPI_AFLAG(w)|XFS_BMAPI_WRITE|
1733
                                        XFS_BMAPI_METADATA,
1734
                                        args->firstblock, args->total,
1735
                                        &mapp[mapi], &nmap, args->flist))) {
1736
                                kmem_free(mapp, sizeof(*mapp) * count);
1737
                                return error;
1738
                        }
1739
                        if (nmap < 1)
1740
                                break;
1741
                        mapi += nmap;
1742
                        b = mapp[mapi - 1].br_startoff +
1743
                            mapp[mapi - 1].br_blockcount;
1744
                }
1745
        } else {
1746
                mapi = 0;
1747
                mapp = NULL;
1748
        }
1749
        /*
1750
         * Count the blocks we got, make sure it matches the total.
1751
         */
1752
        for (i = 0, got = 0; i < mapi; i++)
1753
                got += mapp[i].br_blockcount;
1754
        if (got != count || mapp[0].br_startoff != bno ||
1755
            mapp[mapi - 1].br_startoff + mapp[mapi - 1].br_blockcount !=
1756
            bno + count) {
1757
                if (mapp != &map)
1758
                        kmem_free(mapp, sizeof(*mapp) * count);
1759
                return XFS_ERROR(ENOSPC);
1760
        }
1761
        if (mapp != &map)
1762
                kmem_free(mapp, sizeof(*mapp) * count);
1763
        *new_blkno = (xfs_dablk_t)bno;
1764
        /*
1765
         * For version 1 directories, adjust the file size if it changed.
1766
         */
1767
        if (w == XFS_DATA_FORK && XFS_DIR_IS_V1(mp)) {
1768
                ASSERT(mapi == 1);
1769
                if ((error = xfs_bmap_last_offset(tp, dp, &bno, w)))
1770
                        return error;
1771
                size = XFS_FSB_TO_B(mp, bno);
1772
                if (size != dp->i_d.di_size) {
1773
                        dp->i_d.di_size = size;
1774
                        xfs_trans_log_inode(tp, dp, XFS_ILOG_CORE);
1775
                }
1776
        }
1777
        return 0;
1778
}
1779
 
1780
/*
1781
 * Ick.  We need to always be able to remove a btree block, even
1782
 * if there's no space reservation because the filesystem is full.
1783
 * This is called if xfs_bunmapi on a btree block fails due to ENOSPC.
1784
 * It swaps the target block with the last block in the file.  The
1785
 * last block in the file can always be removed since it can't cause
1786
 * a bmap btree split to do that.
1787
 */
1788
STATIC int
1789
xfs_da_swap_lastblock(xfs_da_args_t *args, xfs_dablk_t *dead_blknop,
1790
                      xfs_dabuf_t **dead_bufp)
1791
{
1792
        xfs_dablk_t dead_blkno, last_blkno, sib_blkno, par_blkno;
1793
        xfs_dabuf_t *dead_buf, *last_buf, *sib_buf, *par_buf;
1794
        xfs_fileoff_t lastoff;
1795
        xfs_inode_t *ip;
1796
        xfs_trans_t *tp;
1797
        xfs_mount_t *mp;
1798
        int error, w, entno, level, dead_level;
1799
        xfs_da_blkinfo_t *dead_info, *sib_info;
1800
        xfs_da_intnode_t *par_node, *dead_node;
1801
        xfs_dir_leafblock_t *dead_leaf;
1802
        xfs_dir2_leaf_t *dead_leaf2;
1803
        xfs_dahash_t dead_hash;
1804
 
1805
        dead_buf = *dead_bufp;
1806
        dead_blkno = *dead_blknop;
1807
        tp = args->trans;
1808
        ip = args->dp;
1809
        w = args->whichfork;
1810
        ASSERT(w == XFS_DATA_FORK);
1811
        mp = ip->i_mount;
1812
        if (XFS_DIR_IS_V2(mp)) {
1813
                lastoff = mp->m_dirfreeblk;
1814
                error = xfs_bmap_last_before(tp, ip, &lastoff, w);
1815
        } else
1816
                error = xfs_bmap_last_offset(tp, ip, &lastoff, w);
1817
        if (error)
1818
                return error;
1819
        if (unlikely(lastoff == 0)) {
1820
                XFS_ERROR_REPORT("xfs_da_swap_lastblock(1)", XFS_ERRLEVEL_LOW,
1821
                                 mp);
1822
                return XFS_ERROR(EFSCORRUPTED);
1823
        }
1824
        /*
1825
         * Read the last block in the btree space.
1826
         */
1827
        last_blkno = (xfs_dablk_t)lastoff - mp->m_dirblkfsbs;
1828
        if ((error = xfs_da_read_buf(tp, ip, last_blkno, -1, &last_buf, w)))
1829
                return error;
1830
        /*
1831
         * Copy the last block into the dead buffer and log it.
1832
         */
1833
        memcpy(dead_buf->data, last_buf->data, mp->m_dirblksize);
1834
        xfs_da_log_buf(tp, dead_buf, 0, mp->m_dirblksize - 1);
1835
        dead_info = dead_buf->data;
1836
        /*
1837
         * Get values from the moved block.
1838
         */
1839
        if (INT_GET(dead_info->magic, ARCH_CONVERT) == XFS_DIR_LEAF_MAGIC) {
1840
                ASSERT(XFS_DIR_IS_V1(mp));
1841
                dead_leaf = (xfs_dir_leafblock_t *)dead_info;
1842
                dead_level = 0;
1843
                dead_hash =
1844
                        INT_GET(dead_leaf->entries[INT_GET(dead_leaf->hdr.count, ARCH_CONVERT) - 1].hashval, ARCH_CONVERT);
1845
        } else if (INT_GET(dead_info->magic, ARCH_CONVERT) == XFS_DIR2_LEAFN_MAGIC) {
1846
                ASSERT(XFS_DIR_IS_V2(mp));
1847
                dead_leaf2 = (xfs_dir2_leaf_t *)dead_info;
1848
                dead_level = 0;
1849
                dead_hash = INT_GET(dead_leaf2->ents[INT_GET(dead_leaf2->hdr.count, ARCH_CONVERT) - 1].hashval, ARCH_CONVERT);
1850
        } else {
1851
                ASSERT(INT_GET(dead_info->magic, ARCH_CONVERT) == XFS_DA_NODE_MAGIC);
1852
                dead_node = (xfs_da_intnode_t *)dead_info;
1853
                dead_level = INT_GET(dead_node->hdr.level, ARCH_CONVERT);
1854
                dead_hash = INT_GET(dead_node->btree[INT_GET(dead_node->hdr.count, ARCH_CONVERT) - 1].hashval, ARCH_CONVERT);
1855
        }
1856
        sib_buf = par_buf = NULL;
1857
        /*
1858
         * If the moved block has a left sibling, fix up the pointers.
1859
         */
1860
        if ((sib_blkno = INT_GET(dead_info->back, ARCH_CONVERT))) {
1861
                if ((error = xfs_da_read_buf(tp, ip, sib_blkno, -1, &sib_buf, w)))
1862
                        goto done;
1863
                sib_info = sib_buf->data;
1864
                if (unlikely(
1865
                    INT_GET(sib_info->forw, ARCH_CONVERT) != last_blkno ||
1866
                    INT_GET(sib_info->magic, ARCH_CONVERT) != INT_GET(dead_info->magic, ARCH_CONVERT))) {
1867
                        XFS_ERROR_REPORT("xfs_da_swap_lastblock(2)",
1868
                                         XFS_ERRLEVEL_LOW, mp);
1869
                        error = XFS_ERROR(EFSCORRUPTED);
1870
                        goto done;
1871
                }
1872
                INT_SET(sib_info->forw, ARCH_CONVERT, dead_blkno);
1873
                xfs_da_log_buf(tp, sib_buf,
1874
                        XFS_DA_LOGRANGE(sib_info, &sib_info->forw,
1875
                                        sizeof(sib_info->forw)));
1876
                xfs_da_buf_done(sib_buf);
1877
                sib_buf = NULL;
1878
        }
1879
        /*
1880
         * If the moved block has a right sibling, fix up the pointers.
1881
         */
1882
        if ((sib_blkno = INT_GET(dead_info->forw, ARCH_CONVERT))) {
1883
                if ((error = xfs_da_read_buf(tp, ip, sib_blkno, -1, &sib_buf, w)))
1884
                        goto done;
1885
                sib_info = sib_buf->data;
1886
                if (unlikely(
1887
                       INT_GET(sib_info->back, ARCH_CONVERT) != last_blkno
1888
                    || INT_GET(sib_info->magic, ARCH_CONVERT)
1889
                                != INT_GET(dead_info->magic, ARCH_CONVERT))) {
1890
                        XFS_ERROR_REPORT("xfs_da_swap_lastblock(3)",
1891
                                         XFS_ERRLEVEL_LOW, mp);
1892
                        error = XFS_ERROR(EFSCORRUPTED);
1893
                        goto done;
1894
                }
1895
                INT_SET(sib_info->back, ARCH_CONVERT, dead_blkno);
1896
                xfs_da_log_buf(tp, sib_buf,
1897
                        XFS_DA_LOGRANGE(sib_info, &sib_info->back,
1898
                                        sizeof(sib_info->back)));
1899
                xfs_da_buf_done(sib_buf);
1900
                sib_buf = NULL;
1901
        }
1902
        par_blkno = XFS_DIR_IS_V1(mp) ? 0 : mp->m_dirleafblk;
1903
        level = -1;
1904
        /*
1905
         * Walk down the tree looking for the parent of the moved block.
1906
         */
1907
        for (;;) {
1908
                if ((error = xfs_da_read_buf(tp, ip, par_blkno, -1, &par_buf, w)))
1909
                        goto done;
1910
                par_node = par_buf->data;
1911
                if (unlikely(
1912
                    INT_GET(par_node->hdr.info.magic, ARCH_CONVERT) != XFS_DA_NODE_MAGIC ||
1913
                    (level >= 0 && level != INT_GET(par_node->hdr.level, ARCH_CONVERT) + 1))) {
1914
                        XFS_ERROR_REPORT("xfs_da_swap_lastblock(4)",
1915
                                         XFS_ERRLEVEL_LOW, mp);
1916
                        error = XFS_ERROR(EFSCORRUPTED);
1917
                        goto done;
1918
                }
1919
                level = INT_GET(par_node->hdr.level, ARCH_CONVERT);
1920
                for (entno = 0;
1921
                     entno < INT_GET(par_node->hdr.count, ARCH_CONVERT) &&
1922
                     INT_GET(par_node->btree[entno].hashval, ARCH_CONVERT) < dead_hash;
1923
                     entno++)
1924
                        continue;
1925
                if (unlikely(entno == INT_GET(par_node->hdr.count, ARCH_CONVERT))) {
1926
                        XFS_ERROR_REPORT("xfs_da_swap_lastblock(5)",
1927
                                         XFS_ERRLEVEL_LOW, mp);
1928
                        error = XFS_ERROR(EFSCORRUPTED);
1929
                        goto done;
1930
                }
1931
                par_blkno = INT_GET(par_node->btree[entno].before, ARCH_CONVERT);
1932
                if (level == dead_level + 1)
1933
                        break;
1934
                xfs_da_brelse(tp, par_buf);
1935
                par_buf = NULL;
1936
        }
1937
        /*
1938
         * We're in the right parent block.
1939
         * Look for the right entry.
1940
         */
1941
        for (;;) {
1942
                for (;
1943
                     entno < INT_GET(par_node->hdr.count, ARCH_CONVERT) &&
1944
                     INT_GET(par_node->btree[entno].before, ARCH_CONVERT) != last_blkno;
1945
                     entno++)
1946
                        continue;
1947
                if (entno < INT_GET(par_node->hdr.count, ARCH_CONVERT))
1948
                        break;
1949
                par_blkno = INT_GET(par_node->hdr.info.forw, ARCH_CONVERT);
1950
                xfs_da_brelse(tp, par_buf);
1951
                par_buf = NULL;
1952
                if (unlikely(par_blkno == 0)) {
1953
                        XFS_ERROR_REPORT("xfs_da_swap_lastblock(6)",
1954
                                         XFS_ERRLEVEL_LOW, mp);
1955
                        error = XFS_ERROR(EFSCORRUPTED);
1956
                        goto done;
1957
                }
1958
                if ((error = xfs_da_read_buf(tp, ip, par_blkno, -1, &par_buf, w)))
1959
                        goto done;
1960
                par_node = par_buf->data;
1961
                if (unlikely(
1962
                    INT_GET(par_node->hdr.level, ARCH_CONVERT) != level ||
1963
                    INT_GET(par_node->hdr.info.magic, ARCH_CONVERT) != XFS_DA_NODE_MAGIC)) {
1964
                        XFS_ERROR_REPORT("xfs_da_swap_lastblock(7)",
1965
                                         XFS_ERRLEVEL_LOW, mp);
1966
                        error = XFS_ERROR(EFSCORRUPTED);
1967
                        goto done;
1968
                }
1969
                entno = 0;
1970
        }
1971
        /*
1972
         * Update the parent entry pointing to the moved block.
1973
         */
1974
        INT_SET(par_node->btree[entno].before, ARCH_CONVERT, dead_blkno);
1975
        xfs_da_log_buf(tp, par_buf,
1976
                XFS_DA_LOGRANGE(par_node, &par_node->btree[entno].before,
1977
                                sizeof(par_node->btree[entno].before)));
1978
        xfs_da_buf_done(par_buf);
1979
        xfs_da_buf_done(dead_buf);
1980
        *dead_blknop = last_blkno;
1981
        *dead_bufp = last_buf;
1982
        return 0;
1983
done:
1984
        if (par_buf)
1985
                xfs_da_brelse(tp, par_buf);
1986
        if (sib_buf)
1987
                xfs_da_brelse(tp, sib_buf);
1988
        xfs_da_brelse(tp, last_buf);
1989
        return error;
1990
}
1991
 
1992
/*
1993
 * Remove a btree block from a directory or attribute.
1994
 */
1995
int
1996
xfs_da_shrink_inode(xfs_da_args_t *args, xfs_dablk_t dead_blkno,
1997
                    xfs_dabuf_t *dead_buf)
1998
{
1999
        xfs_inode_t *dp;
2000
        int done, error, w, count;
2001
        xfs_fileoff_t bno;
2002
        xfs_fsize_t size;
2003
        xfs_trans_t *tp;
2004
        xfs_mount_t *mp;
2005
 
2006
        dp = args->dp;
2007
        w = args->whichfork;
2008
        tp = args->trans;
2009
        mp = dp->i_mount;
2010
        if (w == XFS_DATA_FORK && XFS_DIR_IS_V2(mp))
2011
                count = mp->m_dirblkfsbs;
2012
        else
2013
                count = 1;
2014
        for (;;) {
2015
                /*
2016
                 * Remove extents.  If we get ENOSPC for a dir we have to move
2017
                 * the last block to the place we want to kill.
2018
                 */
2019
                if ((error = xfs_bunmapi(tp, dp, dead_blkno, count,
2020
                                XFS_BMAPI_AFLAG(w)|XFS_BMAPI_METADATA,
2021
                                0, args->firstblock, args->flist,
2022
                                &done)) == ENOSPC) {
2023
                        if (w != XFS_DATA_FORK)
2024
                                goto done;
2025
                        if ((error = xfs_da_swap_lastblock(args, &dead_blkno,
2026
                                        &dead_buf)))
2027
                                goto done;
2028
                } else if (error)
2029
                        goto done;
2030
                else
2031
                        break;
2032
        }
2033
        ASSERT(done);
2034
        xfs_da_binval(tp, dead_buf);
2035
        /*
2036
         * Adjust the directory size for version 1.
2037
         */
2038
        if (w == XFS_DATA_FORK && XFS_DIR_IS_V1(mp)) {
2039
                if ((error = xfs_bmap_last_offset(tp, dp, &bno, w)))
2040
                        return error;
2041
                size = XFS_FSB_TO_B(dp->i_mount, bno);
2042
                if (size != dp->i_d.di_size) {
2043
                        dp->i_d.di_size = size;
2044
                        xfs_trans_log_inode(tp, dp, XFS_ILOG_CORE);
2045
                }
2046
        }
2047
        return 0;
2048
done:
2049
        xfs_da_binval(tp, dead_buf);
2050
        return error;
2051
}
2052
 
2053
/*
2054
 * See if the mapping(s) for this btree block are valid, i.e.
2055
 * don't contain holes, are logically contiguous, and cover the whole range.
2056
 */
2057
STATIC int
2058
xfs_da_map_covers_blocks(
2059
        int             nmap,
2060
        xfs_bmbt_irec_t *mapp,
2061
        xfs_dablk_t     bno,
2062
        int             count)
2063
{
2064
        int             i;
2065
        xfs_fileoff_t   off;
2066
 
2067
        for (i = 0, off = bno; i < nmap; i++) {
2068
                if (mapp[i].br_startblock == HOLESTARTBLOCK ||
2069
                    mapp[i].br_startblock == DELAYSTARTBLOCK) {
2070
                        return 0;
2071
                }
2072
                if (off != mapp[i].br_startoff) {
2073
                        return 0;
2074
                }
2075
                off += mapp[i].br_blockcount;
2076
        }
2077
        return off == bno + count;
2078
}
2079
 
2080
/*
2081
 * Make a dabuf.
2082
 * Used for get_buf, read_buf, read_bufr, and reada_buf.
2083
 */
2084
STATIC int
2085
xfs_da_do_buf(
2086
        xfs_trans_t     *trans,
2087
        xfs_inode_t     *dp,
2088
        xfs_dablk_t     bno,
2089
        xfs_daddr_t     *mappedbnop,
2090
        xfs_dabuf_t     **bpp,
2091
        int             whichfork,
2092
        int             caller,
2093
        inst_t          *ra)
2094
{
2095
        xfs_buf_t       *bp = 0;
2096
        xfs_buf_t       **bplist;
2097
        int             error=0;
2098
        int             i;
2099
        xfs_bmbt_irec_t map;
2100
        xfs_bmbt_irec_t *mapp;
2101
        xfs_daddr_t     mappedbno;
2102
        xfs_mount_t     *mp;
2103
        int             nbplist=0;
2104
        int             nfsb;
2105
        int             nmap;
2106
        xfs_dabuf_t     *rbp;
2107
 
2108
        mp = dp->i_mount;
2109
        if (whichfork == XFS_DATA_FORK && XFS_DIR_IS_V2(mp))
2110
                nfsb = mp->m_dirblkfsbs;
2111
        else
2112
                nfsb = 1;
2113
        mappedbno = *mappedbnop;
2114
        /*
2115
         * Caller doesn't have a mapping.  -2 means don't complain
2116
         * if we land in a hole.
2117
         */
2118
        if (mappedbno == -1 || mappedbno == -2) {
2119
                /*
2120
                 * Optimize the one-block case.
2121
                 */
2122
                if (nfsb == 1) {
2123
                        xfs_fsblock_t   fsb;
2124
 
2125
                        if ((error =
2126
                            xfs_bmapi_single(trans, dp, whichfork, &fsb,
2127
                                    (xfs_fileoff_t)bno))) {
2128
                                return error;
2129
                        }
2130
                        mapp = &map;
2131
                        if (fsb == NULLFSBLOCK) {
2132
                                nmap = 0;
2133
                        } else {
2134
                                map.br_startblock = fsb;
2135
                                map.br_startoff = (xfs_fileoff_t)bno;
2136
                                map.br_blockcount = 1;
2137
                                nmap = 1;
2138
                        }
2139
                } else {
2140
                        mapp = kmem_alloc(sizeof(*mapp) * nfsb, KM_SLEEP);
2141
                        nmap = nfsb;
2142
                        if ((error = xfs_bmapi(trans, dp, (xfs_fileoff_t)bno,
2143
                                        nfsb,
2144
                                        XFS_BMAPI_METADATA |
2145
                                                XFS_BMAPI_AFLAG(whichfork),
2146
                                        NULL, 0, mapp, &nmap, NULL)))
2147
                                goto exit0;
2148
                }
2149
        } else {
2150
                map.br_startblock = XFS_DADDR_TO_FSB(mp, mappedbno);
2151
                map.br_startoff = (xfs_fileoff_t)bno;
2152
                map.br_blockcount = nfsb;
2153
                mapp = &map;
2154
                nmap = 1;
2155
        }
2156
        if (!xfs_da_map_covers_blocks(nmap, mapp, bno, nfsb)) {
2157
                error = mappedbno == -2 ? 0 : XFS_ERROR(EFSCORRUPTED);
2158
                if (unlikely(error == EFSCORRUPTED)) {
2159
                        if (xfs_error_level >= XFS_ERRLEVEL_LOW) {
2160
                                int     i;
2161
                                cmn_err(CE_ALERT, "xfs_da_do_buf: bno %lld\n",
2162
                                        (long long)bno);
2163
                                cmn_err(CE_ALERT, "dir: inode %lld\n",
2164
                                        (long long)dp->i_ino);
2165
                                for (i = 0; i < nmap; i++) {
2166
                                        cmn_err(CE_ALERT,
2167
                                                "[%02d] br_startoff %lld br_startblock %lld br_blockcount %lld br_state %d\n",
2168
                                                i,
2169
                                                mapp[i].br_startoff,
2170
                                                mapp[i].br_startblock,
2171
                                                mapp[i].br_blockcount,
2172
                                                mapp[i].br_state);
2173
                                }
2174
                        }
2175
                        XFS_ERROR_REPORT("xfs_da_do_buf(1)",
2176
                                         XFS_ERRLEVEL_LOW, mp);
2177
                }
2178
                goto exit0;
2179
        }
2180
        if (caller != 3 && nmap > 1) {
2181
                bplist = kmem_alloc(sizeof(*bplist) * nmap, KM_SLEEP);
2182
                nbplist = 0;
2183
        } else
2184
                bplist = NULL;
2185
        /*
2186
         * Turn the mapping(s) into buffer(s).
2187
         */
2188
        for (i = 0; i < nmap; i++) {
2189
                int     nmapped;
2190
 
2191
                mappedbno = XFS_FSB_TO_DADDR(mp, mapp[i].br_startblock);
2192
                if (i == 0)
2193
                        *mappedbnop = mappedbno;
2194
                nmapped = (int)XFS_FSB_TO_BB(mp, mapp[i].br_blockcount);
2195
                switch (caller) {
2196
                case 0:
2197
                        bp = xfs_trans_get_buf(trans, mp->m_ddev_targp,
2198
                                mappedbno, nmapped, 0);
2199
                        error = bp ? XFS_BUF_GETERROR(bp) : XFS_ERROR(EIO);
2200
                        break;
2201
                case 1:
2202
#ifndef __KERNEL__
2203
                case 2:
2204
#endif
2205
                        bp = NULL;
2206
                        error = xfs_trans_read_buf(mp, trans, mp->m_ddev_targp,
2207
                                mappedbno, nmapped, 0, &bp);
2208
                        break;
2209
#ifdef __KERNEL__
2210
                case 3:
2211
                        xfs_baread(mp->m_ddev_targp, mappedbno, nmapped);
2212
                        error = 0;
2213
                        bp = NULL;
2214
                        break;
2215
#endif
2216
                }
2217
                if (error) {
2218
                        if (bp)
2219
                                xfs_trans_brelse(trans, bp);
2220
                        goto exit1;
2221
                }
2222
                if (!bp)
2223
                        continue;
2224
                if (caller == 1) {
2225
                        if (whichfork == XFS_ATTR_FORK) {
2226
                                XFS_BUF_SET_VTYPE_REF(bp, B_FS_ATTR_BTREE,
2227
                                                XFS_ATTR_BTREE_REF);
2228
                        } else {
2229
                                XFS_BUF_SET_VTYPE_REF(bp, B_FS_DIR_BTREE,
2230
                                                XFS_DIR_BTREE_REF);
2231
                        }
2232
                }
2233
                if (bplist) {
2234
                        bplist[nbplist++] = bp;
2235
                }
2236
        }
2237
        /*
2238
         * Build a dabuf structure.
2239
         */
2240
        if (bplist) {
2241
                rbp = xfs_da_buf_make(nbplist, bplist, ra);
2242
        } else if (bp)
2243
                rbp = xfs_da_buf_make(1, &bp, ra);
2244
        else
2245
                rbp = NULL;
2246
        /*
2247
         * For read_buf, check the magic number.
2248
         */
2249
        if (caller == 1) {
2250
                xfs_dir2_data_t         *data;
2251
                xfs_dir2_free_t         *free;
2252
                xfs_da_blkinfo_t        *info;
2253
                uint                    magic, magic1;
2254
 
2255
                info = rbp->data;
2256
                data = rbp->data;
2257
                free = rbp->data;
2258
                magic = INT_GET(info->magic, ARCH_CONVERT);
2259
                magic1 = INT_GET(data->hdr.magic, ARCH_CONVERT);
2260
                if (unlikely(
2261
                    XFS_TEST_ERROR((magic != XFS_DA_NODE_MAGIC) &&
2262
                                   (magic != XFS_DIR_LEAF_MAGIC) &&
2263
                                   (magic != XFS_ATTR_LEAF_MAGIC) &&
2264
                                   (magic != XFS_DIR2_LEAF1_MAGIC) &&
2265
                                   (magic != XFS_DIR2_LEAFN_MAGIC) &&
2266
                                   (magic1 != XFS_DIR2_BLOCK_MAGIC) &&
2267
                                   (magic1 != XFS_DIR2_DATA_MAGIC) &&
2268
                                   (INT_GET(free->hdr.magic, ARCH_CONVERT) != XFS_DIR2_FREE_MAGIC),
2269
                                mp, XFS_ERRTAG_DA_READ_BUF,
2270
                                XFS_RANDOM_DA_READ_BUF))) {
2271
                        xfs_buftrace("DA READ ERROR", rbp->bps[0]);
2272
                        XFS_CORRUPTION_ERROR("xfs_da_do_buf(2)",
2273
                                             XFS_ERRLEVEL_LOW, mp, info);
2274
                        error = XFS_ERROR(EFSCORRUPTED);
2275
                        xfs_da_brelse(trans, rbp);
2276
                        nbplist = 0;
2277
                        goto exit1;
2278
                }
2279
        }
2280
        if (bplist) {
2281
                kmem_free(bplist, sizeof(*bplist) * nmap);
2282
        }
2283
        if (mapp != &map) {
2284
                kmem_free(mapp, sizeof(*mapp) * nfsb);
2285
        }
2286
        if (bpp)
2287
                *bpp = rbp;
2288
        return 0;
2289
exit1:
2290
        if (bplist) {
2291
                for (i = 0; i < nbplist; i++)
2292
                        xfs_trans_brelse(trans, bplist[i]);
2293
                kmem_free(bplist, sizeof(*bplist) * nmap);
2294
        }
2295
exit0:
2296
        if (mapp != &map)
2297
                kmem_free(mapp, sizeof(*mapp) * nfsb);
2298
        if (bpp)
2299
                *bpp = NULL;
2300
        return error;
2301
}
2302
 
2303
/*
2304
 * Get a buffer for the dir/attr block.
2305
 */
2306
int
2307
xfs_da_get_buf(
2308
        xfs_trans_t     *trans,
2309
        xfs_inode_t     *dp,
2310
        xfs_dablk_t     bno,
2311
        xfs_daddr_t             mappedbno,
2312
        xfs_dabuf_t     **bpp,
2313
        int             whichfork)
2314
{
2315
        return xfs_da_do_buf(trans, dp, bno, &mappedbno, bpp, whichfork, 0,
2316
                                                 (inst_t *)__return_address);
2317
}
2318
 
2319
/*
2320
 * Get a buffer for the dir/attr block, fill in the contents.
2321
 */
2322
int
2323
xfs_da_read_buf(
2324
        xfs_trans_t     *trans,
2325
        xfs_inode_t     *dp,
2326
        xfs_dablk_t     bno,
2327
        xfs_daddr_t             mappedbno,
2328
        xfs_dabuf_t     **bpp,
2329
        int             whichfork)
2330
{
2331
        return xfs_da_do_buf(trans, dp, bno, &mappedbno, bpp, whichfork, 1,
2332
                (inst_t *)__return_address);
2333
}
2334
 
2335
/*
2336
 * Readahead the dir/attr block.
2337
 */
2338
xfs_daddr_t
2339
xfs_da_reada_buf(
2340
        xfs_trans_t     *trans,
2341
        xfs_inode_t     *dp,
2342
        xfs_dablk_t     bno,
2343
        int             whichfork)
2344
{
2345
        xfs_daddr_t             rval;
2346
 
2347
        rval = -1;
2348
        if (xfs_da_do_buf(trans, dp, bno, &rval, NULL, whichfork, 3,
2349
                        (inst_t *)__return_address))
2350
                return -1;
2351
        else
2352
                return rval;
2353
}
2354
 
2355
/*
2356
 * Calculate the number of bits needed to hold i different values.
2357
 */
2358
uint
2359
xfs_da_log2_roundup(uint i)
2360
{
2361
        uint rval;
2362
 
2363
        for (rval = 0; rval < NBBY * sizeof(i); rval++) {
2364
                if ((1 << rval) >= i)
2365
                        break;
2366
        }
2367
        return(rval);
2368
}
2369
 
2370
kmem_zone_t *xfs_da_state_zone; /* anchor for state struct zone */
2371
kmem_zone_t *xfs_dabuf_zone;            /* dabuf zone */
2372
 
2373
/*
2374
 * Allocate a dir-state structure.
2375
 * We don't put them on the stack since they're large.
2376
 */
2377
xfs_da_state_t *
2378
xfs_da_state_alloc(void)
2379
{
2380
        return kmem_zone_zalloc(xfs_da_state_zone, KM_SLEEP);
2381
}
2382
 
2383
/*
2384
 * Kill the altpath contents of a da-state structure.
2385
 */
2386
void
2387
xfs_da_state_kill_altpath(xfs_da_state_t *state)
2388
{
2389
        int     i;
2390
 
2391
        for (i = 0; i < state->altpath.active; i++) {
2392
                if (state->altpath.blk[i].bp) {
2393
                        if (state->altpath.blk[i].bp != state->path.blk[i].bp)
2394
                                xfs_da_buf_done(state->altpath.blk[i].bp);
2395
                        state->altpath.blk[i].bp = NULL;
2396
                }
2397
        }
2398
        state->altpath.active = 0;
2399
}
2400
 
2401
/*
2402
 * Free a da-state structure.
2403
 */
2404
void
2405
xfs_da_state_free(xfs_da_state_t *state)
2406
{
2407
        int     i;
2408
 
2409
        xfs_da_state_kill_altpath(state);
2410
        for (i = 0; i < state->path.active; i++) {
2411
                if (state->path.blk[i].bp)
2412
                        xfs_da_buf_done(state->path.blk[i].bp);
2413
        }
2414
        if (state->extravalid && state->extrablk.bp)
2415
                xfs_da_buf_done(state->extrablk.bp);
2416
#ifdef DEBUG
2417
        memset((char *)state, 0, sizeof(*state));
2418
#endif /* DEBUG */
2419
        kmem_zone_free(xfs_da_state_zone, state);
2420
}
2421
 
2422
#ifdef XFS_DABUF_DEBUG
2423
xfs_dabuf_t     *xfs_dabuf_global_list;
2424
lock_t          xfs_dabuf_global_lock;
2425
#endif
2426
 
2427
/*
2428
 * Create a dabuf.
2429
 */
2430
/* ARGSUSED */
2431
STATIC xfs_dabuf_t *
2432
xfs_da_buf_make(int nbuf, xfs_buf_t **bps, inst_t *ra)
2433
{
2434
        xfs_buf_t       *bp;
2435
        xfs_dabuf_t     *dabuf;
2436
        int             i;
2437
        int             off;
2438
 
2439
        if (nbuf == 1)
2440
                dabuf = kmem_zone_alloc(xfs_dabuf_zone, KM_SLEEP);
2441
        else
2442
                dabuf = kmem_alloc(XFS_DA_BUF_SIZE(nbuf), KM_SLEEP);
2443
        dabuf->dirty = 0;
2444
#ifdef XFS_DABUF_DEBUG
2445
        dabuf->ra = ra;
2446
        dabuf->target = XFS_BUF_TARGET(bps[0]);
2447
        dabuf->blkno = XFS_BUF_ADDR(bps[0]);
2448
#endif
2449
        if (nbuf == 1) {
2450
                dabuf->nbuf = 1;
2451
                bp = bps[0];
2452
                dabuf->bbcount = (short)BTOBB(XFS_BUF_COUNT(bp));
2453
                dabuf->data = XFS_BUF_PTR(bp);
2454
                dabuf->bps[0] = bp;
2455
        } else {
2456
                dabuf->nbuf = nbuf;
2457
                for (i = 0, dabuf->bbcount = 0; i < nbuf; i++) {
2458
                        dabuf->bps[i] = bp = bps[i];
2459
                        dabuf->bbcount += BTOBB(XFS_BUF_COUNT(bp));
2460
                }
2461
                dabuf->data = kmem_alloc(BBTOB(dabuf->bbcount), KM_SLEEP);
2462
                for (i = off = 0; i < nbuf; i++, off += XFS_BUF_COUNT(bp)) {
2463
                        bp = bps[i];
2464
                        memcpy((char *)dabuf->data + off, XFS_BUF_PTR(bp),
2465
                                XFS_BUF_COUNT(bp));
2466
                }
2467
        }
2468
#ifdef XFS_DABUF_DEBUG
2469
        {
2470
                SPLDECL(s);
2471
                xfs_dabuf_t     *p;
2472
 
2473
                s = mutex_spinlock(&xfs_dabuf_global_lock);
2474
                for (p = xfs_dabuf_global_list; p; p = p->next) {
2475
                        ASSERT(p->blkno != dabuf->blkno ||
2476
                               p->target != dabuf->target);
2477
                }
2478
                dabuf->prev = NULL;
2479
                if (xfs_dabuf_global_list)
2480
                        xfs_dabuf_global_list->prev = dabuf;
2481
                dabuf->next = xfs_dabuf_global_list;
2482
                xfs_dabuf_global_list = dabuf;
2483
                mutex_spinunlock(&xfs_dabuf_global_lock, s);
2484
        }
2485
#endif
2486
        return dabuf;
2487
}
2488
 
2489
/*
2490
 * Un-dirty a dabuf.
2491
 */
2492
STATIC void
2493
xfs_da_buf_clean(xfs_dabuf_t *dabuf)
2494
{
2495
        xfs_buf_t       *bp;
2496
        int             i;
2497
        int             off;
2498
 
2499
        if (dabuf->dirty) {
2500
                ASSERT(dabuf->nbuf > 1);
2501
                dabuf->dirty = 0;
2502
                for (i = off = 0; i < dabuf->nbuf;
2503
                                i++, off += XFS_BUF_COUNT(bp)) {
2504
                        bp = dabuf->bps[i];
2505
                        memcpy(XFS_BUF_PTR(bp), (char *)dabuf->data + off,
2506
                                XFS_BUF_COUNT(bp));
2507
                }
2508
        }
2509
}
2510
 
2511
/*
2512
 * Release a dabuf.
2513
 */
2514
void
2515
xfs_da_buf_done(xfs_dabuf_t *dabuf)
2516
{
2517
        ASSERT(dabuf);
2518
        ASSERT(dabuf->nbuf && dabuf->data && dabuf->bbcount && dabuf->bps[0]);
2519
        if (dabuf->dirty)
2520
                xfs_da_buf_clean(dabuf);
2521
        if (dabuf->nbuf > 1)
2522
                kmem_free(dabuf->data, BBTOB(dabuf->bbcount));
2523
#ifdef XFS_DABUF_DEBUG
2524
        {
2525
                SPLDECL(s);
2526
 
2527
                s = mutex_spinlock(&xfs_dabuf_global_lock);
2528
                if (dabuf->prev)
2529
                        dabuf->prev->next = dabuf->next;
2530
                else
2531
                        xfs_dabuf_global_list = dabuf->next;
2532
                if (dabuf->next)
2533
                        dabuf->next->prev = dabuf->prev;
2534
                mutex_spinunlock(&xfs_dabuf_global_lock, s);
2535
        }
2536
        memset(dabuf, 0, XFS_DA_BUF_SIZE(dabuf->nbuf));
2537
#endif
2538
        if (dabuf->nbuf == 1)
2539
                kmem_zone_free(xfs_dabuf_zone, dabuf);
2540
        else
2541
                kmem_free(dabuf, XFS_DA_BUF_SIZE(dabuf->nbuf));
2542
}
2543
 
2544
/*
2545
 * Log transaction from a dabuf.
2546
 */
2547
void
2548
xfs_da_log_buf(xfs_trans_t *tp, xfs_dabuf_t *dabuf, uint first, uint last)
2549
{
2550
        xfs_buf_t       *bp;
2551
        uint            f;
2552
        int             i;
2553
        uint            l;
2554
        int             off;
2555
 
2556
        ASSERT(dabuf->nbuf && dabuf->data && dabuf->bbcount && dabuf->bps[0]);
2557
        if (dabuf->nbuf == 1) {
2558
                ASSERT(dabuf->data == (void *)XFS_BUF_PTR(dabuf->bps[0]));
2559
                xfs_trans_log_buf(tp, dabuf->bps[0], first, last);
2560
                return;
2561
        }
2562
        dabuf->dirty = 1;
2563
        ASSERT(first <= last);
2564
        for (i = off = 0; i < dabuf->nbuf; i++, off += XFS_BUF_COUNT(bp)) {
2565
                bp = dabuf->bps[i];
2566
                f = off;
2567
                l = f + XFS_BUF_COUNT(bp) - 1;
2568
                if (f < first)
2569
                        f = first;
2570
                if (l > last)
2571
                        l = last;
2572
                if (f <= l)
2573
                        xfs_trans_log_buf(tp, bp, f - off, l - off);
2574
                /*
2575
                 * B_DONE is set by xfs_trans_log buf.
2576
                 * If we don't set it on a new buffer (get not read)
2577
                 * then if we don't put anything in the buffer it won't
2578
                 * be set, and at commit it it released into the cache,
2579
                 * and then a read will fail.
2580
                 */
2581
                else if (!(XFS_BUF_ISDONE(bp)))
2582
                  XFS_BUF_DONE(bp);
2583
        }
2584
        ASSERT(last < off);
2585
}
2586
 
2587
/*
2588
 * Release dabuf from a transaction.
2589
 * Have to free up the dabuf before the buffers are released,
2590
 * since the synchronization on the dabuf is really the lock on the buffer.
2591
 */
2592
void
2593
xfs_da_brelse(xfs_trans_t *tp, xfs_dabuf_t *dabuf)
2594
{
2595
        xfs_buf_t       *bp;
2596
        xfs_buf_t       **bplist;
2597
        int             i;
2598
        int             nbuf;
2599
 
2600
        ASSERT(dabuf->nbuf && dabuf->data && dabuf->bbcount && dabuf->bps[0]);
2601
        if ((nbuf = dabuf->nbuf) == 1) {
2602
                bplist = &bp;
2603
                bp = dabuf->bps[0];
2604
        } else {
2605
                bplist = kmem_alloc(nbuf * sizeof(*bplist), KM_SLEEP);
2606
                memcpy(bplist, dabuf->bps, nbuf * sizeof(*bplist));
2607
        }
2608
        xfs_da_buf_done(dabuf);
2609
        for (i = 0; i < nbuf; i++)
2610
                xfs_trans_brelse(tp, bplist[i]);
2611
        if (bplist != &bp)
2612
                kmem_free(bplist, nbuf * sizeof(*bplist));
2613
}
2614
 
2615
/*
2616
 * Invalidate dabuf from a transaction.
2617
 */
2618
void
2619
xfs_da_binval(xfs_trans_t *tp, xfs_dabuf_t *dabuf)
2620
{
2621
        xfs_buf_t       *bp;
2622
        xfs_buf_t       **bplist;
2623
        int             i;
2624
        int             nbuf;
2625
 
2626
        ASSERT(dabuf->nbuf && dabuf->data && dabuf->bbcount && dabuf->bps[0]);
2627
        if ((nbuf = dabuf->nbuf) == 1) {
2628
                bplist = &bp;
2629
                bp = dabuf->bps[0];
2630
        } else {
2631
                bplist = kmem_alloc(nbuf * sizeof(*bplist), KM_SLEEP);
2632
                memcpy(bplist, dabuf->bps, nbuf * sizeof(*bplist));
2633
        }
2634
        xfs_da_buf_done(dabuf);
2635
        for (i = 0; i < nbuf; i++)
2636
                xfs_trans_binval(tp, bplist[i]);
2637
        if (bplist != &bp)
2638
                kmem_free(bplist, nbuf * sizeof(*bplist));
2639
}
2640
 
2641
/*
2642
 * Get the first daddr from a dabuf.
2643
 */
2644
xfs_daddr_t
2645
xfs_da_blkno(xfs_dabuf_t *dabuf)
2646
{
2647
        ASSERT(dabuf->nbuf);
2648
        ASSERT(dabuf->data);
2649
        return XFS_BUF_ADDR(dabuf->bps[0]);
2650
}

powered by: WebSVN 2.1.0

© copyright 1999-2024 OpenCores.org, equivalent to Oliscience, all rights reserved. OpenCores®, registered trademark.