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

« back to all changes in this revision

Viewing changes to libxfs/xfs_bmap.c

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

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
/*
 
2
 * Copyright (c) 2000 Silicon Graphics, Inc.  All Rights Reserved.
 
3
 * 
 
4
 * This program is free software; you can redistribute it and/or modify it
 
5
 * under the terms of version 2 of the GNU General Public License as
 
6
 * published by the Free Software Foundation.
 
7
 * 
 
8
 * This program is distributed in the hope that it would be useful, but
 
9
 * WITHOUT ANY WARRANTY; without even the implied warranty of
 
10
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
 
11
 * 
 
12
 * Further, this software is distributed without any warranty that it is
 
13
 * free of the rightful claim of any third person regarding infringement
 
14
 * or the like.  Any license provided herein, whether implied or
 
15
 * otherwise, applies only to this software file.  Patent licenses, if
 
16
 * any, provided herein do not apply to combinations of this program with
 
17
 * other software, or any other product whatsoever.
 
18
 * 
 
19
 * You should have received a copy of the GNU General Public License along
 
20
 * with this program; if not, write the Free Software Foundation, Inc., 59
 
21
 * Temple Place - Suite 330, Boston MA 02111-1307, USA.
 
22
 * 
 
23
 * Contact information: Silicon Graphics, Inc., 1600 Amphitheatre Pkwy,
 
24
 * Mountain View, CA  94043, or:
 
25
 * 
 
26
 * http://www.sgi.com 
 
27
 * 
 
28
 * For further information regarding this notice, see: 
 
29
 * 
 
30
 * http://oss.sgi.com/projects/GenInfo/SGIGPLNoticeExplan/
 
31
 */
 
32
 
 
33
#include <xfs.h>
 
34
 
 
35
xfs_zone_t              *xfs_bmap_free_item_zone;
 
36
 
 
37
/*
 
38
 * Called by xfs_bmapi to update extent list structure and the btree
 
39
 * after allocating space (or doing a delayed allocation).
 
40
 */
 
41
STATIC int                              /* error */
 
42
xfs_bmap_add_extent(
 
43
        xfs_inode_t             *ip,    /* incore inode pointer */
 
44
        xfs_extnum_t            idx,    /* extent number to update/insert */
 
45
        xfs_btree_cur_t         **curp, /* if *curp is null, not a btree */
 
46
        xfs_bmbt_irec_t         *new,   /* new data to put in extent list */
 
47
        xfs_fsblock_t           *first, /* pointer to firstblock variable */
 
48
        xfs_bmap_free_t         *flist, /* list of extents to be freed */
 
49
        int                     *logflagsp, /* inode logging flags */
 
50
        int                     whichfork, /* data or attr fork */
 
51
        int                     rsvd)   /* OK to use reserved data blocks */
 
52
{
 
53
        xfs_btree_cur_t         *cur;   /* btree cursor or null */
 
54
        xfs_filblks_t           da_new; /* new count del alloc blocks used */
 
55
        xfs_filblks_t           da_old; /* old count del alloc blocks used */
 
56
        int                     error;  /* error return value */
 
57
#ifdef XFS_BMAP_TRACE
 
58
        static char             fname[] = "xfs_bmap_add_extent";
 
59
#endif
 
60
        xfs_ifork_t             *ifp;   /* inode fork ptr */
 
61
        int                     logflags; /* returned value */
 
62
        xfs_extnum_t            nextents; /* number of extents in file now */
 
63
 
 
64
        XFS_STATS_INC(xfsstats.xs_add_exlist);
 
65
        cur = *curp;
 
66
        ifp = XFS_IFORK_PTR(ip, whichfork);
 
67
        nextents = ifp->if_bytes / (uint)sizeof(xfs_bmbt_rec_t);
 
68
        ASSERT(idx <= nextents);
 
69
        da_old = da_new = 0;
 
70
        error = 0;
 
71
        /*
 
72
         * This is the first extent added to a new/empty file.
 
73
         * Special case this one, so other routines get to assume there are
 
74
         * already extents in the list.
 
75
         */
 
76
        if (nextents == 0) {
 
77
                xfs_bmap_trace_insert(fname, "insert empty", ip, 0, 1, new,
 
78
                        NULL, whichfork);
 
79
                xfs_bmap_insert_exlist(ip, 0, 1, new, whichfork);
 
80
                ASSERT(cur == NULL);
 
81
                ifp->if_lastex = 0;
 
82
                if (!ISNULLSTARTBLOCK(new->br_startblock)) {
 
83
                        XFS_IFORK_NEXT_SET(ip, whichfork, 1);
 
84
                        logflags = XFS_ILOG_CORE | XFS_ILOG_FEXT(whichfork);
 
85
                } else
 
86
                        logflags = 0;
 
87
        }
 
88
        /*
 
89
         * Any kind of new delayed allocation goes here.
 
90
         */
 
91
        else if (ISNULLSTARTBLOCK(new->br_startblock)) {
 
92
                if (cur)
 
93
                        ASSERT((cur->bc_private.b.flags &
 
94
                                XFS_BTCUR_BPRV_WASDEL) == 0);
 
95
                if ((error = xfs_bmap_add_extent_hole_delay(ip, idx, cur, new,
 
96
                                &logflags, rsvd)))
 
97
                        goto done;
 
98
        }
 
99
        /*
 
100
         * Real allocation off the end of the file.
 
101
         */
 
102
        else if (idx == nextents) {
 
103
                if (cur)
 
104
                        ASSERT((cur->bc_private.b.flags &
 
105
                                XFS_BTCUR_BPRV_WASDEL) == 0);
 
106
                if ((error = xfs_bmap_add_extent_hole_real(ip, idx, cur, new,
 
107
                                &logflags, whichfork)))
 
108
                        goto done;
 
109
        } else {
 
110
                xfs_bmbt_irec_t prev;   /* old extent at offset idx */
 
111
 
 
112
                /*
 
113
                 * Get the record referred to by idx.
 
114
                 */
 
115
                xfs_bmbt_get_all(&ifp->if_u1.if_extents[idx], &prev);
 
116
                /*
 
117
                 * If it's a real allocation record, and the new allocation ends
 
118
                 * after the start of the referred to record, then we're filling
 
119
                 * in a delayed or unwritten allocation with a real one, or
 
120
                 * converting real back to unwritten.
 
121
                 */
 
122
                if (!ISNULLSTARTBLOCK(new->br_startblock) &&
 
123
                    new->br_startoff + new->br_blockcount > prev.br_startoff) {
 
124
                        if (prev.br_state != XFS_EXT_UNWRITTEN && 
 
125
                            ISNULLSTARTBLOCK(prev.br_startblock)) {
 
126
                                da_old = STARTBLOCKVAL(prev.br_startblock);
 
127
                                if (cur)
 
128
                                        ASSERT(cur->bc_private.b.flags &
 
129
                                                XFS_BTCUR_BPRV_WASDEL);
 
130
                                if ((error = xfs_bmap_add_extent_delay_real(ip,
 
131
                                        idx, &cur, new, &da_new, first, flist,
 
132
                                        &logflags, rsvd)))
 
133
                                        goto done;
 
134
                        } else if (new->br_state == XFS_EXT_NORM) {
 
135
                                ASSERT(new->br_state == XFS_EXT_NORM);
 
136
                                if ((error = xfs_bmap_add_extent_unwritten_real(
 
137
                                        ip, idx, &cur, new, &logflags)))
 
138
                                        goto done;
 
139
                        } else {
 
140
                                ASSERT(new->br_state == XFS_EXT_UNWRITTEN);
 
141
                                if ((error = xfs_bmap_add_extent_unwritten_real(
 
142
                                        ip, idx, &cur, new, &logflags)))
 
143
                                        goto done;
 
144
                        }
 
145
                        ASSERT(*curp == cur || *curp == NULL);
 
146
                }
 
147
                /*
 
148
                 * Otherwise we're filling in a hole with an allocation.
 
149
                 */
 
150
                else {
 
151
                        if (cur)
 
152
                                ASSERT((cur->bc_private.b.flags &
 
153
                                        XFS_BTCUR_BPRV_WASDEL) == 0);
 
154
                        if ((error = xfs_bmap_add_extent_hole_real(ip, idx, cur,
 
155
                                        new, &logflags, whichfork)))
 
156
                                goto done;
 
157
                }
 
158
        }
 
159
 
 
160
        ASSERT(*curp == cur || *curp == NULL);
 
161
        /*
 
162
         * Convert to a btree if necessary.
 
163
         */
 
164
        if (XFS_IFORK_FORMAT(ip, whichfork) == XFS_DINODE_FMT_EXTENTS &&
 
165
            XFS_IFORK_NEXTENTS(ip, whichfork) > ifp->if_ext_max) {
 
166
                int     tmp_logflags;   /* partial log flag return val */
 
167
 
 
168
                ASSERT(cur == NULL);
 
169
                error = xfs_bmap_extents_to_btree(ip->i_transp, ip, first,
 
170
                        flist, &cur, da_old > 0, &tmp_logflags, whichfork);
 
171
                logflags |= tmp_logflags;
 
172
                if (error)
 
173
                        goto done;
 
174
        }
 
175
        /*
 
176
         * Adjust for changes in reserved delayed indirect blocks.
 
177
         * Nothing to do for disk quotas here.
 
178
         */
 
179
        if (da_old || da_new) {
 
180
                xfs_filblks_t   nblks;
 
181
 
 
182
                nblks = da_new;
 
183
                if (cur)
 
184
                        nblks += cur->bc_private.b.allocated;
 
185
                ASSERT(nblks <= da_old);
 
186
                if (nblks < da_old)
 
187
                        xfs_mod_incore_sb(ip->i_mount, XFS_SBS_FDBLOCKS,
 
188
                                (int)(da_old - nblks), rsvd);
 
189
        }
 
190
        /*
 
191
         * Clear out the allocated field, done with it now in any case.
 
192
         */
 
193
        if (cur) {
 
194
                cur->bc_private.b.allocated = 0;
 
195
                *curp = cur;
 
196
        }
 
197
done:
 
198
#ifdef XFSDEBUG
 
199
        if (!error)
 
200
                xfs_bmap_check_leaf_extents(*curp, ip, whichfork);
 
201
#endif
 
202
        *logflagsp = logflags;
 
203
        return error;
 
204
}
 
205
 
 
206
/*
 
207
 * Called by xfs_bmap_add_extent to handle cases converting a delayed
 
208
 * allocation to a real allocation.
 
209
 */
 
210
STATIC int                              /* error */
 
211
xfs_bmap_add_extent_delay_real(
 
212
        xfs_inode_t             *ip,    /* incore inode pointer */
 
213
        xfs_extnum_t            idx,    /* extent number to update/insert */
 
214
        xfs_btree_cur_t         **curp, /* if *curp is null, not a btree */
 
215
        xfs_bmbt_irec_t         *new,   /* new data to put in extent list */
 
216
        xfs_filblks_t           *dnew,  /* new delayed-alloc indirect blocks */
 
217
        xfs_fsblock_t           *first, /* pointer to firstblock variable */
 
218
        xfs_bmap_free_t         *flist, /* list of extents to be freed */
 
219
        int                     *logflagsp, /* inode logging flags */
 
220
        int                     rsvd)   /* OK to use reserved data block allocation */
 
221
{
 
222
        xfs_bmbt_rec_t          *base;  /* base of extent entry list */
 
223
        xfs_btree_cur_t         *cur;   /* btree cursor */
 
224
        int                     diff;   /* temp value */
 
225
        xfs_bmbt_rec_t          *ep;    /* extent entry for idx */
 
226
        int                     error;  /* error return value */
 
227
#ifdef XFS_BMAP_TRACE
 
228
        static char             fname[] = "xfs_bmap_add_extent_delay_real";
 
229
#endif
 
230
        int                     i;      /* temp state */
 
231
        xfs_fileoff_t           new_endoff;     /* end offset of new entry */
 
232
        xfs_bmbt_irec_t         r[3];   /* neighbor extent entries */
 
233
                                        /* left is 0, right is 1, prev is 2 */
 
234
        int                     rval=0; /* return value (logging flags) */
 
235
        int                     state = 0;/* state bits, accessed thru macros */
 
236
        xfs_filblks_t           temp;   /* value for dnew calculations */
 
237
        xfs_filblks_t           temp2;  /* value for dnew calculations */
 
238
        int                     tmp_rval;       /* partial logging flags */
 
239
        enum {                          /* bit number definitions for state */
 
240
                LEFT_CONTIG,    RIGHT_CONTIG,
 
241
                LEFT_FILLING,   RIGHT_FILLING,
 
242
                LEFT_DELAY,     RIGHT_DELAY,
 
243
                LEFT_VALID,     RIGHT_VALID
 
244
        };
 
245
 
 
246
#define LEFT            r[0]
 
247
#define RIGHT           r[1]
 
248
#define PREV            r[2]
 
249
#define MASK(b)         (1 << (b))
 
250
#define MASK2(a,b)      (MASK(a) | MASK(b))
 
251
#define MASK3(a,b,c)    (MASK2(a,b) | MASK(c))
 
252
#define MASK4(a,b,c,d)  (MASK3(a,b,c) | MASK(d))
 
253
#define STATE_SET(b,v)  ((v) ? (state |= MASK(b)) : (state &= ~MASK(b)))
 
254
#define STATE_TEST(b)   (state & MASK(b))
 
255
#define STATE_SET_TEST(b,v)     ((v) ? ((state |= MASK(b)), 1) : \
 
256
                                       ((state &= ~MASK(b)), 0))
 
257
#define SWITCH_STATE            \
 
258
        (state & MASK4(LEFT_FILLING, RIGHT_FILLING, LEFT_CONTIG, RIGHT_CONTIG))
 
259
 
 
260
        /*
 
261
         * Set up a bunch of variables to make the tests simpler.
 
262
         */
 
263
        cur = *curp;
 
264
        base = ip->i_df.if_u1.if_extents;
 
265
        ep = &base[idx];
 
266
        xfs_bmbt_get_all(ep, &PREV);
 
267
        new_endoff = new->br_startoff + new->br_blockcount;
 
268
        ASSERT(PREV.br_startoff <= new->br_startoff);
 
269
        ASSERT(PREV.br_startoff + PREV.br_blockcount >= new_endoff);
 
270
        /*
 
271
         * Set flags determining what part of the previous delayed allocation
 
272
         * extent is being replaced by a real allocation.
 
273
         */
 
274
        STATE_SET(LEFT_FILLING, PREV.br_startoff == new->br_startoff);
 
275
        STATE_SET(RIGHT_FILLING,
 
276
                PREV.br_startoff + PREV.br_blockcount == new_endoff);
 
277
        /*
 
278
         * Check and set flags if this segment has a left neighbor.
 
279
         * Don't set contiguous if the combined extent would be too large.
 
280
         */
 
281
        if (STATE_SET_TEST(LEFT_VALID, idx > 0)) {
 
282
                xfs_bmbt_get_all(ep - 1, &LEFT);
 
283
                STATE_SET(LEFT_DELAY, ISNULLSTARTBLOCK(LEFT.br_startblock));
 
284
        }
 
285
        STATE_SET(LEFT_CONTIG, 
 
286
                STATE_TEST(LEFT_VALID) && !STATE_TEST(LEFT_DELAY) &&
 
287
                LEFT.br_startoff + LEFT.br_blockcount == new->br_startoff &&
 
288
                LEFT.br_startblock + LEFT.br_blockcount == new->br_startblock &&
 
289
                LEFT.br_state == new->br_state &&
 
290
                LEFT.br_blockcount + new->br_blockcount <= MAXEXTLEN);
 
291
        /*
 
292
         * Check and set flags if this segment has a right neighbor.
 
293
         * Don't set contiguous if the combined extent would be too large.
 
294
         * Also check for all-three-contiguous being too large.
 
295
         */
 
296
        if (STATE_SET_TEST(RIGHT_VALID,
 
297
                        idx <
 
298
                        ip->i_df.if_bytes / (uint)sizeof(xfs_bmbt_rec_t) - 1)) {
 
299
                xfs_bmbt_get_all(ep + 1, &RIGHT);
 
300
                STATE_SET(RIGHT_DELAY, ISNULLSTARTBLOCK(RIGHT.br_startblock));
 
301
        }
 
302
        STATE_SET(RIGHT_CONTIG, 
 
303
                STATE_TEST(RIGHT_VALID) && !STATE_TEST(RIGHT_DELAY) &&
 
304
                new_endoff == RIGHT.br_startoff &&
 
305
                new->br_startblock + new->br_blockcount ==
 
306
                    RIGHT.br_startblock &&
 
307
                new->br_state == RIGHT.br_state &&
 
308
                new->br_blockcount + RIGHT.br_blockcount <= MAXEXTLEN &&
 
309
                ((state & MASK3(LEFT_CONTIG, LEFT_FILLING, RIGHT_FILLING)) !=
 
310
                  MASK3(LEFT_CONTIG, LEFT_FILLING, RIGHT_FILLING) ||
 
311
                 LEFT.br_blockcount + new->br_blockcount + RIGHT.br_blockcount
 
312
                     <= MAXEXTLEN));
 
313
        error = 0;
 
314
        /*
 
315
         * Switch out based on the FILLING and CONTIG state bits.
 
316
         */
 
317
        switch (SWITCH_STATE) {
 
318
 
 
319
        case MASK4(LEFT_FILLING, RIGHT_FILLING, LEFT_CONTIG, RIGHT_CONTIG):
 
320
                /*
 
321
                 * Filling in all of a previously delayed allocation extent.
 
322
                 * The left and right neighbors are both contiguous with new.
 
323
                 */
 
324
                xfs_bmap_trace_pre_update(fname, "LF|RF|LC|RC", ip, idx - 1,
 
325
                        XFS_DATA_FORK);
 
326
                xfs_bmbt_set_blockcount(ep - 1,
 
327
                        LEFT.br_blockcount + PREV.br_blockcount +
 
328
                        RIGHT.br_blockcount);
 
329
                xfs_bmap_trace_post_update(fname, "LF|RF|LC|RC", ip, idx - 1,
 
330
                        XFS_DATA_FORK);
 
331
                xfs_bmap_trace_delete(fname, "LF|RF|LC|RC", ip, idx, 2,
 
332
                        XFS_DATA_FORK);
 
333
                xfs_bmap_delete_exlist(ip, idx, 2, XFS_DATA_FORK);
 
334
                ip->i_df.if_lastex = idx - 1;
 
335
                ip->i_d.di_nextents--;
 
336
                if (cur == NULL)
 
337
                        rval = XFS_ILOG_CORE | XFS_ILOG_DEXT;
 
338
                else {
 
339
                        rval = XFS_ILOG_CORE;
 
340
                        if ((error = xfs_bmbt_lookup_eq(cur, RIGHT.br_startoff,
 
341
                                        RIGHT.br_startblock,
 
342
                                        RIGHT.br_blockcount, &i)))
 
343
                                goto done;
 
344
                        ASSERT(i == 1);
 
345
                        if ((error = xfs_bmbt_delete(cur, 0, &i)))
 
346
                                goto done;
 
347
                        ASSERT(i == 1);
 
348
                        if ((error = xfs_bmbt_decrement(cur, 0, &i)))
 
349
                                goto done;
 
350
                        ASSERT(i == 1);
 
351
                        if ((error = xfs_bmbt_update(cur, LEFT.br_startoff,
 
352
                                        LEFT.br_startblock,
 
353
                                        LEFT.br_blockcount +
 
354
                                        PREV.br_blockcount +
 
355
                                        RIGHT.br_blockcount, LEFT.br_state)))
 
356
                                goto done;
 
357
                }
 
358
                *dnew = 0;
 
359
                break;
 
360
 
 
361
        case MASK3(LEFT_FILLING, RIGHT_FILLING, LEFT_CONTIG):
 
362
                /*
 
363
                 * Filling in all of a previously delayed allocation extent.
 
364
                 * The left neighbor is contiguous, the right is not.
 
365
                 */
 
366
                xfs_bmap_trace_pre_update(fname, "LF|RF|LC", ip, idx - 1,
 
367
                        XFS_DATA_FORK);
 
368
                xfs_bmbt_set_blockcount(ep - 1,
 
369
                        LEFT.br_blockcount + PREV.br_blockcount);
 
370
                xfs_bmap_trace_post_update(fname, "LF|RF|LC", ip, idx - 1,
 
371
                        XFS_DATA_FORK);
 
372
                ip->i_df.if_lastex = idx - 1;
 
373
                xfs_bmap_trace_delete(fname, "LF|RF|LC", ip, idx, 1,
 
374
                        XFS_DATA_FORK);
 
375
                xfs_bmap_delete_exlist(ip, idx, 1, XFS_DATA_FORK);
 
376
                if (cur == NULL)
 
377
                        rval = XFS_ILOG_DEXT;
 
378
                else {
 
379
                        rval = 0;
 
380
                        if ((error = xfs_bmbt_lookup_eq(cur, LEFT.br_startoff,
 
381
                                        LEFT.br_startblock, LEFT.br_blockcount,
 
382
                                        &i)))
 
383
                                goto done;
 
384
                        ASSERT(i == 1);
 
385
                        if ((error = xfs_bmbt_update(cur, LEFT.br_startoff,
 
386
                                        LEFT.br_startblock,
 
387
                                        LEFT.br_blockcount +
 
388
                                        PREV.br_blockcount, LEFT.br_state)))
 
389
                                goto done;
 
390
                }
 
391
                *dnew = 0;
 
392
                break;
 
393
 
 
394
        case MASK3(LEFT_FILLING, RIGHT_FILLING, RIGHT_CONTIG):
 
395
                /*
 
396
                 * Filling in all of a previously delayed allocation extent.
 
397
                 * The right neighbor is contiguous, the left is not.
 
398
                 */
 
399
                xfs_bmap_trace_pre_update(fname, "LF|RF|RC", ip, idx,
 
400
                        XFS_DATA_FORK);
 
401
                xfs_bmbt_set_startblock(ep, new->br_startblock);
 
402
                xfs_bmbt_set_blockcount(ep,
 
403
                        PREV.br_blockcount + RIGHT.br_blockcount);
 
404
                xfs_bmap_trace_post_update(fname, "LF|RF|RC", ip, idx,
 
405
                        XFS_DATA_FORK);
 
406
                ip->i_df.if_lastex = idx;
 
407
                xfs_bmap_trace_delete(fname, "LF|RF|RC", ip, idx + 1, 1,
 
408
                        XFS_DATA_FORK);
 
409
                xfs_bmap_delete_exlist(ip, idx + 1, 1, XFS_DATA_FORK);
 
410
                if (cur == NULL)
 
411
                        rval = XFS_ILOG_DEXT;
 
412
                else {
 
413
                        rval = 0;
 
414
                        if ((error = xfs_bmbt_lookup_eq(cur, RIGHT.br_startoff,
 
415
                                        RIGHT.br_startblock,
 
416
                                        RIGHT.br_blockcount, &i)))
 
417
                                goto done;
 
418
                        ASSERT(i == 1);
 
419
                        if ((error = xfs_bmbt_update(cur, PREV.br_startoff,
 
420
                                        new->br_startblock,
 
421
                                        PREV.br_blockcount +
 
422
                                        RIGHT.br_blockcount, PREV.br_state)))
 
423
                                goto done;
 
424
                }
 
425
                *dnew = 0;
 
426
                break;
 
427
 
 
428
        case MASK2(LEFT_FILLING, RIGHT_FILLING):
 
429
                /*
 
430
                 * Filling in all of a previously delayed allocation extent.
 
431
                 * Neither the left nor right neighbors are contiguous with
 
432
                 * the new one.
 
433
                 */
 
434
                xfs_bmap_trace_pre_update(fname, "LF|RF", ip, idx,
 
435
                        XFS_DATA_FORK);
 
436
                xfs_bmbt_set_startblock(ep, new->br_startblock);
 
437
                xfs_bmap_trace_post_update(fname, "LF|RF", ip, idx,
 
438
                        XFS_DATA_FORK);
 
439
                ip->i_df.if_lastex = idx;
 
440
                ip->i_d.di_nextents++;
 
441
                if (cur == NULL)
 
442
                        rval = XFS_ILOG_CORE | XFS_ILOG_DEXT;
 
443
                else {
 
444
                        rval = XFS_ILOG_CORE;
 
445
                        if ((error = xfs_bmbt_lookup_eq(cur, new->br_startoff,
 
446
                                        new->br_startblock, new->br_blockcount,
 
447
                                        &i)))
 
448
                                goto done;
 
449
                        ASSERT(i == 0);
 
450
                        cur->bc_rec.b.br_state = XFS_EXT_NORM;
 
451
                        if ((error = xfs_bmbt_insert(cur, &i)))
 
452
                                goto done;
 
453
                        ASSERT(i == 1);
 
454
                }
 
455
                *dnew = 0;
 
456
                break;
 
457
 
 
458
        case MASK2(LEFT_FILLING, LEFT_CONTIG):
 
459
                /*
 
460
                 * Filling in the first part of a previous delayed allocation.
 
461
                 * The left neighbor is contiguous.
 
462
                 */
 
463
                xfs_bmap_trace_pre_update(fname, "LF|LC", ip, idx - 1,
 
464
                        XFS_DATA_FORK);
 
465
                xfs_bmbt_set_blockcount(ep - 1,
 
466
                        LEFT.br_blockcount + new->br_blockcount);
 
467
                xfs_bmbt_set_startoff(ep,
 
468
                        PREV.br_startoff + new->br_blockcount);
 
469
                xfs_bmap_trace_post_update(fname, "LF|LC", ip, idx - 1,
 
470
                        XFS_DATA_FORK);
 
471
                temp = PREV.br_blockcount - new->br_blockcount;
 
472
                xfs_bmap_trace_pre_update(fname, "LF|LC", ip, idx,
 
473
                        XFS_DATA_FORK);
 
474
                xfs_bmbt_set_blockcount(ep, temp);
 
475
                ip->i_df.if_lastex = idx - 1;
 
476
                if (cur == NULL)
 
477
                        rval = XFS_ILOG_DEXT;
 
478
                else {
 
479
                        rval = 0;
 
480
                        if ((error = xfs_bmbt_lookup_eq(cur, LEFT.br_startoff,
 
481
                                        LEFT.br_startblock, LEFT.br_blockcount,
 
482
                                        &i)))
 
483
                                goto done;
 
484
                        ASSERT(i == 1);
 
485
                        if ((error = xfs_bmbt_update(cur, LEFT.br_startoff,
 
486
                                        LEFT.br_startblock,
 
487
                                        LEFT.br_blockcount +
 
488
                                        new->br_blockcount,
 
489
                                        LEFT.br_state)))
 
490
                                goto done;
 
491
                }
 
492
                temp = XFS_FILBLKS_MIN(xfs_bmap_worst_indlen(ip, temp),
 
493
                        STARTBLOCKVAL(PREV.br_startblock));
 
494
                xfs_bmbt_set_startblock(ep, NULLSTARTBLOCK((int)temp));
 
495
                xfs_bmap_trace_post_update(fname, "LF|LC", ip, idx,
 
496
                        XFS_DATA_FORK);
 
497
                *dnew = temp;
 
498
                break;
 
499
 
 
500
        case MASK(LEFT_FILLING):
 
501
                /*
 
502
                 * Filling in the first part of a previous delayed allocation.
 
503
                 * The left neighbor is not contiguous.
 
504
                 */
 
505
                xfs_bmap_trace_pre_update(fname, "LF", ip, idx, XFS_DATA_FORK);
 
506
                xfs_bmbt_set_startoff(ep, new_endoff);
 
507
                temp = PREV.br_blockcount - new->br_blockcount;
 
508
                xfs_bmbt_set_blockcount(ep, temp);
 
509
                xfs_bmap_trace_insert(fname, "LF", ip, idx, 1, new, NULL,
 
510
                        XFS_DATA_FORK);
 
511
                xfs_bmap_insert_exlist(ip, idx, 1, new, XFS_DATA_FORK);
 
512
                ip->i_df.if_lastex = idx;
 
513
                ip->i_d.di_nextents++;
 
514
                if (cur == NULL)
 
515
                        rval = XFS_ILOG_CORE | XFS_ILOG_DEXT;
 
516
                else {
 
517
                        rval = XFS_ILOG_CORE;
 
518
                        if ((error = xfs_bmbt_lookup_eq(cur, new->br_startoff,
 
519
                                        new->br_startblock, new->br_blockcount,
 
520
                                        &i)))
 
521
                                goto done;
 
522
                        ASSERT(i == 0);
 
523
                        cur->bc_rec.b.br_state = XFS_EXT_NORM;
 
524
                        if ((error = xfs_bmbt_insert(cur, &i)))
 
525
                                goto done;
 
526
                        ASSERT(i == 1);
 
527
                }
 
528
                if (ip->i_d.di_format == XFS_DINODE_FMT_EXTENTS &&
 
529
                    ip->i_d.di_nextents > ip->i_df.if_ext_max) {
 
530
                        error = xfs_bmap_extents_to_btree(ip->i_transp, ip,
 
531
                                        first, flist, &cur, 1, &tmp_rval,
 
532
                                        XFS_DATA_FORK);
 
533
                        rval |= tmp_rval;
 
534
                        if (error)
 
535
                                goto done;
 
536
                }
 
537
                temp = XFS_FILBLKS_MIN(xfs_bmap_worst_indlen(ip, temp),
 
538
                        STARTBLOCKVAL(PREV.br_startblock) -
 
539
                        (cur ? cur->bc_private.b.allocated : 0));
 
540
                base = ip->i_df.if_u1.if_extents;
 
541
                ep = &base[idx + 1];
 
542
                xfs_bmbt_set_startblock(ep, NULLSTARTBLOCK((int)temp));
 
543
                xfs_bmap_trace_post_update(fname, "LF", ip, idx + 1,
 
544
                        XFS_DATA_FORK);
 
545
                *dnew = temp;
 
546
                break;
 
547
 
 
548
        case MASK2(RIGHT_FILLING, RIGHT_CONTIG):
 
549
                /*
 
550
                 * Filling in the last part of a previous delayed allocation.
 
551
                 * The right neighbor is contiguous with the new allocation.
 
552
                 */
 
553
                temp = PREV.br_blockcount - new->br_blockcount;
 
554
                xfs_bmap_trace_pre_update(fname, "RF|RC", ip, idx,
 
555
                        XFS_DATA_FORK);
 
556
                xfs_bmap_trace_pre_update(fname, "RF|RC", ip, idx + 1,
 
557
                        XFS_DATA_FORK);
 
558
                xfs_bmbt_set_blockcount(ep, temp);
 
559
                xfs_bmbt_set_allf(ep + 1, new->br_startoff, new->br_startblock,
 
560
                        new->br_blockcount + RIGHT.br_blockcount, 
 
561
                        RIGHT.br_state);
 
562
                xfs_bmap_trace_post_update(fname, "RF|RC", ip, idx + 1,
 
563
                        XFS_DATA_FORK);
 
564
                ip->i_df.if_lastex = idx + 1;
 
565
                if (cur == NULL)
 
566
                        rval = XFS_ILOG_DEXT;
 
567
                else {
 
568
                        rval = 0;
 
569
                        if ((error = xfs_bmbt_lookup_eq(cur, RIGHT.br_startoff,
 
570
                                        RIGHT.br_startblock,
 
571
                                        RIGHT.br_blockcount, &i)))
 
572
                                goto done;
 
573
                        ASSERT(i == 1);
 
574
                        if ((error = xfs_bmbt_update(cur, new->br_startoff,
 
575
                                        new->br_startblock,
 
576
                                        new->br_blockcount +
 
577
                                        RIGHT.br_blockcount,
 
578
                                        RIGHT.br_state)))
 
579
                                goto done;
 
580
                }
 
581
                temp = XFS_FILBLKS_MIN(xfs_bmap_worst_indlen(ip, temp),
 
582
                        STARTBLOCKVAL(PREV.br_startblock));
 
583
                xfs_bmbt_set_startblock(ep, NULLSTARTBLOCK((int)temp));
 
584
                xfs_bmap_trace_post_update(fname, "RF|RC", ip, idx,
 
585
                        XFS_DATA_FORK);
 
586
                *dnew = temp;
 
587
                break;
 
588
 
 
589
        case MASK(RIGHT_FILLING):
 
590
                /*
 
591
                 * Filling in the last part of a previous delayed allocation.
 
592
                 * The right neighbor is not contiguous.
 
593
                 */
 
594
                temp = PREV.br_blockcount - new->br_blockcount;
 
595
                xfs_bmap_trace_pre_update(fname, "RF", ip, idx, XFS_DATA_FORK);
 
596
                xfs_bmbt_set_blockcount(ep, temp);
 
597
                xfs_bmap_trace_insert(fname, "RF", ip, idx + 1, 1,
 
598
                        new, NULL, XFS_DATA_FORK);
 
599
                xfs_bmap_insert_exlist(ip, idx + 1, 1, new, XFS_DATA_FORK);
 
600
                ip->i_df.if_lastex = idx + 1;
 
601
                ip->i_d.di_nextents++;
 
602
                if (cur == NULL)
 
603
                        rval = XFS_ILOG_CORE | XFS_ILOG_DEXT;
 
604
                else {
 
605
                        rval = XFS_ILOG_CORE;
 
606
                        if ((error = xfs_bmbt_lookup_eq(cur, new->br_startoff,
 
607
                                        new->br_startblock, new->br_blockcount,
 
608
                                        &i)))
 
609
                                goto done;
 
610
                        ASSERT(i == 0);
 
611
                        cur->bc_rec.b.br_state = XFS_EXT_NORM;
 
612
                        if ((error = xfs_bmbt_insert(cur, &i)))
 
613
                                goto done;
 
614
                        ASSERT(i == 1);
 
615
                }
 
616
                if (ip->i_d.di_format == XFS_DINODE_FMT_EXTENTS &&
 
617
                    ip->i_d.di_nextents > ip->i_df.if_ext_max) {
 
618
                        error = xfs_bmap_extents_to_btree(ip->i_transp, ip,
 
619
                                first, flist, &cur, 1, &tmp_rval,
 
620
                                XFS_DATA_FORK);
 
621
                        rval |= tmp_rval;
 
622
                        if (error)
 
623
                                goto done;
 
624
                }
 
625
                temp = XFS_FILBLKS_MIN(xfs_bmap_worst_indlen(ip, temp),
 
626
                        STARTBLOCKVAL(PREV.br_startblock) -
 
627
                        (cur ? cur->bc_private.b.allocated : 0));
 
628
                base = ip->i_df.if_u1.if_extents;
 
629
                ep = &base[idx];
 
630
                xfs_bmbt_set_startblock(ep, NULLSTARTBLOCK((int)temp));
 
631
                xfs_bmap_trace_post_update(fname, "RF", ip, idx, XFS_DATA_FORK);
 
632
                *dnew = temp;
 
633
                break;
 
634
 
 
635
        case 0:
 
636
                /*
 
637
                 * Filling in the middle part of a previous delayed allocation.
 
638
                 * Contiguity is impossible here.
 
639
                 * This case is avoided almost all the time.
 
640
                 */
 
641
                temp = new->br_startoff - PREV.br_startoff;
 
642
                xfs_bmap_trace_pre_update(fname, "0", ip, idx, XFS_DATA_FORK);
 
643
                xfs_bmbt_set_blockcount(ep, temp);
 
644
                r[0] = *new;
 
645
                r[1].br_startoff = new_endoff;
 
646
                temp2 = PREV.br_startoff + PREV.br_blockcount - new_endoff;
 
647
                r[1].br_blockcount = temp2;
 
648
                xfs_bmap_trace_insert(fname, "0", ip, idx + 1, 2, &r[0], &r[1],
 
649
                        XFS_DATA_FORK);
 
650
                xfs_bmap_insert_exlist(ip, idx + 1, 2, &r[0], XFS_DATA_FORK);
 
651
                ip->i_df.if_lastex = idx + 1;
 
652
                ip->i_d.di_nextents++;
 
653
                if (cur == NULL)
 
654
                        rval = XFS_ILOG_CORE | XFS_ILOG_DEXT;
 
655
                else {
 
656
                        rval = XFS_ILOG_CORE;
 
657
                        if ((error = xfs_bmbt_lookup_eq(cur, new->br_startoff,
 
658
                                        new->br_startblock, new->br_blockcount,
 
659
                                        &i)))
 
660
                                goto done;
 
661
                        ASSERT(i == 0);
 
662
                        cur->bc_rec.b.br_state = XFS_EXT_NORM;
 
663
                        if ((error = xfs_bmbt_insert(cur, &i)))
 
664
                                goto done;
 
665
                        ASSERT(i == 1);
 
666
                }
 
667
                if (ip->i_d.di_format == XFS_DINODE_FMT_EXTENTS &&
 
668
                    ip->i_d.di_nextents > ip->i_df.if_ext_max) {
 
669
                        error = xfs_bmap_extents_to_btree(ip->i_transp, ip,
 
670
                                        first, flist, &cur, 1, &tmp_rval,
 
671
                                        XFS_DATA_FORK);
 
672
                        rval |= tmp_rval;
 
673
                        if (error)
 
674
                                goto done;
 
675
                }
 
676
                temp = xfs_bmap_worst_indlen(ip, temp);
 
677
                temp2 = xfs_bmap_worst_indlen(ip, temp2);
 
678
                diff = (int)(temp + temp2 - STARTBLOCKVAL(PREV.br_startblock) -
 
679
                        (cur ? cur->bc_private.b.allocated : 0));
 
680
                if (diff > 0 &&
 
681
                    xfs_mod_incore_sb(ip->i_mount, XFS_SBS_FDBLOCKS, -diff, rsvd)) {
 
682
                        /*
 
683
                         * Ick gross gag me with a spoon.
 
684
                         */
 
685
                        ASSERT(0);      /* want to see if this ever happens! */
 
686
                        while (diff > 0) {
 
687
                                if (temp) {
 
688
                                        temp--;
 
689
                                        diff--;
 
690
                                        if (!diff ||
 
691
                                            !xfs_mod_incore_sb(ip->i_mount,
 
692
                                                    XFS_SBS_FDBLOCKS, -diff, rsvd))
 
693
                                                break;
 
694
                                }
 
695
                                if (temp2) {
 
696
                                        temp2--;
 
697
                                        diff--;
 
698
                                        if (!diff ||
 
699
                                            !xfs_mod_incore_sb(ip->i_mount,
 
700
                                                    XFS_SBS_FDBLOCKS, -diff, rsvd))
 
701
                                                break;
 
702
                                }
 
703
                        }
 
704
                }
 
705
                base = ip->i_df.if_u1.if_extents;
 
706
                ep = &base[idx];
 
707
                xfs_bmbt_set_startblock(ep, NULLSTARTBLOCK((int)temp));
 
708
                xfs_bmap_trace_post_update(fname, "0", ip, idx, XFS_DATA_FORK);
 
709
                xfs_bmap_trace_pre_update(fname, "0", ip, idx + 2,
 
710
                        XFS_DATA_FORK);
 
711
                xfs_bmbt_set_startblock(ep + 2, NULLSTARTBLOCK((int)temp2));
 
712
                xfs_bmap_trace_post_update(fname, "0", ip, idx + 2,
 
713
                        XFS_DATA_FORK);
 
714
                *dnew = temp + temp2;
 
715
                break;
 
716
 
 
717
        case MASK3(LEFT_FILLING, LEFT_CONTIG, RIGHT_CONTIG):
 
718
        case MASK3(RIGHT_FILLING, LEFT_CONTIG, RIGHT_CONTIG):
 
719
        case MASK2(LEFT_FILLING, RIGHT_CONTIG):
 
720
        case MASK2(RIGHT_FILLING, LEFT_CONTIG):
 
721
        case MASK2(LEFT_CONTIG, RIGHT_CONTIG):
 
722
        case MASK(LEFT_CONTIG):
 
723
        case MASK(RIGHT_CONTIG):
 
724
                /*
 
725
                 * These cases are all impossible.
 
726
                 */
 
727
                ASSERT(0);
 
728
        }
 
729
        *curp = cur;
 
730
done:
 
731
        *logflagsp = rval;
 
732
        return error;
 
733
#undef  LEFT
 
734
#undef  RIGHT
 
735
#undef  PREV
 
736
#undef  MASK
 
737
#undef  MASK2
 
738
#undef  MASK3
 
739
#undef  MASK4
 
740
#undef  STATE_SET
 
741
#undef  STATE_TEST
 
742
#undef  STATE_SET_TEST
 
743
#undef  SWITCH_STATE
 
744
}
 
745
 
 
746
/*
 
747
 * Called by xfs_bmap_add_extent to handle cases converting an unwritten
 
748
 * allocation to a real allocation or vice versa.
 
749
 */
 
750
STATIC int                              /* error */
 
751
xfs_bmap_add_extent_unwritten_real(
 
752
        xfs_inode_t             *ip,    /* incore inode pointer */
 
753
        xfs_extnum_t            idx,    /* extent number to update/insert */
 
754
        xfs_btree_cur_t         **curp, /* if *curp is null, not a btree */
 
755
        xfs_bmbt_irec_t         *new,   /* new data to put in extent list */
 
756
        int                     *logflagsp) /* inode logging flags */
 
757
{
 
758
        xfs_bmbt_rec_t          *base;  /* base of extent entry list */
 
759
        xfs_btree_cur_t         *cur;   /* btree cursor */
 
760
        xfs_bmbt_rec_t          *ep;    /* extent entry for idx */
 
761
        int                     error;  /* error return value */
 
762
#ifdef XFS_BMAP_TRACE
 
763
        static char             fname[] = "xfs_bmap_add_extent_unwritten_real";
 
764
#endif
 
765
        int                     i;      /* temp state */
 
766
        xfs_fileoff_t           new_endoff;     /* end offset of new entry */
 
767
        xfs_exntst_t            newext; /* new extent state */
 
768
        xfs_exntst_t            oldext; /* old extent state */
 
769
        xfs_bmbt_irec_t         r[3];   /* neighbor extent entries */
 
770
                                        /* left is 0, right is 1, prev is 2 */
 
771
        int                     rval=0; /* return value (logging flags) */
 
772
        int                     state = 0;/* state bits, accessed thru macros */
 
773
        enum {                          /* bit number definitions for state */
 
774
                LEFT_CONTIG,    RIGHT_CONTIG,
 
775
                LEFT_FILLING,   RIGHT_FILLING,
 
776
                LEFT_DELAY,     RIGHT_DELAY,
 
777
                LEFT_VALID,     RIGHT_VALID
 
778
        };
 
779
 
 
780
#define LEFT            r[0]
 
781
#define RIGHT           r[1]
 
782
#define PREV            r[2]
 
783
#define MASK(b)         (1 << (b))
 
784
#define MASK2(a,b)      (MASK(a) | MASK(b))
 
785
#define MASK3(a,b,c)    (MASK2(a,b) | MASK(c))
 
786
#define MASK4(a,b,c,d)  (MASK3(a,b,c) | MASK(d))
 
787
#define STATE_SET(b,v)  ((v) ? (state |= MASK(b)) : (state &= ~MASK(b)))
 
788
#define STATE_TEST(b)   (state & MASK(b))
 
789
#define STATE_SET_TEST(b,v)     ((v) ? ((state |= MASK(b)), 1) : \
 
790
                                       ((state &= ~MASK(b)), 0))
 
791
#define SWITCH_STATE            \
 
792
        (state & MASK4(LEFT_FILLING, RIGHT_FILLING, LEFT_CONTIG, RIGHT_CONTIG))
 
793
 
 
794
        /*
 
795
         * Set up a bunch of variables to make the tests simpler.
 
796
         */
 
797
        error = 0;
 
798
        cur = *curp;
 
799
        base = ip->i_df.if_u1.if_extents;
 
800
        ep = &base[idx];
 
801
        xfs_bmbt_get_all(ep, &PREV);
 
802
        newext = new->br_state;
 
803
        oldext = (newext == XFS_EXT_UNWRITTEN) ?
 
804
                XFS_EXT_NORM : XFS_EXT_UNWRITTEN;
 
805
        ASSERT(PREV.br_state == oldext);
 
806
        new_endoff = new->br_startoff + new->br_blockcount;
 
807
        ASSERT(PREV.br_startoff <= new->br_startoff);
 
808
        ASSERT(PREV.br_startoff + PREV.br_blockcount >= new_endoff);
 
809
        /*
 
810
         * Set flags determining what part of the previous oldext allocation
 
811
         * extent is being replaced by a newext allocation.
 
812
         */
 
813
        STATE_SET(LEFT_FILLING, PREV.br_startoff == new->br_startoff);
 
814
        STATE_SET(RIGHT_FILLING,
 
815
                PREV.br_startoff + PREV.br_blockcount == new_endoff);
 
816
        /*
 
817
         * Check and set flags if this segment has a left neighbor.
 
818
         * Don't set contiguous if the combined extent would be too large.
 
819
         */
 
820
        if (STATE_SET_TEST(LEFT_VALID, idx > 0)) {
 
821
                xfs_bmbt_get_all(ep - 1, &LEFT);
 
822
                STATE_SET(LEFT_DELAY, ISNULLSTARTBLOCK(LEFT.br_startblock));
 
823
        }
 
824
        STATE_SET(LEFT_CONTIG, 
 
825
                STATE_TEST(LEFT_VALID) && !STATE_TEST(LEFT_DELAY) &&
 
826
                LEFT.br_startoff + LEFT.br_blockcount == new->br_startoff &&
 
827
                LEFT.br_startblock + LEFT.br_blockcount == new->br_startblock &&
 
828
                LEFT.br_state == newext &&
 
829
                LEFT.br_blockcount + new->br_blockcount <= MAXEXTLEN);
 
830
        /*
 
831
         * Check and set flags if this segment has a right neighbor.
 
832
         * Don't set contiguous if the combined extent would be too large.
 
833
         * Also check for all-three-contiguous being too large.
 
834
         */
 
835
        if (STATE_SET_TEST(RIGHT_VALID,
 
836
                        idx <
 
837
                        ip->i_df.if_bytes / (uint)sizeof(xfs_bmbt_rec_t) - 1)) {
 
838
                xfs_bmbt_get_all(ep + 1, &RIGHT);
 
839
                STATE_SET(RIGHT_DELAY, ISNULLSTARTBLOCK(RIGHT.br_startblock));
 
840
        }
 
841
        STATE_SET(RIGHT_CONTIG, 
 
842
                STATE_TEST(RIGHT_VALID) && !STATE_TEST(RIGHT_DELAY) &&
 
843
                new_endoff == RIGHT.br_startoff &&
 
844
                new->br_startblock + new->br_blockcount ==
 
845
                    RIGHT.br_startblock &&
 
846
                newext == RIGHT.br_state &&
 
847
                new->br_blockcount + RIGHT.br_blockcount <= MAXEXTLEN &&
 
848
                ((state & MASK3(LEFT_CONTIG, LEFT_FILLING, RIGHT_FILLING)) !=
 
849
                  MASK3(LEFT_CONTIG, LEFT_FILLING, RIGHT_FILLING) ||
 
850
                 LEFT.br_blockcount + new->br_blockcount + RIGHT.br_blockcount
 
851
                     <= MAXEXTLEN));
 
852
        /*
 
853
         * Switch out based on the FILLING and CONTIG state bits.
 
854
         */
 
855
        switch (SWITCH_STATE) {
 
856
 
 
857
        case MASK4(LEFT_FILLING, RIGHT_FILLING, LEFT_CONTIG, RIGHT_CONTIG):
 
858
                /*
 
859
                 * Setting all of a previous oldext extent to newext.
 
860
                 * The left and right neighbors are both contiguous with new.
 
861
                 */
 
862
                xfs_bmap_trace_pre_update(fname, "LF|RF|LC|RC", ip, idx - 1,
 
863
                        XFS_DATA_FORK);
 
864
                xfs_bmbt_set_blockcount(ep - 1,
 
865
                        LEFT.br_blockcount + PREV.br_blockcount +
 
866
                        RIGHT.br_blockcount);
 
867
                xfs_bmap_trace_post_update(fname, "LF|RF|LC|RC", ip, idx - 1,
 
868
                        XFS_DATA_FORK);
 
869
                xfs_bmap_trace_delete(fname, "LF|RF|LC|RC", ip, idx, 2,
 
870
                        XFS_DATA_FORK);
 
871
                xfs_bmap_delete_exlist(ip, idx, 2, XFS_DATA_FORK);
 
872
                ip->i_df.if_lastex = idx - 1;
 
873
                ip->i_d.di_nextents -= 2;
 
874
                if (cur == NULL)
 
875
                        rval = XFS_ILOG_CORE | XFS_ILOG_DEXT;
 
876
                else {
 
877
                        rval = XFS_ILOG_CORE;
 
878
                        if ((error = xfs_bmbt_lookup_eq(cur, RIGHT.br_startoff,
 
879
                                        RIGHT.br_startblock,
 
880
                                        RIGHT.br_blockcount, &i)))
 
881
                                goto done;
 
882
                        ASSERT(i == 1);
 
883
                        if ((error = xfs_bmbt_delete(cur, 0, &i)))
 
884
                                goto done;
 
885
                        ASSERT(i == 1);
 
886
                        if ((error = xfs_bmbt_decrement(cur, 0, &i)))
 
887
                                goto done;
 
888
                        ASSERT(i == 1);
 
889
                        if ((error = xfs_bmbt_delete(cur, 0, &i)))
 
890
                                goto done;
 
891
                        ASSERT(i == 1);
 
892
                        if ((error = xfs_bmbt_decrement(cur, 0, &i)))
 
893
                                goto done;
 
894
                        ASSERT(i == 1);
 
895
                        if ((error = xfs_bmbt_update(cur, LEFT.br_startoff,
 
896
                                LEFT.br_startblock,
 
897
                                LEFT.br_blockcount + PREV.br_blockcount +
 
898
                                RIGHT.br_blockcount, LEFT.br_state)))
 
899
                                goto done;
 
900
                }
 
901
                break;
 
902
 
 
903
        case MASK3(LEFT_FILLING, RIGHT_FILLING, LEFT_CONTIG):
 
904
                /*
 
905
                 * Setting all of a previous oldext extent to newext.
 
906
                 * The left neighbor is contiguous, the right is not.
 
907
                 */
 
908
                xfs_bmap_trace_pre_update(fname, "LF|RF|LC", ip, idx - 1,
 
909
                        XFS_DATA_FORK);
 
910
                xfs_bmbt_set_blockcount(ep - 1,
 
911
                        LEFT.br_blockcount + PREV.br_blockcount);
 
912
                xfs_bmap_trace_post_update(fname, "LF|RF|LC", ip, idx - 1,
 
913
                        XFS_DATA_FORK);
 
914
                ip->i_df.if_lastex = idx - 1;
 
915
                xfs_bmap_trace_delete(fname, "LF|RF|LC", ip, idx, 1,
 
916
                        XFS_DATA_FORK);
 
917
                xfs_bmap_delete_exlist(ip, idx, 1, XFS_DATA_FORK);
 
918
                ip->i_d.di_nextents--;
 
919
                if (cur == NULL)
 
920
                        rval = XFS_ILOG_CORE | XFS_ILOG_DEXT;
 
921
                else {
 
922
                        rval = XFS_ILOG_CORE;
 
923
                        if ((error = xfs_bmbt_lookup_eq(cur, PREV.br_startoff,
 
924
                                        PREV.br_startblock, PREV.br_blockcount,
 
925
                                        &i)))
 
926
                                goto done;
 
927
                        ASSERT(i == 1);
 
928
                        if ((error = xfs_bmbt_delete(cur, 0, &i)))
 
929
                                goto done;
 
930
                        ASSERT(i == 1);
 
931
                        if ((error = xfs_bmbt_decrement(cur, 0, &i)))
 
932
                                goto done;
 
933
                        ASSERT(i == 1);
 
934
                        if ((error = xfs_bmbt_update(cur, LEFT.br_startoff,
 
935
                                LEFT.br_startblock,
 
936
                                LEFT.br_blockcount + PREV.br_blockcount,
 
937
                                LEFT.br_state)))
 
938
                                goto done;
 
939
                }
 
940
                break;
 
941
 
 
942
        case MASK3(LEFT_FILLING, RIGHT_FILLING, RIGHT_CONTIG):
 
943
                /*
 
944
                 * Setting all of a previous oldext extent to newext.
 
945
                 * The right neighbor is contiguous, the left is not.
 
946
                 */
 
947
                xfs_bmap_trace_pre_update(fname, "LF|RF|RC", ip, idx,
 
948
                        XFS_DATA_FORK);
 
949
                xfs_bmbt_set_blockcount(ep,
 
950
                        PREV.br_blockcount + RIGHT.br_blockcount);
 
951
                xfs_bmbt_set_state(ep, newext);
 
952
                xfs_bmap_trace_post_update(fname, "LF|RF|RC", ip, idx,
 
953
                        XFS_DATA_FORK);
 
954
                ip->i_df.if_lastex = idx;
 
955
                xfs_bmap_trace_delete(fname, "LF|RF|RC", ip, idx + 1, 1,
 
956
                        XFS_DATA_FORK);
 
957
                xfs_bmap_delete_exlist(ip, idx + 1, 1, XFS_DATA_FORK);
 
958
                ip->i_d.di_nextents--;
 
959
                if (cur == NULL)
 
960
                        rval = XFS_ILOG_CORE | XFS_ILOG_DEXT;
 
961
                else {
 
962
                        rval = XFS_ILOG_CORE;
 
963
                        if ((error = xfs_bmbt_lookup_eq(cur, RIGHT.br_startoff,
 
964
                                        RIGHT.br_startblock,
 
965
                                        RIGHT.br_blockcount, &i)))
 
966
                                goto done;
 
967
                        ASSERT(i == 1);
 
968
                        if ((error = xfs_bmbt_delete(cur, 0, &i)))
 
969
                                goto done;
 
970
                        ASSERT(i == 1);
 
971
                        if ((error = xfs_bmbt_decrement(cur, 0, &i)))
 
972
                                goto done;
 
973
                        ASSERT(i == 1);
 
974
                        if ((error = xfs_bmbt_update(cur, new->br_startoff,
 
975
                                new->br_startblock,
 
976
                                new->br_blockcount + RIGHT.br_blockcount,
 
977
                                newext)))
 
978
                                goto done;
 
979
                }
 
980
                break;
 
981
 
 
982
        case MASK2(LEFT_FILLING, RIGHT_FILLING):
 
983
                /*
 
984
                 * Setting all of a previous oldext extent to newext.
 
985
                 * Neither the left nor right neighbors are contiguous with
 
986
                 * the new one.
 
987
                 */
 
988
                xfs_bmap_trace_pre_update(fname, "LF|RF", ip, idx,
 
989
                        XFS_DATA_FORK);
 
990
                xfs_bmbt_set_state(ep, newext);
 
991
                xfs_bmap_trace_post_update(fname, "LF|RF", ip, idx,
 
992
                        XFS_DATA_FORK);
 
993
                ip->i_df.if_lastex = idx;
 
994
                if (cur == NULL)
 
995
                        rval = XFS_ILOG_DEXT;
 
996
                else {
 
997
                        rval = 0;
 
998
                        if ((error = xfs_bmbt_lookup_eq(cur, new->br_startoff,
 
999
                                        new->br_startblock, new->br_blockcount,
 
1000
                                        &i)))
 
1001
                                goto done;
 
1002
                        ASSERT(i == 1);
 
1003
                        if ((error = xfs_bmbt_update(cur, new->br_startoff,
 
1004
                                new->br_startblock, new->br_blockcount,
 
1005
                                newext)))
 
1006
                                goto done;
 
1007
                }
 
1008
                break;
 
1009
 
 
1010
        case MASK2(LEFT_FILLING, LEFT_CONTIG):
 
1011
                /*
 
1012
                 * Setting the first part of a previous oldext extent to newext.
 
1013
                 * The left neighbor is contiguous.
 
1014
                 */
 
1015
                xfs_bmap_trace_pre_update(fname, "LF|LC", ip, idx - 1,
 
1016
                        XFS_DATA_FORK);
 
1017
                xfs_bmbt_set_blockcount(ep - 1,
 
1018
                        LEFT.br_blockcount + new->br_blockcount);
 
1019
                xfs_bmbt_set_startoff(ep,
 
1020
                        PREV.br_startoff + new->br_blockcount);
 
1021
                xfs_bmap_trace_post_update(fname, "LF|LC", ip, idx - 1,
 
1022
                        XFS_DATA_FORK);
 
1023
                xfs_bmap_trace_pre_update(fname, "LF|LC", ip, idx,
 
1024
                        XFS_DATA_FORK);
 
1025
                xfs_bmbt_set_startblock(ep,
 
1026
                        new->br_startblock + new->br_blockcount);
 
1027
                xfs_bmbt_set_blockcount(ep,
 
1028
                        PREV.br_blockcount - new->br_blockcount);
 
1029
                xfs_bmap_trace_post_update(fname, "LF|LC", ip, idx,
 
1030
                        XFS_DATA_FORK);
 
1031
                ip->i_df.if_lastex = idx - 1;
 
1032
                if (cur == NULL)
 
1033
                        rval = XFS_ILOG_DEXT;
 
1034
                else {
 
1035
                        rval = 0;
 
1036
                        if ((error = xfs_bmbt_lookup_eq(cur, PREV.br_startoff,
 
1037
                                        PREV.br_startblock, PREV.br_blockcount,
 
1038
                                        &i)))
 
1039
                                goto done;
 
1040
                        ASSERT(i == 1);
 
1041
                        if ((error = xfs_bmbt_update(cur,
 
1042
                                PREV.br_startoff + new->br_blockcount,
 
1043
                                PREV.br_startblock + new->br_blockcount,
 
1044
                                PREV.br_blockcount - new->br_blockcount,
 
1045
                                oldext)))
 
1046
                                goto done;
 
1047
                        if ((error = xfs_bmbt_decrement(cur, 0, &i)))
 
1048
                                goto done;
 
1049
                        if (xfs_bmbt_update(cur, LEFT.br_startoff,
 
1050
                                LEFT.br_startblock,
 
1051
                                LEFT.br_blockcount + new->br_blockcount,
 
1052
                                LEFT.br_state))
 
1053
                                goto done;
 
1054
                }
 
1055
                break;
 
1056
 
 
1057
        case MASK(LEFT_FILLING):
 
1058
                /*
 
1059
                 * Setting the first part of a previous oldext extent to newext.
 
1060
                 * The left neighbor is not contiguous.
 
1061
                 */
 
1062
                xfs_bmap_trace_pre_update(fname, "LF", ip, idx, XFS_DATA_FORK);
 
1063
                ASSERT(ep && xfs_bmbt_get_state(ep) == oldext);
 
1064
                xfs_bmbt_set_startoff(ep, new_endoff);
 
1065
                xfs_bmbt_set_blockcount(ep,
 
1066
                        PREV.br_blockcount - new->br_blockcount);
 
1067
                xfs_bmbt_set_startblock(ep,
 
1068
                        new->br_startblock + new->br_blockcount);
 
1069
                xfs_bmap_trace_post_update(fname, "LF", ip, idx, XFS_DATA_FORK);
 
1070
                xfs_bmap_trace_insert(fname, "LF", ip, idx, 1, new, NULL,
 
1071
                        XFS_DATA_FORK);
 
1072
                xfs_bmap_insert_exlist(ip, idx, 1, new, XFS_DATA_FORK);
 
1073
                ip->i_df.if_lastex = idx;
 
1074
                ip->i_d.di_nextents++;
 
1075
                if (cur == NULL)
 
1076
                        rval = XFS_ILOG_CORE | XFS_ILOG_DEXT;
 
1077
                else {
 
1078
                        rval = XFS_ILOG_CORE;
 
1079
                        if ((error = xfs_bmbt_lookup_eq(cur, PREV.br_startoff,
 
1080
                                        PREV.br_startblock, PREV.br_blockcount,
 
1081
                                        &i)))
 
1082
                                goto done;
 
1083
                        ASSERT(i == 1);
 
1084
                        if ((error = xfs_bmbt_update(cur,
 
1085
                                PREV.br_startoff + new->br_blockcount,
 
1086
                                PREV.br_startblock + new->br_blockcount,
 
1087
                                PREV.br_blockcount - new->br_blockcount,
 
1088
                                oldext)))
 
1089
                                goto done;
 
1090
                        cur->bc_rec.b = *new;
 
1091
                        if ((error = xfs_bmbt_insert(cur, &i)))
 
1092
                                goto done;
 
1093
                        ASSERT(i == 1);
 
1094
                }
 
1095
                break;
 
1096
 
 
1097
        case MASK2(RIGHT_FILLING, RIGHT_CONTIG):
 
1098
                /*
 
1099
                 * Setting the last part of a previous oldext extent to newext.
 
1100
                 * The right neighbor is contiguous with the new allocation.
 
1101
                 */
 
1102
                xfs_bmap_trace_pre_update(fname, "RF|RC", ip, idx,
 
1103
                        XFS_DATA_FORK);
 
1104
                xfs_bmap_trace_pre_update(fname, "RF|RC", ip, idx + 1,
 
1105
                        XFS_DATA_FORK);
 
1106
                xfs_bmbt_set_blockcount(ep,
 
1107
                        PREV.br_blockcount - new->br_blockcount);
 
1108
                xfs_bmap_trace_post_update(fname, "RF|RC", ip, idx,
 
1109
                        XFS_DATA_FORK);
 
1110
                xfs_bmbt_set_allf(ep + 1, new->br_startoff, new->br_startblock,
 
1111
                        new->br_blockcount + RIGHT.br_blockcount, newext);
 
1112
                xfs_bmap_trace_post_update(fname, "RF|RC", ip, idx + 1,
 
1113
                        XFS_DATA_FORK);
 
1114
                ip->i_df.if_lastex = idx + 1;
 
1115
                if (cur == NULL)
 
1116
                        rval = XFS_ILOG_DEXT;
 
1117
                else {
 
1118
                        rval = 0;
 
1119
                        if ((error = xfs_bmbt_lookup_eq(cur, PREV.br_startoff,
 
1120
                                        PREV.br_startblock,
 
1121
                                        PREV.br_blockcount, &i)))
 
1122
                                goto done;
 
1123
                        ASSERT(i == 1);
 
1124
                        if ((error = xfs_bmbt_update(cur, PREV.br_startoff,
 
1125
                                PREV.br_startblock, 
 
1126
                                PREV.br_blockcount - new->br_blockcount,
 
1127
                                oldext)))
 
1128
                                goto done;
 
1129
                        if ((error = xfs_bmbt_increment(cur, 0, &i)))
 
1130
                                goto done;
 
1131
                        if ((error = xfs_bmbt_update(cur, new->br_startoff,
 
1132
                                new->br_startblock,
 
1133
                                new->br_blockcount + RIGHT.br_blockcount,
 
1134
                                newext)))
 
1135
                                goto done;
 
1136
                }
 
1137
                break;
 
1138
 
 
1139
        case MASK(RIGHT_FILLING):
 
1140
                /*
 
1141
                 * Setting the last part of a previous oldext extent to newext.
 
1142
                 * The right neighbor is not contiguous.
 
1143
                 */
 
1144
                xfs_bmap_trace_pre_update(fname, "RF", ip, idx, XFS_DATA_FORK);
 
1145
                xfs_bmbt_set_blockcount(ep,
 
1146
                        PREV.br_blockcount - new->br_blockcount);
 
1147
                xfs_bmap_trace_post_update(fname, "RF", ip, idx, XFS_DATA_FORK);
 
1148
                xfs_bmap_trace_insert(fname, "RF", ip, idx + 1, 1,
 
1149
                        new, NULL, XFS_DATA_FORK);
 
1150
                xfs_bmap_insert_exlist(ip, idx + 1, 1, new, XFS_DATA_FORK);
 
1151
                ip->i_df.if_lastex = idx + 1;
 
1152
                ip->i_d.di_nextents++;
 
1153
                if (cur == NULL)
 
1154
                        rval = XFS_ILOG_CORE | XFS_ILOG_DEXT;
 
1155
                else {
 
1156
                        rval = XFS_ILOG_CORE;
 
1157
                        if ((error = xfs_bmbt_lookup_eq(cur, PREV.br_startoff,
 
1158
                                        PREV.br_startblock, PREV.br_blockcount,
 
1159
                                        &i)))
 
1160
                                goto done;
 
1161
                        ASSERT(i == 1);
 
1162
                        if ((error = xfs_bmbt_update(cur, PREV.br_startoff,
 
1163
                                PREV.br_startblock, 
 
1164
                                PREV.br_blockcount - new->br_blockcount,
 
1165
                                oldext)))
 
1166
                                goto done;
 
1167
                        if ((error = xfs_bmbt_lookup_eq(cur, new->br_startoff,
 
1168
                                        new->br_startblock, new->br_blockcount,
 
1169
                                        &i)))
 
1170
                                goto done;
 
1171
                        ASSERT(i == 0);
 
1172
                        cur->bc_rec.b.br_state = XFS_EXT_NORM;
 
1173
                        if ((error = xfs_bmbt_insert(cur, &i)))
 
1174
                                goto done;
 
1175
                        ASSERT(i == 1);
 
1176
                }
 
1177
                break;
 
1178
 
 
1179
        case 0:
 
1180
                /*
 
1181
                 * Setting the middle part of a previous oldext extent to
 
1182
                 * newext.  Contiguity is impossible here.
 
1183
                 * One extent becomes three extents.
 
1184
                 */
 
1185
                xfs_bmap_trace_pre_update(fname, "0", ip, idx, XFS_DATA_FORK);
 
1186
                xfs_bmbt_set_blockcount(ep,
 
1187
                        new->br_startoff - PREV.br_startoff);
 
1188
                xfs_bmap_trace_post_update(fname, "0", ip, idx, XFS_DATA_FORK);
 
1189
                r[0] = *new;
 
1190
                r[1].br_startoff = new_endoff;
 
1191
                r[1].br_blockcount =
 
1192
                        PREV.br_startoff + PREV.br_blockcount - new_endoff;
 
1193
                r[1].br_startblock = new->br_startblock + new->br_blockcount;
 
1194
                r[1].br_state = oldext;
 
1195
                xfs_bmap_trace_insert(fname, "0", ip, idx + 1, 2, &r[0], &r[1],
 
1196
                        XFS_DATA_FORK);
 
1197
                xfs_bmap_insert_exlist(ip, idx + 1, 2, &r[0], XFS_DATA_FORK);
 
1198
                ip->i_df.if_lastex = idx + 1;
 
1199
                ip->i_d.di_nextents += 2;
 
1200
                if (cur == NULL)
 
1201
                        rval = XFS_ILOG_CORE | XFS_ILOG_DEXT;
 
1202
                else {
 
1203
                        rval = XFS_ILOG_CORE;
 
1204
                        if ((error = xfs_bmbt_lookup_eq(cur, PREV.br_startoff,
 
1205
                                        PREV.br_startblock, PREV.br_blockcount,
 
1206
                                        &i)))
 
1207
                                goto done;
 
1208
                        ASSERT(i == 1);
 
1209
                        /* new right extent - oldext */
 
1210
                        if ((error = xfs_bmbt_update(cur, r[1].br_startoff,
 
1211
                                r[1].br_startblock, r[1].br_blockcount,
 
1212
                                r[1].br_state)))
 
1213
                                goto done;
 
1214
                        /* new left extent - oldext */
 
1215
                        PREV.br_blockcount =
 
1216
                                new->br_startoff - PREV.br_startoff;
 
1217
                        cur->bc_rec.b = PREV;
 
1218
                        if ((error = xfs_bmbt_insert(cur, &i)))
 
1219
                                goto done;
 
1220
                        ASSERT(i == 1);
 
1221
                        if ((error = xfs_bmbt_increment(cur, 0, &i)))
 
1222
                                goto done;
 
1223
                        ASSERT(i == 1);
 
1224
                        /* new middle extent - newext */
 
1225
                        cur->bc_rec.b = *new;
 
1226
                        if ((error = xfs_bmbt_insert(cur, &i)))
 
1227
                                goto done;
 
1228
                        ASSERT(i == 1);
 
1229
                }
 
1230
                break;
 
1231
 
 
1232
        case MASK3(LEFT_FILLING, LEFT_CONTIG, RIGHT_CONTIG):
 
1233
        case MASK3(RIGHT_FILLING, LEFT_CONTIG, RIGHT_CONTIG):
 
1234
        case MASK2(LEFT_FILLING, RIGHT_CONTIG):
 
1235
        case MASK2(RIGHT_FILLING, LEFT_CONTIG):
 
1236
        case MASK2(LEFT_CONTIG, RIGHT_CONTIG):
 
1237
        case MASK(LEFT_CONTIG):
 
1238
        case MASK(RIGHT_CONTIG):
 
1239
                /*
 
1240
                 * These cases are all impossible.
 
1241
                 */
 
1242
                ASSERT(0);
 
1243
        }
 
1244
        *curp = cur;
 
1245
done:
 
1246
        *logflagsp = rval;
 
1247
        return error;
 
1248
#undef  LEFT
 
1249
#undef  RIGHT
 
1250
#undef  PREV
 
1251
#undef  MASK
 
1252
#undef  MASK2
 
1253
#undef  MASK3
 
1254
#undef  MASK4
 
1255
#undef  STATE_SET
 
1256
#undef  STATE_TEST
 
1257
#undef  STATE_SET_TEST
 
1258
#undef  SWITCH_STATE
 
1259
}
 
1260
 
 
1261
/*
 
1262
 * Called by xfs_bmap_add_extent to handle cases converting a hole
 
1263
 * to a delayed allocation.
 
1264
 */
 
1265
/*ARGSUSED*/
 
1266
STATIC int                              /* error */
 
1267
xfs_bmap_add_extent_hole_delay(
 
1268
        xfs_inode_t             *ip,    /* incore inode pointer */
 
1269
        xfs_extnum_t            idx,    /* extent number to update/insert */
 
1270
        xfs_btree_cur_t         *cur,   /* if null, not a btree */
 
1271
        xfs_bmbt_irec_t         *new,   /* new data to put in extent list */
 
1272
        int                     *logflagsp, /* inode logging flags */
 
1273
        int                     rsvd)           /* OK to allocate reserved blocks */
 
1274
{
 
1275
        xfs_bmbt_rec_t          *base;  /* base of extent entry list */
 
1276
        xfs_bmbt_rec_t          *ep;    /* extent list entry for idx */
 
1277
#ifdef XFS_BMAP_TRACE
 
1278
        static char             fname[] = "xfs_bmap_add_extent_hole_delay";
 
1279
#endif
 
1280
        xfs_bmbt_irec_t         left;   /* left neighbor extent entry */
 
1281
        xfs_filblks_t           newlen=0;       /* new indirect size */
 
1282
        xfs_filblks_t           oldlen=0;       /* old indirect size */
 
1283
        xfs_bmbt_irec_t         right;  /* right neighbor extent entry */
 
1284
        int                     state;  /* state bits, accessed thru macros */
 
1285
        xfs_filblks_t           temp;   /* temp for indirect calculations */
 
1286
        enum {                          /* bit number definitions for state */
 
1287
                LEFT_CONTIG,    RIGHT_CONTIG,
 
1288
                LEFT_DELAY,     RIGHT_DELAY,
 
1289
                LEFT_VALID,     RIGHT_VALID
 
1290
        };
 
1291
 
 
1292
#define MASK(b)                 (1 << (b))
 
1293
#define MASK2(a,b)              (MASK(a) | MASK(b))
 
1294
#define STATE_SET(b,v)          ((v) ? (state |= MASK(b)) : (state &= ~MASK(b)))
 
1295
#define STATE_TEST(b)           (state & MASK(b))
 
1296
#define STATE_SET_TEST(b,v)     ((v) ? ((state |= MASK(b)), 1) : \
 
1297
                                       ((state &= ~MASK(b)), 0))
 
1298
#define SWITCH_STATE            (state & MASK2(LEFT_CONTIG, RIGHT_CONTIG))
 
1299
 
 
1300
        base = ip->i_df.if_u1.if_extents;
 
1301
        ep = &base[idx];
 
1302
        state = 0;
 
1303
        ASSERT(ISNULLSTARTBLOCK(new->br_startblock));
 
1304
        /*
 
1305
         * Check and set flags if this segment has a left neighbor
 
1306
         */
 
1307
        if (STATE_SET_TEST(LEFT_VALID, idx > 0)) {
 
1308
                xfs_bmbt_get_all(ep - 1, &left);
 
1309
                STATE_SET(LEFT_DELAY, ISNULLSTARTBLOCK(left.br_startblock));
 
1310
        }
 
1311
        /*
 
1312
         * Check and set flags if the current (right) segment exists.
 
1313
         * If it doesn't exist, we're converting the hole at end-of-file.
 
1314
         */
 
1315
        if (STATE_SET_TEST(RIGHT_VALID,
 
1316
                           idx <
 
1317
                           ip->i_df.if_bytes / (uint)sizeof(xfs_bmbt_rec_t))) {
 
1318
                xfs_bmbt_get_all(ep, &right);
 
1319
                STATE_SET(RIGHT_DELAY, ISNULLSTARTBLOCK(right.br_startblock));
 
1320
        }
 
1321
        /*
 
1322
         * Set contiguity flags on the left and right neighbors.
 
1323
         * Don't let extents get too large, even if the pieces are contiguous.
 
1324
         */
 
1325
        STATE_SET(LEFT_CONTIG, 
 
1326
                STATE_TEST(LEFT_VALID) && STATE_TEST(LEFT_DELAY) &&
 
1327
                left.br_startoff + left.br_blockcount == new->br_startoff &&
 
1328
                left.br_blockcount + new->br_blockcount <= MAXEXTLEN);
 
1329
        STATE_SET(RIGHT_CONTIG,
 
1330
                STATE_TEST(RIGHT_VALID) && STATE_TEST(RIGHT_DELAY) &&
 
1331
                new->br_startoff + new->br_blockcount == right.br_startoff &&
 
1332
                new->br_blockcount + right.br_blockcount <= MAXEXTLEN &&
 
1333
                (!STATE_TEST(LEFT_CONTIG) ||
 
1334
                 (left.br_blockcount + new->br_blockcount +
 
1335
                     right.br_blockcount <= MAXEXTLEN)));
 
1336
        /*
 
1337
         * Switch out based on the contiguity flags.
 
1338
         */
 
1339
        switch (SWITCH_STATE) {
 
1340
 
 
1341
        case MASK2(LEFT_CONTIG, RIGHT_CONTIG):
 
1342
                /*
 
1343
                 * New allocation is contiguous with delayed allocations
 
1344
                 * on the left and on the right.
 
1345
                 * Merge all three into a single extent list entry.
 
1346
                 */
 
1347
                temp = left.br_blockcount + new->br_blockcount +
 
1348
                        right.br_blockcount;
 
1349
                xfs_bmap_trace_pre_update(fname, "LC|RC", ip, idx - 1,
 
1350
                        XFS_DATA_FORK);
 
1351
                xfs_bmbt_set_blockcount(ep - 1, temp);
 
1352
                oldlen = STARTBLOCKVAL(left.br_startblock) +
 
1353
                        STARTBLOCKVAL(new->br_startblock) +
 
1354
                        STARTBLOCKVAL(right.br_startblock);
 
1355
                newlen = xfs_bmap_worst_indlen(ip, temp);
 
1356
                xfs_bmbt_set_startblock(ep - 1, NULLSTARTBLOCK((int)newlen));
 
1357
                xfs_bmap_trace_post_update(fname, "LC|RC", ip, idx - 1,
 
1358
                        XFS_DATA_FORK);
 
1359
                xfs_bmap_trace_delete(fname, "LC|RC", ip, idx, 1,
 
1360
                        XFS_DATA_FORK);
 
1361
                xfs_bmap_delete_exlist(ip, idx, 1, XFS_DATA_FORK);
 
1362
                ip->i_df.if_lastex = idx - 1;
 
1363
                break;
 
1364
 
 
1365
        case MASK(LEFT_CONTIG):
 
1366
                /*
 
1367
                 * New allocation is contiguous with a delayed allocation
 
1368
                 * on the left.
 
1369
                 * Merge the new allocation with the left neighbor.
 
1370
                 */
 
1371
                temp = left.br_blockcount + new->br_blockcount;
 
1372
                xfs_bmap_trace_pre_update(fname, "LC", ip, idx - 1,
 
1373
                        XFS_DATA_FORK);
 
1374
                xfs_bmbt_set_blockcount(ep - 1, temp);
 
1375
                oldlen = STARTBLOCKVAL(left.br_startblock) +
 
1376
                        STARTBLOCKVAL(new->br_startblock);
 
1377
                newlen = xfs_bmap_worst_indlen(ip, temp);
 
1378
                xfs_bmbt_set_startblock(ep - 1, NULLSTARTBLOCK((int)newlen));
 
1379
                xfs_bmap_trace_post_update(fname, "LC", ip, idx - 1,
 
1380
                        XFS_DATA_FORK);
 
1381
                ip->i_df.if_lastex = idx - 1;
 
1382
                break;
 
1383
 
 
1384
        case MASK(RIGHT_CONTIG):
 
1385
                /*
 
1386
                 * New allocation is contiguous with a delayed allocation
 
1387
                 * on the right.
 
1388
                 * Merge the new allocation with the right neighbor.
 
1389
                 */
 
1390
                xfs_bmap_trace_pre_update(fname, "RC", ip, idx, XFS_DATA_FORK);
 
1391
                temp = new->br_blockcount + right.br_blockcount;
 
1392
                oldlen = STARTBLOCKVAL(new->br_startblock) +
 
1393
                        STARTBLOCKVAL(right.br_startblock);
 
1394
                newlen = xfs_bmap_worst_indlen(ip, temp);
 
1395
                xfs_bmbt_set_allf(ep, new->br_startoff,
 
1396
                        NULLSTARTBLOCK((int)newlen), temp, right.br_state); 
 
1397
                xfs_bmap_trace_post_update(fname, "RC", ip, idx, XFS_DATA_FORK);
 
1398
                ip->i_df.if_lastex = idx;
 
1399
                break;
 
1400
 
 
1401
        case 0:
 
1402
                /*
 
1403
                 * New allocation is not contiguous with another
 
1404
                 * delayed allocation.
 
1405
                 * Insert a new entry.
 
1406
                 */
 
1407
                oldlen = newlen = 0;
 
1408
                xfs_bmap_trace_insert(fname, "0", ip, idx, 1, new, NULL,
 
1409
                        XFS_DATA_FORK);
 
1410
                xfs_bmap_insert_exlist(ip, idx, 1, new, XFS_DATA_FORK);
 
1411
                ip->i_df.if_lastex = idx;
 
1412
                break;
 
1413
        }
 
1414
        if (oldlen != newlen) {
 
1415
                ASSERT(oldlen > newlen);
 
1416
                xfs_mod_incore_sb(ip->i_mount, XFS_SBS_FDBLOCKS,
 
1417
                        (int)(oldlen - newlen), rsvd);
 
1418
                /*
 
1419
                 * Nothing to do for disk quota accounting here.
 
1420
                 */
 
1421
        }
 
1422
        *logflagsp = 0;
 
1423
        return 0;
 
1424
#undef  MASK
 
1425
#undef  MASK2
 
1426
#undef  STATE_SET
 
1427
#undef  STATE_TEST
 
1428
#undef  STATE_SET_TEST
 
1429
#undef  SWITCH_STATE
 
1430
}
 
1431
 
 
1432
/*
 
1433
 * Called by xfs_bmap_add_extent to handle cases converting a hole
 
1434
 * to a real allocation.
 
1435
 */
 
1436
STATIC int                              /* error */
 
1437
xfs_bmap_add_extent_hole_real(
 
1438
        xfs_inode_t             *ip,    /* incore inode pointer */
 
1439
        xfs_extnum_t            idx,    /* extent number to update/insert */
 
1440
        xfs_btree_cur_t         *cur,   /* if null, not a btree */
 
1441
        xfs_bmbt_irec_t         *new,   /* new data to put in extent list */
 
1442
        int                     *logflagsp, /* inode logging flags */
 
1443
        int                     whichfork) /* data or attr fork */
 
1444
{
 
1445
        xfs_bmbt_rec_t          *ep;    /* pointer to extent entry ins. point */
 
1446
        int                     error;  /* error return value */
 
1447
#ifdef XFS_BMAP_TRACE
 
1448
        static char             fname[] = "xfs_bmap_add_extent_hole_real";
 
1449
#endif
 
1450
        int                     i;      /* temp state */
 
1451
        xfs_ifork_t             *ifp;   /* inode fork pointer */
 
1452
        xfs_bmbt_irec_t         left;   /* left neighbor extent entry */
 
1453
        xfs_bmbt_irec_t         right;  /* right neighbor extent entry */
 
1454
        int                     state;  /* state bits, accessed thru macros */
 
1455
        enum {                          /* bit number definitions for state */
 
1456
                LEFT_CONTIG,    RIGHT_CONTIG,
 
1457
                LEFT_DELAY,     RIGHT_DELAY,
 
1458
                LEFT_VALID,     RIGHT_VALID
 
1459
        };
 
1460
 
 
1461
#define MASK(b)                 (1 << (b))
 
1462
#define MASK2(a,b)              (MASK(a) | MASK(b))
 
1463
#define STATE_SET(b,v)          ((v) ? (state |= MASK(b)) : (state &= ~MASK(b)))
 
1464
#define STATE_TEST(b)           (state & MASK(b))
 
1465
#define STATE_SET_TEST(b,v)     ((v) ? ((state |= MASK(b)), 1) : \
 
1466
                                       ((state &= ~MASK(b)), 0))
 
1467
#define SWITCH_STATE            (state & MASK2(LEFT_CONTIG, RIGHT_CONTIG))
 
1468
 
 
1469
        ifp = XFS_IFORK_PTR(ip, whichfork);
 
1470
        ASSERT(idx <= ifp->if_bytes / (uint)sizeof(xfs_bmbt_rec_t));
 
1471
        ep = &ifp->if_u1.if_extents[idx];
 
1472
        state = 0;
 
1473
        /*
 
1474
         * Check and set flags if this segment has a left neighbor.
 
1475
         */
 
1476
        if (STATE_SET_TEST(LEFT_VALID, idx > 0)) {
 
1477
                xfs_bmbt_get_all(ep - 1, &left);
 
1478
                STATE_SET(LEFT_DELAY, ISNULLSTARTBLOCK(left.br_startblock));
 
1479
        }
 
1480
        /*
 
1481
         * Check and set flags if this segment has a current value.
 
1482
         * Not true if we're inserting into the "hole" at eof.
 
1483
         */
 
1484
        if (STATE_SET_TEST(RIGHT_VALID,
 
1485
                           idx <
 
1486
                           ifp->if_bytes / (uint)sizeof(xfs_bmbt_rec_t))) {
 
1487
                xfs_bmbt_get_all(ep, &right);
 
1488
                STATE_SET(RIGHT_DELAY, ISNULLSTARTBLOCK(right.br_startblock));
 
1489
        }
 
1490
        /*
 
1491
         * We're inserting a real allocation between "left" and "right".
 
1492
         * Set the contiguity flags.  Don't let extents get too large.
 
1493
         */
 
1494
        STATE_SET(LEFT_CONTIG, 
 
1495
                STATE_TEST(LEFT_VALID) && !STATE_TEST(LEFT_DELAY) &&
 
1496
                left.br_startoff + left.br_blockcount == new->br_startoff &&
 
1497
                left.br_startblock + left.br_blockcount == new->br_startblock &&
 
1498
                left.br_state == new->br_state &&
 
1499
                left.br_blockcount + new->br_blockcount <= MAXEXTLEN);
 
1500
        STATE_SET(RIGHT_CONTIG,
 
1501
                STATE_TEST(RIGHT_VALID) && !STATE_TEST(RIGHT_DELAY) &&
 
1502
                new->br_startoff + new->br_blockcount == right.br_startoff &&
 
1503
                new->br_startblock + new->br_blockcount ==
 
1504
                    right.br_startblock &&
 
1505
                new->br_state == right.br_state &&
 
1506
                new->br_blockcount + right.br_blockcount <= MAXEXTLEN &&
 
1507
                (!STATE_TEST(LEFT_CONTIG) ||
 
1508
                 left.br_blockcount + new->br_blockcount +
 
1509
                     right.br_blockcount <= MAXEXTLEN));
 
1510
 
 
1511
        /*
 
1512
         * Select which case we're in here, and implement it.
 
1513
         */
 
1514
        switch (SWITCH_STATE) {
 
1515
 
 
1516
        case MASK2(LEFT_CONTIG, RIGHT_CONTIG):
 
1517
                /*
 
1518
                 * New allocation is contiguous with real allocations on the
 
1519
                 * left and on the right.
 
1520
                 * Merge all three into a single extent list entry.
 
1521
                 */
 
1522
                xfs_bmap_trace_pre_update(fname, "LC|RC", ip, idx - 1,
 
1523
                        whichfork);
 
1524
                xfs_bmbt_set_blockcount(ep - 1,
 
1525
                        left.br_blockcount + new->br_blockcount +
 
1526
                        right.br_blockcount);
 
1527
                xfs_bmap_trace_post_update(fname, "LC|RC", ip, idx - 1,
 
1528
                        whichfork);
 
1529
                xfs_bmap_trace_delete(fname, "LC|RC", ip,
 
1530
                        idx, 1, whichfork);
 
1531
                xfs_bmap_delete_exlist(ip, idx, 1, whichfork);
 
1532
                ifp->if_lastex = idx - 1;
 
1533
                XFS_IFORK_NEXT_SET(ip, whichfork,
 
1534
                        XFS_IFORK_NEXTENTS(ip, whichfork) - 1);
 
1535
                if (cur == NULL) {
 
1536
                        *logflagsp = XFS_ILOG_CORE | XFS_ILOG_FEXT(whichfork);
 
1537
                        return 0;
 
1538
                }
 
1539
                *logflagsp = XFS_ILOG_CORE;
 
1540
                if ((error = xfs_bmbt_lookup_eq(cur, right.br_startoff,
 
1541
                                right.br_startblock, right.br_blockcount, &i)))
 
1542
                        return error;
 
1543
                ASSERT(i == 1);
 
1544
                if ((error = xfs_bmbt_delete(cur, 0, &i)))
 
1545
                        return error;
 
1546
                ASSERT(i == 1);
 
1547
                if ((error = xfs_bmbt_decrement(cur, 0, &i)))
 
1548
                        return error;
 
1549
                ASSERT(i == 1);
 
1550
                error = xfs_bmbt_update(cur, left.br_startoff,
 
1551
                                left.br_startblock,
 
1552
                                left.br_blockcount + new->br_blockcount +
 
1553
                                right.br_blockcount, left.br_state);
 
1554
                return error;
 
1555
 
 
1556
        case MASK(LEFT_CONTIG):
 
1557
                /*
 
1558
                 * New allocation is contiguous with a real allocation
 
1559
                 * on the left.
 
1560
                 * Merge the new allocation with the left neighbor.
 
1561
                 */
 
1562
                xfs_bmap_trace_pre_update(fname, "LC", ip, idx - 1, whichfork);
 
1563
                xfs_bmbt_set_blockcount(ep - 1,
 
1564
                        left.br_blockcount + new->br_blockcount);
 
1565
                xfs_bmap_trace_post_update(fname, "LC", ip, idx - 1, whichfork);
 
1566
                ifp->if_lastex = idx - 1;
 
1567
                if (cur == NULL) {
 
1568
                        *logflagsp = XFS_ILOG_FEXT(whichfork);
 
1569
                        return 0;
 
1570
                }
 
1571
                *logflagsp = 0;
 
1572
                if ((error = xfs_bmbt_lookup_eq(cur, left.br_startoff,
 
1573
                                left.br_startblock, left.br_blockcount, &i)))
 
1574
                        return error;
 
1575
                ASSERT(i == 1);
 
1576
                error = xfs_bmbt_update(cur, left.br_startoff,
 
1577
                                left.br_startblock,
 
1578
                                left.br_blockcount + new->br_blockcount,
 
1579
                                left.br_state);
 
1580
                return error;
 
1581
 
 
1582
        case MASK(RIGHT_CONTIG):
 
1583
                /*
 
1584
                 * New allocation is contiguous with a real allocation
 
1585
                 * on the right.
 
1586
                 * Merge the new allocation with the right neighbor.
 
1587
                 */
 
1588
                xfs_bmap_trace_pre_update(fname, "RC", ip, idx, whichfork);
 
1589
                xfs_bmbt_set_allf(ep, new->br_startoff, new->br_startblock,
 
1590
                        new->br_blockcount + right.br_blockcount,
 
1591
                        right.br_state);
 
1592
                xfs_bmap_trace_post_update(fname, "RC", ip, idx, whichfork);
 
1593
                ifp->if_lastex = idx;
 
1594
                if (cur == NULL) {
 
1595
                        *logflagsp = XFS_ILOG_FEXT(whichfork);
 
1596
                        return 0;
 
1597
                }
 
1598
                *logflagsp = 0;
 
1599
                if ((error = xfs_bmbt_lookup_eq(cur, right.br_startoff,
 
1600
                                right.br_startblock, right.br_blockcount, &i)))
 
1601
                        return error;
 
1602
                ASSERT(i == 1);
 
1603
                error = xfs_bmbt_update(cur, new->br_startoff,
 
1604
                                new->br_startblock,
 
1605
                                new->br_blockcount + right.br_blockcount,
 
1606
                                right.br_state);
 
1607
                return error;
 
1608
 
 
1609
        case 0:
 
1610
                /*
 
1611
                 * New allocation is not contiguous with another
 
1612
                 * real allocation.
 
1613
                 * Insert a new entry.
 
1614
                 */
 
1615
                xfs_bmap_trace_insert(fname, "0", ip, idx, 1, new, NULL,
 
1616
                        whichfork);
 
1617
                xfs_bmap_insert_exlist(ip, idx, 1, new, whichfork);
 
1618
                ifp->if_lastex = idx;
 
1619
                XFS_IFORK_NEXT_SET(ip, whichfork,
 
1620
                        XFS_IFORK_NEXTENTS(ip, whichfork) + 1);
 
1621
                if (cur == NULL) {
 
1622
                        *logflagsp = XFS_ILOG_CORE | XFS_ILOG_FEXT(whichfork);
 
1623
                        return 0;
 
1624
                }
 
1625
                *logflagsp = XFS_ILOG_CORE;
 
1626
                if ((error = xfs_bmbt_lookup_eq(cur, new->br_startoff,
 
1627
                                new->br_startblock, new->br_blockcount, &i)))
 
1628
                        return error;
 
1629
                ASSERT(i == 0);
 
1630
                cur->bc_rec.b.br_state = new->br_state;
 
1631
                if ((error = xfs_bmbt_insert(cur, &i)))
 
1632
                        return error;
 
1633
                ASSERT(i == 1);
 
1634
                return 0;
 
1635
        }
 
1636
#undef  MASK
 
1637
#undef  MASK2
 
1638
#undef  STATE_SET
 
1639
#undef  STATE_TEST
 
1640
#undef  STATE_SET_TEST
 
1641
#undef  SWITCH_STATE
 
1642
        /* NOTREACHED */
 
1643
        ASSERT(0);
 
1644
        return 0; /* keep gcc quite */
 
1645
}
 
1646
 
 
1647
#define XFS_ALLOC_GAP_UNITS     4
 
1648
 
 
1649
/*
 
1650
 * xfs_bmap_alloc is called by xfs_bmapi to allocate an extent for a file.
 
1651
 * It figures out where to ask the underlying allocator to put the new extent.
 
1652
 */
 
1653
STATIC int                              /* error */
 
1654
xfs_bmap_alloc(
 
1655
        xfs_bmalloca_t  *ap)            /* bmap alloc argument struct */
 
1656
{
 
1657
        xfs_fsblock_t   adjust;         /* adjustment to block numbers */
 
1658
        xfs_alloctype_t atype=0;        /* type for allocation routines */
 
1659
        int             error;          /* error return value */
 
1660
        xfs_agnumber_t  fb_agno;        /* ag number of ap->firstblock */
 
1661
        xfs_mount_t     *mp;            /* mount point structure */
 
1662
        int             nullfb;         /* true if ap->firstblock isn't set */
 
1663
        int             rt;             /* true if inode is realtime */
 
1664
#ifdef __KERNEL__
 
1665
        xfs_extlen_t    prod=0;         /* product factor for allocators */
 
1666
        xfs_extlen_t    ralen=0;        /* realtime allocation length */
 
1667
#endif
 
1668
 
 
1669
#define ISLEGAL(x,y)    \
 
1670
        (rt ? \
 
1671
                (x) < mp->m_sb.sb_rblocks : \
 
1672
                XFS_FSB_TO_AGNO(mp, x) == XFS_FSB_TO_AGNO(mp, y) && \
 
1673
                XFS_FSB_TO_AGNO(mp, x) < mp->m_sb.sb_agcount && \
 
1674
                XFS_FSB_TO_AGBNO(mp, x) < mp->m_sb.sb_agblocks)
 
1675
 
 
1676
        /*
 
1677
         * Set up variables.
 
1678
         */
 
1679
        mp = ap->ip->i_mount;
 
1680
        nullfb = ap->firstblock == NULLFSBLOCK;
 
1681
        rt = (ap->ip->i_d.di_flags & XFS_DIFLAG_REALTIME) && ap->userdata;
 
1682
        fb_agno = nullfb ? NULLAGNUMBER : XFS_FSB_TO_AGNO(mp, ap->firstblock);
 
1683
#ifdef __KERNEL__
 
1684
        if (rt) {
 
1685
                xfs_extlen_t    extsz;          /* file extent size for rt */
 
1686
                xfs_fileoff_t   nexto;          /* next file offset */
 
1687
                xfs_extlen_t    orig_alen;      /* original ap->alen */
 
1688
                xfs_fileoff_t   orig_end;       /* original off+len */
 
1689
                xfs_fileoff_t   orig_off;       /* original ap->off */
 
1690
                xfs_extlen_t    mod_off;        /* modulus calculations */
 
1691
                xfs_fileoff_t   prevo;          /* previous file offset */
 
1692
                xfs_rtblock_t   rtx;            /* realtime extent number */
 
1693
                xfs_extlen_t    temp;           /* temp for rt calculations */
 
1694
 
 
1695
                /*
 
1696
                 * Set prod to match the realtime extent size.
 
1697
                 */
 
1698
                if (!(extsz = ap->ip->i_d.di_extsize))
 
1699
                        extsz = mp->m_sb.sb_rextsize;
 
1700
                prod = extsz / mp->m_sb.sb_rextsize;
 
1701
                orig_off = ap->off;
 
1702
                orig_alen = ap->alen;
 
1703
                orig_end = orig_off + orig_alen;
 
1704
                /*
 
1705
                 * If the file offset is unaligned vs. the extent size
 
1706
                 * we need to align it.  This will be possible unless
 
1707
                 * the file was previously written with a kernel that didn't
 
1708
                 * perform this alignment.
 
1709
                 */
 
1710
                mod_off = do_mod(orig_off, extsz);
 
1711
                if (mod_off) {
 
1712
                        ap->alen += mod_off;
 
1713
                        ap->off -= mod_off;
 
1714
                }
 
1715
                /*
 
1716
                 * Same adjustment for the end of the requested area.
 
1717
                 */
 
1718
                if ((temp = (ap->alen % extsz)))
 
1719
                        ap->alen += extsz - temp;
 
1720
                /*
 
1721
                 * If the previous block overlaps with this proposed allocation
 
1722
                 * then move the start forward without adjusting the length.
 
1723
                 */
 
1724
                prevo =
 
1725
                        ap->prevp->br_startoff == NULLFILEOFF ?
 
1726
                                0 :
 
1727
                                (ap->prevp->br_startoff +
 
1728
                                 ap->prevp->br_blockcount);
 
1729
                if (ap->off != orig_off && ap->off < prevo)
 
1730
                        ap->off = prevo;
 
1731
                /*
 
1732
                 * If the next block overlaps with this proposed allocation
 
1733
                 * then move the start back without adjusting the length,
 
1734
                 * but not before offset 0.
 
1735
                 * This may of course make the start overlap previous block,
 
1736
                 * and if we hit the offset 0 limit then the next block
 
1737
                 * can still overlap too.
 
1738
                 */
 
1739
                nexto = (ap->eof || ap->gotp->br_startoff == NULLFILEOFF) ? 
 
1740
                        NULLFILEOFF : ap->gotp->br_startoff;
 
1741
                if (!ap->eof &&
 
1742
                    ap->off + ap->alen != orig_end &&
 
1743
                    ap->off + ap->alen > nexto)
 
1744
                        ap->off = nexto > ap->alen ? nexto - ap->alen : 0;
 
1745
                /*
 
1746
                 * If we're now overlapping the next or previous extent that
 
1747
                 * means we can't fit an extsz piece in this hole.  Just move
 
1748
                 * the start forward to the first legal spot and set
 
1749
                 * the length so we hit the end.
 
1750
                 */
 
1751
                if ((ap->off != orig_off && ap->off < prevo) ||
 
1752
                    (ap->off + ap->alen != orig_end &&
 
1753
                     ap->off + ap->alen > nexto)) {
 
1754
                        ap->off = prevo;
 
1755
                        ap->alen = nexto - prevo;
 
1756
                }
 
1757
                /*
 
1758
                 * If the result isn't a multiple of rtextents we need to
 
1759
                 * remove blocks until it is.
 
1760
                 */
 
1761
                if ((temp = (ap->alen % mp->m_sb.sb_rextsize))) {
 
1762
                        /*
 
1763
                         * We're not covering the original request, or
 
1764
                         * we won't be able to once we fix the length.
 
1765
                         */
 
1766
                        if (orig_off < ap->off ||
 
1767
                            orig_end > ap->off + ap->alen ||
 
1768
                            ap->alen - temp < orig_alen)
 
1769
                                return XFS_ERROR(EINVAL);
 
1770
                        /*
 
1771
                         * Try to fix it by moving the start up.
 
1772
                         */
 
1773
                        if (ap->off + temp <= orig_off) {
 
1774
                                ap->alen -= temp;
 
1775
                                ap->off += temp;
 
1776
                        }
 
1777
                        /*
 
1778
                         * Try to fix it by moving the end in.
 
1779
                         */
 
1780
                        else if (ap->off + ap->alen - temp >= orig_end)
 
1781
                                ap->alen -= temp;
 
1782
                        /*
 
1783
                         * Set the start to the minimum then trim the length.
 
1784
                         */
 
1785
                        else {
 
1786
                                ap->alen -= orig_off - ap->off;
 
1787
                                ap->off = orig_off;
 
1788
                                ap->alen -= ap->alen % mp->m_sb.sb_rextsize;
 
1789
                        }
 
1790
                        /*
 
1791
                         * Result doesn't cover the request, fail it.
 
1792
                         */
 
1793
                        if (orig_off < ap->off || orig_end > ap->off + ap->alen)
 
1794
                                return XFS_ERROR(EINVAL);
 
1795
                }
 
1796
                ASSERT(ap->alen % mp->m_sb.sb_rextsize == 0);
 
1797
                /*
 
1798
                 * If the offset & length are not perfectly aligned
 
1799
                 * then kill prod, it will just get us in trouble.
 
1800
                 */
 
1801
                if (do_mod(ap->off, extsz) || ap->alen % extsz)
 
1802
                        prod = 1;
 
1803
                /*
 
1804
                 * Set ralen to be the actual requested length in rtextents.
 
1805
                 */
 
1806
                ralen = ap->alen / mp->m_sb.sb_rextsize;
 
1807
                /*
 
1808
                 * If the old value was close enough to MAXEXTLEN that
 
1809
                 * we rounded up to it, cut it back so it's legal again.
 
1810
                 * Note that if it's a really large request (bigger than
 
1811
                 * MAXEXTLEN), we don't hear about that number, and can't
 
1812
                 * adjust the starting point to match it.
 
1813
                 */
 
1814
                if (ralen * mp->m_sb.sb_rextsize >= MAXEXTLEN)
 
1815
                        ralen = MAXEXTLEN / mp->m_sb.sb_rextsize;
 
1816
                /*
 
1817
                 * If it's an allocation to an empty file at offset 0,
 
1818
                 * pick an extent that will space things out in the rt area.
 
1819
                 */
 
1820
                if (ap->eof && ap->off == 0) {
 
1821
                        error = xfs_rtpick_extent(mp, ap->tp, ralen, &rtx);
 
1822
                        if (error)
 
1823
                                return error;
 
1824
                        ap->rval = rtx * mp->m_sb.sb_rextsize;
 
1825
                } else
 
1826
                        ap->rval = 0;
 
1827
        }
 
1828
#else
 
1829
        if (rt)
 
1830
                ap->rval = 0;
 
1831
#endif  /* __KERNEL__ */
 
1832
        else if (nullfb)
 
1833
                ap->rval = XFS_INO_TO_FSB(mp, ap->ip->i_ino);
 
1834
        else
 
1835
                ap->rval = ap->firstblock;
 
1836
        /*
 
1837
         * If allocating at eof, and there's a previous real block,
 
1838
         * try to use it's last block as our starting point.
 
1839
         */
 
1840
        if (ap->eof && ap->prevp->br_startoff != NULLFILEOFF &&
 
1841
            !ISNULLSTARTBLOCK(ap->prevp->br_startblock) &&
 
1842
            ISLEGAL(ap->prevp->br_startblock + ap->prevp->br_blockcount,
 
1843
                    ap->prevp->br_startblock)) {
 
1844
                ap->rval = ap->prevp->br_startblock + ap->prevp->br_blockcount;
 
1845
                /*
 
1846
                 * Adjust for the gap between prevp and us.
 
1847
                 */
 
1848
                adjust = ap->off -
 
1849
                        (ap->prevp->br_startoff + ap->prevp->br_blockcount);
 
1850
                if (adjust &&
 
1851
                    ISLEGAL(ap->rval + adjust, ap->prevp->br_startblock))
 
1852
                        ap->rval += adjust;
 
1853
        }
 
1854
        /*
 
1855
         * If not at eof, then compare the two neighbor blocks.
 
1856
         * Figure out whether either one gives us a good starting point,
 
1857
         * and pick the better one.
 
1858
         */
 
1859
        else if (!ap->eof) {
 
1860
                xfs_fsblock_t   gotbno;         /* right side block number */
 
1861
                xfs_fsblock_t   gotdiff=0;      /* right side difference */
 
1862
                xfs_fsblock_t   prevbno;        /* left side block number */
 
1863
                xfs_fsblock_t   prevdiff=0;     /* left side difference */
 
1864
 
 
1865
                /*
 
1866
                 * If there's a previous (left) block, select a requested
 
1867
                 * start block based on it.
 
1868
                 */
 
1869
                if (ap->prevp->br_startoff != NULLFILEOFF &&
 
1870
                    !ISNULLSTARTBLOCK(ap->prevp->br_startblock) &&
 
1871
                    (prevbno = ap->prevp->br_startblock +
 
1872
                               ap->prevp->br_blockcount) &&
 
1873
                    ISLEGAL(prevbno, ap->prevp->br_startblock)) {
 
1874
                        /*
 
1875
                         * Calculate gap to end of previous block.
 
1876
                         */
 
1877
                        adjust = prevdiff = ap->off -
 
1878
                                (ap->prevp->br_startoff +
 
1879
                                 ap->prevp->br_blockcount);
 
1880
                        /*
 
1881
                         * Figure the startblock based on the previous block's
 
1882
                         * end and the gap size.
 
1883
                         * Heuristic!
 
1884
                         * If the gap is large relative to the piece we're
 
1885
                         * allocating, or using it gives us an illegal block
 
1886
                         * number, then just use the end of the previous block.
 
1887
                         */
 
1888
                        if (prevdiff <= XFS_ALLOC_GAP_UNITS * ap->alen &&
 
1889
                            ISLEGAL(prevbno + prevdiff,
 
1890
                                    ap->prevp->br_startblock))
 
1891
                                prevbno += adjust;
 
1892
                        else
 
1893
                                prevdiff += adjust;
 
1894
                        /*
 
1895
                         * If the firstblock forbids it, can't use it, 
 
1896
                         * must use default.
 
1897
                         */
 
1898
                        if (!rt && !nullfb &&
 
1899
                            XFS_FSB_TO_AGNO(mp, prevbno) != fb_agno)
 
1900
                                prevbno = NULLFSBLOCK;
 
1901
                }
 
1902
                /*
 
1903
                 * No previous block or can't follow it, just default.
 
1904
                 */
 
1905
                else
 
1906
                        prevbno = NULLFSBLOCK;
 
1907
                /*
 
1908
                 * If there's a following (right) block, select a requested
 
1909
                 * start block based on it.
 
1910
                 */
 
1911
                if (!ISNULLSTARTBLOCK(ap->gotp->br_startblock)) {
 
1912
                        /*
 
1913
                         * Calculate gap to start of next block.
 
1914
                         */
 
1915
                        adjust = gotdiff = ap->gotp->br_startoff - ap->off;
 
1916
                        /*
 
1917
                         * Figure the startblock based on the next block's
 
1918
                         * start and the gap size.
 
1919
                         */
 
1920
                        gotbno = ap->gotp->br_startblock;
 
1921
                        /*
 
1922
                         * Heuristic!
 
1923
                         * If the gap is large relative to the piece we're
 
1924
                         * allocating, or using it gives us an illegal block
 
1925
                         * number, then just use the start of the next block
 
1926
                         * offset by our length.
 
1927
                         */
 
1928
                        if (gotdiff <= XFS_ALLOC_GAP_UNITS * ap->alen &&
 
1929
                            ISLEGAL(gotbno - gotdiff, gotbno))
 
1930
                                gotbno -= adjust;
 
1931
                        else if (ISLEGAL(gotbno - ap->alen, gotbno)) {
 
1932
                                gotbno -= ap->alen;
 
1933
                                gotdiff += adjust - ap->alen;
 
1934
                        } else
 
1935
                                gotdiff += adjust;
 
1936
                        /*
 
1937
                         * If the firstblock forbids it, can't use it, 
 
1938
                         * must use default.
 
1939
                         */
 
1940
                        if (!rt && !nullfb &&
 
1941
                            XFS_FSB_TO_AGNO(mp, gotbno) != fb_agno)
 
1942
                                gotbno = NULLFSBLOCK;
 
1943
                }
 
1944
                /*
 
1945
                 * No next block, just default.
 
1946
                 */
 
1947
                else
 
1948
                        gotbno = NULLFSBLOCK;
 
1949
                /*
 
1950
                 * If both valid, pick the better one, else the only good
 
1951
                 * one, else ap->rval is already set (to 0 or the inode block).
 
1952
                 */
 
1953
                if (prevbno != NULLFSBLOCK && gotbno != NULLFSBLOCK)
 
1954
                        ap->rval = prevdiff <= gotdiff ? prevbno : gotbno;
 
1955
                else if (prevbno != NULLFSBLOCK)
 
1956
                        ap->rval = prevbno;
 
1957
                else if (gotbno != NULLFSBLOCK)
 
1958
                        ap->rval = gotbno;
 
1959
        }
 
1960
        /*
 
1961
         * If allowed, use ap->rval; otherwise must use firstblock since
 
1962
         * it's in the right allocation group.
 
1963
         */
 
1964
        if (nullfb || rt || XFS_FSB_TO_AGNO(mp, ap->rval) == fb_agno)
 
1965
                ;
 
1966
        else
 
1967
                ap->rval = ap->firstblock;
 
1968
        /*
 
1969
         * Realtime allocation, done through xfs_rtallocate_extent.
 
1970
         */
 
1971
        if (rt) {
 
1972
#ifndef __KERNEL__
 
1973
                ASSERT(0);
 
1974
#else
 
1975
                xfs_rtblock_t   rtb;
 
1976
 
 
1977
                atype = ap->rval == 0 ?
 
1978
                        XFS_ALLOCTYPE_ANY_AG : XFS_ALLOCTYPE_NEAR_BNO;
 
1979
                do_div(ap->rval, mp->m_sb.sb_rextsize);
 
1980
                rtb = ap->rval;
 
1981
                ap->alen = ralen;
 
1982
                if ((error = xfs_rtallocate_extent(ap->tp, ap->rval, 1, ap->alen,
 
1983
                                &ralen, atype, ap->wasdel, prod, &rtb)))
 
1984
                        return error;
 
1985
                if (rtb == NULLFSBLOCK && prod > 1 &&
 
1986
                    (error = xfs_rtallocate_extent(ap->tp, ap->rval, 1,
 
1987
                                                   ap->alen, &ralen, atype,
 
1988
                                                   ap->wasdel, 1, &rtb)))
 
1989
                        return error;
 
1990
                ap->rval = rtb;
 
1991
                if (ap->rval != NULLFSBLOCK) {
 
1992
                        ap->rval *= mp->m_sb.sb_rextsize;
 
1993
                        ralen *= mp->m_sb.sb_rextsize;
 
1994
                        ap->alen = ralen;
 
1995
                        ap->ip->i_d.di_nblocks += ralen;
 
1996
                        xfs_trans_log_inode(ap->tp, ap->ip, XFS_ILOG_CORE);
 
1997
                        if (ap->wasdel)
 
1998
                                ap->ip->i_delayed_blks -= ralen;
 
1999
                        /*
 
2000
                         * Adjust the disk quota also. This was reserved 
 
2001
                         * earlier.
 
2002
                         */
 
2003
                        if (XFS_IS_QUOTA_ON(mp) &&
 
2004
                            ap->ip->i_ino != mp->m_sb.sb_uquotino &&
 
2005
                            ap->ip->i_ino != mp->m_sb.sb_gquotino)
 
2006
                                xfs_trans_mod_dquot_byino(ap->tp, ap->ip,
 
2007
                                        ap->wasdel ?
 
2008
                                                XFS_TRANS_DQ_DELRTBCOUNT :
 
2009
                                                XFS_TRANS_DQ_RTBCOUNT,
 
2010
                                        (long)ralen);
 
2011
                } else
 
2012
                        ap->alen = 0;
 
2013
#endif  /* __KERNEL__ */
 
2014
        }
 
2015
        /*
 
2016
         * Normal allocation, done through xfs_alloc_vextent.
 
2017
         */
 
2018
        else {
 
2019
                xfs_agnumber_t  ag;
 
2020
                xfs_alloc_arg_t args;
 
2021
                xfs_extlen_t    blen;
 
2022
                xfs_extlen_t    delta;
 
2023
                int             isaligned;
 
2024
                xfs_extlen_t    longest;
 
2025
                xfs_extlen_t    need;
 
2026
                xfs_extlen_t    nextminlen=0;
 
2027
                int             notinit;
 
2028
                xfs_perag_t     *pag;
 
2029
                xfs_agnumber_t  startag;
 
2030
                int             tryagain;
 
2031
 
 
2032
                tryagain = isaligned = 0;
 
2033
                args.tp = ap->tp;
 
2034
                args.mp = mp;
 
2035
                args.fsbno = ap->rval;
 
2036
                args.maxlen = MIN(ap->alen, mp->m_sb.sb_agblocks);
 
2037
                blen = 0;
 
2038
                if (nullfb) {
 
2039
                        args.type = XFS_ALLOCTYPE_START_BNO;
 
2040
                        args.total = ap->total;
 
2041
                        /*
 
2042
                         * Find the longest available space.
 
2043
                         * We're going to try for the whole allocation at once.
 
2044
                         */
 
2045
                        startag = ag = XFS_FSB_TO_AGNO(mp, args.fsbno);
 
2046
                        notinit = 0;
 
2047
                        mrlock(&mp->m_peraglock, MR_ACCESS, PINOD);
 
2048
                        while (blen < ap->alen) {
 
2049
                                pag = &mp->m_perag[ag];
 
2050
                                if (!pag->pagf_init &&
 
2051
                                    (error = xfs_alloc_pagf_init(mp, args.tp,
 
2052
                                            ag, XFS_ALLOC_FLAG_TRYLOCK))) {
 
2053
                                        mrunlock(&mp->m_peraglock);
 
2054
                                        return error;
 
2055
                                }
 
2056
                                /*
 
2057
                                 * See xfs_alloc_fix_freelist...
 
2058
                                 */
 
2059
                                if (pag->pagf_init) {
 
2060
                                        need = XFS_MIN_FREELIST_PAG(pag, mp);
 
2061
                                        delta = need > pag->pagf_flcount ?
 
2062
                                                need - pag->pagf_flcount : 0;
 
2063
                                        longest = (pag->pagf_longest > delta) ?
 
2064
                                                (pag->pagf_longest - delta) :
 
2065
                                                (pag->pagf_flcount > 0 ||
 
2066
                                                 pag->pagf_longest > 0);
 
2067
                                        if (blen < longest)
 
2068
                                                blen = longest;
 
2069
                                } else
 
2070
                                        notinit = 1;
 
2071
                                if (++ag == mp->m_sb.sb_agcount) 
 
2072
                                        ag = 0;
 
2073
                                if (ag == startag)
 
2074
                                        break;
 
2075
                        }
 
2076
                        mrunlock(&mp->m_peraglock);
 
2077
                        /* 
 
2078
                         * Since the above loop did a BUF_TRYLOCK, it is
 
2079
                         * possible that there is space for this request.
 
2080
                         */ 
 
2081
                        if (notinit || blen < ap->minlen)
 
2082
                                args.minlen = ap->minlen;       
 
2083
                        /*
 
2084
                         * If the best seen length is less than the request
 
2085
                         * length, use the best as the minimum.
 
2086
                         */
 
2087
                        else if (blen < ap->alen)
 
2088
                                args.minlen = blen;
 
2089
                        /*
 
2090
                         * Otherwise we've seen an extent as big as alen,
 
2091
                         * use that as the minimum.
 
2092
                         */
 
2093
                        else 
 
2094
                                args.minlen = ap->alen;
 
2095
                } else if (ap->low) {
 
2096
                        args.type = XFS_ALLOCTYPE_FIRST_AG;
 
2097
                        args.total = args.minlen = ap->minlen;
 
2098
                } else {
 
2099
                        args.type = XFS_ALLOCTYPE_NEAR_BNO;
 
2100
                        args.total = ap->total;
 
2101
                        args.minlen = ap->minlen;
 
2102
                }
 
2103
                if (ap->ip->i_d.di_extsize) {
 
2104
                        args.prod = ap->ip->i_d.di_extsize;
 
2105
                        if ((args.mod = (xfs_extlen_t)do_mod(ap->off, args.prod)))
 
2106
                                args.mod = (xfs_extlen_t)(args.prod - args.mod);
 
2107
                } else if (mp->m_sb.sb_blocksize >= NBPP) {
 
2108
                        args.prod = 1;
 
2109
                        args.mod = 0;
 
2110
                } else {
 
2111
                        args.prod = NBPP >> mp->m_sb.sb_blocklog;
 
2112
                        if ((args.mod = (xfs_extlen_t)(do_mod(ap->off, args.prod))))
 
2113
                                args.mod = (xfs_extlen_t)(args.prod - args.mod);
 
2114
                }
 
2115
                /*
 
2116
                 * If we are not low on available data blocks, and the 
 
2117
                 * underlying logical volume manager is a stripe, and
 
2118
                 * the file offset is zero then try to allocate data 
 
2119
                 * blocks on stripe unit boundary.
 
2120
                 * NOTE: ap->aeof is only set if the allocation length
 
2121
                 * is >= the stripe unit and the allocation offset is
 
2122
                 * at the end of file. 
 
2123
                 */ 
 
2124
                if (!ap->low && ap->aeof) {
 
2125
                        if (!ap->off) {
 
2126
                                args.alignment = mp->m_dalign;
 
2127
                                atype = args.type;
 
2128
                                isaligned = 1;
 
2129
                                /*
 
2130
                                 * Adjust for alignment
 
2131
                                 */
 
2132
                                if (blen > args.alignment && blen <= ap->alen) 
 
2133
                                        args.minlen = blen - args.alignment;
 
2134
                                args.minalignslop = 0;
 
2135
                        } else {
 
2136
                                /*
 
2137
                                 * First try an exact bno allocation.
 
2138
                                 * If it fails then do a near or start bno
 
2139
                                 * allocation with alignment turned on.
 
2140
                                 */
 
2141
                                atype = args.type;
 
2142
                                tryagain = 1;
 
2143
                                args.type = XFS_ALLOCTYPE_THIS_BNO;
 
2144
                                args.alignment = 1;
 
2145
                                /*
 
2146
                                 * Compute the minlen+alignment for the
 
2147
                                 * next case.  Set slop so that the value
 
2148
                                 * of minlen+alignment+slop doesn't go up
 
2149
                                 * between the calls.
 
2150
                                 */
 
2151
                                if (blen > mp->m_dalign && blen <= ap->alen) 
 
2152
                                        nextminlen = blen - mp->m_dalign;
 
2153
                                else
 
2154
                                        nextminlen = args.minlen;
 
2155
                                if (nextminlen + mp->m_dalign > args.minlen + 1)
 
2156
                                        args.minalignslop =
 
2157
                                                nextminlen + mp->m_dalign -
 
2158
                                                args.minlen - 1;
 
2159
                                else
 
2160
                                        args.minalignslop = 0;
 
2161
                        }
 
2162
                } else {
 
2163
                        args.alignment = 1;
 
2164
                        args.minalignslop = 0;
 
2165
                }
 
2166
                args.minleft = ap->minleft;
 
2167
                args.wasdel = ap->wasdel;
 
2168
                args.isfl = 0;
 
2169
                args.userdata = ap->userdata;
 
2170
                if ((error = xfs_alloc_vextent(&args)))
 
2171
                        return error;
 
2172
                if (tryagain && args.fsbno == NULLFSBLOCK) {
 
2173
                        /*
 
2174
                         * Exact allocation failed. Now try with alignment
 
2175
                         * turned on.
 
2176
                         */
 
2177
                        args.type = atype;
 
2178
                        args.fsbno = ap->rval;
 
2179
                        args.alignment = mp->m_dalign;
 
2180
                        args.minlen = nextminlen;
 
2181
                        args.minalignslop = 0;
 
2182
                        isaligned = 1;
 
2183
                        if ((error = xfs_alloc_vextent(&args)))
 
2184
                                return error;
 
2185
                }
 
2186
                if (isaligned && args.fsbno == NULLFSBLOCK) {
 
2187
                        /* 
 
2188
                         * allocation failed, so turn off alignment and
 
2189
                         * try again.
 
2190
                         */
 
2191
                        args.type = atype;
 
2192
                        args.fsbno = ap->rval;
 
2193
                        args.alignment = 0;
 
2194
                        if ((error = xfs_alloc_vextent(&args)))
 
2195
                                return error;
 
2196
                }
 
2197
                if (args.fsbno == NULLFSBLOCK && nullfb &&
 
2198
                    args.minlen > ap->minlen) {
 
2199
                        args.minlen = ap->minlen;
 
2200
                        args.type = XFS_ALLOCTYPE_START_BNO;
 
2201
                        args.fsbno = ap->rval;
 
2202
                        if ((error = xfs_alloc_vextent(&args)))
 
2203
                                return error;
 
2204
                }
 
2205
                if (args.fsbno == NULLFSBLOCK && nullfb) {
 
2206
                        args.fsbno = 0;
 
2207
                        args.type = XFS_ALLOCTYPE_FIRST_AG;
 
2208
                        args.total = ap->minlen;
 
2209
                        args.minleft = 0;
 
2210
                        if ((error = xfs_alloc_vextent(&args)))
 
2211
                                return error;
 
2212
                        ap->low = 1;
 
2213
                }
 
2214
                if (args.fsbno != NULLFSBLOCK) {
 
2215
                        ap->firstblock = ap->rval = args.fsbno;
 
2216
                        ASSERT(nullfb || fb_agno == args.agno ||
 
2217
                               (ap->low && fb_agno < args.agno));
 
2218
                        ap->alen = args.len;
 
2219
                        ap->ip->i_d.di_nblocks += args.len;
 
2220
                        xfs_trans_log_inode(ap->tp, ap->ip, XFS_ILOG_CORE);
 
2221
                        if (ap->wasdel)
 
2222
                                ap->ip->i_delayed_blks -= args.len;
 
2223
                        /*
 
2224
                         * Adjust the disk quota also. This was reserved 
 
2225
                         * earlier.
 
2226
                         */
 
2227
                        if (XFS_IS_QUOTA_ON(mp) &&
 
2228
                            ap->ip->i_ino != mp->m_sb.sb_uquotino &&
 
2229
                            ap->ip->i_ino != mp->m_sb.sb_gquotino)
 
2230
                                xfs_trans_mod_dquot_byino(ap->tp, ap->ip,
 
2231
                                        ap->wasdel ?
 
2232
                                                XFS_TRANS_DQ_DELBCOUNT :
 
2233
                                                XFS_TRANS_DQ_BCOUNT,
 
2234
                                        (long)args.len);
 
2235
                } else {
 
2236
                        ap->rval = NULLFSBLOCK;
 
2237
                        ap->alen = 0;
 
2238
                }
 
2239
        }
 
2240
        return 0;
 
2241
#undef  ISLEGAL
 
2242
}
 
2243
 
 
2244
/*
 
2245
 * Transform a btree format file with only one leaf node, where the
 
2246
 * extents list will fit in the inode, into an extents format file.
 
2247
 * Since the extent list is already in-core, all we have to do is
 
2248
 * give up the space for the btree root and pitch the leaf block.
 
2249
 */
 
2250
STATIC int                              /* error */
 
2251
xfs_bmap_btree_to_extents(
 
2252
        xfs_trans_t             *tp,    /* transaction pointer */
 
2253
        xfs_inode_t             *ip,    /* incore inode pointer */
 
2254
        xfs_btree_cur_t         *cur,   /* btree cursor */
 
2255
        int                     *logflagsp, /* inode logging flags */
 
2256
        int                     whichfork,  /* data or attr fork */
 
2257
        int                     async)      /* xaction can be async */
 
2258
{
 
2259
        /* REFERENCED */
 
2260
        xfs_bmbt_block_t        *cblock;/* child btree block */
 
2261
        xfs_fsblock_t           cbno;   /* child block number */
 
2262
        xfs_buf_t               *cbp;   /* child block's buffer */
 
2263
        int                     error;  /* error return value */
 
2264
        xfs_ifork_t             *ifp;   /* inode fork data */
 
2265
        xfs_mount_t             *mp;    /* mount point structure */
 
2266
        xfs_bmbt_ptr_t          *pp;    /* ptr to block address */
 
2267
        xfs_bmbt_block_t        *rblock;/* root btree block */
 
2268
 
 
2269
        ifp = XFS_IFORK_PTR(ip, whichfork);
 
2270
        ASSERT(ifp->if_flags & XFS_IFEXTENTS);
 
2271
        ASSERT(XFS_IFORK_FORMAT(ip, whichfork) == XFS_DINODE_FMT_BTREE);
 
2272
        rblock = ifp->if_broot;
 
2273
        ASSERT(INT_GET(rblock->bb_level, ARCH_CONVERT) == 1);
 
2274
        ASSERT(INT_GET(rblock->bb_numrecs, ARCH_CONVERT) == 1);
 
2275
        ASSERT(XFS_BMAP_BROOT_MAXRECS(ifp->if_broot_bytes) == 1);
 
2276
        mp = ip->i_mount;
 
2277
        pp = XFS_BMAP_BROOT_PTR_ADDR(rblock, 1, ifp->if_broot_bytes);
 
2278
        *logflagsp = 0;
 
2279
#ifdef DEBUG
 
2280
        if ((error = xfs_btree_check_lptr(cur, INT_GET(*pp, ARCH_CONVERT), 1)))
 
2281
                return error;
 
2282
#endif
 
2283
        cbno = INT_GET(*pp, ARCH_CONVERT);
 
2284
        if ((error = xfs_btree_read_bufl(mp, tp, cbno, 0, &cbp,
 
2285
                        XFS_BMAP_BTREE_REF)))
 
2286
                return error;
 
2287
        cblock = XFS_BUF_TO_BMBT_BLOCK(cbp);
 
2288
        if ((error = xfs_btree_check_lblock(cur, cblock, 0, cbp)))
 
2289
                return error;
 
2290
        xfs_bmap_add_free(cbno, 1, cur->bc_private.b.flist, mp);
 
2291
        if (!async)
 
2292
                xfs_trans_set_sync(tp);
 
2293
        ip->i_d.di_nblocks--;
 
2294
        if (XFS_IS_QUOTA_ON(mp) &&
 
2295
            ip->i_ino != mp->m_sb.sb_uquotino &&
 
2296
            ip->i_ino != mp->m_sb.sb_gquotino)
 
2297
                xfs_trans_mod_dquot_byino(tp, ip, XFS_TRANS_DQ_BCOUNT, -1L);
 
2298
        xfs_trans_binval(tp, cbp);
 
2299
        if (cur->bc_bufs[0] == cbp)
 
2300
                cur->bc_bufs[0] = NULL;
 
2301
        xfs_iroot_realloc(ip, -1, whichfork);
 
2302
        ASSERT(ifp->if_broot == NULL);
 
2303
        ASSERT((ifp->if_flags & XFS_IFBROOT) == 0);
 
2304
        XFS_IFORK_FMT_SET(ip, whichfork, XFS_DINODE_FMT_EXTENTS);
 
2305
        *logflagsp = XFS_ILOG_CORE | XFS_ILOG_FEXT(whichfork);
 
2306
        return 0;
 
2307
}
 
2308
 
 
2309
/*
 
2310
 * Called by xfs_bmapi to update extent list structure and the btree
 
2311
 * after removing space (or undoing a delayed allocation).
 
2312
 */
 
2313
STATIC int                              /* error */
 
2314
xfs_bmap_del_extent(
 
2315
        xfs_inode_t             *ip,    /* incore inode pointer */
 
2316
        xfs_trans_t             *tp,    /* current transaction pointer */
 
2317
        xfs_extnum_t            idx,    /* extent number to update/delete */
 
2318
        xfs_bmap_free_t         *flist, /* list of extents to be freed */
 
2319
        xfs_btree_cur_t         *cur,   /* if null, not a btree */
 
2320
        xfs_bmbt_irec_t         *del,   /* data to remove from extent list */
 
2321
        int                     iflags, /* input flags */           
 
2322
        int                     *logflagsp, /* inode logging flags */
 
2323
        int                     whichfork, /* data or attr fork */
 
2324
        int                     rsvd)   /* OK to allocate reserved blocks */
 
2325
{
 
2326
        xfs_filblks_t           da_new; /* new delay-alloc indirect blocks */
 
2327
        xfs_filblks_t           da_old; /* old delay-alloc indirect blocks */
 
2328
        xfs_fsblock_t           del_endblock=0; /* first block past del */
 
2329
        xfs_fileoff_t           del_endoff;     /* first offset past del */
 
2330
        int                     delay;  /* current block is delayed allocated */
 
2331
        int                     do_fx;  /* free extent at end of routine */
 
2332
        xfs_bmbt_rec_t          *ep;    /* current extent entry pointer */
 
2333
        int                     error;  /* error return value */
 
2334
        int                     flags;  /* inode logging flags */
 
2335
#ifdef XFS_BMAP_TRACE
 
2336
        static char             fname[] = "xfs_bmap_del_extent";
 
2337
#endif
 
2338
        xfs_bmbt_irec_t         got;    /* current extent entry */
 
2339
        xfs_fileoff_t           got_endoff;     /* first offset past got */
 
2340
        int                     i;      /* temp state */
 
2341
        xfs_ifork_t             *ifp;   /* inode fork pointer */
 
2342
        xfs_mount_t             *mp;    /* mount structure */
 
2343
        xfs_filblks_t           nblks;  /* quota/sb block count */
 
2344
        xfs_bmbt_irec_t         new;    /* new record to be inserted */
 
2345
        /* REFERENCED */
 
2346
        xfs_extnum_t            nextents;       /* number of extents in list */
 
2347
        uint                    qfield; /* quota field to update */
 
2348
        xfs_filblks_t           temp;   /* for indirect length calculations */
 
2349
        xfs_filblks_t           temp2;  /* for indirect length calculations */
 
2350
        
 
2351
        XFS_STATS_INC(xfsstats.xs_del_exlist);
 
2352
        mp = ip->i_mount;       
 
2353
        ifp = XFS_IFORK_PTR(ip, whichfork);
 
2354
        nextents = ifp->if_bytes / (uint)sizeof(xfs_bmbt_rec_t);
 
2355
        ASSERT(idx >= 0 && idx < nextents);
 
2356
        ASSERT(del->br_blockcount > 0);
 
2357
        ep = &ifp->if_u1.if_extents[idx];
 
2358
        xfs_bmbt_get_all(ep, &got);
 
2359
        ASSERT(got.br_startoff <= del->br_startoff);
 
2360
        del_endoff = del->br_startoff + del->br_blockcount;
 
2361
        got_endoff = got.br_startoff + got.br_blockcount;
 
2362
        ASSERT(got_endoff >= del_endoff);
 
2363
        delay = ISNULLSTARTBLOCK(got.br_startblock);
 
2364
        ASSERT(ISNULLSTARTBLOCK(del->br_startblock) == delay);
 
2365
        flags = 0;
 
2366
        qfield = 0;
 
2367
        error = 0;
 
2368
        /*
 
2369
         * If deleting a real allocation, must free up the disk space.
 
2370
         */
 
2371
        if (!delay) {
 
2372
                flags = XFS_ILOG_CORE;
 
2373
                /*
 
2374
                 * Realtime allocation.  Free it and record di_nblocks update.
 
2375
                 */
 
2376
                if (whichfork == XFS_DATA_FORK &&
 
2377
                    (ip->i_d.di_flags & XFS_DIFLAG_REALTIME)) {
 
2378
                        xfs_fsblock_t   bno;
 
2379
                        xfs_filblks_t   len;
 
2380
 
 
2381
                        ASSERT(do_mod(del->br_blockcount,
 
2382
                                      mp->m_sb.sb_rextsize) == 0);
 
2383
                        ASSERT(do_mod(del->br_startblock,
 
2384
                                      mp->m_sb.sb_rextsize) == 0);
 
2385
                        bno = del->br_startblock;
 
2386
                        len = del->br_blockcount;
 
2387
                        do_div(bno, mp->m_sb.sb_rextsize);
 
2388
                        do_div(len, mp->m_sb.sb_rextsize);
 
2389
                        if ((error = xfs_rtfree_extent(ip->i_transp, bno,
 
2390
                                        (xfs_extlen_t)len)))
 
2391
                                goto done;
 
2392
                        do_fx = 0;
 
2393
                        nblks = len * mp->m_sb.sb_rextsize;
 
2394
                        if (XFS_IS_QUOTA_ON(mp) &&
 
2395
                            ip->i_ino != mp->m_sb.sb_uquotino &&
 
2396
                            ip->i_ino != mp->m_sb.sb_gquotino)
 
2397
                                qfield = XFS_TRANS_DQ_RTBCOUNT;
 
2398
                }
 
2399
                /*
 
2400
                 * Ordinary allocation.
 
2401
                 */
 
2402
                else {
 
2403
                        do_fx = 1;
 
2404
                        nblks = del->br_blockcount;
 
2405
                        if (XFS_IS_QUOTA_ON(mp) &&
 
2406
                            ip->i_ino != mp->m_sb.sb_uquotino &&
 
2407
                            ip->i_ino != mp->m_sb.sb_gquotino)
 
2408
                                qfield = XFS_TRANS_DQ_BCOUNT;
 
2409
                }
 
2410
                /*
 
2411
                 * Set up del_endblock and cur for later.
 
2412
                 */
 
2413
                del_endblock = del->br_startblock + del->br_blockcount;
 
2414
                if (cur) {
 
2415
                        if ((error = xfs_bmbt_lookup_eq(cur, got.br_startoff,
 
2416
                                        got.br_startblock, got.br_blockcount,
 
2417
                                        &i)))
 
2418
                                goto done;
 
2419
                        ASSERT(i == 1);
 
2420
                }
 
2421
                da_old = da_new = 0;
 
2422
        } else {
 
2423
                da_old = STARTBLOCKVAL(got.br_startblock);
 
2424
                da_new = 0;
 
2425
                nblks = 0;
 
2426
                do_fx = 0;
 
2427
        }
 
2428
        /*
 
2429
         * Set flag value to use in switch statement.
 
2430
         * Left-contig is 2, right-contig is 1.
 
2431
         */
 
2432
        switch (((got.br_startoff == del->br_startoff) << 1) |
 
2433
                (got_endoff == del_endoff)) {
 
2434
        case 3:
 
2435
                /*
 
2436
                 * Matches the whole extent.  Delete the entry.
 
2437
                 */
 
2438
                xfs_bmap_trace_delete(fname, "3", ip, idx, 1, whichfork);
 
2439
                xfs_bmap_delete_exlist(ip, idx, 1, whichfork);
 
2440
                ifp->if_lastex = idx;
 
2441
                if (delay)
 
2442
                        break;
 
2443
                XFS_IFORK_NEXT_SET(ip, whichfork,
 
2444
                        XFS_IFORK_NEXTENTS(ip, whichfork) - 1);
 
2445
                flags |= XFS_ILOG_CORE;
 
2446
                if (!cur) {
 
2447
                        flags |= XFS_ILOG_FEXT(whichfork);
 
2448
                        break;
 
2449
                }
 
2450
                if ((error = xfs_bmbt_delete(cur, iflags & XFS_BMAPI_ASYNC, &i)))
 
2451
                        goto done;
 
2452
                ASSERT(i == 1);
 
2453
                break;
 
2454
 
 
2455
        case 2:
 
2456
                /*
 
2457
                 * Deleting the first part of the extent.
 
2458
                 */
 
2459
                xfs_bmap_trace_pre_update(fname, "2", ip, idx, whichfork);
 
2460
                xfs_bmbt_set_startoff(ep, del_endoff);
 
2461
                temp = got.br_blockcount - del->br_blockcount;
 
2462
                xfs_bmbt_set_blockcount(ep, temp);
 
2463
                ifp->if_lastex = idx;
 
2464
                if (delay) {
 
2465
                        temp = XFS_FILBLKS_MIN(xfs_bmap_worst_indlen(ip, temp),
 
2466
                                da_old);
 
2467
                        xfs_bmbt_set_startblock(ep, NULLSTARTBLOCK((int)temp));
 
2468
                        xfs_bmap_trace_post_update(fname, "2", ip, idx,
 
2469
                                whichfork);
 
2470
                        da_new = temp;
 
2471
                        break;
 
2472
                }
 
2473
                xfs_bmbt_set_startblock(ep, del_endblock);
 
2474
                xfs_bmap_trace_post_update(fname, "2", ip, idx, whichfork);
 
2475
                if (!cur) {
 
2476
                        flags |= XFS_ILOG_FEXT(whichfork);
 
2477
                        break;
 
2478
                }
 
2479
                if ((error = xfs_bmbt_update(cur, del_endoff, del_endblock,
 
2480
                                got.br_blockcount - del->br_blockcount,
 
2481
                                got.br_state)))
 
2482
                        goto done;
 
2483
                break;
 
2484
 
 
2485
        case 1:
 
2486
                /*
 
2487
                 * Deleting the last part of the extent.
 
2488
                 */
 
2489
                temp = got.br_blockcount - del->br_blockcount;
 
2490
                xfs_bmap_trace_pre_update(fname, "1", ip, idx, whichfork);
 
2491
                xfs_bmbt_set_blockcount(ep, temp);
 
2492
                ifp->if_lastex = idx;
 
2493
                if (delay) {
 
2494
                        temp = XFS_FILBLKS_MIN(xfs_bmap_worst_indlen(ip, temp),
 
2495
                                da_old);
 
2496
                        xfs_bmbt_set_startblock(ep, NULLSTARTBLOCK((int)temp));
 
2497
                        xfs_bmap_trace_post_update(fname, "1", ip, idx,
 
2498
                                whichfork);
 
2499
                        da_new = temp;
 
2500
                        break;
 
2501
                }
 
2502
                xfs_bmap_trace_post_update(fname, "1", ip, idx, whichfork);
 
2503
                if (!cur) {
 
2504
                        flags |= XFS_ILOG_FEXT(whichfork);
 
2505
                        break;
 
2506
                }
 
2507
                if ((error = xfs_bmbt_update(cur, got.br_startoff,
 
2508
                                got.br_startblock,
 
2509
                                got.br_blockcount - del->br_blockcount,
 
2510
                                got.br_state)))
 
2511
                        goto done;
 
2512
                break;
 
2513
        
 
2514
        case 0:
 
2515
                /*
 
2516
                 * Deleting the middle of the extent.
 
2517
                 */
 
2518
                temp = del->br_startoff - got.br_startoff;
 
2519
                xfs_bmap_trace_pre_update(fname, "0", ip, idx, whichfork);
 
2520
                xfs_bmbt_set_blockcount(ep, temp);
 
2521
                new.br_startoff = del_endoff;
 
2522
                temp2 = got_endoff - del_endoff;
 
2523
                new.br_blockcount = temp2;
 
2524
                new.br_state = got.br_state;
 
2525
                if (!delay) {
 
2526
                        new.br_startblock = del_endblock;
 
2527
                        flags |= XFS_ILOG_CORE;
 
2528
                        if (cur) {
 
2529
                                if ((error = xfs_bmbt_update(cur,
 
2530
                                                got.br_startoff,
 
2531
                                                got.br_startblock, temp,
 
2532
                                                got.br_state)))
 
2533
                                        goto done;
 
2534
                                if ((error = xfs_bmbt_increment(cur, 0, &i)))
 
2535
                                        goto done;
 
2536
                                cur->bc_rec.b = new;
 
2537
                                error = xfs_bmbt_insert(cur, &i);
 
2538
                                if (error && error != ENOSPC)
 
2539
                                        goto done;
 
2540
                                /*
 
2541
                                 * If get no-space back from btree insert,
 
2542
                                 * it tried a split, and we have a zero
 
2543
                                 * block reservation.
 
2544
                                 * Fix up our state and return the error.
 
2545
                                 */
 
2546
                                if (error == ENOSPC) {
 
2547
                                        /* 
 
2548
                                         * Reset the cursor, don't trust
 
2549
                                         * it after any insert operation.
 
2550
                                         */
 
2551
                                        if ((error = xfs_bmbt_lookup_eq(cur,
 
2552
                                                        got.br_startoff,
 
2553
                                                        got.br_startblock,
 
2554
                                                        temp, &i)))
 
2555
                                                goto done;
 
2556
                                        ASSERT(i == 1);
 
2557
                                        /*
 
2558
                                         * Update the btree record back
 
2559
                                         * to the original value.
 
2560
                                         */
 
2561
                                        if ((error = xfs_bmbt_update(cur,
 
2562
                                                        got.br_startoff,
 
2563
                                                        got.br_startblock,
 
2564
                                                        got.br_blockcount,
 
2565
                                                        got.br_state)))
 
2566
                                                goto done;
 
2567
                                        /*
 
2568
                                         * Reset the extent record back
 
2569
                                         * to the original value.
 
2570
                                         */
 
2571
                                        xfs_bmbt_set_blockcount(ep,
 
2572
                                                got.br_blockcount);
 
2573
                                        flags = 0;
 
2574
                                        error = XFS_ERROR(ENOSPC);
 
2575
                                        goto done;
 
2576
                                }
 
2577
                                ASSERT(i == 1);
 
2578
                        } else
 
2579
                                flags |= XFS_ILOG_FEXT(whichfork);
 
2580
                        XFS_IFORK_NEXT_SET(ip, whichfork,
 
2581
                                XFS_IFORK_NEXTENTS(ip, whichfork) + 1);
 
2582
                } else {
 
2583
                        ASSERT(whichfork == XFS_DATA_FORK);
 
2584
                        temp = xfs_bmap_worst_indlen(ip, temp);
 
2585
                        xfs_bmbt_set_startblock(ep, NULLSTARTBLOCK((int)temp));
 
2586
                        temp2 = xfs_bmap_worst_indlen(ip, temp2);
 
2587
                        new.br_startblock = NULLSTARTBLOCK((int)temp2);
 
2588
                        da_new = temp + temp2;
 
2589
                        while (da_new > da_old) {
 
2590
                                if (temp) {
 
2591
                                        temp--;
 
2592
                                        da_new--;
 
2593
                                        xfs_bmbt_set_startblock(ep,
 
2594
                                                NULLSTARTBLOCK((int)temp));
 
2595
                                }
 
2596
                                if (da_new == da_old)
 
2597
                                        break;
 
2598
                                if (temp2) {
 
2599
                                        temp2--;
 
2600
                                        da_new--;
 
2601
                                        new.br_startblock = 
 
2602
                                                NULLSTARTBLOCK((int)temp2);
 
2603
                                }
 
2604
                        }
 
2605
                }
 
2606
                xfs_bmap_trace_post_update(fname, "0", ip, idx, whichfork);
 
2607
                xfs_bmap_trace_insert(fname, "0", ip, idx + 1, 1, &new, NULL,
 
2608
                        whichfork);
 
2609
                xfs_bmap_insert_exlist(ip, idx + 1, 1, &new, whichfork);
 
2610
                ifp->if_lastex = idx + 1;
 
2611
                break;
 
2612
        }
 
2613
        /*
 
2614
         * If we need to, add to list of extents to delete.
 
2615
         */
 
2616
        if (do_fx)
 
2617
                xfs_bmap_add_free(del->br_startblock, del->br_blockcount, flist,
 
2618
                        mp);
 
2619
        /*
 
2620
         * Adjust inode # blocks in the file.
 
2621
         */
 
2622
        if (nblks)
 
2623
                ip->i_d.di_nblocks -= nblks;
 
2624
        /*
 
2625
         * Adjust quota data.
 
2626
         */
 
2627
        if (qfield)
 
2628
                xfs_trans_mod_dquot_byino(tp, ip, qfield, (long)-nblks);
 
2629
        /*
 
2630
         * Account for change in delayed indirect blocks.
 
2631
         * Nothing to do for disk quota accounting here.
 
2632
         */
 
2633
        ASSERT(da_old >= da_new);
 
2634
        if (da_old > da_new) 
 
2635
                xfs_mod_incore_sb(mp, XFS_SBS_FDBLOCKS, (int)(da_old - da_new),
 
2636
                        rsvd);
 
2637
done:
 
2638
        *logflagsp = flags;
 
2639
        return error;
 
2640
}
 
2641
 
 
2642
/*
 
2643
 * Remove the entry "free" from the free item list.  Prev points to the
 
2644
 * previous entry, unless "free" is the head of the list.
 
2645
 */
 
2646
STATIC void
 
2647
xfs_bmap_del_free(
 
2648
        xfs_bmap_free_t         *flist, /* free item list header */
 
2649
        xfs_bmap_free_item_t    *prev,  /* previous item on list, if any */
 
2650
        xfs_bmap_free_item_t    *free)  /* list item to be freed */
 
2651
{
 
2652
        if (prev)
 
2653
                prev->xbfi_next = free->xbfi_next;
 
2654
        else
 
2655
                flist->xbf_first = free->xbfi_next;
 
2656
        flist->xbf_count--;
 
2657
        kmem_zone_free(xfs_bmap_free_item_zone, free);
 
2658
}
 
2659
 
 
2660
/*
 
2661
 * Remove count entries from the extents array for inode "ip", starting
 
2662
 * at index "idx".  Copies the remaining items down over the deleted ones,
 
2663
 * and gives back the excess memory.
 
2664
 */
 
2665
STATIC void
 
2666
xfs_bmap_delete_exlist(
 
2667
        xfs_inode_t     *ip,            /* incore inode pointer */
 
2668
        xfs_extnum_t    idx,            /* starting delete index */
 
2669
        xfs_extnum_t    count,          /* count of items to delete */
 
2670
        int             whichfork)      /* data or attr fork */
 
2671
{
 
2672
        xfs_bmbt_rec_t  *base;          /* base of extent list */
 
2673
        xfs_ifork_t     *ifp;           /* inode fork pointer */
 
2674
        xfs_extnum_t    nextents;       /* number of extents in list after */
 
2675
 
 
2676
        ifp = XFS_IFORK_PTR(ip, whichfork);
 
2677
        ASSERT(ifp->if_flags & XFS_IFEXTENTS);
 
2678
        base = ifp->if_u1.if_extents;
 
2679
        nextents = ifp->if_bytes / (uint)sizeof(xfs_bmbt_rec_t) - count;
 
2680
        ovbcopy(&base[idx + count], &base[idx],
 
2681
                (nextents - idx) * sizeof(*base));
 
2682
        xfs_iext_realloc(ip, -count, whichfork);
 
2683
}
 
2684
 
 
2685
/*
 
2686
 * Convert an extents-format file into a btree-format file.
 
2687
 * The new file will have a root block (in the inode) and a single child block.
 
2688
 */
 
2689
STATIC int                                      /* error */
 
2690
xfs_bmap_extents_to_btree(
 
2691
        xfs_trans_t             *tp,            /* transaction pointer */
 
2692
        xfs_inode_t             *ip,            /* incore inode pointer */
 
2693
        xfs_fsblock_t           *firstblock,    /* first-block-allocated */
 
2694
        xfs_bmap_free_t         *flist,         /* blocks freed in xaction */
 
2695
        xfs_btree_cur_t         **curp,         /* cursor returned to caller */
 
2696
        int                     wasdel,         /* converting a delayed alloc */
 
2697
        int                     *logflagsp,     /* inode logging flags */
 
2698
        int                     whichfork)      /* data or attr fork */
 
2699
{
 
2700
        xfs_bmbt_block_t        *ablock;        /* allocated (child) bt block */
 
2701
        xfs_buf_t               *abp;           /* buffer for ablock */
 
2702
        xfs_alloc_arg_t         args;           /* allocation arguments */
 
2703
        xfs_bmbt_rec_t          *arp;           /* child record pointer */
 
2704
        xfs_bmbt_block_t        *block;         /* btree root block */
 
2705
        xfs_btree_cur_t         *cur;           /* bmap btree cursor */
 
2706
        xfs_bmbt_rec_t          *ep;            /* extent list pointer */
 
2707
        int                     error;          /* error return value */
 
2708
        xfs_extnum_t            i;              /* extent list index */
 
2709
        xfs_ifork_t             *ifp;           /* inode fork pointer */
 
2710
        xfs_bmbt_key_t          *kp;            /* root block key pointer */
 
2711
        xfs_mount_t             *mp;            /* mount structure */
 
2712
        xfs_extnum_t            nextents;       /* extent list size */
 
2713
        xfs_bmbt_ptr_t          *pp;            /* root block address pointer */
 
2714
 
 
2715
        ifp = XFS_IFORK_PTR(ip, whichfork);
 
2716
        ASSERT(XFS_IFORK_FORMAT(ip, whichfork) == XFS_DINODE_FMT_EXTENTS);
 
2717
        ASSERT(ifp->if_ext_max ==
 
2718
               XFS_IFORK_SIZE(ip, whichfork) / (uint)sizeof(xfs_bmbt_rec_t));
 
2719
        /*
 
2720
         * Make space in the inode incore.
 
2721
         */
 
2722
        xfs_iroot_realloc(ip, 1, whichfork);
 
2723
        ifp->if_flags |= XFS_IFBROOT;
 
2724
        /*
 
2725
         * Fill in the root.
 
2726
         */
 
2727
        block = ifp->if_broot;
 
2728
        INT_SET(block->bb_magic, ARCH_CONVERT, XFS_BMAP_MAGIC);
 
2729
        INT_SET(block->bb_level, ARCH_CONVERT, 1);
 
2730
        INT_SET(block->bb_numrecs, ARCH_CONVERT, 1);
 
2731
        INT_SET(block->bb_leftsib, ARCH_CONVERT, NULLDFSBNO);
 
2732
        INT_SET(block->bb_rightsib, ARCH_CONVERT, NULLDFSBNO);
 
2733
        /*
 
2734
         * Need a cursor.  Can't allocate until bb_level is filled in.
 
2735
         */
 
2736
        mp = ip->i_mount;
 
2737
        cur = xfs_btree_init_cursor(mp, tp, NULL, 0, XFS_BTNUM_BMAP, ip,
 
2738
                whichfork);
 
2739
        cur->bc_private.b.firstblock = *firstblock;
 
2740
        cur->bc_private.b.flist = flist;
 
2741
        cur->bc_private.b.flags = wasdel ? XFS_BTCUR_BPRV_WASDEL : 0;
 
2742
        /*
 
2743
         * Convert to a btree with two levels, one record in root.
 
2744
         */
 
2745
        XFS_IFORK_FMT_SET(ip, whichfork, XFS_DINODE_FMT_BTREE);
 
2746
        args.tp = tp;
 
2747
        args.mp = mp;
 
2748
        if (*firstblock == NULLFSBLOCK) {
 
2749
                args.type = XFS_ALLOCTYPE_START_BNO;
 
2750
                args.fsbno = XFS_INO_TO_FSB(mp, ip->i_ino);
 
2751
        } else if (flist->xbf_low) {
 
2752
                args.type = XFS_ALLOCTYPE_START_BNO;
 
2753
                args.fsbno = *firstblock;
 
2754
        } else {
 
2755
                args.type = XFS_ALLOCTYPE_NEAR_BNO;
 
2756
                args.fsbno = *firstblock;
 
2757
        }
 
2758
        args.minlen = args.maxlen = args.prod = 1;
 
2759
        args.total = args.minleft = args.alignment = args.mod = args.isfl =
 
2760
                args.minalignslop = 0;
 
2761
        args.wasdel = wasdel;
 
2762
        *logflagsp = 0;
 
2763
        if ((error = xfs_alloc_vextent(&args))) {
 
2764
                xfs_iroot_realloc(ip, -1, whichfork);
 
2765
                xfs_btree_del_cursor(cur, XFS_BTREE_ERROR);
 
2766
                return error;
 
2767
        }
 
2768
        /*
 
2769
         * Allocation can't fail, the space was reserved.
 
2770
         */
 
2771
        ASSERT(args.fsbno != NULLFSBLOCK);
 
2772
        ASSERT(*firstblock == NULLFSBLOCK ||
 
2773
               args.agno == XFS_FSB_TO_AGNO(mp, *firstblock) ||
 
2774
               (flist->xbf_low &&
 
2775
                args.agno > XFS_FSB_TO_AGNO(mp, *firstblock)));
 
2776
        *firstblock = cur->bc_private.b.firstblock = args.fsbno;
 
2777
        cur->bc_private.b.allocated++;
 
2778
        ip->i_d.di_nblocks++;
 
2779
        if (XFS_IS_QUOTA_ON(mp) &&
 
2780
            ip->i_ino != mp->m_sb.sb_uquotino &&
 
2781
            ip->i_ino != mp->m_sb.sb_gquotino)
 
2782
                xfs_trans_mod_dquot_byino(tp, ip, XFS_TRANS_DQ_BCOUNT, 1L);
 
2783
        abp = xfs_btree_get_bufl(mp, tp, args.fsbno, 0);
 
2784
        /*
 
2785
         * Fill in the child block.
 
2786
         */
 
2787
        ablock = XFS_BUF_TO_BMBT_BLOCK(abp);
 
2788
        INT_SET(ablock->bb_magic, ARCH_CONVERT, XFS_BMAP_MAGIC);
 
2789
        INT_ZERO(ablock->bb_level, ARCH_CONVERT);
 
2790
        INT_ZERO(ablock->bb_numrecs, ARCH_CONVERT);
 
2791
        INT_SET(ablock->bb_leftsib, ARCH_CONVERT, NULLDFSBNO);
 
2792
        INT_SET(ablock->bb_rightsib, ARCH_CONVERT, NULLDFSBNO);
 
2793
        arp = XFS_BMAP_REC_IADDR(ablock, 1, cur);
 
2794
        nextents = ifp->if_bytes / (uint)sizeof(xfs_bmbt_rec_t);
 
2795
        for (ep = ifp->if_u1.if_extents, i = 0; i < nextents; i++, ep++) {
 
2796
                if (!ISNULLSTARTBLOCK(xfs_bmbt_get_startblock(ep))) {
 
2797
                        *arp++ = *ep;
 
2798
                        INT_MOD(ablock->bb_numrecs, ARCH_CONVERT, +1);
 
2799
                }
 
2800
        }
 
2801
        ASSERT(INT_GET(ablock->bb_numrecs, ARCH_CONVERT) == XFS_IFORK_NEXTENTS(ip, whichfork));
 
2802
        /*
 
2803
         * Fill in the root key and pointer.
 
2804
         */
 
2805
        kp = XFS_BMAP_KEY_IADDR(block, 1, cur);
 
2806
        arp = XFS_BMAP_REC_IADDR(ablock, 1, cur);
 
2807
        INT_SET(kp->br_startoff, ARCH_CONVERT, xfs_bmbt_get_startoff(arp));
 
2808
        pp = XFS_BMAP_PTR_IADDR(block, 1, cur);
 
2809
        INT_SET(*pp, ARCH_CONVERT, args.fsbno);
 
2810
        /*
 
2811
         * Do all this logging at the end so that 
 
2812
         * the root is at the right level.
 
2813
         */
 
2814
        xfs_bmbt_log_block(cur, abp, XFS_BB_ALL_BITS);
 
2815
        xfs_bmbt_log_recs(cur, abp, 1, INT_GET(ablock->bb_numrecs, ARCH_CONVERT));
 
2816
        ASSERT(*curp == NULL);
 
2817
        *curp = cur;
 
2818
        *logflagsp = XFS_ILOG_CORE | XFS_ILOG_FBROOT(whichfork);
 
2819
        return 0;
 
2820
}
 
2821
 
 
2822
/*
 
2823
 * Insert new item(s) in the extent list for inode "ip".
 
2824
 * Count new items are inserted at offset idx.
 
2825
 */
 
2826
STATIC void
 
2827
xfs_bmap_insert_exlist(
 
2828
        xfs_inode_t     *ip,            /* incore inode pointer */
 
2829
        xfs_extnum_t    idx,            /* starting index of new items */
 
2830
        xfs_extnum_t    count,          /* number of inserted items */
 
2831
        xfs_bmbt_irec_t *new,           /* items to insert */
 
2832
        int             whichfork)      /* data or attr fork */
 
2833
{
 
2834
        xfs_bmbt_rec_t  *base;          /* extent list base */
 
2835
        xfs_ifork_t     *ifp;           /* inode fork pointer */
 
2836
        xfs_extnum_t    nextents;       /* extent list size */
 
2837
        xfs_extnum_t    to;             /* extent list index */
 
2838
 
 
2839
        ifp = XFS_IFORK_PTR(ip, whichfork);
 
2840
        ASSERT(ifp->if_flags & XFS_IFEXTENTS);
 
2841
        xfs_iext_realloc(ip, count, whichfork);
 
2842
        base = ifp->if_u1.if_extents;
 
2843
        nextents = ifp->if_bytes / (uint)sizeof(xfs_bmbt_rec_t);
 
2844
        ovbcopy(&base[idx], &base[idx + count],
 
2845
                (nextents - (idx + count)) * sizeof(*base));
 
2846
        for (to = idx; to < idx + count; to++, new++)
 
2847
                xfs_bmbt_set_all(&base[to], new);
 
2848
}
 
2849
 
 
2850
/*
 
2851
 * Convert a local file to an extents file.
 
2852
 * This code is out of bounds for data forks of regular files,
 
2853
 * since the file data needs to get logged so things will stay consistent.
 
2854
 * (The bmap-level manipulations are ok, though).
 
2855
 */
 
2856
STATIC int                              /* error */
 
2857
xfs_bmap_local_to_extents(
 
2858
        xfs_trans_t     *tp,            /* transaction pointer */
 
2859
        xfs_inode_t     *ip,            /* incore inode pointer */
 
2860
        xfs_fsblock_t   *firstblock,    /* first block allocated in xaction */
 
2861
        xfs_extlen_t    total,          /* total blocks needed by transaction */
 
2862
        int             *logflagsp,     /* inode logging flags */
 
2863
        int             whichfork)      /* data or attr fork */
 
2864
{
 
2865
        int             error;          /* error return value */
 
2866
        int             flags;          /* logging flags returned */
 
2867
#ifdef XFS_BMAP_TRACE
 
2868
        static char     fname[] = "xfs_bmap_local_to_extents";
 
2869
#endif
 
2870
        xfs_ifork_t     *ifp;           /* inode fork pointer */
 
2871
 
 
2872
        /*
 
2873
         * We don't want to deal with the case of keeping inode data inline yet.
 
2874
         * So sending the data fork of a regular inode is illegal.
 
2875
         */
 
2876
        ASSERT(!((ip->i_d.di_mode & IFMT) == IFREG && 
 
2877
                 whichfork == XFS_DATA_FORK));
 
2878
        ifp = XFS_IFORK_PTR(ip, whichfork);
 
2879
        ASSERT(XFS_IFORK_FORMAT(ip, whichfork) == XFS_DINODE_FMT_LOCAL);
 
2880
        flags = 0;
 
2881
        error = 0;
 
2882
        if (ifp->if_bytes) {
 
2883
                xfs_alloc_arg_t args;   /* allocation arguments */
 
2884
                xfs_buf_t       *bp;    /* buffer for extent list block */
 
2885
                xfs_bmbt_rec_t  *ep;    /* extent list pointer */
 
2886
 
 
2887
                args.tp = tp;
 
2888
                args.mp = ip->i_mount;
 
2889
                ASSERT(ifp->if_flags & XFS_IFINLINE);
 
2890
                /*
 
2891
                 * Allocate a block.  We know we need only one, since the
 
2892
                 * file currently fits in an inode.
 
2893
                 */
 
2894
                if (*firstblock == NULLFSBLOCK) {
 
2895
                        args.fsbno = XFS_INO_TO_FSB(args.mp, ip->i_ino);
 
2896
                        args.type = XFS_ALLOCTYPE_START_BNO;
 
2897
                } else {
 
2898
                        args.fsbno = *firstblock;
 
2899
                        args.type = XFS_ALLOCTYPE_NEAR_BNO;
 
2900
                }
 
2901
                args.total = total;
 
2902
                args.mod = args.minleft = args.alignment = args.wasdel =
 
2903
                        args.isfl = args.minalignslop = 0;
 
2904
                args.minlen = args.maxlen = args.prod = 1;
 
2905
                if ((error = xfs_alloc_vextent(&args)))
 
2906
                        goto done;
 
2907
                /* 
 
2908
                 * Can't fail, the space was reserved.
 
2909
                 */
 
2910
                ASSERT(args.fsbno != NULLFSBLOCK);
 
2911
                ASSERT(args.len == 1);
 
2912
                *firstblock = args.fsbno;
 
2913
                bp = xfs_btree_get_bufl(args.mp, tp, args.fsbno, 0);
 
2914
                bcopy(ifp->if_u1.if_data, (char *)XFS_BUF_PTR(bp),
 
2915
                        ifp->if_bytes);
 
2916
                xfs_trans_log_buf(tp, bp, 0, ifp->if_bytes - 1);
 
2917
                xfs_idata_realloc(ip, -ifp->if_bytes, whichfork);
 
2918
                xfs_iext_realloc(ip, 1, whichfork);
 
2919
                ep = ifp->if_u1.if_extents;
 
2920
                xfs_bmbt_set_allf(ep, 0, args.fsbno, 1, XFS_EXT_NORM);
 
2921
                xfs_bmap_trace_post_update(fname, "new", ip, 0, whichfork);
 
2922
                XFS_IFORK_NEXT_SET(ip, whichfork, 1);
 
2923
                ip->i_d.di_nblocks = 1;
 
2924
                if (XFS_IS_QUOTA_ON(args.mp) &&
 
2925
                    ip->i_ino != args.mp->m_sb.sb_uquotino &&
 
2926
                    ip->i_ino != args.mp->m_sb.sb_gquotino)
 
2927
                        xfs_trans_mod_dquot_byino(tp, ip, XFS_TRANS_DQ_BCOUNT,
 
2928
                                1L);
 
2929
                flags |= XFS_ILOG_FEXT(whichfork);
 
2930
        } else
 
2931
                ASSERT(XFS_IFORK_NEXTENTS(ip, whichfork) == 0);
 
2932
        ifp->if_flags &= ~XFS_IFINLINE;
 
2933
        ifp->if_flags |= XFS_IFEXTENTS;
 
2934
        XFS_IFORK_FMT_SET(ip, whichfork, XFS_DINODE_FMT_EXTENTS);
 
2935
        flags |= XFS_ILOG_CORE;
 
2936
done:
 
2937
        *logflagsp = flags;
 
2938
        return error;
 
2939
}
 
2940
 
 
2941
xfs_bmbt_rec_t *                        /* pointer to found extent entry */
 
2942
xfs_bmap_do_search_extents(
 
2943
        xfs_bmbt_rec_t  *base,          /* base of extent list */
 
2944
        xfs_extnum_t    lastx,          /* last extent index used */
 
2945
        xfs_extnum_t    nextents,       /* extent list size */
 
2946
        xfs_fileoff_t   bno,            /* block number searched for */
 
2947
        int             *eofp,          /* out: end of file found */
 
2948
        xfs_extnum_t    *lastxp,        /* out: last extent index */
 
2949
        xfs_bmbt_irec_t *gotp,          /* out: extent entry found */
 
2950
        xfs_bmbt_irec_t *prevp)         /* out: previous extent entry found */
 
2951
{
 
2952
        xfs_bmbt_rec_t  *ep;            /* extent list entry pointer */
 
2953
        xfs_bmbt_irec_t got;            /* extent list entry, decoded */
 
2954
        int             high;           /* high index of binary search */
 
2955
        int             low;            /* low index of binary search */
 
2956
 
 
2957
        if (lastx != NULLEXTNUM && lastx < nextents)
 
2958
                ep = base + lastx;
 
2959
        else
 
2960
                ep = NULL;
 
2961
        prevp->br_startoff = NULLFILEOFF;
 
2962
        if (ep && bno >= (got.br_startoff = xfs_bmbt_get_startoff(ep)) &&
 
2963
            bno < got.br_startoff +
 
2964
                  (got.br_blockcount = xfs_bmbt_get_blockcount(ep)))
 
2965
                *eofp = 0;
 
2966
        else if (ep && lastx < nextents - 1 &&
 
2967
                 bno >= (got.br_startoff = xfs_bmbt_get_startoff(ep + 1)) &&
 
2968
                 bno < got.br_startoff +
 
2969
                       (got.br_blockcount = xfs_bmbt_get_blockcount(ep + 1))) {
 
2970
                lastx++;
 
2971
                ep++;
 
2972
                *eofp = 0;
 
2973
        } else if (nextents == 0)
 
2974
                *eofp = 1;
 
2975
        else if (bno == 0 &&
 
2976
                 (got.br_startoff = xfs_bmbt_get_startoff(base)) == 0) {
 
2977
                ep = base;
 
2978
                lastx = 0;
 
2979
                got.br_blockcount = xfs_bmbt_get_blockcount(ep);
 
2980
                *eofp = 0;
 
2981
        } else {
 
2982
                /* binary search the extents array */
 
2983
                low = 0;
 
2984
                high = nextents - 1;
 
2985
                while (low <= high) {
 
2986
                        XFS_STATS_INC(xfsstats.xs_cmp_exlist);
 
2987
                        lastx = (low + high) >> 1;
 
2988
                        ep = base + lastx;
 
2989
                        got.br_startoff = xfs_bmbt_get_startoff(ep);
 
2990
                        got.br_blockcount = xfs_bmbt_get_blockcount(ep);
 
2991
                        if (bno < got.br_startoff)
 
2992
                                high = lastx - 1;
 
2993
                        else if (bno >= got.br_startoff + got.br_blockcount)
 
2994
                                low = lastx + 1;
 
2995
                        else {
 
2996
                                got.br_startblock = xfs_bmbt_get_startblock(ep);
 
2997
                                got.br_state = xfs_bmbt_get_state(ep);
 
2998
                                *eofp = 0;
 
2999
                                *lastxp = lastx;
 
3000
                                *gotp = got;
 
3001
                                return ep;
 
3002
                        }
 
3003
                }
 
3004
                if (bno >= got.br_startoff + got.br_blockcount) {
 
3005
                        lastx++;
 
3006
                        if (lastx == nextents) {
 
3007
                                *eofp = 1;
 
3008
                                got.br_startblock = xfs_bmbt_get_startblock(ep);
 
3009
                                got.br_state = xfs_bmbt_get_state(ep);
 
3010
                                *prevp = got;
 
3011
                                ep = NULL;
 
3012
                        } else {
 
3013
                                *eofp = 0;
 
3014
                                xfs_bmbt_get_all(ep, prevp);
 
3015
                                ep++;
 
3016
                                got.br_startoff = xfs_bmbt_get_startoff(ep);
 
3017
                                got.br_blockcount = xfs_bmbt_get_blockcount(ep);
 
3018
                        }
 
3019
                } else {
 
3020
                        *eofp = 0;
 
3021
                        if (ep > base)
 
3022
                                xfs_bmbt_get_all(ep - 1, prevp);
 
3023
                }
 
3024
        }
 
3025
        if (ep) {
 
3026
                got.br_startblock = xfs_bmbt_get_startblock(ep);
 
3027
                got.br_state = xfs_bmbt_get_state(ep);
 
3028
        }
 
3029
        *lastxp = lastx;
 
3030
        *gotp = got;
 
3031
        return ep;
 
3032
}
 
3033
 
 
3034
/*
 
3035
 * Search the extents list for the inode, for the extent containing bno.
 
3036
 * If bno lies in a hole, point to the next entry.  If bno lies past eof,
 
3037
 * *eofp will be set, and *prevp will contain the last entry (null if none).
 
3038
 * Else, *lastxp will be set to the index of the found
 
3039
 * entry; *gotp will contain the entry.
 
3040
 */
 
3041
STATIC xfs_bmbt_rec_t *                 /* pointer to found extent entry */
 
3042
xfs_bmap_search_extents(
 
3043
        xfs_inode_t     *ip,            /* incore inode pointer */
 
3044
        xfs_fileoff_t   bno,            /* block number searched for */
 
3045
        int             whichfork,      /* data or attr fork */
 
3046
        int             *eofp,          /* out: end of file found */
 
3047
        xfs_extnum_t    *lastxp,        /* out: last extent index */
 
3048
        xfs_bmbt_irec_t *gotp,          /* out: extent entry found */
 
3049
        xfs_bmbt_irec_t *prevp)         /* out: previous extent entry found */
 
3050
 
3051
        xfs_ifork_t     *ifp;           /* inode fork pointer */
 
3052
        xfs_bmbt_rec_t  *base;          /* base of extent list */
 
3053
        xfs_extnum_t    lastx;          /* last extent index used */
 
3054
        xfs_extnum_t    nextents;       /* extent list size */
 
3055
 
 
3056
        XFS_STATS_INC(xfsstats.xs_look_exlist);
 
3057
        ifp = XFS_IFORK_PTR(ip, whichfork);
 
3058
        lastx = ifp->if_lastex;
 
3059
        nextents = ifp->if_bytes / (uint)sizeof(xfs_bmbt_rec_t);
 
3060
        base = &ifp->if_u1.if_extents[0];
 
3061
 
 
3062
        return xfs_bmap_do_search_extents(base, lastx, nextents, bno, eofp,
 
3063
                                          lastxp, gotp, prevp);
 
3064
}
 
3065
 
 
3066
/*
 
3067
 * Compute the worst-case number of indirect blocks that will be used
 
3068
 * for ip's delayed extent of length "len".
 
3069
 */
 
3070
STATIC xfs_filblks_t
 
3071
xfs_bmap_worst_indlen(
 
3072
        xfs_inode_t     *ip,            /* incore inode pointer */
 
3073
        xfs_filblks_t   len)            /* delayed extent length */
 
3074
{
 
3075
        int             level;          /* btree level number */
 
3076
        int             maxrecs;        /* maximum record count at this level */
 
3077
        xfs_mount_t     *mp;            /* mount structure */
 
3078
        xfs_filblks_t   rval;           /* return value */
 
3079
 
 
3080
        mp = ip->i_mount;
 
3081
        maxrecs = mp->m_bmap_dmxr[0];
 
3082
        for (level = 0, rval = 0;
 
3083
             level < XFS_BM_MAXLEVELS(mp, XFS_DATA_FORK);
 
3084
             level++) {
 
3085
                len += maxrecs - 1;
 
3086
                do_div(len, maxrecs);
 
3087
                rval += len;
 
3088
                if (len == 1)
 
3089
                        return rval + XFS_BM_MAXLEVELS(mp, XFS_DATA_FORK) -
 
3090
                                level - 1;
 
3091
                if (level == 0)
 
3092
                        maxrecs = mp->m_bmap_dmxr[1];
 
3093
        }
 
3094
        return rval;
 
3095
}
 
3096
 
 
3097
/*
 
3098
 * Add the extent to the list of extents to be free at transaction end.
 
3099
 * The list is maintained sorted (by block number).
 
3100
 */
 
3101
/* ARGSUSED */
 
3102
void
 
3103
xfs_bmap_add_free(
 
3104
        xfs_fsblock_t           bno,            /* fs block number of extent */
 
3105
        xfs_filblks_t           len,            /* length of extent */
 
3106
        xfs_bmap_free_t         *flist,         /* list of extents */
 
3107
        xfs_mount_t             *mp)            /* mount point structure */
 
3108
{
 
3109
        xfs_bmap_free_item_t    *cur;           /* current (next) element */
 
3110
        xfs_bmap_free_item_t    *new;           /* new element */
 
3111
        xfs_bmap_free_item_t    *prev;          /* previous element */
 
3112
#ifdef DEBUG
 
3113
        xfs_agnumber_t          agno;
 
3114
        xfs_agblock_t           agbno;
 
3115
 
 
3116
        ASSERT(bno != NULLFSBLOCK);
 
3117
        ASSERT(len > 0);
 
3118
        ASSERT(len <= MAXEXTLEN);
 
3119
        ASSERT(!ISNULLSTARTBLOCK(bno));
 
3120
        agno = XFS_FSB_TO_AGNO(mp, bno);
 
3121
        agbno = XFS_FSB_TO_AGBNO(mp, bno);
 
3122
        ASSERT(agno < mp->m_sb.sb_agcount);
 
3123
        ASSERT(agbno < mp->m_sb.sb_agblocks);
 
3124
        ASSERT(len < mp->m_sb.sb_agblocks);
 
3125
        ASSERT(agbno + len <= mp->m_sb.sb_agblocks);
 
3126
#endif
 
3127
        ASSERT(xfs_bmap_free_item_zone != NULL);
 
3128
        new = kmem_zone_alloc(xfs_bmap_free_item_zone, KM_SLEEP);
 
3129
        new->xbfi_startblock = bno;
 
3130
        new->xbfi_blockcount = (xfs_extlen_t)len;
 
3131
        for (prev = NULL, cur = flist->xbf_first;
 
3132
             cur != NULL;
 
3133
             prev = cur, cur = cur->xbfi_next) {
 
3134
                if (cur->xbfi_startblock >= bno)
 
3135
                        break;
 
3136
        }
 
3137
        if (prev)
 
3138
                prev->xbfi_next = new;
 
3139
        else
 
3140
                flist->xbf_first = new;
 
3141
        new->xbfi_next = cur;
 
3142
        flist->xbf_count++;
 
3143
}
 
3144
 
 
3145
/* 
 
3146
 * Compute and fill in the value of the maximum depth of a bmap btree
 
3147
 * in this filesystem.  Done once, during mount.
 
3148
 */
 
3149
void
 
3150
xfs_bmap_compute_maxlevels(
 
3151
        xfs_mount_t     *mp,            /* file system mount structure */
 
3152
        int             whichfork)      /* data or attr fork */
 
3153
{
 
3154
        int             level;          /* btree level */
 
3155
        uint            maxblocks;      /* max blocks at this level */
 
3156
        uint            maxleafents;    /* max leaf entries possible */
 
3157
        int             maxrootrecs;    /* max records in root block */
 
3158
        int             minleafrecs;    /* min records in leaf block */
 
3159
        int             minnoderecs;    /* min records in node block */
 
3160
        int             sz;             /* root block size */
 
3161
 
 
3162
        /*
 
3163
         * The maximum number of extents in a file, hence the maximum
 
3164
         * number of leaf entries, is controlled by the type of di_nextents
 
3165
         * (a signed 32-bit number, xfs_extnum_t), or by di_anextents
 
3166
         * (a signed 16-bit number, xfs_aextnum_t).
 
3167
         */
 
3168
        maxleafents = (whichfork == XFS_DATA_FORK) ? MAXEXTNUM : MAXAEXTNUM;
 
3169
        minleafrecs = mp->m_bmap_dmnr[0];
 
3170
        minnoderecs = mp->m_bmap_dmnr[1];
 
3171
        sz = (whichfork == XFS_DATA_FORK) ?
 
3172
                mp->m_attroffset :
 
3173
                mp->m_sb.sb_inodesize - mp->m_attroffset;
 
3174
        maxrootrecs = (int)XFS_BTREE_BLOCK_MAXRECS(sz, xfs_bmdr, 0);
 
3175
        maxblocks = (maxleafents + minleafrecs - 1) / minleafrecs;
 
3176
        for (level = 1; maxblocks > 1; level++) {
 
3177
                if (maxblocks <= maxrootrecs)
 
3178
                        maxblocks = 1;
 
3179
                else
 
3180
                        maxblocks = (maxblocks + minnoderecs - 1) / minnoderecs;
 
3181
        }
 
3182
        mp->m_bm_maxlevels[whichfork] = level;
 
3183
}
 
3184
 
 
3185
/*
 
3186
 * Returns the file-relative block number of the first unused block(s)
 
3187
 * in the file with at least "len" logically contiguous blocks free.
 
3188
 * This is the lowest-address hole if the file has holes, else the first block
 
3189
 * past the end of file.
 
3190
 * Return 0 if the file is currently local (in-inode).
 
3191
 */
 
3192
int                                             /* error */
 
3193
xfs_bmap_first_unused(
 
3194
        xfs_trans_t     *tp,                    /* transaction pointer */
 
3195
        xfs_inode_t     *ip,                    /* incore inode */
 
3196
        xfs_extlen_t    len,                    /* size of hole to find */
 
3197
        xfs_fileoff_t   *first_unused,          /* unused block */
 
3198
        int             whichfork)              /* data or attr fork */
 
3199
{
 
3200
        xfs_bmbt_rec_t  *base;                  /* base of extent array */
 
3201
        xfs_bmbt_rec_t  *ep;                    /* pointer to an extent entry */
 
3202
        int             error;                  /* error return value */
 
3203
        xfs_ifork_t     *ifp;                   /* inode fork pointer */
 
3204
        xfs_fileoff_t   lastaddr;               /* last block number seen */
 
3205
        xfs_fileoff_t   lowest;                 /* lowest useful block */
 
3206
        xfs_fileoff_t   max;                    /* starting useful block */
 
3207
        xfs_fileoff_t   off;                    /* offset for this block */
 
3208
        xfs_extnum_t    nextents;               /* number of extent entries */
 
3209
 
 
3210
        ASSERT(XFS_IFORK_FORMAT(ip, whichfork) == XFS_DINODE_FMT_BTREE ||
 
3211
               XFS_IFORK_FORMAT(ip, whichfork) == XFS_DINODE_FMT_EXTENTS ||
 
3212
               XFS_IFORK_FORMAT(ip, whichfork) == XFS_DINODE_FMT_LOCAL);
 
3213
        if (XFS_IFORK_FORMAT(ip, whichfork) == XFS_DINODE_FMT_LOCAL) {
 
3214
                *first_unused = 0;
 
3215
                return 0;
 
3216
        }
 
3217
        ifp = XFS_IFORK_PTR(ip, whichfork);
 
3218
        if (!(ifp->if_flags & XFS_IFEXTENTS) &&
 
3219
            (error = xfs_iread_extents(tp, ip, whichfork)))
 
3220
                return error;
 
3221
        lowest = *first_unused;
 
3222
        nextents = ifp->if_bytes / (uint)sizeof(xfs_bmbt_rec_t);
 
3223
        base = &ifp->if_u1.if_extents[0];
 
3224
        for (lastaddr = 0, max = lowest, ep = base;
 
3225
             ep < &base[nextents];
 
3226
             ep++) {
 
3227
                off = xfs_bmbt_get_startoff(ep);
 
3228
                /*
 
3229
                 * See if the hole before this extent will work.
 
3230
                 */
 
3231
                if (off >= lowest + len && off - max >= len) {
 
3232
                        *first_unused = max;
 
3233
                        return 0;
 
3234
                }
 
3235
                lastaddr = off + xfs_bmbt_get_blockcount(ep);
 
3236
                max = XFS_FILEOFF_MAX(lastaddr, lowest);
 
3237
        }
 
3238
        *first_unused = max;
 
3239
        return 0;
 
3240
}
 
3241
 
 
3242
/*
 
3243
 * Returns the file-relative block number of the last block + 1 before
 
3244
 * last_block (input value) in the file.
 
3245
 * This is not based on i_size, it is based on the extent list.
 
3246
 * Returns 0 for local files, as they do not have an extent list.
 
3247
 */
 
3248
int                                             /* error */
 
3249
xfs_bmap_last_before(
 
3250
        xfs_trans_t     *tp,                    /* transaction pointer */
 
3251
        xfs_inode_t     *ip,                    /* incore inode */
 
3252
        xfs_fileoff_t   *last_block,            /* last block */
 
3253
        int             whichfork)              /* data or attr fork */
 
3254
{
 
3255
        xfs_fileoff_t   bno;                    /* input file offset */
 
3256
        int             eof;                    /* hit end of file */
 
3257
        xfs_bmbt_rec_t  *ep;                    /* pointer to last extent */
 
3258
        int             error;                  /* error return value */
 
3259
        xfs_bmbt_irec_t got;                    /* current extent value */
 
3260
        xfs_ifork_t     *ifp;                   /* inode fork pointer */
 
3261
        xfs_extnum_t    lastx;                  /* last extent used */
 
3262
        xfs_bmbt_irec_t prev;                   /* previous extent value */
 
3263
 
 
3264
        if (XFS_IFORK_FORMAT(ip, whichfork) != XFS_DINODE_FMT_BTREE &&
 
3265
            XFS_IFORK_FORMAT(ip, whichfork) != XFS_DINODE_FMT_EXTENTS &&
 
3266
            XFS_IFORK_FORMAT(ip, whichfork) != XFS_DINODE_FMT_LOCAL)
 
3267
               return XFS_ERROR(EIO);
 
3268
        if (XFS_IFORK_FORMAT(ip, whichfork) == XFS_DINODE_FMT_LOCAL) {
 
3269
                *last_block = 0;
 
3270
                return 0;
 
3271
        }
 
3272
        ifp = XFS_IFORK_PTR(ip, whichfork);
 
3273
        if (!(ifp->if_flags & XFS_IFEXTENTS) &&
 
3274
            (error = xfs_iread_extents(tp, ip, whichfork)))
 
3275
                return error;
 
3276
        bno = *last_block - 1;
 
3277
        ep = xfs_bmap_search_extents(ip, bno, whichfork, &eof, &lastx, &got,
 
3278
                &prev);
 
3279
        if (eof || xfs_bmbt_get_startoff(ep) > bno) {
 
3280
                if (prev.br_startoff == NULLFILEOFF)
 
3281
                        *last_block = 0;
 
3282
                else
 
3283
                        *last_block = prev.br_startoff + prev.br_blockcount;
 
3284
        }
 
3285
        /*
 
3286
         * Otherwise *last_block is already the right answer.
 
3287
         */
 
3288
        return 0;
 
3289
}
 
3290
 
 
3291
/*
 
3292
 * Returns the file-relative block number of the first block past eof in
 
3293
 * the file.  This is not based on i_size, it is based on the extent list.
 
3294
 * Returns 0 for local files, as they do not have an extent list.
 
3295
 */
 
3296
int                                             /* error */
 
3297
xfs_bmap_last_offset(
 
3298
        xfs_trans_t     *tp,                    /* transaction pointer */
 
3299
        xfs_inode_t     *ip,                    /* incore inode */
 
3300
        xfs_fileoff_t   *last_block,            /* last block */
 
3301
        int             whichfork)              /* data or attr fork */
 
3302
{
 
3303
        xfs_bmbt_rec_t  *base;                  /* base of extent array */
 
3304
        xfs_bmbt_rec_t  *ep;                    /* pointer to last extent */
 
3305
        int             error;                  /* error return value */
 
3306
        xfs_ifork_t     *ifp;                   /* inode fork pointer */
 
3307
        xfs_extnum_t    nextents;               /* number of extent entries */
 
3308
 
 
3309
        if (XFS_IFORK_FORMAT(ip, whichfork) != XFS_DINODE_FMT_BTREE &&
 
3310
            XFS_IFORK_FORMAT(ip, whichfork) != XFS_DINODE_FMT_EXTENTS &&
 
3311
            XFS_IFORK_FORMAT(ip, whichfork) != XFS_DINODE_FMT_LOCAL)
 
3312
               return XFS_ERROR(EIO);
 
3313
        if (XFS_IFORK_FORMAT(ip, whichfork) == XFS_DINODE_FMT_LOCAL) {
 
3314
                *last_block = 0;
 
3315
                return 0;
 
3316
        }
 
3317
        ifp = XFS_IFORK_PTR(ip, whichfork);
 
3318
        if (!(ifp->if_flags & XFS_IFEXTENTS) &&
 
3319
            (error = xfs_iread_extents(tp, ip, whichfork)))
 
3320
                return error;
 
3321
        nextents = ifp->if_bytes / (uint)sizeof(xfs_bmbt_rec_t);
 
3322
        if (!nextents) {
 
3323
                *last_block = 0;
 
3324
                return 0;
 
3325
        }
 
3326
        base = &ifp->if_u1.if_extents[0];
 
3327
        ASSERT(base != NULL);
 
3328
        ep = &base[nextents - 1];
 
3329
        *last_block = xfs_bmbt_get_startoff(ep) + xfs_bmbt_get_blockcount(ep);
 
3330
        return 0;
 
3331
}
 
3332
 
 
3333
/*
 
3334
 * Returns whether the selected fork of the inode has exactly one
 
3335
 * block or not.  For the data fork we check this matches di_size,
 
3336
 * implying the file's range is 0..bsize-1.
 
3337
 */
 
3338
int                                     /* 1=>1 block, 0=>otherwise */
 
3339
xfs_bmap_one_block(
 
3340
        xfs_inode_t     *ip,            /* incore inode */
 
3341
        int             whichfork)      /* data or attr fork */
 
3342
{
 
3343
        xfs_bmbt_rec_t  *ep;            /* ptr to fork's extent */
 
3344
        xfs_ifork_t     *ifp;           /* inode fork pointer */
 
3345
        int             rval;           /* return value */
 
3346
        xfs_bmbt_irec_t s;              /* internal version of extent */
 
3347
 
 
3348
#ifndef DEBUG
 
3349
        if (whichfork == XFS_DATA_FORK)
 
3350
                return ip->i_d.di_size == ip->i_mount->m_sb.sb_blocksize;
 
3351
#endif  /* !DEBUG */
 
3352
        if (XFS_IFORK_NEXTENTS(ip, whichfork) != 1)
 
3353
                return 0;
 
3354
        if (XFS_IFORK_FORMAT(ip, whichfork) != XFS_DINODE_FMT_EXTENTS)
 
3355
                return 0;
 
3356
        ifp = XFS_IFORK_PTR(ip, whichfork);
 
3357
        ASSERT(ifp->if_flags & XFS_IFEXTENTS);
 
3358
        ep = ifp->if_u1.if_extents;
 
3359
        xfs_bmbt_get_all(ep, &s);
 
3360
        rval = s.br_startoff == 0 && s.br_blockcount == 1;
 
3361
        if (rval && whichfork == XFS_DATA_FORK)
 
3362
                ASSERT(ip->i_d.di_size == ip->i_mount->m_sb.sb_blocksize);
 
3363
        return rval;
 
3364
}
 
3365
 
 
3366
/*
 
3367
 * Read in the extents to if_extents.
 
3368
 * All inode fields are set up by caller, we just traverse the btree
 
3369
 * and copy the records in. If the file system cannot contain unwritten
 
3370
 * extents, the records are checked for no "state" flags.
 
3371
 */
 
3372
int                                     /* error */
 
3373
xfs_bmap_read_extents(
 
3374
        xfs_trans_t             *tp,    /* transaction pointer */
 
3375
        xfs_inode_t             *ip,    /* incore inode */
 
3376
        int                     whichfork) /* data or attr fork */
 
3377
{
 
3378
        xfs_bmbt_block_t        *block; /* current btree block */
 
3379
        xfs_fsblock_t           bno;    /* block # of "block" */
 
3380
        xfs_buf_t               *bp;    /* buffer for "block" */
 
3381
        int                     error;  /* error return value */
 
3382
        xfs_exntfmt_t           exntf;  /* XFS_EXTFMT_NOSTATE, if checking */
 
3383
#ifdef XFS_BMAP_TRACE
 
3384
        static char             fname[] = "xfs_bmap_read_extents";
 
3385
#endif
 
3386
        xfs_extnum_t            i;      /* index into the extents list */
 
3387
        xfs_ifork_t             *ifp;   /* fork structure */
 
3388
        int                     level;  /* btree level, for checking */
 
3389
        xfs_mount_t             *mp;    /* file system mount structure */
 
3390
        xfs_bmbt_ptr_t          *pp;    /* pointer to block address */
 
3391
        /* REFERENCED */
 
3392
        xfs_extnum_t            room;   /* number of entries there's room for */
 
3393
        xfs_bmbt_rec_t          *trp;   /* target record pointer */
 
3394
 
 
3395
        bno = NULLFSBLOCK;
 
3396
        mp = ip->i_mount;
 
3397
        ifp = XFS_IFORK_PTR(ip, whichfork);
 
3398
        exntf = (whichfork != XFS_DATA_FORK) ? XFS_EXTFMT_NOSTATE :
 
3399
                                        XFS_EXTFMT_INODE(ip);
 
3400
        block = ifp->if_broot;
 
3401
        /*
 
3402
         * Root level must use BMAP_BROOT_PTR_ADDR macro to get ptr out.
 
3403
         */
 
3404
        ASSERT(INT_GET(block->bb_level, ARCH_CONVERT) > 0);
 
3405
        level = INT_GET(block->bb_level, ARCH_CONVERT);
 
3406
        pp = XFS_BMAP_BROOT_PTR_ADDR(block, 1, ifp->if_broot_bytes);
 
3407
        ASSERT(INT_GET(*pp, ARCH_CONVERT) != NULLDFSBNO);
 
3408
        ASSERT(XFS_FSB_TO_AGNO(mp, INT_GET(*pp, ARCH_CONVERT)) < mp->m_sb.sb_agcount);
 
3409
        ASSERT(XFS_FSB_TO_AGBNO(mp, INT_GET(*pp, ARCH_CONVERT)) < mp->m_sb.sb_agblocks);
 
3410
        bno = INT_GET(*pp, ARCH_CONVERT);
 
3411
        /*
 
3412
         * Go down the tree until leaf level is reached, following the first
 
3413
         * pointer (leftmost) at each level.
 
3414
         */
 
3415
        while (level-- > 0) {
 
3416
                if ((error = xfs_btree_read_bufl(mp, tp, bno, 0, &bp,
 
3417
                                XFS_BMAP_BTREE_REF)))
 
3418
                        return error;
 
3419
                block = XFS_BUF_TO_BMBT_BLOCK(bp);
 
3420
                XFS_WANT_CORRUPTED_GOTO(
 
3421
                        XFS_BMAP_SANITY_CHECK(mp, block, level),
 
3422
                        error0);
 
3423
                if (level == 0)
 
3424
                        break;
 
3425
                pp = XFS_BTREE_PTR_ADDR(mp->m_sb.sb_blocksize, xfs_bmbt, block,
 
3426
                        1, mp->m_bmap_dmxr[1]);
 
3427
#ifndef __KERNEL__
 
3428
                XFS_WANT_CORRUPTED_GOTO(
 
3429
                        XFS_FSB_SANITY_CHECK(mp, INT_GET(*pp, ARCH_CONVERT)),
 
3430
                        error0);
 
3431
#else   /* additional, temporary, debugging code */
 
3432
                if (!(XFS_FSB_SANITY_CHECK(mp, INT_GET(*pp, ARCH_CONVERT)))) {
 
3433
                        cmn_err(CE_NOTE,
 
3434
                        "xfs_bmap_read_extents: FSB Sanity Check:");
 
3435
                        if (!(XFS_FSB_TO_AGNO(mp, INT_GET(*pp, ARCH_CONVERT)) < mp->m_sb.sb_agcount))
 
3436
                                cmn_err(CE_NOTE,
 
3437
                                        "bad AG count %d < agcount %d",
 
3438
                                        XFS_FSB_TO_AGNO(mp, INT_GET(*pp, ARCH_CONVERT)),
 
3439
                                        mp->m_sb.sb_agcount);
 
3440
                        if (!(XFS_FSB_TO_AGBNO(mp, INT_GET(*pp, ARCH_CONVERT)) < mp->m_sb.sb_agblocks))
 
3441
                                cmn_err(CE_NOTE,
 
3442
                                        "bad AG BNO %d < %d",
 
3443
                                        XFS_FSB_TO_AGBNO(mp, INT_GET(*pp, ARCH_CONVERT)),
 
3444
                                        mp->m_sb.sb_agblocks);
 
3445
                        error = XFS_ERROR(EFSCORRUPTED);
 
3446
                        goto error0;
 
3447
                }
 
3448
#endif
 
3449
                bno = INT_GET(*pp, ARCH_CONVERT);
 
3450
                xfs_trans_brelse(tp, bp);
 
3451
        }
 
3452
        /*
 
3453
         * Here with bp and block set to the leftmost leaf node in the tree.
 
3454
         */
 
3455
        room = ifp->if_bytes / (uint)sizeof(*trp);
 
3456
        trp = ifp->if_u1.if_extents;
 
3457
        i = 0;
 
3458
        /*
 
3459
         * Loop over all leaf nodes.  Copy information to the extent list.
 
3460
         */
 
3461
        for (;;) {
 
3462
                xfs_bmbt_rec_t  *frp;
 
3463
                xfs_fsblock_t   nextbno;
 
3464
                xfs_extnum_t    num_recs;
 
3465
 
 
3466
 
 
3467
                num_recs = INT_GET(block->bb_numrecs, ARCH_CONVERT);
 
3468
                if (i + num_recs > room) {
 
3469
                        ASSERT(i + num_recs <= room);
 
3470
                        xfs_fs_cmn_err(CE_WARN, ip->i_mount,
 
3471
                                "corrupt dinode %Lu, (btree extents).  "
 
3472
                                "Unmount and run xfs_repair.",
 
3473
                                (unsigned long long) ip->i_ino);
 
3474
                        goto error0;
 
3475
                }
 
3476
#ifndef __KERNEL__
 
3477
                XFS_WANT_CORRUPTED_GOTO(
 
3478
                        XFS_BMAP_SANITY_CHECK(mp, block, 0),
 
3479
                        error0);
 
3480
#else   /* additional, temporary, debugging code */
 
3481
                if (!(XFS_BMAP_SANITY_CHECK(mp, block, 0))) {
 
3482
                        cmn_err(CE_NOTE,
 
3483
                        "xfs_bmap_read_extents: BMAP Sanity Check:");
 
3484
                        if (!(INT_GET(block->bb_magic, ARCH_CONVERT) == XFS_BMAP_MAGIC))
 
3485
                                cmn_err(CE_NOTE,
 
3486
                                        "bb_magic 0x%x",
 
3487
                                        INT_GET(block->bb_magic, ARCH_CONVERT));
 
3488
                        if (!(INT_GET(block->bb_level, ARCH_CONVERT) == level))
 
3489
                                cmn_err(CE_NOTE,
 
3490
                                        "bb_level %d",
 
3491
                                        INT_GET(block->bb_level, ARCH_CONVERT));
 
3492
                        if (!(INT_GET(block->bb_numrecs, ARCH_CONVERT) > 0))
 
3493
                                cmn_err(CE_NOTE,
 
3494
                                        "bb_numrecs %d",
 
3495
                                        INT_GET(block->bb_numrecs, ARCH_CONVERT));
 
3496
                        if (!(INT_GET(block->bb_numrecs, ARCH_CONVERT) <= (mp)->m_bmap_dmxr[(level) != 0]))
 
3497
                                cmn_err(CE_NOTE,
 
3498
                                        "bb_numrecs %d < m_bmap_dmxr[] %d",
 
3499
                                        INT_GET(block->bb_numrecs, ARCH_CONVERT),
 
3500
                                        (mp)->m_bmap_dmxr[(level) != 0]);
 
3501
                        error = XFS_ERROR(EFSCORRUPTED);
 
3502
                        goto error0;
 
3503
                }
 
3504
#endif
 
3505
                /*
 
3506
                 * Read-ahead the next leaf block, if any.
 
3507
                 */
 
3508
                nextbno = INT_GET(block->bb_rightsib, ARCH_CONVERT);
 
3509
                if (nextbno != NULLFSBLOCK)
 
3510
                        xfs_btree_reada_bufl(mp, nextbno, 1);
 
3511
                /*
 
3512
                 * Copy records into the extent list.
 
3513
                 */
 
3514
                frp = XFS_BTREE_REC_ADDR(mp->m_sb.sb_blocksize, xfs_bmbt,
 
3515
                        block, 1, mp->m_bmap_dmxr[0]);
 
3516
                bcopy(frp, trp, num_recs * sizeof(*frp));
 
3517
                if (exntf == XFS_EXTFMT_NOSTATE) {
 
3518
                        /*
 
3519
                         * Check all attribute bmap btree records and
 
3520
                         * any "older" data bmap btree records for a 
 
3521
                         * set bit in the "extent flag" position.
 
3522
                         */
 
3523
                        if (xfs_check_nostate_extents(trp, num_recs)) {
 
3524
                                goto error0;
 
3525
                        }
 
3526
                }
 
3527
                trp += num_recs;
 
3528
                i += num_recs;
 
3529
                xfs_trans_brelse(tp, bp);
 
3530
                bno = nextbno;
 
3531
                /*
 
3532
                 * If we've reached the end, stop.
 
3533
                 */
 
3534
                if (bno == NULLFSBLOCK)
 
3535
                        break;
 
3536
                if ((error = xfs_btree_read_bufl(mp, tp, bno, 0, &bp,
 
3537
                                XFS_BMAP_BTREE_REF)))
 
3538
                        return error;
 
3539
                block = XFS_BUF_TO_BMBT_BLOCK(bp);
 
3540
        }
 
3541
        ASSERT(i == ifp->if_bytes / (uint)sizeof(*trp));
 
3542
        ASSERT(i == XFS_IFORK_NEXTENTS(ip, whichfork));
 
3543
        xfs_bmap_trace_exlist(fname, ip, i, whichfork);
 
3544
        return 0;
 
3545
error0:
 
3546
        xfs_trans_brelse(tp, bp);
 
3547
        return XFS_ERROR(EFSCORRUPTED);
 
3548
}
 
3549
 
 
3550
/*
 
3551
 * Map file blocks to filesystem blocks.
 
3552
 * File range is given by the bno/len pair.
 
3553
 * Adds blocks to file if a write ("flags & XFS_BMAPI_WRITE" set)
 
3554
 * into a hole or past eof.
 
3555
 * Only allocates blocks from a single allocation group,
 
3556
 * to avoid locking problems.
 
3557
 * The returned value in "firstblock" from the first call in a transaction
 
3558
 * must be remembered and presented to subsequent calls in "firstblock".
 
3559
 * An upper bound for the number of blocks to be allocated is supplied to
 
3560
 * the first call in "total"; if no allocation group has that many free
 
3561
 * blocks then the call will fail (return NULLFSBLOCK in "firstblock").
 
3562
 */
 
3563
int                                     /* error */
 
3564
xfs_bmapi(
 
3565
        xfs_trans_t     *tp,            /* transaction pointer */
 
3566
        xfs_inode_t     *ip,            /* incore inode */
 
3567
        xfs_fileoff_t   bno,            /* starting file offs. mapped */
 
3568
        xfs_filblks_t   len,            /* length to map in file */
 
3569
        int             flags,          /* XFS_BMAPI_... */
 
3570
        xfs_fsblock_t   *firstblock,    /* first allocated block
 
3571
                                           controls a.g. for allocs */
 
3572
        xfs_extlen_t    total,          /* total blocks needed */
 
3573
        xfs_bmbt_irec_t *mval,          /* output: map values */
 
3574
        int             *nmap,          /* i/o: mval size/count */
 
3575
        xfs_bmap_free_t *flist)         /* i/o: list extents to free */
 
3576
{
 
3577
        xfs_fsblock_t   abno;           /* allocated block number */
 
3578
        xfs_extlen_t    alen;           /* allocated extent length */
 
3579
        xfs_fileoff_t   aoff;           /* allocated file offset */
 
3580
        xfs_bmalloca_t  bma;            /* args for xfs_bmap_alloc */
 
3581
        int             contig;         /* allocation must be one extent */
 
3582
        xfs_btree_cur_t *cur;           /* bmap btree cursor */
 
3583
        char            delay;          /* this request is for delayed alloc */
 
3584
        xfs_fileoff_t   end;            /* end of mapped file region */
 
3585
        int             eof;            /* we've hit the end of extent list */
 
3586
        xfs_bmbt_rec_t  *ep;            /* extent list entry pointer */
 
3587
        int             error;          /* error return */
 
3588
        char            exact;          /* don't do all of wasdelayed extent */
 
3589
        xfs_bmbt_irec_t got;            /* current extent list record */
 
3590
        xfs_ifork_t     *ifp;           /* inode fork pointer */
 
3591
        xfs_extlen_t    indlen;         /* indirect blocks length */
 
3592
        char            inhole;         /* current location is hole in file */
 
3593
        xfs_extnum_t    lastx;          /* last useful extent number */
 
3594
        int             logflags;       /* flags for transaction logging */
 
3595
        xfs_extlen_t    minleft;        /* min blocks left after allocation */
 
3596
        xfs_extlen_t    minlen;         /* min allocation size */
 
3597
        xfs_mount_t     *mp;            /* xfs mount structure */
 
3598
        int             n;              /* current extent index */
 
3599
        int             nallocs;        /* number of extents alloc\'d */
 
3600
        xfs_extnum_t    nextents;       /* number of extents in file */
 
3601
        xfs_fileoff_t   obno;           /* old block number (offset) */
 
3602
        xfs_bmbt_irec_t prev;           /* previous extent list record */
 
3603
        int             stateless;      /* ignore state flag set */
 
3604
        int             tmp_logflags;   /* temp flags holder */
 
3605
        char            trim;           /* output trimmed to match range */
 
3606
        char            userdata;       /* allocating non-metadata */
 
3607
        char            wasdelay;       /* old extent was delayed */
 
3608
        int             whichfork;      /* data or attr fork */
 
3609
        char            wr;             /* this is a write request */
 
3610
        int             rsvd;           /* OK to allocate reserved blocks */
 
3611
#ifdef DEBUG
 
3612
        xfs_fileoff_t   orig_bno;       /* original block number value */
 
3613
        int             orig_flags;     /* original flags arg value */
 
3614
        xfs_filblks_t   orig_len;       /* original value of len arg */
 
3615
        xfs_bmbt_irec_t *orig_mval;     /* original value of mval */
 
3616
        int             orig_nmap;      /* original value of *nmap */
 
3617
 
 
3618
        orig_bno = bno;
 
3619
        orig_len = len;
 
3620
        orig_flags = flags;
 
3621
        orig_mval = mval;
 
3622
        orig_nmap = *nmap;
 
3623
#endif
 
3624
        ASSERT(*nmap >= 1);
 
3625
        ASSERT(*nmap <= XFS_BMAP_MAX_NMAP || !(flags & XFS_BMAPI_WRITE));
 
3626
        whichfork = (flags & XFS_BMAPI_ATTRFORK) ?
 
3627
                XFS_ATTR_FORK : XFS_DATA_FORK;
 
3628
        if (XFS_IFORK_FORMAT(ip, whichfork) != XFS_DINODE_FMT_EXTENTS &&
 
3629
            XFS_IFORK_FORMAT(ip, whichfork) != XFS_DINODE_FMT_BTREE &&
 
3630
            XFS_IFORK_FORMAT(ip, whichfork) != XFS_DINODE_FMT_LOCAL) {
 
3631
#ifdef __KERNEL__       /* additional, temporary, debugging code */
 
3632
                cmn_err(CE_NOTE,
 
3633
                        "EFSCORRUPTED returned from file %s line %d",
 
3634
                        __FILE__, __LINE__);
 
3635
#endif
 
3636
                return XFS_ERROR(EFSCORRUPTED);
 
3637
        }
 
3638
        mp = ip->i_mount;
 
3639
        if (XFS_FORCED_SHUTDOWN(mp))
 
3640
                return XFS_ERROR(EIO);
 
3641
        ifp = XFS_IFORK_PTR(ip, whichfork);
 
3642
        ASSERT(ifp->if_ext_max ==
 
3643
               XFS_IFORK_SIZE(ip, whichfork) / (uint)sizeof(xfs_bmbt_rec_t));
 
3644
        if ((wr = (flags & XFS_BMAPI_WRITE)) != 0)
 
3645
                XFS_STATS_INC(xfsstats.xs_blk_mapw);
 
3646
        else
 
3647
                XFS_STATS_INC(xfsstats.xs_blk_mapr);
 
3648
        delay = (flags & XFS_BMAPI_DELAY) != 0;
 
3649
        trim = (flags & XFS_BMAPI_ENTIRE) == 0;
 
3650
        userdata = (flags & XFS_BMAPI_METADATA) == 0;
 
3651
        exact = (flags & XFS_BMAPI_EXACT) != 0;
 
3652
        rsvd = (flags & XFS_BMAPI_RSVBLOCKS) != 0;
 
3653
        contig = (flags & XFS_BMAPI_CONTIG) != 0;
 
3654
        /*
 
3655
         * stateless is used to combine extents which
 
3656
         * differ only due to the state of the extents.
 
3657
         * This technique is used from xfs_getbmap()
 
3658
         * when the caller does not wish to see the
 
3659
         * separation (which is the default).
 
3660
         *
 
3661
         * This technique is also used when writing a 
 
3662
         * buffer which has been partially written,
 
3663
         * (usually by being flushed during a chunkread),
 
3664
         * to ensure one write takes place. This also
 
3665
         * prevents a change in the xfs inode extents at
 
3666
         * this time, intentionally. This change occurs
 
3667
         * on completion of the write operation, in
 
3668
         * xfs_strat_comp(), where the xfs_bmapi() call
 
3669
         * is transactioned, and the extents combined.
 
3670
         */
 
3671
        stateless = (flags & XFS_BMAPI_IGSTATE) != 0;
 
3672
        if (stateless && wr)    /* if writing unwritten space, no */
 
3673
                wr = 0;         /* allocations are allowed */
 
3674
        ASSERT(wr || !delay);
 
3675
        logflags = 0;
 
3676
        nallocs = 0;
 
3677
        cur = NULL;
 
3678
        if (XFS_IFORK_FORMAT(ip, whichfork) == XFS_DINODE_FMT_LOCAL) {
 
3679
                ASSERT(wr && tp);
 
3680
                if ((error = xfs_bmap_local_to_extents(tp, ip, firstblock, total,
 
3681
                                &logflags, whichfork)))
 
3682
                        goto error0;
 
3683
        }
 
3684
        if (wr && *firstblock == NULLFSBLOCK) {
 
3685
                if (XFS_IFORK_FORMAT(ip, whichfork) == XFS_DINODE_FMT_BTREE)
 
3686
                        minleft = INT_GET(ifp->if_broot->bb_level, ARCH_CONVERT) + 1;
 
3687
                else
 
3688
                        minleft = 1;
 
3689
        } else
 
3690
                minleft = 0;
 
3691
        if (!(ifp->if_flags & XFS_IFEXTENTS) &&
 
3692
            (error = xfs_iread_extents(tp, ip, whichfork)))
 
3693
                goto error0;
 
3694
        ep = xfs_bmap_search_extents(ip, bno, whichfork, &eof, &lastx, &got,
 
3695
                &prev);
 
3696
        nextents = ifp->if_bytes / (uint)sizeof(xfs_bmbt_rec_t);
 
3697
        n = 0;
 
3698
        end = bno + len;
 
3699
        obno = bno;
 
3700
        bma.ip = NULL;
 
3701
        while (bno < end && n < *nmap) {
 
3702
                /* 
 
3703
                 * Reading past eof, act as though there's a hole
 
3704
                 * up to end.
 
3705
                 */
 
3706
                if (eof && !wr)
 
3707
                        got.br_startoff = end;
 
3708
                inhole = eof || got.br_startoff > bno;
 
3709
                wasdelay = wr && !inhole && !delay &&
 
3710
                        ISNULLSTARTBLOCK(got.br_startblock);
 
3711
                /*
 
3712
                 * First, deal with the hole before the allocated space 
 
3713
                 * that we found, if any.
 
3714
                 */
 
3715
                if (wr && (inhole || wasdelay)) {
 
3716
                        /*
 
3717
                         * For the wasdelay case, we could also just
 
3718
                         * allocate the stuff asked for in this bmap call
 
3719
                         * but that wouldn't be as good.
 
3720
                         */
 
3721
                        if (wasdelay && !exact) {
 
3722
                                alen = (xfs_extlen_t)got.br_blockcount;
 
3723
                                aoff = got.br_startoff;
 
3724
                                if (lastx != NULLEXTNUM && lastx) {
 
3725
                                        ep = &ifp->if_u1.if_extents[lastx - 1];
 
3726
                                        xfs_bmbt_get_all(ep, &prev);
 
3727
                                }
 
3728
                        } else if (wasdelay) {
 
3729
                                alen = (xfs_extlen_t)
 
3730
                                        XFS_FILBLKS_MIN(len,
 
3731
                                                (got.br_startoff +
 
3732
                                                 got.br_blockcount) - bno);
 
3733
                                aoff = bno;
 
3734
                        } else {
 
3735
                                alen = (xfs_extlen_t)
 
3736
                                        XFS_FILBLKS_MIN(len, MAXEXTLEN);
 
3737
                                if (!eof)
 
3738
                                        alen = (xfs_extlen_t)
 
3739
                                                XFS_FILBLKS_MIN(alen,
 
3740
                                                        got.br_startoff - bno);
 
3741
                                aoff = bno;
 
3742
                        }
 
3743
                        minlen = contig ? alen : 1;
 
3744
                        if (delay) {
 
3745
                                indlen = (xfs_extlen_t)
 
3746
                                        xfs_bmap_worst_indlen(ip, alen);
 
3747
                                ASSERT(indlen > 0);
 
3748
                                /*
 
3749
                                 * Make a transaction-less quota reservation for
 
3750
                                 * delayed allocation blocks. This number gets
 
3751
                                 * adjusted later.
 
3752
                                 * We return EDQUOT if we haven't allocated
 
3753
                                 * blks already inside this loop;
 
3754
                                 */
 
3755
                                if (XFS_IS_QUOTA_ON(ip->i_mount) &&
 
3756
                                    xfs_trans_reserve_blkquota(NULL, ip,
 
3757
                                            (long)alen)) {
 
3758
                                        if (n == 0) {
 
3759
                                                *nmap = 0;
 
3760
                                                ASSERT(cur == NULL);
 
3761
                                                return XFS_ERROR(EDQUOT);
 
3762
                                        }
 
3763
                                        break;
 
3764
                                }
 
3765
                                if (xfs_mod_incore_sb(ip->i_mount,
 
3766
                                                XFS_SBS_FDBLOCKS,
 
3767
                                                -(alen + indlen), rsvd)) {
 
3768
                                        if (XFS_IS_QUOTA_ON(ip->i_mount))
 
3769
                                                xfs_trans_unreserve_blkquota(
 
3770
                                                        NULL, ip, (long)alen);
 
3771
                                        break;
 
3772
                                }
 
3773
                                ip->i_delayed_blks += alen;
 
3774
                                abno = NULLSTARTBLOCK(indlen);
 
3775
                        } else {
 
3776
                                /*
 
3777
                                 * If first time, allocate and fill in
 
3778
                                 * once-only bma fields.
 
3779
                                 */
 
3780
                                if (bma.ip == NULL) {
 
3781
                                        bma.tp = tp;
 
3782
                                        bma.ip = ip;
 
3783
                                        bma.prevp = &prev;
 
3784
                                        bma.gotp = &got;
 
3785
                                        bma.total = total;
 
3786
                                        bma.userdata = 0;
 
3787
                                }
 
3788
                                /* Indicate if this is the first user data
 
3789
                                 * in the file, or just any user data.
 
3790
                                 */
 
3791
                                if (userdata) {
 
3792
                                        bma.userdata = (aoff == 0) ? 
 
3793
                                                XFS_ALLOC_INITIAL_USER_DATA : 
 
3794
                                                XFS_ALLOC_USERDATA;
 
3795
                                }
 
3796
                                /*
 
3797
                                 * Fill in changeable bma fields.
 
3798
                                 */
 
3799
                                bma.eof = eof;
 
3800
                                bma.firstblock = *firstblock;
 
3801
                                bma.alen = alen;
 
3802
                                bma.off = aoff;
 
3803
                                bma.wasdel = wasdelay;
 
3804
                                bma.minlen = minlen;
 
3805
                                bma.low = flist->xbf_low;
 
3806
                                bma.minleft = minleft;
 
3807
                                /*
 
3808
                                 * Only want to do the alignment at the
 
3809
                                 * eof if it is userdata and allocation length 
 
3810
                                 * is larger than a stripe unit.
 
3811
                                 */
 
3812
                                if (mp->m_dalign && alen >= mp->m_dalign &&
 
3813
                                    userdata && whichfork == XFS_DATA_FORK) {
 
3814
                                        if ((error = xfs_bmap_isaeof(ip, aoff,
 
3815
                                                        whichfork, &bma.aeof)))
 
3816
                                                goto error0;
 
3817
                                } else
 
3818
                                        bma.aeof = 0;
 
3819
                                /*
 
3820
                                 * Call allocator.
 
3821
                                 */
 
3822
                                if ((error = xfs_bmap_alloc(&bma)))
 
3823
                                        goto error0;
 
3824
                                /*
 
3825
                                 * Copy out result fields.
 
3826
                                 */
 
3827
                                abno = bma.rval;
 
3828
                                if ((flist->xbf_low = bma.low))
 
3829
                                        minleft = 0;
 
3830
                                alen = bma.alen;
 
3831
                                aoff = bma.off;
 
3832
                                ASSERT(*firstblock == NULLFSBLOCK ||
 
3833
                                       XFS_FSB_TO_AGNO(ip->i_mount,
 
3834
                                               *firstblock) ==
 
3835
                                       XFS_FSB_TO_AGNO(ip->i_mount,
 
3836
                                               bma.firstblock) ||
 
3837
                                       (flist->xbf_low &&
 
3838
                                        XFS_FSB_TO_AGNO(ip->i_mount,
 
3839
                                                *firstblock) <
 
3840
                                        XFS_FSB_TO_AGNO(ip->i_mount,
 
3841
                                                bma.firstblock)));
 
3842
                                *firstblock = bma.firstblock;
 
3843
                                if (cur)
 
3844
                                        cur->bc_private.b.firstblock =
 
3845
                                                *firstblock;
 
3846
                                if (abno == NULLFSBLOCK)
 
3847
                                        break;
 
3848
                                if ((ifp->if_flags & XFS_IFBROOT) && !cur) {
 
3849
                                        cur = xfs_btree_init_cursor(ip->i_mount,
 
3850
                                                tp, NULL, 0, XFS_BTNUM_BMAP,
 
3851
                                                ip, whichfork);
 
3852
                                        cur->bc_private.b.firstblock =
 
3853
                                                *firstblock;
 
3854
                                        cur->bc_private.b.flist = flist;
 
3855
                                }
 
3856
                                /*
 
3857
                                 * Bump the number of extents we've allocated
 
3858
                                 * in this call.
 
3859
                                 */
 
3860
                                nallocs++;
 
3861
                        }
 
3862
                        if (cur)
 
3863
                                cur->bc_private.b.flags =
 
3864
                                        wasdelay ? XFS_BTCUR_BPRV_WASDEL : 0;
 
3865
                        got.br_startoff = aoff;
 
3866
                        got.br_startblock = abno;
 
3867
                        got.br_blockcount = alen;
 
3868
                        got.br_state = XFS_EXT_NORM;    /* assume normal */
 
3869
                        /*
 
3870
                         * Determine state of extent, and the filesystem.
 
3871
                         * A wasdelay extent has been initialized, so 
 
3872
                         * shouldn't be flagged as unwritten.
 
3873
                         */
 
3874
                        if (wr && XFS_SB_VERSION_HASEXTFLGBIT(&mp->m_sb)) {
 
3875
                                if (!wasdelay && (flags & XFS_BMAPI_PREALLOC))
 
3876
                                        got.br_state = XFS_EXT_UNWRITTEN;
 
3877
                        }
 
3878
                        error = xfs_bmap_add_extent(ip, lastx, &cur, &got,
 
3879
                                firstblock, flist, &tmp_logflags, whichfork,
 
3880
                                rsvd);
 
3881
                        logflags |= tmp_logflags;
 
3882
                        if (error)
 
3883
                                goto error0;
 
3884
                        lastx = ifp->if_lastex;
 
3885
                        ep = &ifp->if_u1.if_extents[lastx];
 
3886
                        nextents = ifp->if_bytes / (uint)sizeof(xfs_bmbt_rec_t);
 
3887
                        xfs_bmbt_get_all(ep, &got);
 
3888
                        ASSERT(got.br_startoff <= aoff);
 
3889
                        ASSERT(got.br_startoff + got.br_blockcount >=
 
3890
                                aoff + alen);
 
3891
#ifdef DEBUG
 
3892
                        if (delay) {
 
3893
                                ASSERT(ISNULLSTARTBLOCK(got.br_startblock));
 
3894
                                ASSERT(STARTBLOCKVAL(got.br_startblock) > 0);
 
3895
                        }
 
3896
                        ASSERT(got.br_state == XFS_EXT_NORM ||
 
3897
                               got.br_state == XFS_EXT_UNWRITTEN);
 
3898
#endif
 
3899
                        /*
 
3900
                         * Fall down into the found allocated space case.
 
3901
                         */
 
3902
                } else if (inhole) {
 
3903
                        /*
 
3904
                         * Reading in a hole.
 
3905
                         */
 
3906
                        mval->br_startoff = bno;
 
3907
                        mval->br_startblock = HOLESTARTBLOCK;
 
3908
                        mval->br_blockcount =
 
3909
                                XFS_FILBLKS_MIN(len, got.br_startoff - bno);
 
3910
                        mval->br_state = XFS_EXT_NORM;
 
3911
                        bno += mval->br_blockcount;
 
3912
                        len -= mval->br_blockcount;
 
3913
                        mval++;
 
3914
                        n++;
 
3915
                        continue;
 
3916
                }
 
3917
                /*
 
3918
                 * Then deal with the allocated space we found.
 
3919
                 */
 
3920
                ASSERT(ep != NULL);
 
3921
                if (trim && (got.br_startoff + got.br_blockcount > obno)) {
 
3922
                        if (obno > bno)
 
3923
                                bno = obno;
 
3924
                        ASSERT((bno >= obno) || (n == 0));
 
3925
                        ASSERT(bno < end);
 
3926
                        mval->br_startoff = bno;
 
3927
                        if (ISNULLSTARTBLOCK(got.br_startblock)) {
 
3928
                                ASSERT(!wr || delay);
 
3929
                                mval->br_startblock = DELAYSTARTBLOCK;
 
3930
                        } else
 
3931
                                mval->br_startblock =
 
3932
                                        got.br_startblock +
 
3933
                                        (bno - got.br_startoff);
 
3934
                        /*
 
3935
                         * Return the minimum of what we got and what we
 
3936
                         * asked for for the length.  We can use the len
 
3937
                         * variable here because it is modified below
 
3938
                         * and we could have been there before coming
 
3939
                         * here if the first part of the allocation
 
3940
                         * didn't overlap what was asked for.
 
3941
                         */
 
3942
                        mval->br_blockcount =
 
3943
                                XFS_FILBLKS_MIN(end - bno, got.br_blockcount -
 
3944
                                        (bno - got.br_startoff));
 
3945
                        mval->br_state = got.br_state;
 
3946
                        ASSERT(mval->br_blockcount <= len);
 
3947
                } else {
 
3948
                        *mval = got;
 
3949
                        if (ISNULLSTARTBLOCK(mval->br_startblock)) {
 
3950
                                ASSERT(!wr || delay);
 
3951
                                mval->br_startblock = DELAYSTARTBLOCK;
 
3952
                        }
 
3953
                }
 
3954
 
 
3955
                /*
 
3956
                 * Check if writing previously allocated but
 
3957
                 * unwritten extents.
 
3958
                 */
 
3959
                if (wr && mval->br_state == XFS_EXT_UNWRITTEN &&
 
3960
                    ((flags & (XFS_BMAPI_PREALLOC|XFS_BMAPI_DELAY)) == 0)) {
 
3961
                        /*
 
3962
                         * Modify (by adding) the state flag, if writing.
 
3963
                         */
 
3964
                        ASSERT(mval->br_blockcount <= len);
 
3965
                        if ((ifp->if_flags & XFS_IFBROOT) && !cur) {
 
3966
                                cur = xfs_btree_init_cursor(ip->i_mount,
 
3967
                                        tp, NULL, 0, XFS_BTNUM_BMAP,
 
3968
                                        ip, whichfork);
 
3969
                                cur->bc_private.b.firstblock =
 
3970
                                        *firstblock;
 
3971
                                cur->bc_private.b.flist = flist;
 
3972
                        }
 
3973
                        mval->br_state = XFS_EXT_NORM;
 
3974
                        error = xfs_bmap_add_extent(ip, lastx, &cur, mval,
 
3975
                                firstblock, flist, &tmp_logflags, whichfork,
 
3976
                                rsvd);
 
3977
                        logflags |= tmp_logflags;
 
3978
                        if (error)
 
3979
                                goto error0;
 
3980
                        lastx = ifp->if_lastex;
 
3981
                        ep = &ifp->if_u1.if_extents[lastx];
 
3982
                        nextents = ifp->if_bytes / (uint)sizeof(xfs_bmbt_rec_t);
 
3983
                        xfs_bmbt_get_all(ep, &got);
 
3984
                        /*
 
3985
                         * We may have combined previously unwritten 
 
3986
                         * space with written space, so generate 
 
3987
                         * another request.
 
3988
                         */
 
3989
                        if (mval->br_blockcount < len)
 
3990
                                continue;
 
3991
                }
 
3992
 
 
3993
                ASSERT(!trim ||
 
3994
                       ((mval->br_startoff + mval->br_blockcount) <= end));
 
3995
                ASSERT(!trim || (mval->br_blockcount <= len) ||
 
3996
                       (mval->br_startoff < obno));
 
3997
                bno = mval->br_startoff + mval->br_blockcount;
 
3998
                len = end - bno;
 
3999
                if (n > 0 && mval->br_startoff == mval[-1].br_startoff) {
 
4000
                        ASSERT(mval->br_startblock == mval[-1].br_startblock);
 
4001
                        ASSERT(mval->br_blockcount > mval[-1].br_blockcount);
 
4002
                        ASSERT(mval->br_state == mval[-1].br_state);
 
4003
                        mval[-1].br_blockcount = mval->br_blockcount;
 
4004
                        mval[-1].br_state = mval->br_state;
 
4005
                } else if (n > 0 && mval->br_startblock != DELAYSTARTBLOCK &&
 
4006
                           mval[-1].br_startblock != DELAYSTARTBLOCK &&
 
4007
                           mval[-1].br_startblock != HOLESTARTBLOCK &&
 
4008
                           mval->br_startblock ==
 
4009
                           mval[-1].br_startblock + mval[-1].br_blockcount &&
 
4010
                           (stateless || mval[-1].br_state == mval->br_state)) {
 
4011
                        ASSERT(mval->br_startoff ==
 
4012
                               mval[-1].br_startoff + mval[-1].br_blockcount);
 
4013
                        mval[-1].br_blockcount += mval->br_blockcount;
 
4014
                } else if (n > 0 &&
 
4015
                           mval->br_startblock == DELAYSTARTBLOCK &&
 
4016
                           mval[-1].br_startblock == DELAYSTARTBLOCK &&
 
4017
                           mval->br_startoff ==
 
4018
                           mval[-1].br_startoff + mval[-1].br_blockcount) {
 
4019
                        mval[-1].br_blockcount += mval->br_blockcount;
 
4020
                        mval[-1].br_state = mval->br_state;
 
4021
                } else if (!((n == 0) &&
 
4022
                             ((mval->br_startoff + mval->br_blockcount) <=
 
4023
                              obno))) {
 
4024
                        mval++;
 
4025
                        n++;
 
4026
                }
 
4027
                /*
 
4028
                 * If we're done, stop now.  Stop when we've allocated
 
4029
                 * XFS_BMAP_MAX_NMAP extents no matter what.  Otherwise
 
4030
                 * the transaction may get too big.
 
4031
                 */
 
4032
                if (bno >= end || n >= *nmap || nallocs >= *nmap)
 
4033
                        break;
 
4034
                /*
 
4035
                 * Else go on to the next record.
 
4036
                 */
 
4037
                ep++;
 
4038
                lastx++;
 
4039
                if (lastx >= nextents) {
 
4040
                        eof = 1;
 
4041
                        prev = got;
 
4042
                } else
 
4043
                        xfs_bmbt_get_all(ep, &got);
 
4044
        }
 
4045
        ifp->if_lastex = lastx;
 
4046
        *nmap = n;
 
4047
        /*
 
4048
         * Transform from btree to extents, give it cur.
 
4049
         */
 
4050
        if (tp && XFS_IFORK_FORMAT(ip, whichfork) == XFS_DINODE_FMT_BTREE &&
 
4051
            XFS_IFORK_NEXTENTS(ip, whichfork) <= ifp->if_ext_max) {
 
4052
                ASSERT(wr && cur);
 
4053
                error = xfs_bmap_btree_to_extents(tp, ip, cur,
 
4054
                        &tmp_logflags, whichfork, 0);
 
4055
                logflags |= tmp_logflags;
 
4056
                if (error)
 
4057
                        goto error0;
 
4058
        }
 
4059
        ASSERT(ifp->if_ext_max ==
 
4060
               XFS_IFORK_SIZE(ip, whichfork) / (uint)sizeof(xfs_bmbt_rec_t));
 
4061
        ASSERT(XFS_IFORK_FORMAT(ip, whichfork) != XFS_DINODE_FMT_BTREE ||
 
4062
               XFS_IFORK_NEXTENTS(ip, whichfork) > ifp->if_ext_max);
 
4063
        error = 0;
 
4064
 
 
4065
error0:
 
4066
        /*
 
4067
         * Log everything.  Do this after conversion, there's no point in
 
4068
         * logging the extent list if we've converted to btree format.
 
4069
         */
 
4070
        if ((logflags & XFS_ILOG_FEXT(whichfork)) &&
 
4071
            XFS_IFORK_FORMAT(ip, whichfork) != XFS_DINODE_FMT_EXTENTS)
 
4072
                logflags &= ~XFS_ILOG_FEXT(whichfork);
 
4073
        else if ((logflags & XFS_ILOG_FBROOT(whichfork)) &&
 
4074
                 XFS_IFORK_FORMAT(ip, whichfork) != XFS_DINODE_FMT_BTREE)
 
4075
                logflags &= ~XFS_ILOG_FBROOT(whichfork);
 
4076
        /*
 
4077
         * Log whatever the flags say, even if error.  Otherwise we might miss
 
4078
         * detecting a case where the data is changed, there's an error,
 
4079
         * and it's not logged so we don't shutdown when we should.
 
4080
         */
 
4081
        if (logflags) {
 
4082
                ASSERT(tp && wr);
 
4083
                xfs_trans_log_inode(tp, ip, logflags);
 
4084
        }
 
4085
        if (cur) {
 
4086
                if (!error) {
 
4087
                        ASSERT(*firstblock == NULLFSBLOCK ||
 
4088
                               XFS_FSB_TO_AGNO(ip->i_mount, *firstblock) ==
 
4089
                               XFS_FSB_TO_AGNO(ip->i_mount,
 
4090
                                       cur->bc_private.b.firstblock) ||
 
4091
                               (flist->xbf_low &&
 
4092
                                XFS_FSB_TO_AGNO(ip->i_mount, *firstblock) < 
 
4093
                                XFS_FSB_TO_AGNO(ip->i_mount,
 
4094
                                        cur->bc_private.b.firstblock)));
 
4095
                        *firstblock = cur->bc_private.b.firstblock;
 
4096
                }
 
4097
                xfs_btree_del_cursor(cur,
 
4098
                        error ? XFS_BTREE_ERROR : XFS_BTREE_NOERROR);
 
4099
        }
 
4100
        if (!error)
 
4101
                xfs_bmap_validate_ret(orig_bno, orig_len, orig_flags, orig_mval,
 
4102
                        orig_nmap, *nmap);
 
4103
        return error;
 
4104
}
 
4105
 
 
4106
/*
 
4107
 * Map file blocks to filesystem blocks, simple version.
 
4108
 * One block (extent) only, read-only.
 
4109
 * For flags, only the XFS_BMAPI_ATTRFORK flag is examined.
 
4110
 * For the other flag values, the effect is as if XFS_BMAPI_METADATA
 
4111
 * was set and all the others were clear.
 
4112
 */
 
4113
int                                             /* error */
 
4114
xfs_bmapi_single(
 
4115
        xfs_trans_t     *tp,            /* transaction pointer */
 
4116
        xfs_inode_t     *ip,            /* incore inode */
 
4117
        int             whichfork,      /* data or attr fork */
 
4118
        xfs_fsblock_t   *fsb,           /* output: mapped block */
 
4119
        xfs_fileoff_t   bno)            /* starting file offs. mapped */
 
4120
{
 
4121
        int             eof;            /* we've hit the end of extent list */
 
4122
        int             error;          /* error return */
 
4123
        xfs_bmbt_irec_t got;            /* current extent list record */
 
4124
        xfs_ifork_t     *ifp;           /* inode fork pointer */
 
4125
        xfs_extnum_t    lastx;          /* last useful extent number */
 
4126
        xfs_bmbt_irec_t prev;           /* previous extent list record */
 
4127
 
 
4128
        ifp = XFS_IFORK_PTR(ip, whichfork);
 
4129
        if (XFS_IFORK_FORMAT(ip, whichfork) != XFS_DINODE_FMT_BTREE &&
 
4130
            XFS_IFORK_FORMAT(ip, whichfork) != XFS_DINODE_FMT_EXTENTS) {
 
4131
#ifdef __KERNEL__       /* additional, temporary, debugging code */
 
4132
                cmn_err(CE_NOTE,
 
4133
                        "EFSCORRUPTED returned from file %s line %d",
 
4134
                        __FILE__, __LINE__);
 
4135
#endif
 
4136
               return XFS_ERROR(EFSCORRUPTED);
 
4137
        }
 
4138
        if (XFS_FORCED_SHUTDOWN(ip->i_mount))
 
4139
                return XFS_ERROR(EIO);
 
4140
        XFS_STATS_INC(xfsstats.xs_blk_mapr);
 
4141
        if (!(ifp->if_flags & XFS_IFEXTENTS) &&
 
4142
            (error = xfs_iread_extents(tp, ip, whichfork)))
 
4143
                return error;
 
4144
        (void)xfs_bmap_search_extents(ip, bno, whichfork, &eof, &lastx, &got,
 
4145
                &prev);
 
4146
        /* 
 
4147
         * Reading past eof, act as though there's a hole
 
4148
         * up to end.
 
4149
         */
 
4150
        if (eof || got.br_startoff > bno) {
 
4151
                *fsb = NULLFSBLOCK;
 
4152
                return 0;
 
4153
        }
 
4154
        ASSERT(!ISNULLSTARTBLOCK(got.br_startblock));
 
4155
        ASSERT(bno < got.br_startoff + got.br_blockcount);
 
4156
        *fsb = got.br_startblock + (bno - got.br_startoff);
 
4157
        ifp->if_lastex = lastx;
 
4158
        return 0;
 
4159
}
 
4160
 
 
4161
/*
 
4162
 * Unmap (remove) blocks from a file.
 
4163
 * If nexts is nonzero then the number of extents to remove is limited to
 
4164
 * that value.  If not all extents in the block range can be removed then
 
4165
 * *done is set.
 
4166
 */
 
4167
int                                             /* error */
 
4168
xfs_bunmapi(
 
4169
        xfs_trans_t             *tp,            /* transaction pointer */
 
4170
        struct xfs_inode        *ip,            /* incore inode */
 
4171
        xfs_fileoff_t           bno,            /* starting offset to unmap */
 
4172
        xfs_filblks_t           len,            /* length to unmap in file */
 
4173
        int                     flags,          /* misc flags */            
 
4174
        xfs_extnum_t            nexts,          /* number of extents max */
 
4175
        xfs_fsblock_t           *firstblock,    /* first allocated block
 
4176
                                                   controls a.g. for allocs */
 
4177
        xfs_bmap_free_t         *flist,         /* i/o: list extents to free */
 
4178
        int                     *done)          /* set if not done yet */
 
4179
{
 
4180
        int                     async;          /* xactions can be async */
 
4181
        xfs_btree_cur_t         *cur;           /* bmap btree cursor */
 
4182
        xfs_bmbt_irec_t         del;            /* extent being deleted */
 
4183
        int                     eof;            /* is deleting at eof */
 
4184
        xfs_bmbt_rec_t          *ep;            /* extent list entry pointer */
 
4185
        int                     error;          /* error return value */
 
4186
        xfs_extnum_t            extno;          /* extent number in list */
 
4187
        xfs_bmbt_irec_t         got;            /* current extent list entry */
 
4188
        xfs_ifork_t             *ifp;           /* inode fork pointer */
 
4189
        int                     isrt;           /* freeing in rt area */
 
4190
        xfs_extnum_t            lastx;          /* last extent index used */
 
4191
        int                     logflags;       /* transaction logging flags */
 
4192
        xfs_extlen_t            mod;            /* rt extent offset */
 
4193
        xfs_mount_t             *mp;            /* mount structure */
 
4194
        xfs_extnum_t            nextents;       /* size of extent list */
 
4195
        xfs_bmbt_irec_t         prev;           /* previous extent list entry */
 
4196
        xfs_fileoff_t           start;          /* first file offset deleted */
 
4197
        int                     tmp_logflags;   /* partial logging flags */
 
4198
        int                     wasdel;         /* was a delayed alloc extent */
 
4199
        int                     whichfork;      /* data or attribute fork */
 
4200
        int                     rsvd;           /* OK to allocate reserved blocks */
 
4201
        xfs_fsblock_t           sum;
 
4202
 
 
4203
        xfs_bunmap_trace(ip, bno, len, flags, (inst_t *)__return_address);
 
4204
        whichfork = (flags & XFS_BMAPI_ATTRFORK) ?
 
4205
                XFS_ATTR_FORK : XFS_DATA_FORK;
 
4206
        ifp = XFS_IFORK_PTR(ip, whichfork);
 
4207
        if (XFS_IFORK_FORMAT(ip, whichfork) != XFS_DINODE_FMT_EXTENTS &&
 
4208
            XFS_IFORK_FORMAT(ip, whichfork) != XFS_DINODE_FMT_BTREE) {
 
4209
#ifdef __KERNEL__       /* additional, temporary, debugging code */
 
4210
                cmn_err(CE_NOTE,
 
4211
                        "EFSCORRUPTED returned from file %s line %d",
 
4212
                        __FILE__, __LINE__);
 
4213
#endif
 
4214
                return XFS_ERROR(EFSCORRUPTED);
 
4215
        }
 
4216
        mp = ip->i_mount;
 
4217
        if (XFS_FORCED_SHUTDOWN(mp))
 
4218
                return XFS_ERROR(EIO);
 
4219
        async = flags & XFS_BMAPI_ASYNC;
 
4220
        rsvd = (flags & XFS_BMAPI_RSVBLOCKS) != 0;
 
4221
        ASSERT(len > 0);
 
4222
        ASSERT(nexts >= 0);
 
4223
        ASSERT(ifp->if_ext_max ==
 
4224
               XFS_IFORK_SIZE(ip, whichfork) / (uint)sizeof(xfs_bmbt_rec_t));
 
4225
        if (!(ifp->if_flags & XFS_IFEXTENTS) &&
 
4226
            (error = xfs_iread_extents(tp, ip, whichfork)))
 
4227
                return error;
 
4228
        nextents = ifp->if_bytes / (uint)sizeof(xfs_bmbt_rec_t);
 
4229
        if (nextents == 0) {
 
4230
                *done = 1;
 
4231
                return 0;
 
4232
        }
 
4233
        XFS_STATS_INC(xfsstats.xs_blk_unmap);
 
4234
        isrt = (whichfork == XFS_DATA_FORK) &&
 
4235
               (ip->i_d.di_flags & XFS_DIFLAG_REALTIME);
 
4236
        start = bno;
 
4237
        bno = start + len - 1;
 
4238
        ep = xfs_bmap_search_extents(ip, bno, whichfork, &eof, &lastx, &got,
 
4239
                &prev);
 
4240
        /*
 
4241
         * Check to see if the given block number is past the end of the
 
4242
         * file, back up to the last block if so...
 
4243
         */
 
4244
        if (eof) {
 
4245
                ep = &ifp->if_u1.if_extents[--lastx];
 
4246
                xfs_bmbt_get_all(ep, &got);
 
4247
                bno = got.br_startoff + got.br_blockcount - 1;
 
4248
        }
 
4249
        logflags = 0;
 
4250
        if (ifp->if_flags & XFS_IFBROOT) {
 
4251
                ASSERT(XFS_IFORK_FORMAT(ip, whichfork) == XFS_DINODE_FMT_BTREE);
 
4252
                cur = xfs_btree_init_cursor(mp, tp, NULL, 0, XFS_BTNUM_BMAP, ip,
 
4253
                        whichfork);
 
4254
                cur->bc_private.b.firstblock = *firstblock;
 
4255
                cur->bc_private.b.flist = flist;
 
4256
                cur->bc_private.b.flags = 0;
 
4257
        } else
 
4258
                cur = NULL;
 
4259
        extno = 0;
 
4260
        while (bno != (xfs_fileoff_t)-1 && bno >= start && lastx >= 0 &&
 
4261
               (nexts == 0 || extno < nexts)) {
 
4262
                /*
 
4263
                 * Is the found extent after a hole in which bno lives?
 
4264
                 * Just back up to the previous extent, if so.
 
4265
                 */
 
4266
                if (got.br_startoff > bno) {
 
4267
                        if (--lastx < 0)
 
4268
                                break;
 
4269
                        ep--;
 
4270
                        xfs_bmbt_get_all(ep, &got);
 
4271
                }
 
4272
                /*
 
4273
                 * Is the last block of this extent before the range
 
4274
                 * we're supposed to delete?  If so, we're done.
 
4275
                 */
 
4276
                bno = XFS_FILEOFF_MIN(bno,
 
4277
                        got.br_startoff + got.br_blockcount - 1);
 
4278
                if (bno < start)
 
4279
                        break;
 
4280
                /*
 
4281
                 * Then deal with the (possibly delayed) allocated space
 
4282
                 * we found.
 
4283
                 */
 
4284
                ASSERT(ep != NULL);
 
4285
                del = got;
 
4286
                wasdel = ISNULLSTARTBLOCK(del.br_startblock);
 
4287
                if (got.br_startoff < start) {
 
4288
                        del.br_startoff = start;
 
4289
                        del.br_blockcount -= start - got.br_startoff;
 
4290
                        if (!wasdel)
 
4291
                                del.br_startblock += start - got.br_startoff;
 
4292
                }
 
4293
                if (del.br_startoff + del.br_blockcount > bno + 1)
 
4294
                        del.br_blockcount = bno + 1 - del.br_startoff;
 
4295
                sum = del.br_startblock + del.br_blockcount;
 
4296
                if (isrt &&
 
4297
                    (mod = do_mod(sum, mp->m_sb.sb_rextsize))) {
 
4298
                        /*
 
4299
                         * Realtime extent not lined up at the end.
 
4300
                         * The extent could have been split into written
 
4301
                         * and unwritten pieces, or we could just be
 
4302
                         * unmapping part of it.  But we can't really
 
4303
                         * get rid of part of a realtime extent.
 
4304
                         */
 
4305
                        if (del.br_state == XFS_EXT_UNWRITTEN ||
 
4306
                            !XFS_SB_VERSION_HASEXTFLGBIT(&mp->m_sb)) {
 
4307
                                /*
 
4308
                                 * This piece is unwritten, or we're not
 
4309
                                 * using unwritten extents.  Skip over it.
 
4310
                                 */
 
4311
                                ASSERT(bno >= mod);
 
4312
                                bno -= mod > del.br_blockcount ?
 
4313
                                        del.br_blockcount : mod;
 
4314
                                if (bno < got.br_startoff) {
 
4315
                                        if (--lastx >= 0)
 
4316
                                                xfs_bmbt_get_all(--ep, &got);
 
4317
                                }
 
4318
                                continue;
 
4319
                        }
 
4320
                        /*
 
4321
                         * It's written, turn it unwritten.
 
4322
                         * This is better than zeroing it.
 
4323
                         */
 
4324
                        ASSERT(del.br_state == XFS_EXT_NORM);
 
4325
                        ASSERT(xfs_trans_get_block_res(tp) > 0);
 
4326
                        /*
 
4327
                         * If this spans a realtime extent boundary,
 
4328
                         * chop it back to the start of the one we end at.
 
4329
                         */
 
4330
                        if (del.br_blockcount > mod) {
 
4331
                                del.br_startoff += del.br_blockcount - mod;
 
4332
                                del.br_startblock += del.br_blockcount - mod;
 
4333
                                del.br_blockcount = mod;
 
4334
                        }
 
4335
                        del.br_state = XFS_EXT_UNWRITTEN;
 
4336
                        error = xfs_bmap_add_extent(ip, lastx, &cur, &del,
 
4337
                                firstblock, flist, &logflags, XFS_DATA_FORK, 0);
 
4338
                        if (error)
 
4339
                                goto error0;
 
4340
                        goto nodelete;
 
4341
                }
 
4342
                if (isrt && (mod = do_mod(del.br_startblock, mp->m_sb.sb_rextsize))) {
 
4343
                        /*
 
4344
                         * Realtime extent is lined up at the end but not
 
4345
                         * at the front.  We'll get rid of full extents if
 
4346
                         * we can.
 
4347
                         */
 
4348
                        mod = mp->m_sb.sb_rextsize - mod;
 
4349
                        if (del.br_blockcount > mod) {
 
4350
                                del.br_blockcount -= mod;
 
4351
                                del.br_startoff += mod;
 
4352
                                del.br_startblock += mod;
 
4353
                        } else if ((del.br_startoff == start &&
 
4354
                                    (del.br_state == XFS_EXT_UNWRITTEN ||
 
4355
                                     xfs_trans_get_block_res(tp) == 0)) ||
 
4356
                                   !XFS_SB_VERSION_HASEXTFLGBIT(&mp->m_sb)) {
 
4357
                                /*
 
4358
                                 * Can't make it unwritten.  There isn't
 
4359
                                 * a full extent here so just skip it.
 
4360
                                 */
 
4361
                                ASSERT(bno >= del.br_blockcount);
 
4362
                                bno -= del.br_blockcount;
 
4363
                                if (bno < got.br_startoff) {
 
4364
                                        if (--lastx >= 0)
 
4365
                                                xfs_bmbt_get_all(--ep, &got);
 
4366
                                }
 
4367
                                continue;
 
4368
                        } else if (del.br_state == XFS_EXT_UNWRITTEN) {
 
4369
                                /*
 
4370
                                 * This one is already unwritten.
 
4371
                                 * It must have a written left neighbor.
 
4372
                                 * Unwrite the killed part of that one and
 
4373
                                 * try again.
 
4374
                                 */
 
4375
                                ASSERT(lastx > 0);
 
4376
                                xfs_bmbt_get_all(ep - 1, &prev);
 
4377
                                ASSERT(prev.br_state == XFS_EXT_NORM);
 
4378
                                ASSERT(!ISNULLSTARTBLOCK(prev.br_startblock));
 
4379
                                ASSERT(del.br_startblock ==
 
4380
                                       prev.br_startblock + prev.br_blockcount);
 
4381
                                if (prev.br_startoff < start) {
 
4382
                                        mod = start - prev.br_startoff;
 
4383
                                        prev.br_blockcount -= mod;
 
4384
                                        prev.br_startblock += mod;
 
4385
                                        prev.br_startoff = start;
 
4386
                                }
 
4387
                                prev.br_state = XFS_EXT_UNWRITTEN;
 
4388
                                error = xfs_bmap_add_extent(ip, lastx - 1, &cur,
 
4389
                                        &prev, firstblock, flist, &logflags,
 
4390
                                        XFS_DATA_FORK, 0);
 
4391
                                if (error)
 
4392
                                        goto error0;
 
4393
                                goto nodelete;
 
4394
                        } else {
 
4395
                                ASSERT(del.br_state == XFS_EXT_NORM);
 
4396
                                del.br_state = XFS_EXT_UNWRITTEN;
 
4397
                                error = xfs_bmap_add_extent(ip, lastx, &cur,
 
4398
                                        &del, firstblock, flist, &logflags,
 
4399
                                        XFS_DATA_FORK, 0);
 
4400
                                if (error)
 
4401
                                        goto error0;
 
4402
                                goto nodelete;
 
4403
                        }
 
4404
                }
 
4405
                if (wasdel) {
 
4406
                        ASSERT(STARTBLOCKVAL(del.br_startblock) > 0);
 
4407
                        xfs_mod_incore_sb(mp, XFS_SBS_FDBLOCKS,
 
4408
                                (int)del.br_blockcount, rsvd);
 
4409
                        if (XFS_IS_QUOTA_ON(ip->i_mount)) {
 
4410
                                ASSERT(ip->i_ino != mp->m_sb.sb_uquotino);
 
4411
                                ASSERT(ip->i_ino != mp->m_sb.sb_gquotino);
 
4412
                                if (!isrt)
 
4413
                                        xfs_trans_unreserve_blkquota(NULL, ip, 
 
4414
                                              (long)del.br_blockcount);
 
4415
                                else
 
4416
                                        xfs_trans_unreserve_rtblkquota(NULL, ip,
 
4417
                                              (long)del.br_blockcount);
 
4418
                        }
 
4419
                        ip->i_delayed_blks -= del.br_blockcount;
 
4420
                        if (cur)
 
4421
                                cur->bc_private.b.flags |=
 
4422
                                        XFS_BTCUR_BPRV_WASDEL;
 
4423
                } else if (cur)
 
4424
                        cur->bc_private.b.flags &= ~XFS_BTCUR_BPRV_WASDEL;
 
4425
                /*
 
4426
                 * If it's the case where the directory code is running
 
4427
                 * with no block reservation, and the deleted block is in 
 
4428
                 * the middle of its extent, and the resulting insert
 
4429
                 * of an extent would cause transformation to btree format,
 
4430
                 * then reject it.  The calling code will then swap
 
4431
                 * blocks around instead.
 
4432
                 * We have to do this now, rather than waiting for the
 
4433
                 * conversion to btree format, since the transaction
 
4434
                 * will be dirty.
 
4435
                 */
 
4436
                if (!wasdel && xfs_trans_get_block_res(tp) == 0 &&
 
4437
                    XFS_IFORK_FORMAT(ip, whichfork) == XFS_DINODE_FMT_EXTENTS &&
 
4438
                    XFS_IFORK_NEXTENTS(ip, whichfork) >= ifp->if_ext_max &&
 
4439
                    del.br_startoff > got.br_startoff &&
 
4440
                    del.br_startoff + del.br_blockcount < 
 
4441
                    got.br_startoff + got.br_blockcount) {
 
4442
                        error = XFS_ERROR(ENOSPC);
 
4443
                        goto error0;
 
4444
                }
 
4445
                error = xfs_bmap_del_extent(ip, tp, lastx, flist, cur, &del,
 
4446
                        flags, &tmp_logflags, whichfork, rsvd);
 
4447
                logflags |= tmp_logflags;
 
4448
                if (error)
 
4449
                        goto error0;
 
4450
                bno = del.br_startoff - 1;
 
4451
nodelete:
 
4452
                lastx = ifp->if_lastex;
 
4453
                /*
 
4454
                 * If not done go on to the next (previous) record.
 
4455
                 * Reset ep in case the extents array was re-alloced.
 
4456
                 */
 
4457
                ep = &ifp->if_u1.if_extents[lastx];
 
4458
                if (bno != (xfs_fileoff_t)-1 && bno >= start) {
 
4459
                        if (lastx >= XFS_IFORK_NEXTENTS(ip, whichfork) ||
 
4460
                            xfs_bmbt_get_startoff(ep) > bno) {
 
4461
                                lastx--;
 
4462
                                ep--;
 
4463
                        }
 
4464
                        if (lastx >= 0)
 
4465
                                xfs_bmbt_get_all(ep, &got);
 
4466
                        extno++;
 
4467
                }
 
4468
        }
 
4469
        ifp->if_lastex = lastx;
 
4470
        *done = bno == (xfs_fileoff_t)-1 || bno < start || lastx < 0;
 
4471
        ASSERT(ifp->if_ext_max ==
 
4472
               XFS_IFORK_SIZE(ip, whichfork) / (uint)sizeof(xfs_bmbt_rec_t));
 
4473
        /*
 
4474
         * Convert to a btree if necessary.
 
4475
         */
 
4476
        if (XFS_IFORK_FORMAT(ip, whichfork) == XFS_DINODE_FMT_EXTENTS &&
 
4477
            XFS_IFORK_NEXTENTS(ip, whichfork) > ifp->if_ext_max) {
 
4478
                ASSERT(cur == NULL);
 
4479
                error = xfs_bmap_extents_to_btree(tp, ip, firstblock, flist,
 
4480
                        &cur, 0, &tmp_logflags, whichfork);
 
4481
                logflags |= tmp_logflags;
 
4482
                if (error)
 
4483
                        goto error0;
 
4484
        }
 
4485
        /*
 
4486
         * transform from btree to extents, give it cur
 
4487
         */
 
4488
        else if (XFS_IFORK_FORMAT(ip, whichfork) == XFS_DINODE_FMT_BTREE &&
 
4489
                 XFS_IFORK_NEXTENTS(ip, whichfork) <= ifp->if_ext_max) {
 
4490
                ASSERT(cur != NULL);
 
4491
                error = xfs_bmap_btree_to_extents(tp, ip, cur, &tmp_logflags,
 
4492
                        whichfork, async);
 
4493
                logflags |= tmp_logflags;
 
4494
                if (error)
 
4495
                        goto error0;
 
4496
        }
 
4497
        /*
 
4498
         * transform from extents to local?
 
4499
         */
 
4500
        ASSERT(ifp->if_ext_max ==
 
4501
               XFS_IFORK_SIZE(ip, whichfork) / (uint)sizeof(xfs_bmbt_rec_t));
 
4502
        error = 0;
 
4503
error0:
 
4504
        /*
 
4505
         * Log everything.  Do this after conversion, there's no point in
 
4506
         * logging the extent list if we've converted to btree format.
 
4507
         */
 
4508
        if ((logflags & XFS_ILOG_FEXT(whichfork)) &&
 
4509
            XFS_IFORK_FORMAT(ip, whichfork) != XFS_DINODE_FMT_EXTENTS)
 
4510
                logflags &= ~XFS_ILOG_FEXT(whichfork);
 
4511
        else if ((logflags & XFS_ILOG_FBROOT(whichfork)) &&
 
4512
                 XFS_IFORK_FORMAT(ip, whichfork) != XFS_DINODE_FMT_BTREE)
 
4513
                logflags &= ~XFS_ILOG_FBROOT(whichfork);
 
4514
        /*
 
4515
         * Log inode even in the error case, if the transaction 
 
4516
         * is dirty we'll need to shut down the filesystem.
 
4517
         */
 
4518
        if (logflags)
 
4519
                xfs_trans_log_inode(tp, ip, logflags);
 
4520
        if (cur) {
 
4521
                if (!error) {
 
4522
                        *firstblock = cur->bc_private.b.firstblock;
 
4523
                        cur->bc_private.b.allocated = 0;
 
4524
                }
 
4525
                xfs_btree_del_cursor(cur,
 
4526
                        error ? XFS_BTREE_ERROR : XFS_BTREE_NOERROR);
 
4527
        }
 
4528
        return error;
 
4529
}
 
4530
 
 
4531
/*
 
4532
 * Check the last inode extent to determine whether this allocation will result 
 
4533
 * in blocks being allocated at the end of the file. When we allocate new data 
 
4534
 * blocks at the end of the file which do not start at the previous data block,
 
4535
 * we will try to align the new blocks at stripe unit boundaries.
 
4536
 */
 
4537
int                                     /* error */
 
4538
xfs_bmap_isaeof(
 
4539
        xfs_inode_t     *ip,            /* incore inode pointer */
 
4540
        xfs_fileoff_t   off,            /* file offset in fsblocks */
 
4541
        int             whichfork,      /* data or attribute fork */
 
4542
        int             *aeof)          /* return value */
 
4543
{
 
4544
        int             error;          /* error return value */
 
4545
        xfs_ifork_t     *ifp;           /* inode fork pointer */
 
4546
        xfs_bmbt_rec_t  *lastrec;       /* extent list entry pointer */
 
4547
        xfs_extnum_t    nextents;       /* size of extent list */
 
4548
        xfs_bmbt_irec_t s;              /* expanded extent list entry */
 
4549
 
 
4550
        ASSERT(whichfork == XFS_DATA_FORK);
 
4551
        ifp = XFS_IFORK_PTR(ip, whichfork);
 
4552
        if (!(ifp->if_flags & XFS_IFEXTENTS) &&
 
4553
            (error = xfs_iread_extents(NULL, ip, whichfork)))
 
4554
                return error;
 
4555
        nextents = ifp->if_bytes / (uint)sizeof(xfs_bmbt_rec_t);
 
4556
        if (nextents == 0) {
 
4557
                *aeof = 1;
 
4558
                return 0;
 
4559
        }
 
4560
        /*
 
4561
         * Go to the last extent
 
4562
         */
 
4563
        lastrec = &ifp->if_u1.if_extents[nextents - 1];
 
4564
        xfs_bmbt_get_all(lastrec, &s);
 
4565
        /*
 
4566
         * Check we are allocating in the last extent (for delayed allocations)
 
4567
         * or past the last extent for non-delayed allocations.
 
4568
         */ 
 
4569
        *aeof = (off >= s.br_startoff &&
 
4570
                 off < s.br_startoff + s.br_blockcount &&
 
4571
                 ISNULLSTARTBLOCK(s.br_startblock)) ||
 
4572
                off >= s.br_startoff + s.br_blockcount;
 
4573
        return 0;
 
4574
}