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

Subversion Repositories test_project

[/] [test_project/] [trunk/] [linux_sd_driver/] [fs/] [xfs/] [xfs_bmap.c] - Blame information for rev 82

Go to most recent revision | Details | Compare with Previous | View Log

Line No. Rev Author Line
1 62 marcus.erl
/*
2
 * Copyright (c) 2000-2006 Silicon Graphics, Inc.
3
 * All Rights Reserved.
4
 *
5
 * This program is free software; you can redistribute it and/or
6
 * modify it under the terms of the GNU General Public License as
7
 * published by the Free Software Foundation.
8
 *
9
 * This program is distributed in the hope that it would be useful,
10
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
12
 * GNU General Public License for more details.
13
 *
14
 * You should have received a copy of the GNU General Public License
15
 * along with this program; if not, write the Free Software Foundation,
16
 * Inc.,  51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
17
 */
18
#include "xfs.h"
19
#include "xfs_fs.h"
20
#include "xfs_types.h"
21
#include "xfs_bit.h"
22
#include "xfs_log.h"
23
#include "xfs_inum.h"
24
#include "xfs_trans.h"
25
#include "xfs_sb.h"
26
#include "xfs_ag.h"
27
#include "xfs_dir2.h"
28
#include "xfs_da_btree.h"
29
#include "xfs_bmap_btree.h"
30
#include "xfs_alloc_btree.h"
31
#include "xfs_ialloc_btree.h"
32
#include "xfs_dir2_sf.h"
33
#include "xfs_attr_sf.h"
34
#include "xfs_dinode.h"
35
#include "xfs_inode.h"
36
#include "xfs_btree.h"
37
#include "xfs_dmapi.h"
38
#include "xfs_mount.h"
39
#include "xfs_ialloc.h"
40
#include "xfs_itable.h"
41
#include "xfs_dir2_data.h"
42
#include "xfs_dir2_leaf.h"
43
#include "xfs_dir2_block.h"
44
#include "xfs_inode_item.h"
45
#include "xfs_extfree_item.h"
46
#include "xfs_alloc.h"
47
#include "xfs_bmap.h"
48
#include "xfs_rtalloc.h"
49
#include "xfs_error.h"
50
#include "xfs_attr_leaf.h"
51
#include "xfs_rw.h"
52
#include "xfs_quota.h"
53
#include "xfs_trans_space.h"
54
#include "xfs_buf_item.h"
55
#include "xfs_filestream.h"
56
#include "xfs_vnodeops.h"
57
 
58
 
59
#ifdef DEBUG
60
STATIC void
61
xfs_bmap_check_leaf_extents(xfs_btree_cur_t *cur, xfs_inode_t *ip, int whichfork);
62
#endif
63
 
64
kmem_zone_t             *xfs_bmap_free_item_zone;
65
 
66
/*
67
 * Prototypes for internal bmap routines.
68
 */
69
 
70
 
71
/*
72
 * Called from xfs_bmap_add_attrfork to handle extents format files.
73
 */
74
STATIC int                                      /* error */
75
xfs_bmap_add_attrfork_extents(
76
        xfs_trans_t             *tp,            /* transaction pointer */
77
        xfs_inode_t             *ip,            /* incore inode pointer */
78
        xfs_fsblock_t           *firstblock,    /* first block allocated */
79
        xfs_bmap_free_t         *flist,         /* blocks to free at commit */
80
        int                     *flags);        /* inode logging flags */
81
 
82
/*
83
 * Called from xfs_bmap_add_attrfork to handle local format files.
84
 */
85
STATIC int                                      /* error */
86
xfs_bmap_add_attrfork_local(
87
        xfs_trans_t             *tp,            /* transaction pointer */
88
        xfs_inode_t             *ip,            /* incore inode pointer */
89
        xfs_fsblock_t           *firstblock,    /* first block allocated */
90
        xfs_bmap_free_t         *flist,         /* blocks to free at commit */
91
        int                     *flags);        /* inode logging flags */
92
 
93
/*
94
 * Called by xfs_bmapi to update file extent records and the btree
95
 * after allocating space (or doing a delayed allocation).
96
 */
97
STATIC int                              /* error */
98
xfs_bmap_add_extent(
99
        xfs_inode_t             *ip,    /* incore inode pointer */
100
        xfs_extnum_t            idx,    /* extent number to update/insert */
101
        xfs_btree_cur_t         **curp, /* if *curp is null, not a btree */
102
        xfs_bmbt_irec_t         *new,   /* new data to add to file extents */
103
        xfs_fsblock_t           *first, /* pointer to firstblock variable */
104
        xfs_bmap_free_t         *flist, /* list of extents to be freed */
105
        int                     *logflagsp, /* inode logging flags */
106
        xfs_extdelta_t          *delta, /* Change made to incore extents */
107
        int                     whichfork, /* data or attr fork */
108
        int                     rsvd);  /* OK to allocate reserved blocks */
109
 
110
/*
111
 * Called by xfs_bmap_add_extent to handle cases converting a delayed
112
 * allocation to a real allocation.
113
 */
114
STATIC int                              /* error */
115
xfs_bmap_add_extent_delay_real(
116
        xfs_inode_t             *ip,    /* incore inode pointer */
117
        xfs_extnum_t            idx,    /* extent number to update/insert */
118
        xfs_btree_cur_t         **curp, /* if *curp is null, not a btree */
119
        xfs_bmbt_irec_t         *new,   /* new data to add to file extents */
120
        xfs_filblks_t           *dnew,  /* new delayed-alloc indirect blocks */
121
        xfs_fsblock_t           *first, /* pointer to firstblock variable */
122
        xfs_bmap_free_t         *flist, /* list of extents to be freed */
123
        int                     *logflagsp, /* inode logging flags */
124
        xfs_extdelta_t          *delta, /* Change made to incore extents */
125
        int                     rsvd);  /* OK to allocate reserved blocks */
126
 
127
/*
128
 * Called by xfs_bmap_add_extent to handle cases converting a hole
129
 * to a delayed allocation.
130
 */
131
STATIC int                              /* error */
132
xfs_bmap_add_extent_hole_delay(
133
        xfs_inode_t             *ip,    /* incore inode pointer */
134
        xfs_extnum_t            idx,    /* extent number to update/insert */
135
        xfs_bmbt_irec_t         *new,   /* new data to add to file extents */
136
        int                     *logflagsp,/* inode logging flags */
137
        xfs_extdelta_t          *delta, /* Change made to incore extents */
138
        int                     rsvd);  /* OK to allocate reserved blocks */
139
 
140
/*
141
 * Called by xfs_bmap_add_extent to handle cases converting a hole
142
 * to a real allocation.
143
 */
144
STATIC int                              /* error */
145
xfs_bmap_add_extent_hole_real(
146
        xfs_inode_t             *ip,    /* incore inode pointer */
147
        xfs_extnum_t            idx,    /* extent number to update/insert */
148
        xfs_btree_cur_t         *cur,   /* if null, not a btree */
149
        xfs_bmbt_irec_t         *new,   /* new data to add to file extents */
150
        int                     *logflagsp, /* inode logging flags */
151
        xfs_extdelta_t          *delta, /* Change made to incore extents */
152
        int                     whichfork); /* data or attr fork */
153
 
154
/*
155
 * Called by xfs_bmap_add_extent to handle cases converting an unwritten
156
 * allocation to a real allocation or vice versa.
157
 */
158
STATIC int                              /* error */
159
xfs_bmap_add_extent_unwritten_real(
160
        xfs_inode_t             *ip,    /* incore inode pointer */
161
        xfs_extnum_t            idx,    /* extent number to update/insert */
162
        xfs_btree_cur_t         **curp, /* if *curp is null, not a btree */
163
        xfs_bmbt_irec_t         *new,   /* new data to add to file extents */
164
        int                     *logflagsp, /* inode logging flags */
165
        xfs_extdelta_t          *delta); /* Change made to incore extents */
166
 
167
/*
168
 * xfs_bmap_alloc is called by xfs_bmapi to allocate an extent for a file.
169
 * It figures out where to ask the underlying allocator to put the new extent.
170
 */
171
STATIC int                              /* error */
172
xfs_bmap_alloc(
173
        xfs_bmalloca_t          *ap);   /* bmap alloc argument struct */
174
 
175
/*
176
 * Transform a btree format file with only one leaf node, where the
177
 * extents list will fit in the inode, into an extents format file.
178
 * Since the file extents are already in-core, all we have to do is
179
 * give up the space for the btree root and pitch the leaf block.
180
 */
181
STATIC int                              /* error */
182
xfs_bmap_btree_to_extents(
183
        xfs_trans_t             *tp,    /* transaction pointer */
184
        xfs_inode_t             *ip,    /* incore inode pointer */
185
        xfs_btree_cur_t         *cur,   /* btree cursor */
186
        int                     *logflagsp, /* inode logging flags */
187
        int                     whichfork); /* data or attr fork */
188
 
189
/*
190
 * Called by xfs_bmapi to update file extent records and the btree
191
 * after removing space (or undoing a delayed allocation).
192
 */
193
STATIC int                              /* error */
194
xfs_bmap_del_extent(
195
        xfs_inode_t             *ip,    /* incore inode pointer */
196
        xfs_trans_t             *tp,    /* current trans pointer */
197
        xfs_extnum_t            idx,    /* extent number to update/insert */
198
        xfs_bmap_free_t         *flist, /* list of extents to be freed */
199
        xfs_btree_cur_t         *cur,   /* if null, not a btree */
200
        xfs_bmbt_irec_t         *new,   /* new data to add to file extents */
201
        int                     *logflagsp,/* inode logging flags */
202
        xfs_extdelta_t          *delta, /* Change made to incore extents */
203
        int                     whichfork, /* data or attr fork */
204
        int                     rsvd);   /* OK to allocate reserved blocks */
205
 
206
/*
207
 * Remove the entry "free" from the free item list.  Prev points to the
208
 * previous entry, unless "free" is the head of the list.
209
 */
210
STATIC void
211
xfs_bmap_del_free(
212
        xfs_bmap_free_t         *flist, /* free item list header */
213
        xfs_bmap_free_item_t    *prev,  /* previous item on list, if any */
214
        xfs_bmap_free_item_t    *free); /* list item to be freed */
215
 
216
/*
217
 * Convert an extents-format file into a btree-format file.
218
 * The new file will have a root block (in the inode) and a single child block.
219
 */
220
STATIC int                                      /* error */
221
xfs_bmap_extents_to_btree(
222
        xfs_trans_t             *tp,            /* transaction pointer */
223
        xfs_inode_t             *ip,            /* incore inode pointer */
224
        xfs_fsblock_t           *firstblock,    /* first-block-allocated */
225
        xfs_bmap_free_t         *flist,         /* blocks freed in xaction */
226
        xfs_btree_cur_t         **curp,         /* cursor returned to caller */
227
        int                     wasdel,         /* converting a delayed alloc */
228
        int                     *logflagsp,     /* inode logging flags */
229
        int                     whichfork);     /* data or attr fork */
230
 
231
/*
232
 * Convert a local file to an extents file.
233
 * This code is sort of bogus, since the file data needs to get
234
 * logged so it won't be lost.  The bmap-level manipulations are ok, though.
235
 */
236
STATIC int                              /* error */
237
xfs_bmap_local_to_extents(
238
        xfs_trans_t     *tp,            /* transaction pointer */
239
        xfs_inode_t     *ip,            /* incore inode pointer */
240
        xfs_fsblock_t   *firstblock,    /* first block allocated in xaction */
241
        xfs_extlen_t    total,          /* total blocks needed by transaction */
242
        int             *logflagsp,     /* inode logging flags */
243
        int             whichfork);     /* data or attr fork */
244
 
245
/*
246
 * Search the extents list for the inode, for the extent containing bno.
247
 * If bno lies in a hole, point to the next entry.  If bno lies past eof,
248
 * *eofp will be set, and *prevp will contain the last entry (null if none).
249
 * Else, *lastxp will be set to the index of the found
250
 * entry; *gotp will contain the entry.
251
 */
252
STATIC xfs_bmbt_rec_host_t *            /* pointer to found extent entry */
253
xfs_bmap_search_extents(
254
        xfs_inode_t     *ip,            /* incore inode pointer */
255
        xfs_fileoff_t   bno,            /* block number searched for */
256
        int             whichfork,      /* data or attr fork */
257
        int             *eofp,          /* out: end of file found */
258
        xfs_extnum_t    *lastxp,        /* out: last extent index */
259
        xfs_bmbt_irec_t *gotp,          /* out: extent entry found */
260
        xfs_bmbt_irec_t *prevp);        /* out: previous extent entry found */
261
 
262
/*
263
 * Check the last inode extent to determine whether this allocation will result
264
 * in blocks being allocated at the end of the file. When we allocate new data
265
 * blocks at the end of the file which do not start at the previous data block,
266
 * we will try to align the new blocks at stripe unit boundaries.
267
 */
268
STATIC int                              /* error */
269
xfs_bmap_isaeof(
270
        xfs_inode_t     *ip,            /* incore inode pointer */
271
        xfs_fileoff_t   off,            /* file offset in fsblocks */
272
        int             whichfork,      /* data or attribute fork */
273
        char            *aeof);         /* return value */
274
 
275
#ifdef XFS_BMAP_TRACE
276
/*
277
 * Add bmap trace entry prior to a call to xfs_iext_remove.
278
 */
279
STATIC void
280
xfs_bmap_trace_delete(
281
        const char      *fname,         /* function name */
282
        char            *desc,          /* operation description */
283
        xfs_inode_t     *ip,            /* incore inode pointer */
284
        xfs_extnum_t    idx,            /* index of entry(entries) deleted */
285
        xfs_extnum_t    cnt,            /* count of entries deleted, 1 or 2 */
286
        int             whichfork);     /* data or attr fork */
287
 
288
/*
289
 * Add bmap trace entry prior to a call to xfs_iext_insert, or
290
 * reading in the extents list from the disk (in the btree).
291
 */
292
STATIC void
293
xfs_bmap_trace_insert(
294
        const char      *fname,         /* function name */
295
        char            *desc,          /* operation description */
296
        xfs_inode_t     *ip,            /* incore inode pointer */
297
        xfs_extnum_t    idx,            /* index of entry(entries) inserted */
298
        xfs_extnum_t    cnt,            /* count of entries inserted, 1 or 2 */
299
        xfs_bmbt_irec_t *r1,            /* inserted record 1 */
300
        xfs_bmbt_irec_t *r2,            /* inserted record 2 or null */
301
        int             whichfork);     /* data or attr fork */
302
 
303
/*
304
 * Add bmap trace entry after updating an extent record in place.
305
 */
306
STATIC void
307
xfs_bmap_trace_post_update(
308
        const char      *fname,         /* function name */
309
        char            *desc,          /* operation description */
310
        xfs_inode_t     *ip,            /* incore inode pointer */
311
        xfs_extnum_t    idx,            /* index of entry updated */
312
        int             whichfork);     /* data or attr fork */
313
 
314
/*
315
 * Add bmap trace entry prior to updating an extent record in place.
316
 */
317
STATIC void
318
xfs_bmap_trace_pre_update(
319
        const char      *fname,         /* function name */
320
        char            *desc,          /* operation description */
321
        xfs_inode_t     *ip,            /* incore inode pointer */
322
        xfs_extnum_t    idx,            /* index of entry to be updated */
323
        int             whichfork);     /* data or attr fork */
324
 
325
#define XFS_BMAP_TRACE_DELETE(d,ip,i,c,w)       \
326
        xfs_bmap_trace_delete(__FUNCTION__,d,ip,i,c,w)
327
#define XFS_BMAP_TRACE_INSERT(d,ip,i,c,r1,r2,w) \
328
        xfs_bmap_trace_insert(__FUNCTION__,d,ip,i,c,r1,r2,w)
329
#define XFS_BMAP_TRACE_POST_UPDATE(d,ip,i,w)    \
330
        xfs_bmap_trace_post_update(__FUNCTION__,d,ip,i,w)
331
#define XFS_BMAP_TRACE_PRE_UPDATE(d,ip,i,w)     \
332
        xfs_bmap_trace_pre_update(__FUNCTION__,d,ip,i,w)
333
#else
334
#define XFS_BMAP_TRACE_DELETE(d,ip,i,c,w)
335
#define XFS_BMAP_TRACE_INSERT(d,ip,i,c,r1,r2,w)
336
#define XFS_BMAP_TRACE_POST_UPDATE(d,ip,i,w)
337
#define XFS_BMAP_TRACE_PRE_UPDATE(d,ip,i,w)
338
#endif  /* XFS_BMAP_TRACE */
339
 
340
/*
341
 * Compute the worst-case number of indirect blocks that will be used
342
 * for ip's delayed extent of length "len".
343
 */
344
STATIC xfs_filblks_t
345
xfs_bmap_worst_indlen(
346
        xfs_inode_t             *ip,    /* incore inode pointer */
347
        xfs_filblks_t           len);   /* delayed extent length */
348
 
349
#ifdef DEBUG
350
/*
351
 * Perform various validation checks on the values being returned
352
 * from xfs_bmapi().
353
 */
354
STATIC void
355
xfs_bmap_validate_ret(
356
        xfs_fileoff_t           bno,
357
        xfs_filblks_t           len,
358
        int                     flags,
359
        xfs_bmbt_irec_t         *mval,
360
        int                     nmap,
361
        int                     ret_nmap);
362
#else
363
#define xfs_bmap_validate_ret(bno,len,flags,mval,onmap,nmap)
364
#endif /* DEBUG */
365
 
366
#if defined(XFS_RW_TRACE)
367
STATIC void
368
xfs_bunmap_trace(
369
        xfs_inode_t             *ip,
370
        xfs_fileoff_t           bno,
371
        xfs_filblks_t           len,
372
        int                     flags,
373
        inst_t                  *ra);
374
#else
375
#define xfs_bunmap_trace(ip, bno, len, flags, ra)
376
#endif  /* XFS_RW_TRACE */
377
 
378
STATIC int
379
xfs_bmap_count_tree(
380
        xfs_mount_t     *mp,
381
        xfs_trans_t     *tp,
382
        xfs_ifork_t     *ifp,
383
        xfs_fsblock_t   blockno,
384
        int             levelin,
385
        int             *count);
386
 
387
STATIC int
388
xfs_bmap_count_leaves(
389
        xfs_ifork_t             *ifp,
390
        xfs_extnum_t            idx,
391
        int                     numrecs,
392
        int                     *count);
393
 
394
STATIC int
395
xfs_bmap_disk_count_leaves(
396
        xfs_extnum_t            idx,
397
        xfs_bmbt_block_t        *block,
398
        int                     numrecs,
399
        int                     *count);
400
 
401
/*
402
 * Bmap internal routines.
403
 */
404
 
405
/*
406
 * Called from xfs_bmap_add_attrfork to handle btree format files.
407
 */
408
STATIC int                                      /* error */
409
xfs_bmap_add_attrfork_btree(
410
        xfs_trans_t             *tp,            /* transaction pointer */
411
        xfs_inode_t             *ip,            /* incore inode pointer */
412
        xfs_fsblock_t           *firstblock,    /* first block allocated */
413
        xfs_bmap_free_t         *flist,         /* blocks to free at commit */
414
        int                     *flags)         /* inode logging flags */
415
{
416
        xfs_btree_cur_t         *cur;           /* btree cursor */
417
        int                     error;          /* error return value */
418
        xfs_mount_t             *mp;            /* file system mount struct */
419
        int                     stat;           /* newroot status */
420
 
421
        mp = ip->i_mount;
422
        if (ip->i_df.if_broot_bytes <= XFS_IFORK_DSIZE(ip))
423
                *flags |= XFS_ILOG_DBROOT;
424
        else {
425
                cur = xfs_btree_init_cursor(mp, tp, NULL, 0, XFS_BTNUM_BMAP, ip,
426
                        XFS_DATA_FORK);
427
                cur->bc_private.b.flist = flist;
428
                cur->bc_private.b.firstblock = *firstblock;
429
                if ((error = xfs_bmbt_lookup_ge(cur, 0, 0, 0, &stat)))
430
                        goto error0;
431
                ASSERT(stat == 1);      /* must be at least one entry */
432
                if ((error = xfs_bmbt_newroot(cur, flags, &stat)))
433
                        goto error0;
434
                if (stat == 0) {
435
                        xfs_btree_del_cursor(cur, XFS_BTREE_NOERROR);
436
                        return XFS_ERROR(ENOSPC);
437
                }
438
                *firstblock = cur->bc_private.b.firstblock;
439
                cur->bc_private.b.allocated = 0;
440
                xfs_btree_del_cursor(cur, XFS_BTREE_NOERROR);
441
        }
442
        return 0;
443
error0:
444
        xfs_btree_del_cursor(cur, XFS_BTREE_ERROR);
445
        return error;
446
}
447
 
448
/*
449
 * Called from xfs_bmap_add_attrfork to handle extents format files.
450
 */
451
STATIC int                                      /* error */
452
xfs_bmap_add_attrfork_extents(
453
        xfs_trans_t             *tp,            /* transaction pointer */
454
        xfs_inode_t             *ip,            /* incore inode pointer */
455
        xfs_fsblock_t           *firstblock,    /* first block allocated */
456
        xfs_bmap_free_t         *flist,         /* blocks to free at commit */
457
        int                     *flags)         /* inode logging flags */
458
{
459
        xfs_btree_cur_t         *cur;           /* bmap btree cursor */
460
        int                     error;          /* error return value */
461
 
462
        if (ip->i_d.di_nextents * sizeof(xfs_bmbt_rec_t) <= XFS_IFORK_DSIZE(ip))
463
                return 0;
464
        cur = NULL;
465
        error = xfs_bmap_extents_to_btree(tp, ip, firstblock, flist, &cur, 0,
466
                flags, XFS_DATA_FORK);
467
        if (cur) {
468
                cur->bc_private.b.allocated = 0;
469
                xfs_btree_del_cursor(cur,
470
                        error ? XFS_BTREE_ERROR : XFS_BTREE_NOERROR);
471
        }
472
        return error;
473
}
474
 
475
/*
476
 * Called from xfs_bmap_add_attrfork to handle local format files.
477
 */
478
STATIC int                                      /* error */
479
xfs_bmap_add_attrfork_local(
480
        xfs_trans_t             *tp,            /* transaction pointer */
481
        xfs_inode_t             *ip,            /* incore inode pointer */
482
        xfs_fsblock_t           *firstblock,    /* first block allocated */
483
        xfs_bmap_free_t         *flist,         /* blocks to free at commit */
484
        int                     *flags)         /* inode logging flags */
485
{
486
        xfs_da_args_t           dargs;          /* args for dir/attr code */
487
        int                     error;          /* error return value */
488
        xfs_mount_t             *mp;            /* mount structure pointer */
489
 
490
        if (ip->i_df.if_bytes <= XFS_IFORK_DSIZE(ip))
491
                return 0;
492
        if ((ip->i_d.di_mode & S_IFMT) == S_IFDIR) {
493
                mp = ip->i_mount;
494
                memset(&dargs, 0, sizeof(dargs));
495
                dargs.dp = ip;
496
                dargs.firstblock = firstblock;
497
                dargs.flist = flist;
498
                dargs.total = mp->m_dirblkfsbs;
499
                dargs.whichfork = XFS_DATA_FORK;
500
                dargs.trans = tp;
501
                error = xfs_dir2_sf_to_block(&dargs);
502
        } else
503
                error = xfs_bmap_local_to_extents(tp, ip, firstblock, 1, flags,
504
                        XFS_DATA_FORK);
505
        return error;
506
}
507
 
508
/*
509
 * Called by xfs_bmapi to update file extent records and the btree
510
 * after allocating space (or doing a delayed allocation).
511
 */
512
STATIC int                              /* error */
513
xfs_bmap_add_extent(
514
        xfs_inode_t             *ip,    /* incore inode pointer */
515
        xfs_extnum_t            idx,    /* extent number to update/insert */
516
        xfs_btree_cur_t         **curp, /* if *curp is null, not a btree */
517
        xfs_bmbt_irec_t         *new,   /* new data to add to file extents */
518
        xfs_fsblock_t           *first, /* pointer to firstblock variable */
519
        xfs_bmap_free_t         *flist, /* list of extents to be freed */
520
        int                     *logflagsp, /* inode logging flags */
521
        xfs_extdelta_t          *delta, /* Change made to incore extents */
522
        int                     whichfork, /* data or attr fork */
523
        int                     rsvd)   /* OK to use reserved data blocks */
524
{
525
        xfs_btree_cur_t         *cur;   /* btree cursor or null */
526
        xfs_filblks_t           da_new; /* new count del alloc blocks used */
527
        xfs_filblks_t           da_old; /* old count del alloc blocks used */
528
        int                     error;  /* error return value */
529
        xfs_ifork_t             *ifp;   /* inode fork ptr */
530
        int                     logflags; /* returned value */
531
        xfs_extnum_t            nextents; /* number of extents in file now */
532
 
533
        XFS_STATS_INC(xs_add_exlist);
534
        cur = *curp;
535
        ifp = XFS_IFORK_PTR(ip, whichfork);
536
        nextents = ifp->if_bytes / (uint)sizeof(xfs_bmbt_rec_t);
537
        ASSERT(idx <= nextents);
538
        da_old = da_new = 0;
539
        error = 0;
540
        /*
541
         * This is the first extent added to a new/empty file.
542
         * Special case this one, so other routines get to assume there are
543
         * already extents in the list.
544
         */
545
        if (nextents == 0) {
546
                XFS_BMAP_TRACE_INSERT("insert empty", ip, 0, 1, new, NULL,
547
                        whichfork);
548
                xfs_iext_insert(ifp, 0, 1, new);
549
                ASSERT(cur == NULL);
550
                ifp->if_lastex = 0;
551
                if (!ISNULLSTARTBLOCK(new->br_startblock)) {
552
                        XFS_IFORK_NEXT_SET(ip, whichfork, 1);
553
                        logflags = XFS_ILOG_CORE | XFS_ILOG_FEXT(whichfork);
554
                } else
555
                        logflags = 0;
556
                /* DELTA: single new extent */
557
                if (delta) {
558
                        if (delta->xed_startoff > new->br_startoff)
559
                                delta->xed_startoff = new->br_startoff;
560
                        if (delta->xed_blockcount <
561
                                        new->br_startoff + new->br_blockcount)
562
                                delta->xed_blockcount = new->br_startoff +
563
                                                new->br_blockcount;
564
                }
565
        }
566
        /*
567
         * Any kind of new delayed allocation goes here.
568
         */
569
        else if (ISNULLSTARTBLOCK(new->br_startblock)) {
570
                if (cur)
571
                        ASSERT((cur->bc_private.b.flags &
572
                                XFS_BTCUR_BPRV_WASDEL) == 0);
573
                if ((error = xfs_bmap_add_extent_hole_delay(ip, idx, new,
574
                                &logflags, delta, rsvd)))
575
                        goto done;
576
        }
577
        /*
578
         * Real allocation off the end of the file.
579
         */
580
        else if (idx == nextents) {
581
                if (cur)
582
                        ASSERT((cur->bc_private.b.flags &
583
                                XFS_BTCUR_BPRV_WASDEL) == 0);
584
                if ((error = xfs_bmap_add_extent_hole_real(ip, idx, cur, new,
585
                                &logflags, delta, whichfork)))
586
                        goto done;
587
        } else {
588
                xfs_bmbt_irec_t prev;   /* old extent at offset idx */
589
 
590
                /*
591
                 * Get the record referred to by idx.
592
                 */
593
                xfs_bmbt_get_all(xfs_iext_get_ext(ifp, idx), &prev);
594
                /*
595
                 * If it's a real allocation record, and the new allocation ends
596
                 * after the start of the referred to record, then we're filling
597
                 * in a delayed or unwritten allocation with a real one, or
598
                 * converting real back to unwritten.
599
                 */
600
                if (!ISNULLSTARTBLOCK(new->br_startblock) &&
601
                    new->br_startoff + new->br_blockcount > prev.br_startoff) {
602
                        if (prev.br_state != XFS_EXT_UNWRITTEN &&
603
                            ISNULLSTARTBLOCK(prev.br_startblock)) {
604
                                da_old = STARTBLOCKVAL(prev.br_startblock);
605
                                if (cur)
606
                                        ASSERT(cur->bc_private.b.flags &
607
                                                XFS_BTCUR_BPRV_WASDEL);
608
                                if ((error = xfs_bmap_add_extent_delay_real(ip,
609
                                        idx, &cur, new, &da_new, first, flist,
610
                                        &logflags, delta, rsvd)))
611
                                        goto done;
612
                        } else if (new->br_state == XFS_EXT_NORM) {
613
                                ASSERT(new->br_state == XFS_EXT_NORM);
614
                                if ((error = xfs_bmap_add_extent_unwritten_real(
615
                                        ip, idx, &cur, new, &logflags, delta)))
616
                                        goto done;
617
                        } else {
618
                                ASSERT(new->br_state == XFS_EXT_UNWRITTEN);
619
                                if ((error = xfs_bmap_add_extent_unwritten_real(
620
                                        ip, idx, &cur, new, &logflags, delta)))
621
                                        goto done;
622
                        }
623
                        ASSERT(*curp == cur || *curp == NULL);
624
                }
625
                /*
626
                 * Otherwise we're filling in a hole with an allocation.
627
                 */
628
                else {
629
                        if (cur)
630
                                ASSERT((cur->bc_private.b.flags &
631
                                        XFS_BTCUR_BPRV_WASDEL) == 0);
632
                        if ((error = xfs_bmap_add_extent_hole_real(ip, idx, cur,
633
                                        new, &logflags, delta, whichfork)))
634
                                goto done;
635
                }
636
        }
637
 
638
        ASSERT(*curp == cur || *curp == NULL);
639
        /*
640
         * Convert to a btree if necessary.
641
         */
642
        if (XFS_IFORK_FORMAT(ip, whichfork) == XFS_DINODE_FMT_EXTENTS &&
643
            XFS_IFORK_NEXTENTS(ip, whichfork) > ifp->if_ext_max) {
644
                int     tmp_logflags;   /* partial log flag return val */
645
 
646
                ASSERT(cur == NULL);
647
                error = xfs_bmap_extents_to_btree(ip->i_transp, ip, first,
648
                        flist, &cur, da_old > 0, &tmp_logflags, whichfork);
649
                logflags |= tmp_logflags;
650
                if (error)
651
                        goto done;
652
        }
653
        /*
654
         * Adjust for changes in reserved delayed indirect blocks.
655
         * Nothing to do for disk quotas here.
656
         */
657
        if (da_old || da_new) {
658
                xfs_filblks_t   nblks;
659
 
660
                nblks = da_new;
661
                if (cur)
662
                        nblks += cur->bc_private.b.allocated;
663
                ASSERT(nblks <= da_old);
664
                if (nblks < da_old)
665
                        xfs_mod_incore_sb(ip->i_mount, XFS_SBS_FDBLOCKS,
666
                                (int64_t)(da_old - nblks), rsvd);
667
        }
668
        /*
669
         * Clear out the allocated field, done with it now in any case.
670
         */
671
        if (cur) {
672
                cur->bc_private.b.allocated = 0;
673
                *curp = cur;
674
        }
675
done:
676
#ifdef DEBUG
677
        if (!error)
678
                xfs_bmap_check_leaf_extents(*curp, ip, whichfork);
679
#endif
680
        *logflagsp = logflags;
681
        return error;
682
}
683
 
684
/*
685
 * Called by xfs_bmap_add_extent to handle cases converting a delayed
686
 * allocation to a real allocation.
687
 */
688
STATIC int                              /* error */
689
xfs_bmap_add_extent_delay_real(
690
        xfs_inode_t             *ip,    /* incore inode pointer */
691
        xfs_extnum_t            idx,    /* extent number to update/insert */
692
        xfs_btree_cur_t         **curp, /* if *curp is null, not a btree */
693
        xfs_bmbt_irec_t         *new,   /* new data to add to file extents */
694
        xfs_filblks_t           *dnew,  /* new delayed-alloc indirect blocks */
695
        xfs_fsblock_t           *first, /* pointer to firstblock variable */
696
        xfs_bmap_free_t         *flist, /* list of extents to be freed */
697
        int                     *logflagsp, /* inode logging flags */
698
        xfs_extdelta_t          *delta, /* Change made to incore extents */
699
        int                     rsvd)   /* OK to use reserved data block allocation */
700
{
701
        xfs_btree_cur_t         *cur;   /* btree cursor */
702
        int                     diff;   /* temp value */
703
        xfs_bmbt_rec_host_t     *ep;    /* extent entry for idx */
704
        int                     error;  /* error return value */
705
        int                     i;      /* temp state */
706
        xfs_ifork_t             *ifp;   /* inode fork pointer */
707
        xfs_fileoff_t           new_endoff;     /* end offset of new entry */
708
        xfs_bmbt_irec_t         r[3];   /* neighbor extent entries */
709
                                        /* left is 0, right is 1, prev is 2 */
710
        int                     rval=0;  /* return value (logging flags) */
711
        int                     state = 0;/* state bits, accessed thru macros */
712
        xfs_filblks_t           temp=0;  /* value for dnew calculations */
713
        xfs_filblks_t           temp2=0;/* value for dnew calculations */
714
        int                     tmp_rval;       /* partial logging flags */
715
        enum {                          /* bit number definitions for state */
716
                LEFT_CONTIG,    RIGHT_CONTIG,
717
                LEFT_FILLING,   RIGHT_FILLING,
718
                LEFT_DELAY,     RIGHT_DELAY,
719
                LEFT_VALID,     RIGHT_VALID
720
        };
721
 
722
#define LEFT            r[0]
723
#define RIGHT           r[1]
724
#define PREV            r[2]
725
#define MASK(b)         (1 << (b))
726
#define MASK2(a,b)      (MASK(a) | MASK(b))
727
#define MASK3(a,b,c)    (MASK2(a,b) | MASK(c))
728
#define MASK4(a,b,c,d)  (MASK3(a,b,c) | MASK(d))
729
#define STATE_SET(b,v)  ((v) ? (state |= MASK(b)) : (state &= ~MASK(b)))
730
#define STATE_TEST(b)   (state & MASK(b))
731
#define STATE_SET_TEST(b,v)     ((v) ? ((state |= MASK(b)), 1) : \
732
                                       ((state &= ~MASK(b)), 0))
733
#define SWITCH_STATE            \
734
        (state & MASK4(LEFT_FILLING, RIGHT_FILLING, LEFT_CONTIG, RIGHT_CONTIG))
735
 
736
        /*
737
         * Set up a bunch of variables to make the tests simpler.
738
         */
739
        cur = *curp;
740
        ifp = XFS_IFORK_PTR(ip, XFS_DATA_FORK);
741
        ep = xfs_iext_get_ext(ifp, idx);
742
        xfs_bmbt_get_all(ep, &PREV);
743
        new_endoff = new->br_startoff + new->br_blockcount;
744
        ASSERT(PREV.br_startoff <= new->br_startoff);
745
        ASSERT(PREV.br_startoff + PREV.br_blockcount >= new_endoff);
746
        /*
747
         * Set flags determining what part of the previous delayed allocation
748
         * extent is being replaced by a real allocation.
749
         */
750
        STATE_SET(LEFT_FILLING, PREV.br_startoff == new->br_startoff);
751
        STATE_SET(RIGHT_FILLING,
752
                PREV.br_startoff + PREV.br_blockcount == new_endoff);
753
        /*
754
         * Check and set flags if this segment has a left neighbor.
755
         * Don't set contiguous if the combined extent would be too large.
756
         */
757
        if (STATE_SET_TEST(LEFT_VALID, idx > 0)) {
758
                xfs_bmbt_get_all(xfs_iext_get_ext(ifp, idx - 1), &LEFT);
759
                STATE_SET(LEFT_DELAY, ISNULLSTARTBLOCK(LEFT.br_startblock));
760
        }
761
        STATE_SET(LEFT_CONTIG,
762
                STATE_TEST(LEFT_VALID) && !STATE_TEST(LEFT_DELAY) &&
763
                LEFT.br_startoff + LEFT.br_blockcount == new->br_startoff &&
764
                LEFT.br_startblock + LEFT.br_blockcount == new->br_startblock &&
765
                LEFT.br_state == new->br_state &&
766
                LEFT.br_blockcount + new->br_blockcount <= MAXEXTLEN);
767
        /*
768
         * Check and set flags if this segment has a right neighbor.
769
         * Don't set contiguous if the combined extent would be too large.
770
         * Also check for all-three-contiguous being too large.
771
         */
772
        if (STATE_SET_TEST(RIGHT_VALID,
773
                        idx <
774
                        ip->i_df.if_bytes / (uint)sizeof(xfs_bmbt_rec_t) - 1)) {
775
                xfs_bmbt_get_all(xfs_iext_get_ext(ifp, idx + 1), &RIGHT);
776
                STATE_SET(RIGHT_DELAY, ISNULLSTARTBLOCK(RIGHT.br_startblock));
777
        }
778
        STATE_SET(RIGHT_CONTIG,
779
                STATE_TEST(RIGHT_VALID) && !STATE_TEST(RIGHT_DELAY) &&
780
                new_endoff == RIGHT.br_startoff &&
781
                new->br_startblock + new->br_blockcount ==
782
                    RIGHT.br_startblock &&
783
                new->br_state == RIGHT.br_state &&
784
                new->br_blockcount + RIGHT.br_blockcount <= MAXEXTLEN &&
785
                ((state & MASK3(LEFT_CONTIG, LEFT_FILLING, RIGHT_FILLING)) !=
786
                  MASK3(LEFT_CONTIG, LEFT_FILLING, RIGHT_FILLING) ||
787
                 LEFT.br_blockcount + new->br_blockcount + RIGHT.br_blockcount
788
                     <= MAXEXTLEN));
789
        error = 0;
790
        /*
791
         * Switch out based on the FILLING and CONTIG state bits.
792
         */
793
        switch (SWITCH_STATE) {
794
 
795
        case MASK4(LEFT_FILLING, RIGHT_FILLING, LEFT_CONTIG, RIGHT_CONTIG):
796
                /*
797
                 * Filling in all of a previously delayed allocation extent.
798
                 * The left and right neighbors are both contiguous with new.
799
                 */
800
                XFS_BMAP_TRACE_PRE_UPDATE("LF|RF|LC|RC", ip, idx - 1,
801
                        XFS_DATA_FORK);
802
                xfs_bmbt_set_blockcount(xfs_iext_get_ext(ifp, idx - 1),
803
                        LEFT.br_blockcount + PREV.br_blockcount +
804
                        RIGHT.br_blockcount);
805
                XFS_BMAP_TRACE_POST_UPDATE("LF|RF|LC|RC", ip, idx - 1,
806
                        XFS_DATA_FORK);
807
                XFS_BMAP_TRACE_DELETE("LF|RF|LC|RC", ip, idx, 2, XFS_DATA_FORK);
808
                xfs_iext_remove(ifp, idx, 2);
809
                ip->i_df.if_lastex = idx - 1;
810
                ip->i_d.di_nextents--;
811
                if (cur == NULL)
812
                        rval = XFS_ILOG_CORE | XFS_ILOG_DEXT;
813
                else {
814
                        rval = XFS_ILOG_CORE;
815
                        if ((error = xfs_bmbt_lookup_eq(cur, RIGHT.br_startoff,
816
                                        RIGHT.br_startblock,
817
                                        RIGHT.br_blockcount, &i)))
818
                                goto done;
819
                        ASSERT(i == 1);
820
                        if ((error = xfs_bmbt_delete(cur, &i)))
821
                                goto done;
822
                        ASSERT(i == 1);
823
                        if ((error = xfs_bmbt_decrement(cur, 0, &i)))
824
                                goto done;
825
                        ASSERT(i == 1);
826
                        if ((error = xfs_bmbt_update(cur, LEFT.br_startoff,
827
                                        LEFT.br_startblock,
828
                                        LEFT.br_blockcount +
829
                                        PREV.br_blockcount +
830
                                        RIGHT.br_blockcount, LEFT.br_state)))
831
                                goto done;
832
                }
833
                *dnew = 0;
834
                /* DELTA: Three in-core extents are replaced by one. */
835
                temp = LEFT.br_startoff;
836
                temp2 = LEFT.br_blockcount +
837
                        PREV.br_blockcount +
838
                        RIGHT.br_blockcount;
839
                break;
840
 
841
        case MASK3(LEFT_FILLING, RIGHT_FILLING, LEFT_CONTIG):
842
                /*
843
                 * Filling in all of a previously delayed allocation extent.
844
                 * The left neighbor is contiguous, the right is not.
845
                 */
846
                XFS_BMAP_TRACE_PRE_UPDATE("LF|RF|LC", ip, idx - 1,
847
                        XFS_DATA_FORK);
848
                xfs_bmbt_set_blockcount(xfs_iext_get_ext(ifp, idx - 1),
849
                        LEFT.br_blockcount + PREV.br_blockcount);
850
                XFS_BMAP_TRACE_POST_UPDATE("LF|RF|LC", ip, idx - 1,
851
                        XFS_DATA_FORK);
852
                ip->i_df.if_lastex = idx - 1;
853
                XFS_BMAP_TRACE_DELETE("LF|RF|LC", ip, idx, 1, XFS_DATA_FORK);
854
                xfs_iext_remove(ifp, idx, 1);
855
                if (cur == NULL)
856
                        rval = XFS_ILOG_DEXT;
857
                else {
858
                        rval = 0;
859
                        if ((error = xfs_bmbt_lookup_eq(cur, LEFT.br_startoff,
860
                                        LEFT.br_startblock, LEFT.br_blockcount,
861
                                        &i)))
862
                                goto done;
863
                        ASSERT(i == 1);
864
                        if ((error = xfs_bmbt_update(cur, LEFT.br_startoff,
865
                                        LEFT.br_startblock,
866
                                        LEFT.br_blockcount +
867
                                        PREV.br_blockcount, LEFT.br_state)))
868
                                goto done;
869
                }
870
                *dnew = 0;
871
                /* DELTA: Two in-core extents are replaced by one. */
872
                temp = LEFT.br_startoff;
873
                temp2 = LEFT.br_blockcount +
874
                        PREV.br_blockcount;
875
                break;
876
 
877
        case MASK3(LEFT_FILLING, RIGHT_FILLING, RIGHT_CONTIG):
878
                /*
879
                 * Filling in all of a previously delayed allocation extent.
880
                 * The right neighbor is contiguous, the left is not.
881
                 */
882
                XFS_BMAP_TRACE_PRE_UPDATE("LF|RF|RC", ip, idx, XFS_DATA_FORK);
883
                xfs_bmbt_set_startblock(ep, new->br_startblock);
884
                xfs_bmbt_set_blockcount(ep,
885
                        PREV.br_blockcount + RIGHT.br_blockcount);
886
                XFS_BMAP_TRACE_POST_UPDATE("LF|RF|RC", ip, idx, XFS_DATA_FORK);
887
                ip->i_df.if_lastex = idx;
888
                XFS_BMAP_TRACE_DELETE("LF|RF|RC", ip, idx + 1, 1, XFS_DATA_FORK);
889
                xfs_iext_remove(ifp, idx + 1, 1);
890
                if (cur == NULL)
891
                        rval = XFS_ILOG_DEXT;
892
                else {
893
                        rval = 0;
894
                        if ((error = xfs_bmbt_lookup_eq(cur, RIGHT.br_startoff,
895
                                        RIGHT.br_startblock,
896
                                        RIGHT.br_blockcount, &i)))
897
                                goto done;
898
                        ASSERT(i == 1);
899
                        if ((error = xfs_bmbt_update(cur, PREV.br_startoff,
900
                                        new->br_startblock,
901
                                        PREV.br_blockcount +
902
                                        RIGHT.br_blockcount, PREV.br_state)))
903
                                goto done;
904
                }
905
                *dnew = 0;
906
                /* DELTA: Two in-core extents are replaced by one. */
907
                temp = PREV.br_startoff;
908
                temp2 = PREV.br_blockcount +
909
                        RIGHT.br_blockcount;
910
                break;
911
 
912
        case MASK2(LEFT_FILLING, RIGHT_FILLING):
913
                /*
914
                 * Filling in all of a previously delayed allocation extent.
915
                 * Neither the left nor right neighbors are contiguous with
916
                 * the new one.
917
                 */
918
                XFS_BMAP_TRACE_PRE_UPDATE("LF|RF", ip, idx, XFS_DATA_FORK);
919
                xfs_bmbt_set_startblock(ep, new->br_startblock);
920
                XFS_BMAP_TRACE_POST_UPDATE("LF|RF", ip, idx, XFS_DATA_FORK);
921
                ip->i_df.if_lastex = idx;
922
                ip->i_d.di_nextents++;
923
                if (cur == NULL)
924
                        rval = XFS_ILOG_CORE | XFS_ILOG_DEXT;
925
                else {
926
                        rval = XFS_ILOG_CORE;
927
                        if ((error = xfs_bmbt_lookup_eq(cur, new->br_startoff,
928
                                        new->br_startblock, new->br_blockcount,
929
                                        &i)))
930
                                goto done;
931
                        ASSERT(i == 0);
932
                        cur->bc_rec.b.br_state = XFS_EXT_NORM;
933
                        if ((error = xfs_bmbt_insert(cur, &i)))
934
                                goto done;
935
                        ASSERT(i == 1);
936
                }
937
                *dnew = 0;
938
                /* DELTA: The in-core extent described by new changed type. */
939
                temp = new->br_startoff;
940
                temp2 = new->br_blockcount;
941
                break;
942
 
943
        case MASK2(LEFT_FILLING, LEFT_CONTIG):
944
                /*
945
                 * Filling in the first part of a previous delayed allocation.
946
                 * The left neighbor is contiguous.
947
                 */
948
                XFS_BMAP_TRACE_PRE_UPDATE("LF|LC", ip, idx - 1, XFS_DATA_FORK);
949
                xfs_bmbt_set_blockcount(xfs_iext_get_ext(ifp, idx - 1),
950
                        LEFT.br_blockcount + new->br_blockcount);
951
                xfs_bmbt_set_startoff(ep,
952
                        PREV.br_startoff + new->br_blockcount);
953
                XFS_BMAP_TRACE_POST_UPDATE("LF|LC", ip, idx - 1, XFS_DATA_FORK);
954
                temp = PREV.br_blockcount - new->br_blockcount;
955
                XFS_BMAP_TRACE_PRE_UPDATE("LF|LC", ip, idx, XFS_DATA_FORK);
956
                xfs_bmbt_set_blockcount(ep, temp);
957
                ip->i_df.if_lastex = idx - 1;
958
                if (cur == NULL)
959
                        rval = XFS_ILOG_DEXT;
960
                else {
961
                        rval = 0;
962
                        if ((error = xfs_bmbt_lookup_eq(cur, LEFT.br_startoff,
963
                                        LEFT.br_startblock, LEFT.br_blockcount,
964
                                        &i)))
965
                                goto done;
966
                        ASSERT(i == 1);
967
                        if ((error = xfs_bmbt_update(cur, LEFT.br_startoff,
968
                                        LEFT.br_startblock,
969
                                        LEFT.br_blockcount +
970
                                        new->br_blockcount,
971
                                        LEFT.br_state)))
972
                                goto done;
973
                }
974
                temp = XFS_FILBLKS_MIN(xfs_bmap_worst_indlen(ip, temp),
975
                        STARTBLOCKVAL(PREV.br_startblock));
976
                xfs_bmbt_set_startblock(ep, NULLSTARTBLOCK((int)temp));
977
                XFS_BMAP_TRACE_POST_UPDATE("LF|LC", ip, idx, XFS_DATA_FORK);
978
                *dnew = temp;
979
                /* DELTA: The boundary between two in-core extents moved. */
980
                temp = LEFT.br_startoff;
981
                temp2 = LEFT.br_blockcount +
982
                        PREV.br_blockcount;
983
                break;
984
 
985
        case MASK(LEFT_FILLING):
986
                /*
987
                 * Filling in the first part of a previous delayed allocation.
988
                 * The left neighbor is not contiguous.
989
                 */
990
                XFS_BMAP_TRACE_PRE_UPDATE("LF", ip, idx, XFS_DATA_FORK);
991
                xfs_bmbt_set_startoff(ep, new_endoff);
992
                temp = PREV.br_blockcount - new->br_blockcount;
993
                xfs_bmbt_set_blockcount(ep, temp);
994
                XFS_BMAP_TRACE_INSERT("LF", ip, idx, 1, new, NULL,
995
                        XFS_DATA_FORK);
996
                xfs_iext_insert(ifp, idx, 1, new);
997
                ip->i_df.if_lastex = idx;
998
                ip->i_d.di_nextents++;
999
                if (cur == NULL)
1000
                        rval = XFS_ILOG_CORE | XFS_ILOG_DEXT;
1001
                else {
1002
                        rval = XFS_ILOG_CORE;
1003
                        if ((error = xfs_bmbt_lookup_eq(cur, new->br_startoff,
1004
                                        new->br_startblock, new->br_blockcount,
1005
                                        &i)))
1006
                                goto done;
1007
                        ASSERT(i == 0);
1008
                        cur->bc_rec.b.br_state = XFS_EXT_NORM;
1009
                        if ((error = xfs_bmbt_insert(cur, &i)))
1010
                                goto done;
1011
                        ASSERT(i == 1);
1012
                }
1013
                if (ip->i_d.di_format == XFS_DINODE_FMT_EXTENTS &&
1014
                    ip->i_d.di_nextents > ip->i_df.if_ext_max) {
1015
                        error = xfs_bmap_extents_to_btree(ip->i_transp, ip,
1016
                                        first, flist, &cur, 1, &tmp_rval,
1017
                                        XFS_DATA_FORK);
1018
                        rval |= tmp_rval;
1019
                        if (error)
1020
                                goto done;
1021
                }
1022
                temp = XFS_FILBLKS_MIN(xfs_bmap_worst_indlen(ip, temp),
1023
                        STARTBLOCKVAL(PREV.br_startblock) -
1024
                        (cur ? cur->bc_private.b.allocated : 0));
1025
                ep = xfs_iext_get_ext(ifp, idx + 1);
1026
                xfs_bmbt_set_startblock(ep, NULLSTARTBLOCK((int)temp));
1027
                XFS_BMAP_TRACE_POST_UPDATE("LF", ip, idx + 1, XFS_DATA_FORK);
1028
                *dnew = temp;
1029
                /* DELTA: One in-core extent is split in two. */
1030
                temp = PREV.br_startoff;
1031
                temp2 = PREV.br_blockcount;
1032
                break;
1033
 
1034
        case MASK2(RIGHT_FILLING, RIGHT_CONTIG):
1035
                /*
1036
                 * Filling in the last part of a previous delayed allocation.
1037
                 * The right neighbor is contiguous with the new allocation.
1038
                 */
1039
                temp = PREV.br_blockcount - new->br_blockcount;
1040
                XFS_BMAP_TRACE_PRE_UPDATE("RF|RC", ip, idx, XFS_DATA_FORK);
1041
                XFS_BMAP_TRACE_PRE_UPDATE("RF|RC", ip, idx + 1, XFS_DATA_FORK);
1042
                xfs_bmbt_set_blockcount(ep, temp);
1043
                xfs_bmbt_set_allf(xfs_iext_get_ext(ifp, idx + 1),
1044
                        new->br_startoff, new->br_startblock,
1045
                        new->br_blockcount + RIGHT.br_blockcount,
1046
                        RIGHT.br_state);
1047
                XFS_BMAP_TRACE_POST_UPDATE("RF|RC", ip, idx + 1, XFS_DATA_FORK);
1048
                ip->i_df.if_lastex = idx + 1;
1049
                if (cur == NULL)
1050
                        rval = XFS_ILOG_DEXT;
1051
                else {
1052
                        rval = 0;
1053
                        if ((error = xfs_bmbt_lookup_eq(cur, RIGHT.br_startoff,
1054
                                        RIGHT.br_startblock,
1055
                                        RIGHT.br_blockcount, &i)))
1056
                                goto done;
1057
                        ASSERT(i == 1);
1058
                        if ((error = xfs_bmbt_update(cur, new->br_startoff,
1059
                                        new->br_startblock,
1060
                                        new->br_blockcount +
1061
                                        RIGHT.br_blockcount,
1062
                                        RIGHT.br_state)))
1063
                                goto done;
1064
                }
1065
                temp = XFS_FILBLKS_MIN(xfs_bmap_worst_indlen(ip, temp),
1066
                        STARTBLOCKVAL(PREV.br_startblock));
1067
                xfs_bmbt_set_startblock(ep, NULLSTARTBLOCK((int)temp));
1068
                XFS_BMAP_TRACE_POST_UPDATE("RF|RC", ip, idx, XFS_DATA_FORK);
1069
                *dnew = temp;
1070
                /* DELTA: The boundary between two in-core extents moved. */
1071
                temp = PREV.br_startoff;
1072
                temp2 = PREV.br_blockcount +
1073
                        RIGHT.br_blockcount;
1074
                break;
1075
 
1076
        case MASK(RIGHT_FILLING):
1077
                /*
1078
                 * Filling in the last part of a previous delayed allocation.
1079
                 * The right neighbor is not contiguous.
1080
                 */
1081
                temp = PREV.br_blockcount - new->br_blockcount;
1082
                XFS_BMAP_TRACE_PRE_UPDATE("RF", ip, idx, XFS_DATA_FORK);
1083
                xfs_bmbt_set_blockcount(ep, temp);
1084
                XFS_BMAP_TRACE_INSERT("RF", ip, idx + 1, 1, new, NULL,
1085
                        XFS_DATA_FORK);
1086
                xfs_iext_insert(ifp, idx + 1, 1, new);
1087
                ip->i_df.if_lastex = idx + 1;
1088
                ip->i_d.di_nextents++;
1089
                if (cur == NULL)
1090
                        rval = XFS_ILOG_CORE | XFS_ILOG_DEXT;
1091
                else {
1092
                        rval = XFS_ILOG_CORE;
1093
                        if ((error = xfs_bmbt_lookup_eq(cur, new->br_startoff,
1094
                                        new->br_startblock, new->br_blockcount,
1095
                                        &i)))
1096
                                goto done;
1097
                        ASSERT(i == 0);
1098
                        cur->bc_rec.b.br_state = XFS_EXT_NORM;
1099
                        if ((error = xfs_bmbt_insert(cur, &i)))
1100
                                goto done;
1101
                        ASSERT(i == 1);
1102
                }
1103
                if (ip->i_d.di_format == XFS_DINODE_FMT_EXTENTS &&
1104
                    ip->i_d.di_nextents > ip->i_df.if_ext_max) {
1105
                        error = xfs_bmap_extents_to_btree(ip->i_transp, ip,
1106
                                first, flist, &cur, 1, &tmp_rval,
1107
                                XFS_DATA_FORK);
1108
                        rval |= tmp_rval;
1109
                        if (error)
1110
                                goto done;
1111
                }
1112
                temp = XFS_FILBLKS_MIN(xfs_bmap_worst_indlen(ip, temp),
1113
                        STARTBLOCKVAL(PREV.br_startblock) -
1114
                        (cur ? cur->bc_private.b.allocated : 0));
1115
                ep = xfs_iext_get_ext(ifp, idx);
1116
                xfs_bmbt_set_startblock(ep, NULLSTARTBLOCK((int)temp));
1117
                XFS_BMAP_TRACE_POST_UPDATE("RF", ip, idx, XFS_DATA_FORK);
1118
                *dnew = temp;
1119
                /* DELTA: One in-core extent is split in two. */
1120
                temp = PREV.br_startoff;
1121
                temp2 = PREV.br_blockcount;
1122
                break;
1123
 
1124
        case 0:
1125
                /*
1126
                 * Filling in the middle part of a previous delayed allocation.
1127
                 * Contiguity is impossible here.
1128
                 * This case is avoided almost all the time.
1129
                 */
1130
                temp = new->br_startoff - PREV.br_startoff;
1131
                XFS_BMAP_TRACE_PRE_UPDATE("0", ip, idx, XFS_DATA_FORK);
1132
                xfs_bmbt_set_blockcount(ep, temp);
1133
                r[0] = *new;
1134
                r[1].br_state = PREV.br_state;
1135
                r[1].br_startblock = 0;
1136
                r[1].br_startoff = new_endoff;
1137
                temp2 = PREV.br_startoff + PREV.br_blockcount - new_endoff;
1138
                r[1].br_blockcount = temp2;
1139
                XFS_BMAP_TRACE_INSERT("0", ip, idx + 1, 2, &r[0], &r[1],
1140
                        XFS_DATA_FORK);
1141
                xfs_iext_insert(ifp, idx + 1, 2, &r[0]);
1142
                ip->i_df.if_lastex = idx + 1;
1143
                ip->i_d.di_nextents++;
1144
                if (cur == NULL)
1145
                        rval = XFS_ILOG_CORE | XFS_ILOG_DEXT;
1146
                else {
1147
                        rval = XFS_ILOG_CORE;
1148
                        if ((error = xfs_bmbt_lookup_eq(cur, new->br_startoff,
1149
                                        new->br_startblock, new->br_blockcount,
1150
                                        &i)))
1151
                                goto done;
1152
                        ASSERT(i == 0);
1153
                        cur->bc_rec.b.br_state = XFS_EXT_NORM;
1154
                        if ((error = xfs_bmbt_insert(cur, &i)))
1155
                                goto done;
1156
                        ASSERT(i == 1);
1157
                }
1158
                if (ip->i_d.di_format == XFS_DINODE_FMT_EXTENTS &&
1159
                    ip->i_d.di_nextents > ip->i_df.if_ext_max) {
1160
                        error = xfs_bmap_extents_to_btree(ip->i_transp, ip,
1161
                                        first, flist, &cur, 1, &tmp_rval,
1162
                                        XFS_DATA_FORK);
1163
                        rval |= tmp_rval;
1164
                        if (error)
1165
                                goto done;
1166
                }
1167
                temp = xfs_bmap_worst_indlen(ip, temp);
1168
                temp2 = xfs_bmap_worst_indlen(ip, temp2);
1169
                diff = (int)(temp + temp2 - STARTBLOCKVAL(PREV.br_startblock) -
1170
                        (cur ? cur->bc_private.b.allocated : 0));
1171
                if (diff > 0 &&
1172
                    xfs_mod_incore_sb(ip->i_mount, XFS_SBS_FDBLOCKS, -((int64_t)diff), rsvd)) {
1173
                        /*
1174
                         * Ick gross gag me with a spoon.
1175
                         */
1176
                        ASSERT(0);       /* want to see if this ever happens! */
1177
                        while (diff > 0) {
1178
                                if (temp) {
1179
                                        temp--;
1180
                                        diff--;
1181
                                        if (!diff ||
1182
                                            !xfs_mod_incore_sb(ip->i_mount,
1183
                                                    XFS_SBS_FDBLOCKS, -((int64_t)diff), rsvd))
1184
                                                break;
1185
                                }
1186
                                if (temp2) {
1187
                                        temp2--;
1188
                                        diff--;
1189
                                        if (!diff ||
1190
                                            !xfs_mod_incore_sb(ip->i_mount,
1191
                                                    XFS_SBS_FDBLOCKS, -((int64_t)diff), rsvd))
1192
                                                break;
1193
                                }
1194
                        }
1195
                }
1196
                ep = xfs_iext_get_ext(ifp, idx);
1197
                xfs_bmbt_set_startblock(ep, NULLSTARTBLOCK((int)temp));
1198
                XFS_BMAP_TRACE_POST_UPDATE("0", ip, idx, XFS_DATA_FORK);
1199
                XFS_BMAP_TRACE_PRE_UPDATE("0", ip, idx + 2, XFS_DATA_FORK);
1200
                xfs_bmbt_set_startblock(xfs_iext_get_ext(ifp, idx + 2),
1201
                        NULLSTARTBLOCK((int)temp2));
1202
                XFS_BMAP_TRACE_POST_UPDATE("0", ip, idx + 2, XFS_DATA_FORK);
1203
                *dnew = temp + temp2;
1204
                /* DELTA: One in-core extent is split in three. */
1205
                temp = PREV.br_startoff;
1206
                temp2 = PREV.br_blockcount;
1207
                break;
1208
 
1209
        case MASK3(LEFT_FILLING, LEFT_CONTIG, RIGHT_CONTIG):
1210
        case MASK3(RIGHT_FILLING, LEFT_CONTIG, RIGHT_CONTIG):
1211
        case MASK2(LEFT_FILLING, RIGHT_CONTIG):
1212
        case MASK2(RIGHT_FILLING, LEFT_CONTIG):
1213
        case MASK2(LEFT_CONTIG, RIGHT_CONTIG):
1214
        case MASK(LEFT_CONTIG):
1215
        case MASK(RIGHT_CONTIG):
1216
                /*
1217
                 * These cases are all impossible.
1218
                 */
1219
                ASSERT(0);
1220
        }
1221
        *curp = cur;
1222
        if (delta) {
1223
                temp2 += temp;
1224
                if (delta->xed_startoff > temp)
1225
                        delta->xed_startoff = temp;
1226
                if (delta->xed_blockcount < temp2)
1227
                        delta->xed_blockcount = temp2;
1228
        }
1229
done:
1230
        *logflagsp = rval;
1231
        return error;
1232
#undef  LEFT
1233
#undef  RIGHT
1234
#undef  PREV
1235
#undef  MASK
1236
#undef  MASK2
1237
#undef  MASK3
1238
#undef  MASK4
1239
#undef  STATE_SET
1240
#undef  STATE_TEST
1241
#undef  STATE_SET_TEST
1242
#undef  SWITCH_STATE
1243
}
1244
 
1245
/*
1246
 * Called by xfs_bmap_add_extent to handle cases converting an unwritten
1247
 * allocation to a real allocation or vice versa.
1248
 */
1249
STATIC int                              /* error */
1250
xfs_bmap_add_extent_unwritten_real(
1251
        xfs_inode_t             *ip,    /* incore inode pointer */
1252
        xfs_extnum_t            idx,    /* extent number to update/insert */
1253
        xfs_btree_cur_t         **curp, /* if *curp is null, not a btree */
1254
        xfs_bmbt_irec_t         *new,   /* new data to add to file extents */
1255
        int                     *logflagsp, /* inode logging flags */
1256
        xfs_extdelta_t          *delta) /* Change made to incore extents */
1257
{
1258
        xfs_btree_cur_t         *cur;   /* btree cursor */
1259
        xfs_bmbt_rec_host_t     *ep;    /* extent entry for idx */
1260
        int                     error;  /* error return value */
1261
        int                     i;      /* temp state */
1262
        xfs_ifork_t             *ifp;   /* inode fork pointer */
1263
        xfs_fileoff_t           new_endoff;     /* end offset of new entry */
1264
        xfs_exntst_t            newext; /* new extent state */
1265
        xfs_exntst_t            oldext; /* old extent state */
1266
        xfs_bmbt_irec_t         r[3];   /* neighbor extent entries */
1267
                                        /* left is 0, right is 1, prev is 2 */
1268
        int                     rval=0;  /* return value (logging flags) */
1269
        int                     state = 0;/* state bits, accessed thru macros */
1270
        xfs_filblks_t           temp=0;
1271
        xfs_filblks_t           temp2=0;
1272
        enum {                          /* bit number definitions for state */
1273
                LEFT_CONTIG,    RIGHT_CONTIG,
1274
                LEFT_FILLING,   RIGHT_FILLING,
1275
                LEFT_DELAY,     RIGHT_DELAY,
1276
                LEFT_VALID,     RIGHT_VALID
1277
        };
1278
 
1279
#define LEFT            r[0]
1280
#define RIGHT           r[1]
1281
#define PREV            r[2]
1282
#define MASK(b)         (1 << (b))
1283
#define MASK2(a,b)      (MASK(a) | MASK(b))
1284
#define MASK3(a,b,c)    (MASK2(a,b) | MASK(c))
1285
#define MASK4(a,b,c,d)  (MASK3(a,b,c) | MASK(d))
1286
#define STATE_SET(b,v)  ((v) ? (state |= MASK(b)) : (state &= ~MASK(b)))
1287
#define STATE_TEST(b)   (state & MASK(b))
1288
#define STATE_SET_TEST(b,v)     ((v) ? ((state |= MASK(b)), 1) : \
1289
                                       ((state &= ~MASK(b)), 0))
1290
#define SWITCH_STATE            \
1291
        (state & MASK4(LEFT_FILLING, RIGHT_FILLING, LEFT_CONTIG, RIGHT_CONTIG))
1292
 
1293
        /*
1294
         * Set up a bunch of variables to make the tests simpler.
1295
         */
1296
        error = 0;
1297
        cur = *curp;
1298
        ifp = XFS_IFORK_PTR(ip, XFS_DATA_FORK);
1299
        ep = xfs_iext_get_ext(ifp, idx);
1300
        xfs_bmbt_get_all(ep, &PREV);
1301
        newext = new->br_state;
1302
        oldext = (newext == XFS_EXT_UNWRITTEN) ?
1303
                XFS_EXT_NORM : XFS_EXT_UNWRITTEN;
1304
        ASSERT(PREV.br_state == oldext);
1305
        new_endoff = new->br_startoff + new->br_blockcount;
1306
        ASSERT(PREV.br_startoff <= new->br_startoff);
1307
        ASSERT(PREV.br_startoff + PREV.br_blockcount >= new_endoff);
1308
        /*
1309
         * Set flags determining what part of the previous oldext allocation
1310
         * extent is being replaced by a newext allocation.
1311
         */
1312
        STATE_SET(LEFT_FILLING, PREV.br_startoff == new->br_startoff);
1313
        STATE_SET(RIGHT_FILLING,
1314
                PREV.br_startoff + PREV.br_blockcount == new_endoff);
1315
        /*
1316
         * Check and set flags if this segment has a left neighbor.
1317
         * Don't set contiguous if the combined extent would be too large.
1318
         */
1319
        if (STATE_SET_TEST(LEFT_VALID, idx > 0)) {
1320
                xfs_bmbt_get_all(xfs_iext_get_ext(ifp, idx - 1), &LEFT);
1321
                STATE_SET(LEFT_DELAY, ISNULLSTARTBLOCK(LEFT.br_startblock));
1322
        }
1323
        STATE_SET(LEFT_CONTIG,
1324
                STATE_TEST(LEFT_VALID) && !STATE_TEST(LEFT_DELAY) &&
1325
                LEFT.br_startoff + LEFT.br_blockcount == new->br_startoff &&
1326
                LEFT.br_startblock + LEFT.br_blockcount == new->br_startblock &&
1327
                LEFT.br_state == newext &&
1328
                LEFT.br_blockcount + new->br_blockcount <= MAXEXTLEN);
1329
        /*
1330
         * Check and set flags if this segment has a right neighbor.
1331
         * Don't set contiguous if the combined extent would be too large.
1332
         * Also check for all-three-contiguous being too large.
1333
         */
1334
        if (STATE_SET_TEST(RIGHT_VALID,
1335
                        idx <
1336
                        ip->i_df.if_bytes / (uint)sizeof(xfs_bmbt_rec_t) - 1)) {
1337
                xfs_bmbt_get_all(xfs_iext_get_ext(ifp, idx + 1), &RIGHT);
1338
                STATE_SET(RIGHT_DELAY, ISNULLSTARTBLOCK(RIGHT.br_startblock));
1339
        }
1340
        STATE_SET(RIGHT_CONTIG,
1341
                STATE_TEST(RIGHT_VALID) && !STATE_TEST(RIGHT_DELAY) &&
1342
                new_endoff == RIGHT.br_startoff &&
1343
                new->br_startblock + new->br_blockcount ==
1344
                    RIGHT.br_startblock &&
1345
                newext == RIGHT.br_state &&
1346
                new->br_blockcount + RIGHT.br_blockcount <= MAXEXTLEN &&
1347
                ((state & MASK3(LEFT_CONTIG, LEFT_FILLING, RIGHT_FILLING)) !=
1348
                  MASK3(LEFT_CONTIG, LEFT_FILLING, RIGHT_FILLING) ||
1349
                 LEFT.br_blockcount + new->br_blockcount + RIGHT.br_blockcount
1350
                     <= MAXEXTLEN));
1351
        /*
1352
         * Switch out based on the FILLING and CONTIG state bits.
1353
         */
1354
        switch (SWITCH_STATE) {
1355
 
1356
        case MASK4(LEFT_FILLING, RIGHT_FILLING, LEFT_CONTIG, RIGHT_CONTIG):
1357
                /*
1358
                 * Setting all of a previous oldext extent to newext.
1359
                 * The left and right neighbors are both contiguous with new.
1360
                 */
1361
                XFS_BMAP_TRACE_PRE_UPDATE("LF|RF|LC|RC", ip, idx - 1,
1362
                        XFS_DATA_FORK);
1363
                xfs_bmbt_set_blockcount(xfs_iext_get_ext(ifp, idx - 1),
1364
                        LEFT.br_blockcount + PREV.br_blockcount +
1365
                        RIGHT.br_blockcount);
1366
                XFS_BMAP_TRACE_POST_UPDATE("LF|RF|LC|RC", ip, idx - 1,
1367
                        XFS_DATA_FORK);
1368
                XFS_BMAP_TRACE_DELETE("LF|RF|LC|RC", ip, idx, 2, XFS_DATA_FORK);
1369
                xfs_iext_remove(ifp, idx, 2);
1370
                ip->i_df.if_lastex = idx - 1;
1371
                ip->i_d.di_nextents -= 2;
1372
                if (cur == NULL)
1373
                        rval = XFS_ILOG_CORE | XFS_ILOG_DEXT;
1374
                else {
1375
                        rval = XFS_ILOG_CORE;
1376
                        if ((error = xfs_bmbt_lookup_eq(cur, RIGHT.br_startoff,
1377
                                        RIGHT.br_startblock,
1378
                                        RIGHT.br_blockcount, &i)))
1379
                                goto done;
1380
                        ASSERT(i == 1);
1381
                        if ((error = xfs_bmbt_delete(cur, &i)))
1382
                                goto done;
1383
                        ASSERT(i == 1);
1384
                        if ((error = xfs_bmbt_decrement(cur, 0, &i)))
1385
                                goto done;
1386
                        ASSERT(i == 1);
1387
                        if ((error = xfs_bmbt_delete(cur, &i)))
1388
                                goto done;
1389
                        ASSERT(i == 1);
1390
                        if ((error = xfs_bmbt_decrement(cur, 0, &i)))
1391
                                goto done;
1392
                        ASSERT(i == 1);
1393
                        if ((error = xfs_bmbt_update(cur, LEFT.br_startoff,
1394
                                LEFT.br_startblock,
1395
                                LEFT.br_blockcount + PREV.br_blockcount +
1396
                                RIGHT.br_blockcount, LEFT.br_state)))
1397
                                goto done;
1398
                }
1399
                /* DELTA: Three in-core extents are replaced by one. */
1400
                temp = LEFT.br_startoff;
1401
                temp2 = LEFT.br_blockcount +
1402
                        PREV.br_blockcount +
1403
                        RIGHT.br_blockcount;
1404
                break;
1405
 
1406
        case MASK3(LEFT_FILLING, RIGHT_FILLING, LEFT_CONTIG):
1407
                /*
1408
                 * Setting all of a previous oldext extent to newext.
1409
                 * The left neighbor is contiguous, the right is not.
1410
                 */
1411
                XFS_BMAP_TRACE_PRE_UPDATE("LF|RF|LC", ip, idx - 1,
1412
                        XFS_DATA_FORK);
1413
                xfs_bmbt_set_blockcount(xfs_iext_get_ext(ifp, idx - 1),
1414
                        LEFT.br_blockcount + PREV.br_blockcount);
1415
                XFS_BMAP_TRACE_POST_UPDATE("LF|RF|LC", ip, idx - 1,
1416
                        XFS_DATA_FORK);
1417
                ip->i_df.if_lastex = idx - 1;
1418
                XFS_BMAP_TRACE_DELETE("LF|RF|LC", ip, idx, 1, XFS_DATA_FORK);
1419
                xfs_iext_remove(ifp, idx, 1);
1420
                ip->i_d.di_nextents--;
1421
                if (cur == NULL)
1422
                        rval = XFS_ILOG_CORE | XFS_ILOG_DEXT;
1423
                else {
1424
                        rval = XFS_ILOG_CORE;
1425
                        if ((error = xfs_bmbt_lookup_eq(cur, PREV.br_startoff,
1426
                                        PREV.br_startblock, PREV.br_blockcount,
1427
                                        &i)))
1428
                                goto done;
1429
                        ASSERT(i == 1);
1430
                        if ((error = xfs_bmbt_delete(cur, &i)))
1431
                                goto done;
1432
                        ASSERT(i == 1);
1433
                        if ((error = xfs_bmbt_decrement(cur, 0, &i)))
1434
                                goto done;
1435
                        ASSERT(i == 1);
1436
                        if ((error = xfs_bmbt_update(cur, LEFT.br_startoff,
1437
                                LEFT.br_startblock,
1438
                                LEFT.br_blockcount + PREV.br_blockcount,
1439
                                LEFT.br_state)))
1440
                                goto done;
1441
                }
1442
                /* DELTA: Two in-core extents are replaced by one. */
1443
                temp = LEFT.br_startoff;
1444
                temp2 = LEFT.br_blockcount +
1445
                        PREV.br_blockcount;
1446
                break;
1447
 
1448
        case MASK3(LEFT_FILLING, RIGHT_FILLING, RIGHT_CONTIG):
1449
                /*
1450
                 * Setting all of a previous oldext extent to newext.
1451
                 * The right neighbor is contiguous, the left is not.
1452
                 */
1453
                XFS_BMAP_TRACE_PRE_UPDATE("LF|RF|RC", ip, idx,
1454
                        XFS_DATA_FORK);
1455
                xfs_bmbt_set_blockcount(ep,
1456
                        PREV.br_blockcount + RIGHT.br_blockcount);
1457
                xfs_bmbt_set_state(ep, newext);
1458
                XFS_BMAP_TRACE_POST_UPDATE("LF|RF|RC", ip, idx,
1459
                        XFS_DATA_FORK);
1460
                ip->i_df.if_lastex = idx;
1461
                XFS_BMAP_TRACE_DELETE("LF|RF|RC", ip, idx + 1, 1, XFS_DATA_FORK);
1462
                xfs_iext_remove(ifp, idx + 1, 1);
1463
                ip->i_d.di_nextents--;
1464
                if (cur == NULL)
1465
                        rval = XFS_ILOG_CORE | XFS_ILOG_DEXT;
1466
                else {
1467
                        rval = XFS_ILOG_CORE;
1468
                        if ((error = xfs_bmbt_lookup_eq(cur, RIGHT.br_startoff,
1469
                                        RIGHT.br_startblock,
1470
                                        RIGHT.br_blockcount, &i)))
1471
                                goto done;
1472
                        ASSERT(i == 1);
1473
                        if ((error = xfs_bmbt_delete(cur, &i)))
1474
                                goto done;
1475
                        ASSERT(i == 1);
1476
                        if ((error = xfs_bmbt_decrement(cur, 0, &i)))
1477
                                goto done;
1478
                        ASSERT(i == 1);
1479
                        if ((error = xfs_bmbt_update(cur, new->br_startoff,
1480
                                new->br_startblock,
1481
                                new->br_blockcount + RIGHT.br_blockcount,
1482
                                newext)))
1483
                                goto done;
1484
                }
1485
                /* DELTA: Two in-core extents are replaced by one. */
1486
                temp = PREV.br_startoff;
1487
                temp2 = PREV.br_blockcount +
1488
                        RIGHT.br_blockcount;
1489
                break;
1490
 
1491
        case MASK2(LEFT_FILLING, RIGHT_FILLING):
1492
                /*
1493
                 * Setting all of a previous oldext extent to newext.
1494
                 * Neither the left nor right neighbors are contiguous with
1495
                 * the new one.
1496
                 */
1497
                XFS_BMAP_TRACE_PRE_UPDATE("LF|RF", ip, idx,
1498
                        XFS_DATA_FORK);
1499
                xfs_bmbt_set_state(ep, newext);
1500
                XFS_BMAP_TRACE_POST_UPDATE("LF|RF", ip, idx,
1501
                        XFS_DATA_FORK);
1502
                ip->i_df.if_lastex = idx;
1503
                if (cur == NULL)
1504
                        rval = XFS_ILOG_DEXT;
1505
                else {
1506
                        rval = 0;
1507
                        if ((error = xfs_bmbt_lookup_eq(cur, new->br_startoff,
1508
                                        new->br_startblock, new->br_blockcount,
1509
                                        &i)))
1510
                                goto done;
1511
                        ASSERT(i == 1);
1512
                        if ((error = xfs_bmbt_update(cur, new->br_startoff,
1513
                                new->br_startblock, new->br_blockcount,
1514
                                newext)))
1515
                                goto done;
1516
                }
1517
                /* DELTA: The in-core extent described by new changed type. */
1518
                temp = new->br_startoff;
1519
                temp2 = new->br_blockcount;
1520
                break;
1521
 
1522
        case MASK2(LEFT_FILLING, LEFT_CONTIG):
1523
                /*
1524
                 * Setting the first part of a previous oldext extent to newext.
1525
                 * The left neighbor is contiguous.
1526
                 */
1527
                XFS_BMAP_TRACE_PRE_UPDATE("LF|LC", ip, idx - 1,
1528
                        XFS_DATA_FORK);
1529
                xfs_bmbt_set_blockcount(xfs_iext_get_ext(ifp, idx - 1),
1530
                        LEFT.br_blockcount + new->br_blockcount);
1531
                xfs_bmbt_set_startoff(ep,
1532
                        PREV.br_startoff + new->br_blockcount);
1533
                XFS_BMAP_TRACE_POST_UPDATE("LF|LC", ip, idx - 1,
1534
                        XFS_DATA_FORK);
1535
                XFS_BMAP_TRACE_PRE_UPDATE("LF|LC", ip, idx,
1536
                        XFS_DATA_FORK);
1537
                xfs_bmbt_set_startblock(ep,
1538
                        new->br_startblock + new->br_blockcount);
1539
                xfs_bmbt_set_blockcount(ep,
1540
                        PREV.br_blockcount - new->br_blockcount);
1541
                XFS_BMAP_TRACE_POST_UPDATE("LF|LC", ip, idx,
1542
                        XFS_DATA_FORK);
1543
                ip->i_df.if_lastex = idx - 1;
1544
                if (cur == NULL)
1545
                        rval = XFS_ILOG_DEXT;
1546
                else {
1547
                        rval = 0;
1548
                        if ((error = xfs_bmbt_lookup_eq(cur, PREV.br_startoff,
1549
                                        PREV.br_startblock, PREV.br_blockcount,
1550
                                        &i)))
1551
                                goto done;
1552
                        ASSERT(i == 1);
1553
                        if ((error = xfs_bmbt_update(cur,
1554
                                PREV.br_startoff + new->br_blockcount,
1555
                                PREV.br_startblock + new->br_blockcount,
1556
                                PREV.br_blockcount - new->br_blockcount,
1557
                                oldext)))
1558
                                goto done;
1559
                        if ((error = xfs_bmbt_decrement(cur, 0, &i)))
1560
                                goto done;
1561
                        if (xfs_bmbt_update(cur, LEFT.br_startoff,
1562
                                LEFT.br_startblock,
1563
                                LEFT.br_blockcount + new->br_blockcount,
1564
                                LEFT.br_state))
1565
                                goto done;
1566
                }
1567
                /* DELTA: The boundary between two in-core extents moved. */
1568
                temp = LEFT.br_startoff;
1569
                temp2 = LEFT.br_blockcount +
1570
                        PREV.br_blockcount;
1571
                break;
1572
 
1573
        case MASK(LEFT_FILLING):
1574
                /*
1575
                 * Setting the first part of a previous oldext extent to newext.
1576
                 * The left neighbor is not contiguous.
1577
                 */
1578
                XFS_BMAP_TRACE_PRE_UPDATE("LF", ip, idx, XFS_DATA_FORK);
1579
                ASSERT(ep && xfs_bmbt_get_state(ep) == oldext);
1580
                xfs_bmbt_set_startoff(ep, new_endoff);
1581
                xfs_bmbt_set_blockcount(ep,
1582
                        PREV.br_blockcount - new->br_blockcount);
1583
                xfs_bmbt_set_startblock(ep,
1584
                        new->br_startblock + new->br_blockcount);
1585
                XFS_BMAP_TRACE_POST_UPDATE("LF", ip, idx, XFS_DATA_FORK);
1586
                XFS_BMAP_TRACE_INSERT("LF", ip, idx, 1, new, NULL,
1587
                        XFS_DATA_FORK);
1588
                xfs_iext_insert(ifp, idx, 1, new);
1589
                ip->i_df.if_lastex = idx;
1590
                ip->i_d.di_nextents++;
1591
                if (cur == NULL)
1592
                        rval = XFS_ILOG_CORE | XFS_ILOG_DEXT;
1593
                else {
1594
                        rval = XFS_ILOG_CORE;
1595
                        if ((error = xfs_bmbt_lookup_eq(cur, PREV.br_startoff,
1596
                                        PREV.br_startblock, PREV.br_blockcount,
1597
                                        &i)))
1598
                                goto done;
1599
                        ASSERT(i == 1);
1600
                        if ((error = xfs_bmbt_update(cur,
1601
                                PREV.br_startoff + new->br_blockcount,
1602
                                PREV.br_startblock + new->br_blockcount,
1603
                                PREV.br_blockcount - new->br_blockcount,
1604
                                oldext)))
1605
                                goto done;
1606
                        cur->bc_rec.b = *new;
1607
                        if ((error = xfs_bmbt_insert(cur, &i)))
1608
                                goto done;
1609
                        ASSERT(i == 1);
1610
                }
1611
                /* DELTA: One in-core extent is split in two. */
1612
                temp = PREV.br_startoff;
1613
                temp2 = PREV.br_blockcount;
1614
                break;
1615
 
1616
        case MASK2(RIGHT_FILLING, RIGHT_CONTIG):
1617
                /*
1618
                 * Setting the last part of a previous oldext extent to newext.
1619
                 * The right neighbor is contiguous with the new allocation.
1620
                 */
1621
                XFS_BMAP_TRACE_PRE_UPDATE("RF|RC", ip, idx,
1622
                        XFS_DATA_FORK);
1623
                XFS_BMAP_TRACE_PRE_UPDATE("RF|RC", ip, idx + 1,
1624
                        XFS_DATA_FORK);
1625
                xfs_bmbt_set_blockcount(ep,
1626
                        PREV.br_blockcount - new->br_blockcount);
1627
                XFS_BMAP_TRACE_POST_UPDATE("RF|RC", ip, idx,
1628
                        XFS_DATA_FORK);
1629
                xfs_bmbt_set_allf(xfs_iext_get_ext(ifp, idx + 1),
1630
                        new->br_startoff, new->br_startblock,
1631
                        new->br_blockcount + RIGHT.br_blockcount, newext);
1632
                XFS_BMAP_TRACE_POST_UPDATE("RF|RC", ip, idx + 1,
1633
                        XFS_DATA_FORK);
1634
                ip->i_df.if_lastex = idx + 1;
1635
                if (cur == NULL)
1636
                        rval = XFS_ILOG_DEXT;
1637
                else {
1638
                        rval = 0;
1639
                        if ((error = xfs_bmbt_lookup_eq(cur, PREV.br_startoff,
1640
                                        PREV.br_startblock,
1641
                                        PREV.br_blockcount, &i)))
1642
                                goto done;
1643
                        ASSERT(i == 1);
1644
                        if ((error = xfs_bmbt_update(cur, PREV.br_startoff,
1645
                                PREV.br_startblock,
1646
                                PREV.br_blockcount - new->br_blockcount,
1647
                                oldext)))
1648
                                goto done;
1649
                        if ((error = xfs_bmbt_increment(cur, 0, &i)))
1650
                                goto done;
1651
                        if ((error = xfs_bmbt_update(cur, new->br_startoff,
1652
                                new->br_startblock,
1653
                                new->br_blockcount + RIGHT.br_blockcount,
1654
                                newext)))
1655
                                goto done;
1656
                }
1657
                /* DELTA: The boundary between two in-core extents moved. */
1658
                temp = PREV.br_startoff;
1659
                temp2 = PREV.br_blockcount +
1660
                        RIGHT.br_blockcount;
1661
                break;
1662
 
1663
        case MASK(RIGHT_FILLING):
1664
                /*
1665
                 * Setting the last part of a previous oldext extent to newext.
1666
                 * The right neighbor is not contiguous.
1667
                 */
1668
                XFS_BMAP_TRACE_PRE_UPDATE("RF", ip, idx, XFS_DATA_FORK);
1669
                xfs_bmbt_set_blockcount(ep,
1670
                        PREV.br_blockcount - new->br_blockcount);
1671
                XFS_BMAP_TRACE_POST_UPDATE("RF", ip, idx, XFS_DATA_FORK);
1672
                XFS_BMAP_TRACE_INSERT("RF", ip, idx + 1, 1, new, NULL,
1673
                        XFS_DATA_FORK);
1674
                xfs_iext_insert(ifp, idx + 1, 1, new);
1675
                ip->i_df.if_lastex = idx + 1;
1676
                ip->i_d.di_nextents++;
1677
                if (cur == NULL)
1678
                        rval = XFS_ILOG_CORE | XFS_ILOG_DEXT;
1679
                else {
1680
                        rval = XFS_ILOG_CORE;
1681
                        if ((error = xfs_bmbt_lookup_eq(cur, PREV.br_startoff,
1682
                                        PREV.br_startblock, PREV.br_blockcount,
1683
                                        &i)))
1684
                                goto done;
1685
                        ASSERT(i == 1);
1686
                        if ((error = xfs_bmbt_update(cur, PREV.br_startoff,
1687
                                PREV.br_startblock,
1688
                                PREV.br_blockcount - new->br_blockcount,
1689
                                oldext)))
1690
                                goto done;
1691
                        if ((error = xfs_bmbt_lookup_eq(cur, new->br_startoff,
1692
                                        new->br_startblock, new->br_blockcount,
1693
                                        &i)))
1694
                                goto done;
1695
                        ASSERT(i == 0);
1696
                        cur->bc_rec.b.br_state = XFS_EXT_NORM;
1697
                        if ((error = xfs_bmbt_insert(cur, &i)))
1698
                                goto done;
1699
                        ASSERT(i == 1);
1700
                }
1701
                /* DELTA: One in-core extent is split in two. */
1702
                temp = PREV.br_startoff;
1703
                temp2 = PREV.br_blockcount;
1704
                break;
1705
 
1706
        case 0:
1707
                /*
1708
                 * Setting the middle part of a previous oldext extent to
1709
                 * newext.  Contiguity is impossible here.
1710
                 * One extent becomes three extents.
1711
                 */
1712
                XFS_BMAP_TRACE_PRE_UPDATE("0", ip, idx, XFS_DATA_FORK);
1713
                xfs_bmbt_set_blockcount(ep,
1714
                        new->br_startoff - PREV.br_startoff);
1715
                XFS_BMAP_TRACE_POST_UPDATE("0", ip, idx, XFS_DATA_FORK);
1716
                r[0] = *new;
1717
                r[1].br_startoff = new_endoff;
1718
                r[1].br_blockcount =
1719
                        PREV.br_startoff + PREV.br_blockcount - new_endoff;
1720
                r[1].br_startblock = new->br_startblock + new->br_blockcount;
1721
                r[1].br_state = oldext;
1722
                XFS_BMAP_TRACE_INSERT("0", ip, idx + 1, 2, &r[0], &r[1],
1723
                        XFS_DATA_FORK);
1724
                xfs_iext_insert(ifp, idx + 1, 2, &r[0]);
1725
                ip->i_df.if_lastex = idx + 1;
1726
                ip->i_d.di_nextents += 2;
1727
                if (cur == NULL)
1728
                        rval = XFS_ILOG_CORE | XFS_ILOG_DEXT;
1729
                else {
1730
                        rval = XFS_ILOG_CORE;
1731
                        if ((error = xfs_bmbt_lookup_eq(cur, PREV.br_startoff,
1732
                                        PREV.br_startblock, PREV.br_blockcount,
1733
                                        &i)))
1734
                                goto done;
1735
                        ASSERT(i == 1);
1736
                        /* new right extent - oldext */
1737
                        if ((error = xfs_bmbt_update(cur, r[1].br_startoff,
1738
                                r[1].br_startblock, r[1].br_blockcount,
1739
                                r[1].br_state)))
1740
                                goto done;
1741
                        /* new left extent - oldext */
1742
                        PREV.br_blockcount =
1743
                                new->br_startoff - PREV.br_startoff;
1744
                        cur->bc_rec.b = PREV;
1745
                        if ((error = xfs_bmbt_insert(cur, &i)))
1746
                                goto done;
1747
                        ASSERT(i == 1);
1748
                        if ((error = xfs_bmbt_increment(cur, 0, &i)))
1749
                                goto done;
1750
                        ASSERT(i == 1);
1751
                        /* new middle extent - newext */
1752
                        cur->bc_rec.b = *new;
1753
                        if ((error = xfs_bmbt_insert(cur, &i)))
1754
                                goto done;
1755
                        ASSERT(i == 1);
1756
                }
1757
                /* DELTA: One in-core extent is split in three. */
1758
                temp = PREV.br_startoff;
1759
                temp2 = PREV.br_blockcount;
1760
                break;
1761
 
1762
        case MASK3(LEFT_FILLING, LEFT_CONTIG, RIGHT_CONTIG):
1763
        case MASK3(RIGHT_FILLING, LEFT_CONTIG, RIGHT_CONTIG):
1764
        case MASK2(LEFT_FILLING, RIGHT_CONTIG):
1765
        case MASK2(RIGHT_FILLING, LEFT_CONTIG):
1766
        case MASK2(LEFT_CONTIG, RIGHT_CONTIG):
1767
        case MASK(LEFT_CONTIG):
1768
        case MASK(RIGHT_CONTIG):
1769
                /*
1770
                 * These cases are all impossible.
1771
                 */
1772
                ASSERT(0);
1773
        }
1774
        *curp = cur;
1775
        if (delta) {
1776
                temp2 += temp;
1777
                if (delta->xed_startoff > temp)
1778
                        delta->xed_startoff = temp;
1779
                if (delta->xed_blockcount < temp2)
1780
                        delta->xed_blockcount = temp2;
1781
        }
1782
done:
1783
        *logflagsp = rval;
1784
        return error;
1785
#undef  LEFT
1786
#undef  RIGHT
1787
#undef  PREV
1788
#undef  MASK
1789
#undef  MASK2
1790
#undef  MASK3
1791
#undef  MASK4
1792
#undef  STATE_SET
1793
#undef  STATE_TEST
1794
#undef  STATE_SET_TEST
1795
#undef  SWITCH_STATE
1796
}
1797
 
1798
/*
1799
 * Called by xfs_bmap_add_extent to handle cases converting a hole
1800
 * to a delayed allocation.
1801
 */
1802
/*ARGSUSED*/
1803
STATIC int                              /* error */
1804
xfs_bmap_add_extent_hole_delay(
1805
        xfs_inode_t             *ip,    /* incore inode pointer */
1806
        xfs_extnum_t            idx,    /* extent number to update/insert */
1807
        xfs_bmbt_irec_t         *new,   /* new data to add to file extents */
1808
        int                     *logflagsp, /* inode logging flags */
1809
        xfs_extdelta_t          *delta, /* Change made to incore extents */
1810
        int                     rsvd)           /* OK to allocate reserved blocks */
1811
{
1812
        xfs_bmbt_rec_host_t     *ep;    /* extent record for idx */
1813
        xfs_ifork_t             *ifp;   /* inode fork pointer */
1814
        xfs_bmbt_irec_t         left;   /* left neighbor extent entry */
1815
        xfs_filblks_t           newlen=0;        /* new indirect size */
1816
        xfs_filblks_t           oldlen=0;        /* old indirect size */
1817
        xfs_bmbt_irec_t         right;  /* right neighbor extent entry */
1818
        int                     state;  /* state bits, accessed thru macros */
1819
        xfs_filblks_t           temp=0;  /* temp for indirect calculations */
1820
        xfs_filblks_t           temp2=0;
1821
        enum {                          /* bit number definitions for state */
1822
                LEFT_CONTIG,    RIGHT_CONTIG,
1823
                LEFT_DELAY,     RIGHT_DELAY,
1824
                LEFT_VALID,     RIGHT_VALID
1825
        };
1826
 
1827
#define MASK(b)                 (1 << (b))
1828
#define MASK2(a,b)              (MASK(a) | MASK(b))
1829
#define STATE_SET(b,v)          ((v) ? (state |= MASK(b)) : (state &= ~MASK(b)))
1830
#define STATE_TEST(b)           (state & MASK(b))
1831
#define STATE_SET_TEST(b,v)     ((v) ? ((state |= MASK(b)), 1) : \
1832
                                       ((state &= ~MASK(b)), 0))
1833
#define SWITCH_STATE            (state & MASK2(LEFT_CONTIG, RIGHT_CONTIG))
1834
 
1835
        ifp = XFS_IFORK_PTR(ip, XFS_DATA_FORK);
1836
        ep = xfs_iext_get_ext(ifp, idx);
1837
        state = 0;
1838
        ASSERT(ISNULLSTARTBLOCK(new->br_startblock));
1839
        /*
1840
         * Check and set flags if this segment has a left neighbor
1841
         */
1842
        if (STATE_SET_TEST(LEFT_VALID, idx > 0)) {
1843
                xfs_bmbt_get_all(xfs_iext_get_ext(ifp, idx - 1), &left);
1844
                STATE_SET(LEFT_DELAY, ISNULLSTARTBLOCK(left.br_startblock));
1845
        }
1846
        /*
1847
         * Check and set flags if the current (right) segment exists.
1848
         * If it doesn't exist, we're converting the hole at end-of-file.
1849
         */
1850
        if (STATE_SET_TEST(RIGHT_VALID,
1851
                           idx <
1852
                           ip->i_df.if_bytes / (uint)sizeof(xfs_bmbt_rec_t))) {
1853
                xfs_bmbt_get_all(ep, &right);
1854
                STATE_SET(RIGHT_DELAY, ISNULLSTARTBLOCK(right.br_startblock));
1855
        }
1856
        /*
1857
         * Set contiguity flags on the left and right neighbors.
1858
         * Don't let extents get too large, even if the pieces are contiguous.
1859
         */
1860
        STATE_SET(LEFT_CONTIG,
1861
                STATE_TEST(LEFT_VALID) && STATE_TEST(LEFT_DELAY) &&
1862
                left.br_startoff + left.br_blockcount == new->br_startoff &&
1863
                left.br_blockcount + new->br_blockcount <= MAXEXTLEN);
1864
        STATE_SET(RIGHT_CONTIG,
1865
                STATE_TEST(RIGHT_VALID) && STATE_TEST(RIGHT_DELAY) &&
1866
                new->br_startoff + new->br_blockcount == right.br_startoff &&
1867
                new->br_blockcount + right.br_blockcount <= MAXEXTLEN &&
1868
                (!STATE_TEST(LEFT_CONTIG) ||
1869
                 (left.br_blockcount + new->br_blockcount +
1870
                     right.br_blockcount <= MAXEXTLEN)));
1871
        /*
1872
         * Switch out based on the contiguity flags.
1873
         */
1874
        switch (SWITCH_STATE) {
1875
 
1876
        case MASK2(LEFT_CONTIG, RIGHT_CONTIG):
1877
                /*
1878
                 * New allocation is contiguous with delayed allocations
1879
                 * on the left and on the right.
1880
                 * Merge all three into a single extent record.
1881
                 */
1882
                temp = left.br_blockcount + new->br_blockcount +
1883
                        right.br_blockcount;
1884
                XFS_BMAP_TRACE_PRE_UPDATE("LC|RC", ip, idx - 1,
1885
                        XFS_DATA_FORK);
1886
                xfs_bmbt_set_blockcount(xfs_iext_get_ext(ifp, idx - 1), temp);
1887
                oldlen = STARTBLOCKVAL(left.br_startblock) +
1888
                        STARTBLOCKVAL(new->br_startblock) +
1889
                        STARTBLOCKVAL(right.br_startblock);
1890
                newlen = xfs_bmap_worst_indlen(ip, temp);
1891
                xfs_bmbt_set_startblock(xfs_iext_get_ext(ifp, idx - 1),
1892
                        NULLSTARTBLOCK((int)newlen));
1893
                XFS_BMAP_TRACE_POST_UPDATE("LC|RC", ip, idx - 1,
1894
                        XFS_DATA_FORK);
1895
                XFS_BMAP_TRACE_DELETE("LC|RC", ip, idx, 1, XFS_DATA_FORK);
1896
                xfs_iext_remove(ifp, idx, 1);
1897
                ip->i_df.if_lastex = idx - 1;
1898
                /* DELTA: Two in-core extents were replaced by one. */
1899
                temp2 = temp;
1900
                temp = left.br_startoff;
1901
                break;
1902
 
1903
        case MASK(LEFT_CONTIG):
1904
                /*
1905
                 * New allocation is contiguous with a delayed allocation
1906
                 * on the left.
1907
                 * Merge the new allocation with the left neighbor.
1908
                 */
1909
                temp = left.br_blockcount + new->br_blockcount;
1910
                XFS_BMAP_TRACE_PRE_UPDATE("LC", ip, idx - 1,
1911
                        XFS_DATA_FORK);
1912
                xfs_bmbt_set_blockcount(xfs_iext_get_ext(ifp, idx - 1), temp);
1913
                oldlen = STARTBLOCKVAL(left.br_startblock) +
1914
                        STARTBLOCKVAL(new->br_startblock);
1915
                newlen = xfs_bmap_worst_indlen(ip, temp);
1916
                xfs_bmbt_set_startblock(xfs_iext_get_ext(ifp, idx - 1),
1917
                        NULLSTARTBLOCK((int)newlen));
1918
                XFS_BMAP_TRACE_POST_UPDATE("LC", ip, idx - 1,
1919
                        XFS_DATA_FORK);
1920
                ip->i_df.if_lastex = idx - 1;
1921
                /* DELTA: One in-core extent grew into a hole. */
1922
                temp2 = temp;
1923
                temp = left.br_startoff;
1924
                break;
1925
 
1926
        case MASK(RIGHT_CONTIG):
1927
                /*
1928
                 * New allocation is contiguous with a delayed allocation
1929
                 * on the right.
1930
                 * Merge the new allocation with the right neighbor.
1931
                 */
1932
                XFS_BMAP_TRACE_PRE_UPDATE("RC", ip, idx, XFS_DATA_FORK);
1933
                temp = new->br_blockcount + right.br_blockcount;
1934
                oldlen = STARTBLOCKVAL(new->br_startblock) +
1935
                        STARTBLOCKVAL(right.br_startblock);
1936
                newlen = xfs_bmap_worst_indlen(ip, temp);
1937
                xfs_bmbt_set_allf(ep, new->br_startoff,
1938
                        NULLSTARTBLOCK((int)newlen), temp, right.br_state);
1939
                XFS_BMAP_TRACE_POST_UPDATE("RC", ip, idx, XFS_DATA_FORK);
1940
                ip->i_df.if_lastex = idx;
1941
                /* DELTA: One in-core extent grew into a hole. */
1942
                temp2 = temp;
1943
                temp = new->br_startoff;
1944
                break;
1945
 
1946
        case 0:
1947
                /*
1948
                 * New allocation is not contiguous with another
1949
                 * delayed allocation.
1950
                 * Insert a new entry.
1951
                 */
1952
                oldlen = newlen = 0;
1953
                XFS_BMAP_TRACE_INSERT("0", ip, idx, 1, new, NULL,
1954
                        XFS_DATA_FORK);
1955
                xfs_iext_insert(ifp, idx, 1, new);
1956
                ip->i_df.if_lastex = idx;
1957
                /* DELTA: A new in-core extent was added in a hole. */
1958
                temp2 = new->br_blockcount;
1959
                temp = new->br_startoff;
1960
                break;
1961
        }
1962
        if (oldlen != newlen) {
1963
                ASSERT(oldlen > newlen);
1964
                xfs_mod_incore_sb(ip->i_mount, XFS_SBS_FDBLOCKS,
1965
                        (int64_t)(oldlen - newlen), rsvd);
1966
                /*
1967
                 * Nothing to do for disk quota accounting here.
1968
                 */
1969
        }
1970
        if (delta) {
1971
                temp2 += temp;
1972
                if (delta->xed_startoff > temp)
1973
                        delta->xed_startoff = temp;
1974
                if (delta->xed_blockcount < temp2)
1975
                        delta->xed_blockcount = temp2;
1976
        }
1977
        *logflagsp = 0;
1978
        return 0;
1979
#undef  MASK
1980
#undef  MASK2
1981
#undef  STATE_SET
1982
#undef  STATE_TEST
1983
#undef  STATE_SET_TEST
1984
#undef  SWITCH_STATE
1985
}
1986
 
1987
/*
1988
 * Called by xfs_bmap_add_extent to handle cases converting a hole
1989
 * to a real allocation.
1990
 */
1991
STATIC int                              /* error */
1992
xfs_bmap_add_extent_hole_real(
1993
        xfs_inode_t             *ip,    /* incore inode pointer */
1994
        xfs_extnum_t            idx,    /* extent number to update/insert */
1995
        xfs_btree_cur_t         *cur,   /* if null, not a btree */
1996
        xfs_bmbt_irec_t         *new,   /* new data to add to file extents */
1997
        int                     *logflagsp, /* inode logging flags */
1998
        xfs_extdelta_t          *delta, /* Change made to incore extents */
1999
        int                     whichfork) /* data or attr fork */
2000
{
2001
        xfs_bmbt_rec_host_t     *ep;    /* pointer to extent entry ins. point */
2002
        int                     error;  /* error return value */
2003
        int                     i;      /* temp state */
2004
        xfs_ifork_t             *ifp;   /* inode fork pointer */
2005
        xfs_bmbt_irec_t         left;   /* left neighbor extent entry */
2006
        xfs_bmbt_irec_t         right;  /* right neighbor extent entry */
2007
        int                     rval=0;  /* return value (logging flags) */
2008
        int                     state;  /* state bits, accessed thru macros */
2009
        xfs_filblks_t           temp=0;
2010
        xfs_filblks_t           temp2=0;
2011
        enum {                          /* bit number definitions for state */
2012
                LEFT_CONTIG,    RIGHT_CONTIG,
2013
                LEFT_DELAY,     RIGHT_DELAY,
2014
                LEFT_VALID,     RIGHT_VALID
2015
        };
2016
 
2017
#define MASK(b)                 (1 << (b))
2018
#define MASK2(a,b)              (MASK(a) | MASK(b))
2019
#define STATE_SET(b,v)          ((v) ? (state |= MASK(b)) : (state &= ~MASK(b)))
2020
#define STATE_TEST(b)           (state & MASK(b))
2021
#define STATE_SET_TEST(b,v)     ((v) ? ((state |= MASK(b)), 1) : \
2022
                                       ((state &= ~MASK(b)), 0))
2023
#define SWITCH_STATE            (state & MASK2(LEFT_CONTIG, RIGHT_CONTIG))
2024
 
2025
        ifp = XFS_IFORK_PTR(ip, whichfork);
2026
        ASSERT(idx <= ifp->if_bytes / (uint)sizeof(xfs_bmbt_rec_t));
2027
        ep = xfs_iext_get_ext(ifp, idx);
2028
        state = 0;
2029
        /*
2030
         * Check and set flags if this segment has a left neighbor.
2031
         */
2032
        if (STATE_SET_TEST(LEFT_VALID, idx > 0)) {
2033
                xfs_bmbt_get_all(xfs_iext_get_ext(ifp, idx - 1), &left);
2034
                STATE_SET(LEFT_DELAY, ISNULLSTARTBLOCK(left.br_startblock));
2035
        }
2036
        /*
2037
         * Check and set flags if this segment has a current value.
2038
         * Not true if we're inserting into the "hole" at eof.
2039
         */
2040
        if (STATE_SET_TEST(RIGHT_VALID,
2041
                           idx <
2042
                           ifp->if_bytes / (uint)sizeof(xfs_bmbt_rec_t))) {
2043
                xfs_bmbt_get_all(ep, &right);
2044
                STATE_SET(RIGHT_DELAY, ISNULLSTARTBLOCK(right.br_startblock));
2045
        }
2046
        /*
2047
         * We're inserting a real allocation between "left" and "right".
2048
         * Set the contiguity flags.  Don't let extents get too large.
2049
         */
2050
        STATE_SET(LEFT_CONTIG,
2051
                STATE_TEST(LEFT_VALID) && !STATE_TEST(LEFT_DELAY) &&
2052
                left.br_startoff + left.br_blockcount == new->br_startoff &&
2053
                left.br_startblock + left.br_blockcount == new->br_startblock &&
2054
                left.br_state == new->br_state &&
2055
                left.br_blockcount + new->br_blockcount <= MAXEXTLEN);
2056
        STATE_SET(RIGHT_CONTIG,
2057
                STATE_TEST(RIGHT_VALID) && !STATE_TEST(RIGHT_DELAY) &&
2058
                new->br_startoff + new->br_blockcount == right.br_startoff &&
2059
                new->br_startblock + new->br_blockcount ==
2060
                    right.br_startblock &&
2061
                new->br_state == right.br_state &&
2062
                new->br_blockcount + right.br_blockcount <= MAXEXTLEN &&
2063
                (!STATE_TEST(LEFT_CONTIG) ||
2064
                 left.br_blockcount + new->br_blockcount +
2065
                     right.br_blockcount <= MAXEXTLEN));
2066
 
2067
        error = 0;
2068
        /*
2069
         * Select which case we're in here, and implement it.
2070
         */
2071
        switch (SWITCH_STATE) {
2072
 
2073
        case MASK2(LEFT_CONTIG, RIGHT_CONTIG):
2074
                /*
2075
                 * New allocation is contiguous with real allocations on the
2076
                 * left and on the right.
2077
                 * Merge all three into a single extent record.
2078
                 */
2079
                XFS_BMAP_TRACE_PRE_UPDATE("LC|RC", ip, idx - 1,
2080
                        whichfork);
2081
                xfs_bmbt_set_blockcount(xfs_iext_get_ext(ifp, idx - 1),
2082
                        left.br_blockcount + new->br_blockcount +
2083
                        right.br_blockcount);
2084
                XFS_BMAP_TRACE_POST_UPDATE("LC|RC", ip, idx - 1,
2085
                        whichfork);
2086
                XFS_BMAP_TRACE_DELETE("LC|RC", ip, idx, 1, whichfork);
2087
                xfs_iext_remove(ifp, idx, 1);
2088
                ifp->if_lastex = idx - 1;
2089
                XFS_IFORK_NEXT_SET(ip, whichfork,
2090
                        XFS_IFORK_NEXTENTS(ip, whichfork) - 1);
2091
                if (cur == NULL) {
2092
                        rval = XFS_ILOG_CORE | XFS_ILOG_FEXT(whichfork);
2093
                } else {
2094
                        rval = XFS_ILOG_CORE;
2095
                        if ((error = xfs_bmbt_lookup_eq(cur,
2096
                                        right.br_startoff,
2097
                                        right.br_startblock,
2098
                                        right.br_blockcount, &i)))
2099
                                goto done;
2100
                        ASSERT(i == 1);
2101
                        if ((error = xfs_bmbt_delete(cur, &i)))
2102
                                goto done;
2103
                        ASSERT(i == 1);
2104
                        if ((error = xfs_bmbt_decrement(cur, 0, &i)))
2105
                                goto done;
2106
                        ASSERT(i == 1);
2107
                        if ((error = xfs_bmbt_update(cur, left.br_startoff,
2108
                                        left.br_startblock,
2109
                                        left.br_blockcount +
2110
                                                new->br_blockcount +
2111
                                                right.br_blockcount,
2112
                                        left.br_state)))
2113
                                goto done;
2114
                }
2115
                /* DELTA: Two in-core extents were replaced by one. */
2116
                temp = left.br_startoff;
2117
                temp2 = left.br_blockcount +
2118
                        new->br_blockcount +
2119
                        right.br_blockcount;
2120
                break;
2121
 
2122
        case MASK(LEFT_CONTIG):
2123
                /*
2124
                 * New allocation is contiguous with a real allocation
2125
                 * on the left.
2126
                 * Merge the new allocation with the left neighbor.
2127
                 */
2128
                XFS_BMAP_TRACE_PRE_UPDATE("LC", ip, idx - 1, whichfork);
2129
                xfs_bmbt_set_blockcount(xfs_iext_get_ext(ifp, idx - 1),
2130
                        left.br_blockcount + new->br_blockcount);
2131
                XFS_BMAP_TRACE_POST_UPDATE("LC", ip, idx - 1, whichfork);
2132
                ifp->if_lastex = idx - 1;
2133
                if (cur == NULL) {
2134
                        rval = XFS_ILOG_FEXT(whichfork);
2135
                } else {
2136
                        rval = 0;
2137
                        if ((error = xfs_bmbt_lookup_eq(cur,
2138
                                        left.br_startoff,
2139
                                        left.br_startblock,
2140
                                        left.br_blockcount, &i)))
2141
                                goto done;
2142
                        ASSERT(i == 1);
2143
                        if ((error = xfs_bmbt_update(cur, left.br_startoff,
2144
                                        left.br_startblock,
2145
                                        left.br_blockcount +
2146
                                                new->br_blockcount,
2147
                                        left.br_state)))
2148
                                goto done;
2149
                }
2150
                /* DELTA: One in-core extent grew. */
2151
                temp = left.br_startoff;
2152
                temp2 = left.br_blockcount +
2153
                        new->br_blockcount;
2154
                break;
2155
 
2156
        case MASK(RIGHT_CONTIG):
2157
                /*
2158
                 * New allocation is contiguous with a real allocation
2159
                 * on the right.
2160
                 * Merge the new allocation with the right neighbor.
2161
                 */
2162
                XFS_BMAP_TRACE_PRE_UPDATE("RC", ip, idx, whichfork);
2163
                xfs_bmbt_set_allf(ep, new->br_startoff, new->br_startblock,
2164
                        new->br_blockcount + right.br_blockcount,
2165
                        right.br_state);
2166
                XFS_BMAP_TRACE_POST_UPDATE("RC", ip, idx, whichfork);
2167
                ifp->if_lastex = idx;
2168
                if (cur == NULL) {
2169
                        rval = XFS_ILOG_FEXT(whichfork);
2170
                } else {
2171
                        rval = 0;
2172
                        if ((error = xfs_bmbt_lookup_eq(cur,
2173
                                        right.br_startoff,
2174
                                        right.br_startblock,
2175
                                        right.br_blockcount, &i)))
2176
                                goto done;
2177
                        ASSERT(i == 1);
2178
                        if ((error = xfs_bmbt_update(cur, new->br_startoff,
2179
                                        new->br_startblock,
2180
                                        new->br_blockcount +
2181
                                                right.br_blockcount,
2182
                                        right.br_state)))
2183
                                goto done;
2184
                }
2185
                /* DELTA: One in-core extent grew. */
2186
                temp = new->br_startoff;
2187
                temp2 = new->br_blockcount +
2188
                        right.br_blockcount;
2189
                break;
2190
 
2191
        case 0:
2192
                /*
2193
                 * New allocation is not contiguous with another
2194
                 * real allocation.
2195
                 * Insert a new entry.
2196
                 */
2197
                XFS_BMAP_TRACE_INSERT("0", ip, idx, 1, new, NULL, whichfork);
2198
                xfs_iext_insert(ifp, idx, 1, new);
2199
                ifp->if_lastex = idx;
2200
                XFS_IFORK_NEXT_SET(ip, whichfork,
2201
                        XFS_IFORK_NEXTENTS(ip, whichfork) + 1);
2202
                if (cur == NULL) {
2203
                        rval = XFS_ILOG_CORE | XFS_ILOG_FEXT(whichfork);
2204
                } else {
2205
                        rval = XFS_ILOG_CORE;
2206
                        if ((error = xfs_bmbt_lookup_eq(cur,
2207
                                        new->br_startoff,
2208
                                        new->br_startblock,
2209
                                        new->br_blockcount, &i)))
2210
                                goto done;
2211
                        ASSERT(i == 0);
2212
                        cur->bc_rec.b.br_state = new->br_state;
2213
                        if ((error = xfs_bmbt_insert(cur, &i)))
2214
                                goto done;
2215
                        ASSERT(i == 1);
2216
                }
2217
                /* DELTA: A new extent was added in a hole. */
2218
                temp = new->br_startoff;
2219
                temp2 = new->br_blockcount;
2220
                break;
2221
        }
2222
        if (delta) {
2223
                temp2 += temp;
2224
                if (delta->xed_startoff > temp)
2225
                        delta->xed_startoff = temp;
2226
                if (delta->xed_blockcount < temp2)
2227
                        delta->xed_blockcount = temp2;
2228
        }
2229
done:
2230
        *logflagsp = rval;
2231
        return error;
2232
#undef  MASK
2233
#undef  MASK2
2234
#undef  STATE_SET
2235
#undef  STATE_TEST
2236
#undef  STATE_SET_TEST
2237
#undef  SWITCH_STATE
2238
}
2239
 
2240
/*
2241
 * Adjust the size of the new extent based on di_extsize and rt extsize.
2242
 */
2243
STATIC int
2244
xfs_bmap_extsize_align(
2245
        xfs_mount_t     *mp,
2246
        xfs_bmbt_irec_t *gotp,          /* next extent pointer */
2247
        xfs_bmbt_irec_t *prevp,         /* previous extent pointer */
2248
        xfs_extlen_t    extsz,          /* align to this extent size */
2249
        int             rt,             /* is this a realtime inode? */
2250
        int             eof,            /* is extent at end-of-file? */
2251
        int             delay,          /* creating delalloc extent? */
2252
        int             convert,        /* overwriting unwritten extent? */
2253
        xfs_fileoff_t   *offp,          /* in/out: aligned offset */
2254
        xfs_extlen_t    *lenp)          /* in/out: aligned length */
2255
{
2256
        xfs_fileoff_t   orig_off;       /* original offset */
2257
        xfs_extlen_t    orig_alen;      /* original length */
2258
        xfs_fileoff_t   orig_end;       /* original off+len */
2259
        xfs_fileoff_t   nexto;          /* next file offset */
2260
        xfs_fileoff_t   prevo;          /* previous file offset */
2261
        xfs_fileoff_t   align_off;      /* temp for offset */
2262
        xfs_extlen_t    align_alen;     /* temp for length */
2263
        xfs_extlen_t    temp;           /* temp for calculations */
2264
 
2265
        if (convert)
2266
                return 0;
2267
 
2268
        orig_off = align_off = *offp;
2269
        orig_alen = align_alen = *lenp;
2270
        orig_end = orig_off + orig_alen;
2271
 
2272
        /*
2273
         * If this request overlaps an existing extent, then don't
2274
         * attempt to perform any additional alignment.
2275
         */
2276
        if (!delay && !eof &&
2277
            (orig_off >= gotp->br_startoff) &&
2278
            (orig_end <= gotp->br_startoff + gotp->br_blockcount)) {
2279
                return 0;
2280
        }
2281
 
2282
        /*
2283
         * If the file offset is unaligned vs. the extent size
2284
         * we need to align it.  This will be possible unless
2285
         * the file was previously written with a kernel that didn't
2286
         * perform this alignment, or if a truncate shot us in the
2287
         * foot.
2288
         */
2289
        temp = do_mod(orig_off, extsz);
2290
        if (temp) {
2291
                align_alen += temp;
2292
                align_off -= temp;
2293
        }
2294
        /*
2295
         * Same adjustment for the end of the requested area.
2296
         */
2297
        if ((temp = (align_alen % extsz))) {
2298
                align_alen += extsz - temp;
2299
        }
2300
        /*
2301
         * If the previous block overlaps with this proposed allocation
2302
         * then move the start forward without adjusting the length.
2303
         */
2304
        if (prevp->br_startoff != NULLFILEOFF) {
2305
                if (prevp->br_startblock == HOLESTARTBLOCK)
2306
                        prevo = prevp->br_startoff;
2307
                else
2308
                        prevo = prevp->br_startoff + prevp->br_blockcount;
2309
        } else
2310
                prevo = 0;
2311
        if (align_off != orig_off && align_off < prevo)
2312
                align_off = prevo;
2313
        /*
2314
         * If the next block overlaps with this proposed allocation
2315
         * then move the start back without adjusting the length,
2316
         * but not before offset 0.
2317
         * This may of course make the start overlap previous block,
2318
         * and if we hit the offset 0 limit then the next block
2319
         * can still overlap too.
2320
         */
2321
        if (!eof && gotp->br_startoff != NULLFILEOFF) {
2322
                if ((delay && gotp->br_startblock == HOLESTARTBLOCK) ||
2323
                    (!delay && gotp->br_startblock == DELAYSTARTBLOCK))
2324
                        nexto = gotp->br_startoff + gotp->br_blockcount;
2325
                else
2326
                        nexto = gotp->br_startoff;
2327
        } else
2328
                nexto = NULLFILEOFF;
2329
        if (!eof &&
2330
            align_off + align_alen != orig_end &&
2331
            align_off + align_alen > nexto)
2332
                align_off = nexto > align_alen ? nexto - align_alen : 0;
2333
        /*
2334
         * If we're now overlapping the next or previous extent that
2335
         * means we can't fit an extsz piece in this hole.  Just move
2336
         * the start forward to the first valid spot and set
2337
         * the length so we hit the end.
2338
         */
2339
        if (align_off != orig_off && align_off < prevo)
2340
                align_off = prevo;
2341
        if (align_off + align_alen != orig_end &&
2342
            align_off + align_alen > nexto &&
2343
            nexto != NULLFILEOFF) {
2344
                ASSERT(nexto > prevo);
2345
                align_alen = nexto - align_off;
2346
        }
2347
 
2348
        /*
2349
         * If realtime, and the result isn't a multiple of the realtime
2350
         * extent size we need to remove blocks until it is.
2351
         */
2352
        if (rt && (temp = (align_alen % mp->m_sb.sb_rextsize))) {
2353
                /*
2354
                 * We're not covering the original request, or
2355
                 * we won't be able to once we fix the length.
2356
                 */
2357
                if (orig_off < align_off ||
2358
                    orig_end > align_off + align_alen ||
2359
                    align_alen - temp < orig_alen)
2360
                        return XFS_ERROR(EINVAL);
2361
                /*
2362
                 * Try to fix it by moving the start up.
2363
                 */
2364
                if (align_off + temp <= orig_off) {
2365
                        align_alen -= temp;
2366
                        align_off += temp;
2367
                }
2368
                /*
2369
                 * Try to fix it by moving the end in.
2370
                 */
2371
                else if (align_off + align_alen - temp >= orig_end)
2372
                        align_alen -= temp;
2373
                /*
2374
                 * Set the start to the minimum then trim the length.
2375
                 */
2376
                else {
2377
                        align_alen -= orig_off - align_off;
2378
                        align_off = orig_off;
2379
                        align_alen -= align_alen % mp->m_sb.sb_rextsize;
2380
                }
2381
                /*
2382
                 * Result doesn't cover the request, fail it.
2383
                 */
2384
                if (orig_off < align_off || orig_end > align_off + align_alen)
2385
                        return XFS_ERROR(EINVAL);
2386
        } else {
2387
                ASSERT(orig_off >= align_off);
2388
                ASSERT(orig_end <= align_off + align_alen);
2389
        }
2390
 
2391
#ifdef DEBUG
2392
        if (!eof && gotp->br_startoff != NULLFILEOFF)
2393
                ASSERT(align_off + align_alen <= gotp->br_startoff);
2394
        if (prevp->br_startoff != NULLFILEOFF)
2395
                ASSERT(align_off >= prevp->br_startoff + prevp->br_blockcount);
2396
#endif
2397
 
2398
        *lenp = align_alen;
2399
        *offp = align_off;
2400
        return 0;
2401
}
2402
 
2403
#define XFS_ALLOC_GAP_UNITS     4
2404
 
2405
STATIC int
2406
xfs_bmap_adjacent(
2407
        xfs_bmalloca_t  *ap)            /* bmap alloc argument struct */
2408
{
2409
        xfs_fsblock_t   adjust;         /* adjustment to block numbers */
2410
        xfs_agnumber_t  fb_agno;        /* ag number of ap->firstblock */
2411
        xfs_mount_t     *mp;            /* mount point structure */
2412
        int             nullfb;         /* true if ap->firstblock isn't set */
2413
        int             rt;             /* true if inode is realtime */
2414
 
2415
#define ISVALID(x,y)    \
2416
        (rt ? \
2417
                (x) < mp->m_sb.sb_rblocks : \
2418
                XFS_FSB_TO_AGNO(mp, x) == XFS_FSB_TO_AGNO(mp, y) && \
2419
                XFS_FSB_TO_AGNO(mp, x) < mp->m_sb.sb_agcount && \
2420
                XFS_FSB_TO_AGBNO(mp, x) < mp->m_sb.sb_agblocks)
2421
 
2422
        mp = ap->ip->i_mount;
2423
        nullfb = ap->firstblock == NULLFSBLOCK;
2424
        rt = XFS_IS_REALTIME_INODE(ap->ip) && ap->userdata;
2425
        fb_agno = nullfb ? NULLAGNUMBER : XFS_FSB_TO_AGNO(mp, ap->firstblock);
2426
        /*
2427
         * If allocating at eof, and there's a previous real block,
2428
         * try to use it's last block as our starting point.
2429
         */
2430
        if (ap->eof && ap->prevp->br_startoff != NULLFILEOFF &&
2431
            !ISNULLSTARTBLOCK(ap->prevp->br_startblock) &&
2432
            ISVALID(ap->prevp->br_startblock + ap->prevp->br_blockcount,
2433
                    ap->prevp->br_startblock)) {
2434
                ap->rval = ap->prevp->br_startblock + ap->prevp->br_blockcount;
2435
                /*
2436
                 * Adjust for the gap between prevp and us.
2437
                 */
2438
                adjust = ap->off -
2439
                        (ap->prevp->br_startoff + ap->prevp->br_blockcount);
2440
                if (adjust &&
2441
                    ISVALID(ap->rval + adjust, ap->prevp->br_startblock))
2442
                        ap->rval += adjust;
2443
        }
2444
        /*
2445
         * If not at eof, then compare the two neighbor blocks.
2446
         * Figure out whether either one gives us a good starting point,
2447
         * and pick the better one.
2448
         */
2449
        else if (!ap->eof) {
2450
                xfs_fsblock_t   gotbno;         /* right side block number */
2451
                xfs_fsblock_t   gotdiff=0;       /* right side difference */
2452
                xfs_fsblock_t   prevbno;        /* left side block number */
2453
                xfs_fsblock_t   prevdiff=0;      /* left side difference */
2454
 
2455
                /*
2456
                 * If there's a previous (left) block, select a requested
2457
                 * start block based on it.
2458
                 */
2459
                if (ap->prevp->br_startoff != NULLFILEOFF &&
2460
                    !ISNULLSTARTBLOCK(ap->prevp->br_startblock) &&
2461
                    (prevbno = ap->prevp->br_startblock +
2462
                               ap->prevp->br_blockcount) &&
2463
                    ISVALID(prevbno, ap->prevp->br_startblock)) {
2464
                        /*
2465
                         * Calculate gap to end of previous block.
2466
                         */
2467
                        adjust = prevdiff = ap->off -
2468
                                (ap->prevp->br_startoff +
2469
                                 ap->prevp->br_blockcount);
2470
                        /*
2471
                         * Figure the startblock based on the previous block's
2472
                         * end and the gap size.
2473
                         * Heuristic!
2474
                         * If the gap is large relative to the piece we're
2475
                         * allocating, or using it gives us an invalid block
2476
                         * number, then just use the end of the previous block.
2477
                         */
2478
                        if (prevdiff <= XFS_ALLOC_GAP_UNITS * ap->alen &&
2479
                            ISVALID(prevbno + prevdiff,
2480
                                    ap->prevp->br_startblock))
2481
                                prevbno += adjust;
2482
                        else
2483
                                prevdiff += adjust;
2484
                        /*
2485
                         * If the firstblock forbids it, can't use it,
2486
                         * must use default.
2487
                         */
2488
                        if (!rt && !nullfb &&
2489
                            XFS_FSB_TO_AGNO(mp, prevbno) != fb_agno)
2490
                                prevbno = NULLFSBLOCK;
2491
                }
2492
                /*
2493
                 * No previous block or can't follow it, just default.
2494
                 */
2495
                else
2496
                        prevbno = NULLFSBLOCK;
2497
                /*
2498
                 * If there's a following (right) block, select a requested
2499
                 * start block based on it.
2500
                 */
2501
                if (!ISNULLSTARTBLOCK(ap->gotp->br_startblock)) {
2502
                        /*
2503
                         * Calculate gap to start of next block.
2504
                         */
2505
                        adjust = gotdiff = ap->gotp->br_startoff - ap->off;
2506
                        /*
2507
                         * Figure the startblock based on the next block's
2508
                         * start and the gap size.
2509
                         */
2510
                        gotbno = ap->gotp->br_startblock;
2511
                        /*
2512
                         * Heuristic!
2513
                         * If the gap is large relative to the piece we're
2514
                         * allocating, or using it gives us an invalid block
2515
                         * number, then just use the start of the next block
2516
                         * offset by our length.
2517
                         */
2518
                        if (gotdiff <= XFS_ALLOC_GAP_UNITS * ap->alen &&
2519
                            ISVALID(gotbno - gotdiff, gotbno))
2520
                                gotbno -= adjust;
2521
                        else if (ISVALID(gotbno - ap->alen, gotbno)) {
2522
                                gotbno -= ap->alen;
2523
                                gotdiff += adjust - ap->alen;
2524
                        } else
2525
                                gotdiff += adjust;
2526
                        /*
2527
                         * If the firstblock forbids it, can't use it,
2528
                         * must use default.
2529
                         */
2530
                        if (!rt && !nullfb &&
2531
                            XFS_FSB_TO_AGNO(mp, gotbno) != fb_agno)
2532
                                gotbno = NULLFSBLOCK;
2533
                }
2534
                /*
2535
                 * No next block, just default.
2536
                 */
2537
                else
2538
                        gotbno = NULLFSBLOCK;
2539
                /*
2540
                 * If both valid, pick the better one, else the only good
2541
                 * one, else ap->rval is already set (to 0 or the inode block).
2542
                 */
2543
                if (prevbno != NULLFSBLOCK && gotbno != NULLFSBLOCK)
2544
                        ap->rval = prevdiff <= gotdiff ? prevbno : gotbno;
2545
                else if (prevbno != NULLFSBLOCK)
2546
                        ap->rval = prevbno;
2547
                else if (gotbno != NULLFSBLOCK)
2548
                        ap->rval = gotbno;
2549
        }
2550
#undef ISVALID
2551
        return 0;
2552
}
2553
 
2554
STATIC int
2555
xfs_bmap_rtalloc(
2556
        xfs_bmalloca_t  *ap)            /* bmap alloc argument struct */
2557
{
2558
        xfs_alloctype_t atype = 0;       /* type for allocation routines */
2559
        int             error;          /* error return value */
2560
        xfs_mount_t     *mp;            /* mount point structure */
2561
        xfs_extlen_t    prod = 0;        /* product factor for allocators */
2562
        xfs_extlen_t    ralen = 0;       /* realtime allocation length */
2563
        xfs_extlen_t    align;          /* minimum allocation alignment */
2564
        xfs_rtblock_t   rtb;
2565
 
2566
        mp = ap->ip->i_mount;
2567
        align = xfs_get_extsz_hint(ap->ip);
2568
        prod = align / mp->m_sb.sb_rextsize;
2569
        error = xfs_bmap_extsize_align(mp, ap->gotp, ap->prevp,
2570
                                        align, 1, ap->eof, 0,
2571
                                        ap->conv, &ap->off, &ap->alen);
2572
        if (error)
2573
                return error;
2574
        ASSERT(ap->alen);
2575
        ASSERT(ap->alen % mp->m_sb.sb_rextsize == 0);
2576
 
2577
        /*
2578
         * If the offset & length are not perfectly aligned
2579
         * then kill prod, it will just get us in trouble.
2580
         */
2581
        if (do_mod(ap->off, align) || ap->alen % align)
2582
                prod = 1;
2583
        /*
2584
         * Set ralen to be the actual requested length in rtextents.
2585
         */
2586
        ralen = ap->alen / mp->m_sb.sb_rextsize;
2587
        /*
2588
         * If the old value was close enough to MAXEXTLEN that
2589
         * we rounded up to it, cut it back so it's valid again.
2590
         * Note that if it's a really large request (bigger than
2591
         * MAXEXTLEN), we don't hear about that number, and can't
2592
         * adjust the starting point to match it.
2593
         */
2594
        if (ralen * mp->m_sb.sb_rextsize >= MAXEXTLEN)
2595
                ralen = MAXEXTLEN / mp->m_sb.sb_rextsize;
2596
        /*
2597
         * If it's an allocation to an empty file at offset 0,
2598
         * pick an extent that will space things out in the rt area.
2599
         */
2600
        if (ap->eof && ap->off == 0) {
2601
                xfs_rtblock_t uninitialized_var(rtx); /* realtime extent no */
2602
 
2603
                error = xfs_rtpick_extent(mp, ap->tp, ralen, &rtx);
2604
                if (error)
2605
                        return error;
2606
                ap->rval = rtx * mp->m_sb.sb_rextsize;
2607
        } else {
2608
                ap->rval = 0;
2609
        }
2610
 
2611
        xfs_bmap_adjacent(ap);
2612
 
2613
        /*
2614
         * Realtime allocation, done through xfs_rtallocate_extent.
2615
         */
2616
        atype = ap->rval == 0 ?  XFS_ALLOCTYPE_ANY_AG : XFS_ALLOCTYPE_NEAR_BNO;
2617
        do_div(ap->rval, mp->m_sb.sb_rextsize);
2618
        rtb = ap->rval;
2619
        ap->alen = ralen;
2620
        if ((error = xfs_rtallocate_extent(ap->tp, ap->rval, 1, ap->alen,
2621
                                &ralen, atype, ap->wasdel, prod, &rtb)))
2622
                return error;
2623
        if (rtb == NULLFSBLOCK && prod > 1 &&
2624
            (error = xfs_rtallocate_extent(ap->tp, ap->rval, 1,
2625
                                           ap->alen, &ralen, atype,
2626
                                           ap->wasdel, 1, &rtb)))
2627
                return error;
2628
        ap->rval = rtb;
2629
        if (ap->rval != NULLFSBLOCK) {
2630
                ap->rval *= mp->m_sb.sb_rextsize;
2631
                ralen *= mp->m_sb.sb_rextsize;
2632
                ap->alen = ralen;
2633
                ap->ip->i_d.di_nblocks += ralen;
2634
                xfs_trans_log_inode(ap->tp, ap->ip, XFS_ILOG_CORE);
2635
                if (ap->wasdel)
2636
                        ap->ip->i_delayed_blks -= ralen;
2637
                /*
2638
                 * Adjust the disk quota also. This was reserved
2639
                 * earlier.
2640
                 */
2641
                XFS_TRANS_MOD_DQUOT_BYINO(mp, ap->tp, ap->ip,
2642
                        ap->wasdel ? XFS_TRANS_DQ_DELRTBCOUNT :
2643
                                        XFS_TRANS_DQ_RTBCOUNT, (long) ralen);
2644
        } else {
2645
                ap->alen = 0;
2646
        }
2647
        return 0;
2648
}
2649
 
2650
STATIC int
2651
xfs_bmap_btalloc(
2652
        xfs_bmalloca_t  *ap)            /* bmap alloc argument struct */
2653
{
2654
        xfs_mount_t     *mp;            /* mount point structure */
2655
        xfs_alloctype_t atype = 0;       /* type for allocation routines */
2656
        xfs_extlen_t    align;          /* minimum allocation alignment */
2657
        xfs_agnumber_t  ag;
2658
        xfs_agnumber_t  fb_agno;        /* ag number of ap->firstblock */
2659
        xfs_agnumber_t  startag;
2660
        xfs_alloc_arg_t args;
2661
        xfs_extlen_t    blen;
2662
        xfs_extlen_t    delta;
2663
        xfs_extlen_t    longest;
2664
        xfs_extlen_t    need;
2665
        xfs_extlen_t    nextminlen = 0;
2666
        xfs_perag_t     *pag;
2667
        int             nullfb;         /* true if ap->firstblock isn't set */
2668
        int             isaligned;
2669
        int             notinit;
2670
        int             tryagain;
2671
        int             error;
2672
 
2673
        mp = ap->ip->i_mount;
2674
        align = ap->userdata ? xfs_get_extsz_hint(ap->ip) : 0;
2675
        if (unlikely(align)) {
2676
                error = xfs_bmap_extsize_align(mp, ap->gotp, ap->prevp,
2677
                                                align, 0, ap->eof, 0, ap->conv,
2678
                                                &ap->off, &ap->alen);
2679
                ASSERT(!error);
2680
                ASSERT(ap->alen);
2681
        }
2682
        nullfb = ap->firstblock == NULLFSBLOCK;
2683
        fb_agno = nullfb ? NULLAGNUMBER : XFS_FSB_TO_AGNO(mp, ap->firstblock);
2684
        if (nullfb) {
2685
                if (ap->userdata && xfs_inode_is_filestream(ap->ip)) {
2686
                        ag = xfs_filestream_lookup_ag(ap->ip);
2687
                        ag = (ag != NULLAGNUMBER) ? ag : 0;
2688
                        ap->rval = XFS_AGB_TO_FSB(mp, ag, 0);
2689
                } else {
2690
                        ap->rval = XFS_INO_TO_FSB(mp, ap->ip->i_ino);
2691
                }
2692
        } else
2693
                ap->rval = ap->firstblock;
2694
 
2695
        xfs_bmap_adjacent(ap);
2696
 
2697
        /*
2698
         * If allowed, use ap->rval; otherwise must use firstblock since
2699
         * it's in the right allocation group.
2700
         */
2701
        if (nullfb || XFS_FSB_TO_AGNO(mp, ap->rval) == fb_agno)
2702
                ;
2703
        else
2704
                ap->rval = ap->firstblock;
2705
        /*
2706
         * Normal allocation, done through xfs_alloc_vextent.
2707
         */
2708
        tryagain = isaligned = 0;
2709
        args.tp = ap->tp;
2710
        args.mp = mp;
2711
        args.fsbno = ap->rval;
2712
        args.maxlen = MIN(ap->alen, mp->m_sb.sb_agblocks);
2713
        args.firstblock = ap->firstblock;
2714
        blen = 0;
2715
        if (nullfb) {
2716
                if (ap->userdata && xfs_inode_is_filestream(ap->ip))
2717
                        args.type = XFS_ALLOCTYPE_NEAR_BNO;
2718
                else
2719
                        args.type = XFS_ALLOCTYPE_START_BNO;
2720
                args.total = ap->total;
2721
 
2722
                /*
2723
                 * Search for an allocation group with a single extent
2724
                 * large enough for the request.
2725
                 *
2726
                 * If one isn't found, then adjust the minimum allocation
2727
                 * size to the largest space found.
2728
                 */
2729
                startag = ag = XFS_FSB_TO_AGNO(mp, args.fsbno);
2730
                if (startag == NULLAGNUMBER)
2731
                        startag = ag = 0;
2732
                notinit = 0;
2733
                down_read(&mp->m_peraglock);
2734
                while (blen < ap->alen) {
2735
                        pag = &mp->m_perag[ag];
2736
                        if (!pag->pagf_init &&
2737
                            (error = xfs_alloc_pagf_init(mp, args.tp,
2738
                                    ag, XFS_ALLOC_FLAG_TRYLOCK))) {
2739
                                up_read(&mp->m_peraglock);
2740
                                return error;
2741
                        }
2742
                        /*
2743
                         * See xfs_alloc_fix_freelist...
2744
                         */
2745
                        if (pag->pagf_init) {
2746
                                need = XFS_MIN_FREELIST_PAG(pag, mp);
2747
                                delta = need > pag->pagf_flcount ?
2748
                                        need - pag->pagf_flcount : 0;
2749
                                longest = (pag->pagf_longest > delta) ?
2750
                                        (pag->pagf_longest - delta) :
2751
                                        (pag->pagf_flcount > 0 ||
2752
                                         pag->pagf_longest > 0);
2753
                                if (blen < longest)
2754
                                        blen = longest;
2755
                        } else
2756
                                notinit = 1;
2757
 
2758
                        if (xfs_inode_is_filestream(ap->ip)) {
2759
                                if (blen >= ap->alen)
2760
                                        break;
2761
 
2762
                                if (ap->userdata) {
2763
                                        /*
2764
                                         * If startag is an invalid AG, we've
2765
                                         * come here once before and
2766
                                         * xfs_filestream_new_ag picked the
2767
                                         * best currently available.
2768
                                         *
2769
                                         * Don't continue looping, since we
2770
                                         * could loop forever.
2771
                                         */
2772
                                        if (startag == NULLAGNUMBER)
2773
                                                break;
2774
 
2775
                                        error = xfs_filestream_new_ag(ap, &ag);
2776
                                        if (error) {
2777
                                                up_read(&mp->m_peraglock);
2778
                                                return error;
2779
                                        }
2780
 
2781
                                        /* loop again to set 'blen'*/
2782
                                        startag = NULLAGNUMBER;
2783
                                        continue;
2784
                                }
2785
                        }
2786
                        if (++ag == mp->m_sb.sb_agcount)
2787
                                ag = 0;
2788
                        if (ag == startag)
2789
                                break;
2790
                }
2791
                up_read(&mp->m_peraglock);
2792
                /*
2793
                 * Since the above loop did a BUF_TRYLOCK, it is
2794
                 * possible that there is space for this request.
2795
                 */
2796
                if (notinit || blen < ap->minlen)
2797
                        args.minlen = ap->minlen;
2798
                /*
2799
                 * If the best seen length is less than the request
2800
                 * length, use the best as the minimum.
2801
                 */
2802
                else if (blen < ap->alen)
2803
                        args.minlen = blen;
2804
                /*
2805
                 * Otherwise we've seen an extent as big as alen,
2806
                 * use that as the minimum.
2807
                 */
2808
                else
2809
                        args.minlen = ap->alen;
2810
 
2811
                /*
2812
                 * set the failure fallback case to look in the selected
2813
                 * AG as the stream may have moved.
2814
                 */
2815
                if (xfs_inode_is_filestream(ap->ip))
2816
                        ap->rval = args.fsbno = XFS_AGB_TO_FSB(mp, ag, 0);
2817
        } else if (ap->low) {
2818
                if (xfs_inode_is_filestream(ap->ip))
2819
                        args.type = XFS_ALLOCTYPE_FIRST_AG;
2820
                else
2821
                        args.type = XFS_ALLOCTYPE_START_BNO;
2822
                args.total = args.minlen = ap->minlen;
2823
        } else {
2824
                args.type = XFS_ALLOCTYPE_NEAR_BNO;
2825
                args.total = ap->total;
2826
                args.minlen = ap->minlen;
2827
        }
2828
        /* apply extent size hints if obtained earlier */
2829
        if (unlikely(align)) {
2830
                args.prod = align;
2831
                if ((args.mod = (xfs_extlen_t)do_mod(ap->off, args.prod)))
2832
                        args.mod = (xfs_extlen_t)(args.prod - args.mod);
2833
        } else if (mp->m_sb.sb_blocksize >= NBPP) {
2834
                args.prod = 1;
2835
                args.mod = 0;
2836
        } else {
2837
                args.prod = NBPP >> mp->m_sb.sb_blocklog;
2838
                if ((args.mod = (xfs_extlen_t)(do_mod(ap->off, args.prod))))
2839
                        args.mod = (xfs_extlen_t)(args.prod - args.mod);
2840
        }
2841
        /*
2842
         * If we are not low on available data blocks, and the
2843
         * underlying logical volume manager is a stripe, and
2844
         * the file offset is zero then try to allocate data
2845
         * blocks on stripe unit boundary.
2846
         * NOTE: ap->aeof is only set if the allocation length
2847
         * is >= the stripe unit and the allocation offset is
2848
         * at the end of file.
2849
         */
2850
        if (!ap->low && ap->aeof) {
2851
                if (!ap->off) {
2852
                        args.alignment = mp->m_dalign;
2853
                        atype = args.type;
2854
                        isaligned = 1;
2855
                        /*
2856
                         * Adjust for alignment
2857
                         */
2858
                        if (blen > args.alignment && blen <= ap->alen)
2859
                                args.minlen = blen - args.alignment;
2860
                        args.minalignslop = 0;
2861
                } else {
2862
                        /*
2863
                         * First try an exact bno allocation.
2864
                         * If it fails then do a near or start bno
2865
                         * allocation with alignment turned on.
2866
                         */
2867
                        atype = args.type;
2868
                        tryagain = 1;
2869
                        args.type = XFS_ALLOCTYPE_THIS_BNO;
2870
                        args.alignment = 1;
2871
                        /*
2872
                         * Compute the minlen+alignment for the
2873
                         * next case.  Set slop so that the value
2874
                         * of minlen+alignment+slop doesn't go up
2875
                         * between the calls.
2876
                         */
2877
                        if (blen > mp->m_dalign && blen <= ap->alen)
2878
                                nextminlen = blen - mp->m_dalign;
2879
                        else
2880
                                nextminlen = args.minlen;
2881
                        if (nextminlen + mp->m_dalign > args.minlen + 1)
2882
                                args.minalignslop =
2883
                                        nextminlen + mp->m_dalign -
2884
                                        args.minlen - 1;
2885
                        else
2886
                                args.minalignslop = 0;
2887
                }
2888
        } else {
2889
                args.alignment = 1;
2890
                args.minalignslop = 0;
2891
        }
2892
        args.minleft = ap->minleft;
2893
        args.wasdel = ap->wasdel;
2894
        args.isfl = 0;
2895
        args.userdata = ap->userdata;
2896
        if ((error = xfs_alloc_vextent(&args)))
2897
                return error;
2898
        if (tryagain && args.fsbno == NULLFSBLOCK) {
2899
                /*
2900
                 * Exact allocation failed. Now try with alignment
2901
                 * turned on.
2902
                 */
2903
                args.type = atype;
2904
                args.fsbno = ap->rval;
2905
                args.alignment = mp->m_dalign;
2906
                args.minlen = nextminlen;
2907
                args.minalignslop = 0;
2908
                isaligned = 1;
2909
                if ((error = xfs_alloc_vextent(&args)))
2910
                        return error;
2911
        }
2912
        if (isaligned && args.fsbno == NULLFSBLOCK) {
2913
                /*
2914
                 * allocation failed, so turn off alignment and
2915
                 * try again.
2916
                 */
2917
                args.type = atype;
2918
                args.fsbno = ap->rval;
2919
                args.alignment = 0;
2920
                if ((error = xfs_alloc_vextent(&args)))
2921
                        return error;
2922
        }
2923
        if (args.fsbno == NULLFSBLOCK && nullfb &&
2924
            args.minlen > ap->minlen) {
2925
                args.minlen = ap->minlen;
2926
                args.type = XFS_ALLOCTYPE_START_BNO;
2927
                args.fsbno = ap->rval;
2928
                if ((error = xfs_alloc_vextent(&args)))
2929
                        return error;
2930
        }
2931
        if (args.fsbno == NULLFSBLOCK && nullfb) {
2932
                args.fsbno = 0;
2933
                args.type = XFS_ALLOCTYPE_FIRST_AG;
2934
                args.total = ap->minlen;
2935
                args.minleft = 0;
2936
                if ((error = xfs_alloc_vextent(&args)))
2937
                        return error;
2938
                ap->low = 1;
2939
        }
2940
        if (args.fsbno != NULLFSBLOCK) {
2941
                ap->firstblock = ap->rval = args.fsbno;
2942
                ASSERT(nullfb || fb_agno == args.agno ||
2943
                       (ap->low && fb_agno < args.agno));
2944
                ap->alen = args.len;
2945
                ap->ip->i_d.di_nblocks += args.len;
2946
                xfs_trans_log_inode(ap->tp, ap->ip, XFS_ILOG_CORE);
2947
                if (ap->wasdel)
2948
                        ap->ip->i_delayed_blks -= args.len;
2949
                /*
2950
                 * Adjust the disk quota also. This was reserved
2951
                 * earlier.
2952
                 */
2953
                XFS_TRANS_MOD_DQUOT_BYINO(mp, ap->tp, ap->ip,
2954
                        ap->wasdel ? XFS_TRANS_DQ_DELBCOUNT :
2955
                                        XFS_TRANS_DQ_BCOUNT,
2956
                        (long) args.len);
2957
        } else {
2958
                ap->rval = NULLFSBLOCK;
2959
                ap->alen = 0;
2960
        }
2961
        return 0;
2962
}
2963
 
2964
/*
2965
 * xfs_bmap_alloc is called by xfs_bmapi to allocate an extent for a file.
2966
 * It figures out where to ask the underlying allocator to put the new extent.
2967
 */
2968
STATIC int
2969
xfs_bmap_alloc(
2970
        xfs_bmalloca_t  *ap)            /* bmap alloc argument struct */
2971
{
2972
        if ((ap->ip->i_d.di_flags & XFS_DIFLAG_REALTIME) && ap->userdata)
2973
                return xfs_bmap_rtalloc(ap);
2974
        return xfs_bmap_btalloc(ap);
2975
}
2976
 
2977
/*
2978
 * Transform a btree format file with only one leaf node, where the
2979
 * extents list will fit in the inode, into an extents format file.
2980
 * Since the file extents are already in-core, all we have to do is
2981
 * give up the space for the btree root and pitch the leaf block.
2982
 */
2983
STATIC int                              /* error */
2984
xfs_bmap_btree_to_extents(
2985
        xfs_trans_t             *tp,    /* transaction pointer */
2986
        xfs_inode_t             *ip,    /* incore inode pointer */
2987
        xfs_btree_cur_t         *cur,   /* btree cursor */
2988
        int                     *logflagsp, /* inode logging flags */
2989
        int                     whichfork)  /* data or attr fork */
2990
{
2991
        /* REFERENCED */
2992
        xfs_bmbt_block_t        *cblock;/* child btree block */
2993
        xfs_fsblock_t           cbno;   /* child block number */
2994
        xfs_buf_t               *cbp;   /* child block's buffer */
2995
        int                     error;  /* error return value */
2996
        xfs_ifork_t             *ifp;   /* inode fork data */
2997
        xfs_mount_t             *mp;    /* mount point structure */
2998
        __be64                  *pp;    /* ptr to block address */
2999
        xfs_bmbt_block_t        *rblock;/* root btree block */
3000
 
3001
        ifp = XFS_IFORK_PTR(ip, whichfork);
3002
        ASSERT(ifp->if_flags & XFS_IFEXTENTS);
3003
        ASSERT(XFS_IFORK_FORMAT(ip, whichfork) == XFS_DINODE_FMT_BTREE);
3004
        rblock = ifp->if_broot;
3005
        ASSERT(be16_to_cpu(rblock->bb_level) == 1);
3006
        ASSERT(be16_to_cpu(rblock->bb_numrecs) == 1);
3007
        ASSERT(XFS_BMAP_BROOT_MAXRECS(ifp->if_broot_bytes) == 1);
3008
        mp = ip->i_mount;
3009
        pp = XFS_BMAP_BROOT_PTR_ADDR(rblock, 1, ifp->if_broot_bytes);
3010
        cbno = be64_to_cpu(*pp);
3011
        *logflagsp = 0;
3012
#ifdef DEBUG
3013
        if ((error = xfs_btree_check_lptr(cur, cbno, 1)))
3014
                return error;
3015
#endif
3016
        if ((error = xfs_btree_read_bufl(mp, tp, cbno, 0, &cbp,
3017
                        XFS_BMAP_BTREE_REF)))
3018
                return error;
3019
        cblock = XFS_BUF_TO_BMBT_BLOCK(cbp);
3020
        if ((error = xfs_btree_check_lblock(cur, cblock, 0, cbp)))
3021
                return error;
3022
        xfs_bmap_add_free(cbno, 1, cur->bc_private.b.flist, mp);
3023
        ip->i_d.di_nblocks--;
3024
        XFS_TRANS_MOD_DQUOT_BYINO(mp, tp, ip, XFS_TRANS_DQ_BCOUNT, -1L);
3025
        xfs_trans_binval(tp, cbp);
3026
        if (cur->bc_bufs[0] == cbp)
3027
                cur->bc_bufs[0] = NULL;
3028
        xfs_iroot_realloc(ip, -1, whichfork);
3029
        ASSERT(ifp->if_broot == NULL);
3030
        ASSERT((ifp->if_flags & XFS_IFBROOT) == 0);
3031
        XFS_IFORK_FMT_SET(ip, whichfork, XFS_DINODE_FMT_EXTENTS);
3032
        *logflagsp = XFS_ILOG_CORE | XFS_ILOG_FEXT(whichfork);
3033
        return 0;
3034
}
3035
 
3036
/*
3037
 * Called by xfs_bmapi to update file extent records and the btree
3038
 * after removing space (or undoing a delayed allocation).
3039
 */
3040
STATIC int                              /* error */
3041
xfs_bmap_del_extent(
3042
        xfs_inode_t             *ip,    /* incore inode pointer */
3043
        xfs_trans_t             *tp,    /* current transaction pointer */
3044
        xfs_extnum_t            idx,    /* extent number to update/delete */
3045
        xfs_bmap_free_t         *flist, /* list of extents to be freed */
3046
        xfs_btree_cur_t         *cur,   /* if null, not a btree */
3047
        xfs_bmbt_irec_t         *del,   /* data to remove from extents */
3048
        int                     *logflagsp, /* inode logging flags */
3049
        xfs_extdelta_t          *delta, /* Change made to incore extents */
3050
        int                     whichfork, /* data or attr fork */
3051
        int                     rsvd)   /* OK to allocate reserved blocks */
3052
{
3053
        xfs_filblks_t           da_new; /* new delay-alloc indirect blocks */
3054
        xfs_filblks_t           da_old; /* old delay-alloc indirect blocks */
3055
        xfs_fsblock_t           del_endblock=0;  /* first block past del */
3056
        xfs_fileoff_t           del_endoff;     /* first offset past del */
3057
        int                     delay;  /* current block is delayed allocated */
3058
        int                     do_fx;  /* free extent at end of routine */
3059
        xfs_bmbt_rec_host_t     *ep;    /* current extent entry pointer */
3060
        int                     error;  /* error return value */
3061
        int                     flags;  /* inode logging flags */
3062
        xfs_bmbt_irec_t         got;    /* current extent entry */
3063
        xfs_fileoff_t           got_endoff;     /* first offset past got */
3064
        int                     i;      /* temp state */
3065
        xfs_ifork_t             *ifp;   /* inode fork pointer */
3066
        xfs_mount_t             *mp;    /* mount structure */
3067
        xfs_filblks_t           nblks;  /* quota/sb block count */
3068
        xfs_bmbt_irec_t         new;    /* new record to be inserted */
3069
        /* REFERENCED */
3070
        uint                    qfield; /* quota field to update */
3071
        xfs_filblks_t           temp;   /* for indirect length calculations */
3072
        xfs_filblks_t           temp2;  /* for indirect length calculations */
3073
 
3074
        XFS_STATS_INC(xs_del_exlist);
3075
        mp = ip->i_mount;
3076
        ifp = XFS_IFORK_PTR(ip, whichfork);
3077
        ASSERT((idx >= 0) && (idx < ifp->if_bytes /
3078
                (uint)sizeof(xfs_bmbt_rec_t)));
3079
        ASSERT(del->br_blockcount > 0);
3080
        ep = xfs_iext_get_ext(ifp, idx);
3081
        xfs_bmbt_get_all(ep, &got);
3082
        ASSERT(got.br_startoff <= del->br_startoff);
3083
        del_endoff = del->br_startoff + del->br_blockcount;
3084
        got_endoff = got.br_startoff + got.br_blockcount;
3085
        ASSERT(got_endoff >= del_endoff);
3086
        delay = ISNULLSTARTBLOCK(got.br_startblock);
3087
        ASSERT(ISNULLSTARTBLOCK(del->br_startblock) == delay);
3088
        flags = 0;
3089
        qfield = 0;
3090
        error = 0;
3091
        /*
3092
         * If deleting a real allocation, must free up the disk space.
3093
         */
3094
        if (!delay) {
3095
                flags = XFS_ILOG_CORE;
3096
                /*
3097
                 * Realtime allocation.  Free it and record di_nblocks update.
3098
                 */
3099
                if (whichfork == XFS_DATA_FORK &&
3100
                    (ip->i_d.di_flags & XFS_DIFLAG_REALTIME)) {
3101
                        xfs_fsblock_t   bno;
3102
                        xfs_filblks_t   len;
3103
 
3104
                        ASSERT(do_mod(del->br_blockcount,
3105
                                      mp->m_sb.sb_rextsize) == 0);
3106
                        ASSERT(do_mod(del->br_startblock,
3107
                                      mp->m_sb.sb_rextsize) == 0);
3108
                        bno = del->br_startblock;
3109
                        len = del->br_blockcount;
3110
                        do_div(bno, mp->m_sb.sb_rextsize);
3111
                        do_div(len, mp->m_sb.sb_rextsize);
3112
                        if ((error = xfs_rtfree_extent(ip->i_transp, bno,
3113
                                        (xfs_extlen_t)len)))
3114
                                goto done;
3115
                        do_fx = 0;
3116
                        nblks = len * mp->m_sb.sb_rextsize;
3117
                        qfield = XFS_TRANS_DQ_RTBCOUNT;
3118
                }
3119
                /*
3120
                 * Ordinary allocation.
3121
                 */
3122
                else {
3123
                        do_fx = 1;
3124
                        nblks = del->br_blockcount;
3125
                        qfield = XFS_TRANS_DQ_BCOUNT;
3126
                }
3127
                /*
3128
                 * Set up del_endblock and cur for later.
3129
                 */
3130
                del_endblock = del->br_startblock + del->br_blockcount;
3131
                if (cur) {
3132
                        if ((error = xfs_bmbt_lookup_eq(cur, got.br_startoff,
3133
                                        got.br_startblock, got.br_blockcount,
3134
                                        &i)))
3135
                                goto done;
3136
                        ASSERT(i == 1);
3137
                }
3138
                da_old = da_new = 0;
3139
        } else {
3140
                da_old = STARTBLOCKVAL(got.br_startblock);
3141
                da_new = 0;
3142
                nblks = 0;
3143
                do_fx = 0;
3144
        }
3145
        /*
3146
         * Set flag value to use in switch statement.
3147
         * Left-contig is 2, right-contig is 1.
3148
         */
3149
        switch (((got.br_startoff == del->br_startoff) << 1) |
3150
                (got_endoff == del_endoff)) {
3151
        case 3:
3152
                /*
3153
                 * Matches the whole extent.  Delete the entry.
3154
                 */
3155
                XFS_BMAP_TRACE_DELETE("3", ip, idx, 1, whichfork);
3156
                xfs_iext_remove(ifp, idx, 1);
3157
                ifp->if_lastex = idx;
3158
                if (delay)
3159
                        break;
3160
                XFS_IFORK_NEXT_SET(ip, whichfork,
3161
                        XFS_IFORK_NEXTENTS(ip, whichfork) - 1);
3162
                flags |= XFS_ILOG_CORE;
3163
                if (!cur) {
3164
                        flags |= XFS_ILOG_FEXT(whichfork);
3165
                        break;
3166
                }
3167
                if ((error = xfs_bmbt_delete(cur, &i)))
3168
                        goto done;
3169
                ASSERT(i == 1);
3170
                break;
3171
 
3172
        case 2:
3173
                /*
3174
                 * Deleting the first part of the extent.
3175
                 */
3176
                XFS_BMAP_TRACE_PRE_UPDATE("2", ip, idx, whichfork);
3177
                xfs_bmbt_set_startoff(ep, del_endoff);
3178
                temp = got.br_blockcount - del->br_blockcount;
3179
                xfs_bmbt_set_blockcount(ep, temp);
3180
                ifp->if_lastex = idx;
3181
                if (delay) {
3182
                        temp = XFS_FILBLKS_MIN(xfs_bmap_worst_indlen(ip, temp),
3183
                                da_old);
3184
                        xfs_bmbt_set_startblock(ep, NULLSTARTBLOCK((int)temp));
3185
                        XFS_BMAP_TRACE_POST_UPDATE("2", ip, idx,
3186
                                whichfork);
3187
                        da_new = temp;
3188
                        break;
3189
                }
3190
                xfs_bmbt_set_startblock(ep, del_endblock);
3191
                XFS_BMAP_TRACE_POST_UPDATE("2", ip, idx, whichfork);
3192
                if (!cur) {
3193
                        flags |= XFS_ILOG_FEXT(whichfork);
3194
                        break;
3195
                }
3196
                if ((error = xfs_bmbt_update(cur, del_endoff, del_endblock,
3197
                                got.br_blockcount - del->br_blockcount,
3198
                                got.br_state)))
3199
                        goto done;
3200
                break;
3201
 
3202
        case 1:
3203
                /*
3204
                 * Deleting the last part of the extent.
3205
                 */
3206
                temp = got.br_blockcount - del->br_blockcount;
3207
                XFS_BMAP_TRACE_PRE_UPDATE("1", ip, idx, whichfork);
3208
                xfs_bmbt_set_blockcount(ep, temp);
3209
                ifp->if_lastex = idx;
3210
                if (delay) {
3211
                        temp = XFS_FILBLKS_MIN(xfs_bmap_worst_indlen(ip, temp),
3212
                                da_old);
3213
                        xfs_bmbt_set_startblock(ep, NULLSTARTBLOCK((int)temp));
3214
                        XFS_BMAP_TRACE_POST_UPDATE("1", ip, idx,
3215
                                whichfork);
3216
                        da_new = temp;
3217
                        break;
3218
                }
3219
                XFS_BMAP_TRACE_POST_UPDATE("1", ip, idx, whichfork);
3220
                if (!cur) {
3221
                        flags |= XFS_ILOG_FEXT(whichfork);
3222
                        break;
3223
                }
3224
                if ((error = xfs_bmbt_update(cur, got.br_startoff,
3225
                                got.br_startblock,
3226
                                got.br_blockcount - del->br_blockcount,
3227
                                got.br_state)))
3228
                        goto done;
3229
                break;
3230
 
3231
        case 0:
3232
                /*
3233
                 * Deleting the middle of the extent.
3234
                 */
3235
                temp = del->br_startoff - got.br_startoff;
3236
                XFS_BMAP_TRACE_PRE_UPDATE("0", ip, idx, whichfork);
3237
                xfs_bmbt_set_blockcount(ep, temp);
3238
                new.br_startoff = del_endoff;
3239
                temp2 = got_endoff - del_endoff;
3240
                new.br_blockcount = temp2;
3241
                new.br_state = got.br_state;
3242
                if (!delay) {
3243
                        new.br_startblock = del_endblock;
3244
                        flags |= XFS_ILOG_CORE;
3245
                        if (cur) {
3246
                                if ((error = xfs_bmbt_update(cur,
3247
                                                got.br_startoff,
3248
                                                got.br_startblock, temp,
3249
                                                got.br_state)))
3250
                                        goto done;
3251
                                if ((error = xfs_bmbt_increment(cur, 0, &i)))
3252
                                        goto done;
3253
                                cur->bc_rec.b = new;
3254
                                error = xfs_bmbt_insert(cur, &i);
3255
                                if (error && error != ENOSPC)
3256
                                        goto done;
3257
                                /*
3258
                                 * If get no-space back from btree insert,
3259
                                 * it tried a split, and we have a zero
3260
                                 * block reservation.
3261
                                 * Fix up our state and return the error.
3262
                                 */
3263
                                if (error == ENOSPC) {
3264
                                        /*
3265
                                         * Reset the cursor, don't trust
3266
                                         * it after any insert operation.
3267
                                         */
3268
                                        if ((error = xfs_bmbt_lookup_eq(cur,
3269
                                                        got.br_startoff,
3270
                                                        got.br_startblock,
3271
                                                        temp, &i)))
3272
                                                goto done;
3273
                                        ASSERT(i == 1);
3274
                                        /*
3275
                                         * Update the btree record back
3276
                                         * to the original value.
3277
                                         */
3278
                                        if ((error = xfs_bmbt_update(cur,
3279
                                                        got.br_startoff,
3280
                                                        got.br_startblock,
3281
                                                        got.br_blockcount,
3282
                                                        got.br_state)))
3283
                                                goto done;
3284
                                        /*
3285
                                         * Reset the extent record back
3286
                                         * to the original value.
3287
                                         */
3288
                                        xfs_bmbt_set_blockcount(ep,
3289
                                                got.br_blockcount);
3290
                                        flags = 0;
3291
                                        error = XFS_ERROR(ENOSPC);
3292
                                        goto done;
3293
                                }
3294
                                ASSERT(i == 1);
3295
                        } else
3296
                                flags |= XFS_ILOG_FEXT(whichfork);
3297
                        XFS_IFORK_NEXT_SET(ip, whichfork,
3298
                                XFS_IFORK_NEXTENTS(ip, whichfork) + 1);
3299
                } else {
3300
                        ASSERT(whichfork == XFS_DATA_FORK);
3301
                        temp = xfs_bmap_worst_indlen(ip, temp);
3302
                        xfs_bmbt_set_startblock(ep, NULLSTARTBLOCK((int)temp));
3303
                        temp2 = xfs_bmap_worst_indlen(ip, temp2);
3304
                        new.br_startblock = NULLSTARTBLOCK((int)temp2);
3305
                        da_new = temp + temp2;
3306
                        while (da_new > da_old) {
3307
                                if (temp) {
3308
                                        temp--;
3309
                                        da_new--;
3310
                                        xfs_bmbt_set_startblock(ep,
3311
                                                NULLSTARTBLOCK((int)temp));
3312
                                }
3313
                                if (da_new == da_old)
3314
                                        break;
3315
                                if (temp2) {
3316
                                        temp2--;
3317
                                        da_new--;
3318
                                        new.br_startblock =
3319
                                                NULLSTARTBLOCK((int)temp2);
3320
                                }
3321
                        }
3322
                }
3323
                XFS_BMAP_TRACE_POST_UPDATE("0", ip, idx, whichfork);
3324
                XFS_BMAP_TRACE_INSERT("0", ip, idx + 1, 1, &new, NULL,
3325
                        whichfork);
3326
                xfs_iext_insert(ifp, idx + 1, 1, &new);
3327
                ifp->if_lastex = idx + 1;
3328
                break;
3329
        }
3330
        /*
3331
         * If we need to, add to list of extents to delete.
3332
         */
3333
        if (do_fx)
3334
                xfs_bmap_add_free(del->br_startblock, del->br_blockcount, flist,
3335
                        mp);
3336
        /*
3337
         * Adjust inode # blocks in the file.
3338
         */
3339
        if (nblks)
3340
                ip->i_d.di_nblocks -= nblks;
3341
        /*
3342
         * Adjust quota data.
3343
         */
3344
        if (qfield)
3345
                XFS_TRANS_MOD_DQUOT_BYINO(mp, tp, ip, qfield, (long)-nblks);
3346
 
3347
        /*
3348
         * Account for change in delayed indirect blocks.
3349
         * Nothing to do for disk quota accounting here.
3350
         */
3351
        ASSERT(da_old >= da_new);
3352
        if (da_old > da_new)
3353
                xfs_mod_incore_sb(mp, XFS_SBS_FDBLOCKS, (int64_t)(da_old - da_new),
3354
                        rsvd);
3355
        if (delta) {
3356
                /* DELTA: report the original extent. */
3357
                if (delta->xed_startoff > got.br_startoff)
3358
                        delta->xed_startoff = got.br_startoff;
3359
                if (delta->xed_blockcount < got.br_startoff+got.br_blockcount)
3360
                        delta->xed_blockcount = got.br_startoff +
3361
                                                        got.br_blockcount;
3362
        }
3363
done:
3364
        *logflagsp = flags;
3365
        return error;
3366
}
3367
 
3368
/*
3369
 * Remove the entry "free" from the free item list.  Prev points to the
3370
 * previous entry, unless "free" is the head of the list.
3371
 */
3372
STATIC void
3373
xfs_bmap_del_free(
3374
        xfs_bmap_free_t         *flist, /* free item list header */
3375
        xfs_bmap_free_item_t    *prev,  /* previous item on list, if any */
3376
        xfs_bmap_free_item_t    *free)  /* list item to be freed */
3377
{
3378
        if (prev)
3379
                prev->xbfi_next = free->xbfi_next;
3380
        else
3381
                flist->xbf_first = free->xbfi_next;
3382
        flist->xbf_count--;
3383
        kmem_zone_free(xfs_bmap_free_item_zone, free);
3384
}
3385
 
3386
/*
3387
 * Convert an extents-format file into a btree-format file.
3388
 * The new file will have a root block (in the inode) and a single child block.
3389
 */
3390
STATIC int                                      /* error */
3391
xfs_bmap_extents_to_btree(
3392
        xfs_trans_t             *tp,            /* transaction pointer */
3393
        xfs_inode_t             *ip,            /* incore inode pointer */
3394
        xfs_fsblock_t           *firstblock,    /* first-block-allocated */
3395
        xfs_bmap_free_t         *flist,         /* blocks freed in xaction */
3396
        xfs_btree_cur_t         **curp,         /* cursor returned to caller */
3397
        int                     wasdel,         /* converting a delayed alloc */
3398
        int                     *logflagsp,     /* inode logging flags */
3399
        int                     whichfork)      /* data or attr fork */
3400
{
3401
        xfs_bmbt_block_t        *ablock;        /* allocated (child) bt block */
3402
        xfs_buf_t               *abp;           /* buffer for ablock */
3403
        xfs_alloc_arg_t         args;           /* allocation arguments */
3404
        xfs_bmbt_rec_t          *arp;           /* child record pointer */
3405
        xfs_bmbt_block_t        *block;         /* btree root block */
3406
        xfs_btree_cur_t         *cur;           /* bmap btree cursor */
3407
        xfs_bmbt_rec_host_t     *ep;            /* extent record pointer */
3408
        int                     error;          /* error return value */
3409
        xfs_extnum_t            i, cnt;         /* extent record index */
3410
        xfs_ifork_t             *ifp;           /* inode fork pointer */
3411
        xfs_bmbt_key_t          *kp;            /* root block key pointer */
3412
        xfs_mount_t             *mp;            /* mount structure */
3413
        xfs_extnum_t            nextents;       /* number of file extents */
3414
        xfs_bmbt_ptr_t          *pp;            /* root block address pointer */
3415
 
3416
        ifp = XFS_IFORK_PTR(ip, whichfork);
3417
        ASSERT(XFS_IFORK_FORMAT(ip, whichfork) == XFS_DINODE_FMT_EXTENTS);
3418
        ASSERT(ifp->if_ext_max ==
3419
               XFS_IFORK_SIZE(ip, whichfork) / (uint)sizeof(xfs_bmbt_rec_t));
3420
        /*
3421
         * Make space in the inode incore.
3422
         */
3423
        xfs_iroot_realloc(ip, 1, whichfork);
3424
        ifp->if_flags |= XFS_IFBROOT;
3425
        /*
3426
         * Fill in the root.
3427
         */
3428
        block = ifp->if_broot;
3429
        block->bb_magic = cpu_to_be32(XFS_BMAP_MAGIC);
3430
        block->bb_level = cpu_to_be16(1);
3431
        block->bb_numrecs = cpu_to_be16(1);
3432
        block->bb_leftsib = cpu_to_be64(NULLDFSBNO);
3433
        block->bb_rightsib = cpu_to_be64(NULLDFSBNO);
3434
        /*
3435
         * Need a cursor.  Can't allocate until bb_level is filled in.
3436
         */
3437
        mp = ip->i_mount;
3438
        cur = xfs_btree_init_cursor(mp, tp, NULL, 0, XFS_BTNUM_BMAP, ip,
3439
                whichfork);
3440
        cur->bc_private.b.firstblock = *firstblock;
3441
        cur->bc_private.b.flist = flist;
3442
        cur->bc_private.b.flags = wasdel ? XFS_BTCUR_BPRV_WASDEL : 0;
3443
        /*
3444
         * Convert to a btree with two levels, one record in root.
3445
         */
3446
        XFS_IFORK_FMT_SET(ip, whichfork, XFS_DINODE_FMT_BTREE);
3447
        args.tp = tp;
3448
        args.mp = mp;
3449
        args.firstblock = *firstblock;
3450
        if (*firstblock == NULLFSBLOCK) {
3451
                args.type = XFS_ALLOCTYPE_START_BNO;
3452
                args.fsbno = XFS_INO_TO_FSB(mp, ip->i_ino);
3453
        } else if (flist->xbf_low) {
3454
                args.type = XFS_ALLOCTYPE_START_BNO;
3455
                args.fsbno = *firstblock;
3456
        } else {
3457
                args.type = XFS_ALLOCTYPE_NEAR_BNO;
3458
                args.fsbno = *firstblock;
3459
        }
3460
        args.minlen = args.maxlen = args.prod = 1;
3461
        args.total = args.minleft = args.alignment = args.mod = args.isfl =
3462
                args.minalignslop = 0;
3463
        args.wasdel = wasdel;
3464
        *logflagsp = 0;
3465
        if ((error = xfs_alloc_vextent(&args))) {
3466
                xfs_iroot_realloc(ip, -1, whichfork);
3467
                xfs_btree_del_cursor(cur, XFS_BTREE_ERROR);
3468
                return error;
3469
        }
3470
        /*
3471
         * Allocation can't fail, the space was reserved.
3472
         */
3473
        ASSERT(args.fsbno != NULLFSBLOCK);
3474
        ASSERT(*firstblock == NULLFSBLOCK ||
3475
               args.agno == XFS_FSB_TO_AGNO(mp, *firstblock) ||
3476
               (flist->xbf_low &&
3477
                args.agno > XFS_FSB_TO_AGNO(mp, *firstblock)));
3478
        *firstblock = cur->bc_private.b.firstblock = args.fsbno;
3479
        cur->bc_private.b.allocated++;
3480
        ip->i_d.di_nblocks++;
3481
        XFS_TRANS_MOD_DQUOT_BYINO(mp, tp, ip, XFS_TRANS_DQ_BCOUNT, 1L);
3482
        abp = xfs_btree_get_bufl(mp, tp, args.fsbno, 0);
3483
        /*
3484
         * Fill in the child block.
3485
         */
3486
        ablock = XFS_BUF_TO_BMBT_BLOCK(abp);
3487
        ablock->bb_magic = cpu_to_be32(XFS_BMAP_MAGIC);
3488
        ablock->bb_level = 0;
3489
        ablock->bb_leftsib = cpu_to_be64(NULLDFSBNO);
3490
        ablock->bb_rightsib = cpu_to_be64(NULLDFSBNO);
3491
        arp = XFS_BMAP_REC_IADDR(ablock, 1, cur);
3492
        nextents = ifp->if_bytes / (uint)sizeof(xfs_bmbt_rec_t);
3493
        for (cnt = i = 0; i < nextents; i++) {
3494
                ep = xfs_iext_get_ext(ifp, i);
3495
                if (!ISNULLSTARTBLOCK(xfs_bmbt_get_startblock(ep))) {
3496
                        arp->l0 = cpu_to_be64(ep->l0);
3497
                        arp->l1 = cpu_to_be64(ep->l1);
3498
                        arp++; cnt++;
3499
                }
3500
        }
3501
        ASSERT(cnt == XFS_IFORK_NEXTENTS(ip, whichfork));
3502
        ablock->bb_numrecs = cpu_to_be16(cnt);
3503
        /*
3504
         * Fill in the root key and pointer.
3505
         */
3506
        kp = XFS_BMAP_KEY_IADDR(block, 1, cur);
3507
        arp = XFS_BMAP_REC_IADDR(ablock, 1, cur);
3508
        kp->br_startoff = cpu_to_be64(xfs_bmbt_disk_get_startoff(arp));
3509
        pp = XFS_BMAP_PTR_IADDR(block, 1, cur);
3510
        *pp = cpu_to_be64(args.fsbno);
3511
        /*
3512
         * Do all this logging at the end so that
3513
         * the root is at the right level.
3514
         */
3515
        xfs_bmbt_log_block(cur, abp, XFS_BB_ALL_BITS);
3516
        xfs_bmbt_log_recs(cur, abp, 1, be16_to_cpu(ablock->bb_numrecs));
3517
        ASSERT(*curp == NULL);
3518
        *curp = cur;
3519
        *logflagsp = XFS_ILOG_CORE | XFS_ILOG_FBROOT(whichfork);
3520
        return 0;
3521
}
3522
 
3523
/*
3524
 * Helper routine to reset inode di_forkoff field when switching
3525
 * attribute fork from local to extent format - we reset it where
3526
 * possible to make space available for inline data fork extents.
3527
 */
3528
STATIC void
3529
xfs_bmap_forkoff_reset(
3530
        xfs_mount_t     *mp,
3531
        xfs_inode_t     *ip,
3532
        int             whichfork)
3533
{
3534
        if (whichfork == XFS_ATTR_FORK &&
3535
            (ip->i_d.di_format != XFS_DINODE_FMT_DEV) &&
3536
            (ip->i_d.di_format != XFS_DINODE_FMT_UUID) &&
3537
            (ip->i_d.di_format != XFS_DINODE_FMT_BTREE) &&
3538
            ((mp->m_attroffset >> 3) > ip->i_d.di_forkoff)) {
3539
                ip->i_d.di_forkoff = mp->m_attroffset >> 3;
3540
                ip->i_df.if_ext_max = XFS_IFORK_DSIZE(ip) /
3541
                                        (uint)sizeof(xfs_bmbt_rec_t);
3542
                ip->i_afp->if_ext_max = XFS_IFORK_ASIZE(ip) /
3543
                                        (uint)sizeof(xfs_bmbt_rec_t);
3544
        }
3545
}
3546
 
3547
/*
3548
 * Convert a local file to an extents file.
3549
 * This code is out of bounds for data forks of regular files,
3550
 * since the file data needs to get logged so things will stay consistent.
3551
 * (The bmap-level manipulations are ok, though).
3552
 */
3553
STATIC int                              /* error */
3554
xfs_bmap_local_to_extents(
3555
        xfs_trans_t     *tp,            /* transaction pointer */
3556
        xfs_inode_t     *ip,            /* incore inode pointer */
3557
        xfs_fsblock_t   *firstblock,    /* first block allocated in xaction */
3558
        xfs_extlen_t    total,          /* total blocks needed by transaction */
3559
        int             *logflagsp,     /* inode logging flags */
3560
        int             whichfork)      /* data or attr fork */
3561
{
3562
        int             error;          /* error return value */
3563
        int             flags;          /* logging flags returned */
3564
        xfs_ifork_t     *ifp;           /* inode fork pointer */
3565
 
3566
        /*
3567
         * We don't want to deal with the case of keeping inode data inline yet.
3568
         * So sending the data fork of a regular inode is invalid.
3569
         */
3570
        ASSERT(!((ip->i_d.di_mode & S_IFMT) == S_IFREG &&
3571
                 whichfork == XFS_DATA_FORK));
3572
        ifp = XFS_IFORK_PTR(ip, whichfork);
3573
        ASSERT(XFS_IFORK_FORMAT(ip, whichfork) == XFS_DINODE_FMT_LOCAL);
3574
        flags = 0;
3575
        error = 0;
3576
        if (ifp->if_bytes) {
3577
                xfs_alloc_arg_t args;   /* allocation arguments */
3578
                xfs_buf_t       *bp;    /* buffer for extent block */
3579
                xfs_bmbt_rec_host_t *ep;/* extent record pointer */
3580
 
3581
                args.tp = tp;
3582
                args.mp = ip->i_mount;
3583
                args.firstblock = *firstblock;
3584
                ASSERT((ifp->if_flags &
3585
                        (XFS_IFINLINE|XFS_IFEXTENTS|XFS_IFEXTIREC)) == XFS_IFINLINE);
3586
                /*
3587
                 * Allocate a block.  We know we need only one, since the
3588
                 * file currently fits in an inode.
3589
                 */
3590
                if (*firstblock == NULLFSBLOCK) {
3591
                        args.fsbno = XFS_INO_TO_FSB(args.mp, ip->i_ino);
3592
                        args.type = XFS_ALLOCTYPE_START_BNO;
3593
                } else {
3594
                        args.fsbno = *firstblock;
3595
                        args.type = XFS_ALLOCTYPE_NEAR_BNO;
3596
                }
3597
                args.total = total;
3598
                args.mod = args.minleft = args.alignment = args.wasdel =
3599
                        args.isfl = args.minalignslop = 0;
3600
                args.minlen = args.maxlen = args.prod = 1;
3601
                if ((error = xfs_alloc_vextent(&args)))
3602
                        goto done;
3603
                /*
3604
                 * Can't fail, the space was reserved.
3605
                 */
3606
                ASSERT(args.fsbno != NULLFSBLOCK);
3607
                ASSERT(args.len == 1);
3608
                *firstblock = args.fsbno;
3609
                bp = xfs_btree_get_bufl(args.mp, tp, args.fsbno, 0);
3610
                memcpy((char *)XFS_BUF_PTR(bp), ifp->if_u1.if_data,
3611
                        ifp->if_bytes);
3612
                xfs_trans_log_buf(tp, bp, 0, ifp->if_bytes - 1);
3613
                xfs_bmap_forkoff_reset(args.mp, ip, whichfork);
3614
                xfs_idata_realloc(ip, -ifp->if_bytes, whichfork);
3615
                xfs_iext_add(ifp, 0, 1);
3616
                ep = xfs_iext_get_ext(ifp, 0);
3617
                xfs_bmbt_set_allf(ep, 0, args.fsbno, 1, XFS_EXT_NORM);
3618
                XFS_BMAP_TRACE_POST_UPDATE("new", ip, 0, whichfork);
3619
                XFS_IFORK_NEXT_SET(ip, whichfork, 1);
3620
                ip->i_d.di_nblocks = 1;
3621
                XFS_TRANS_MOD_DQUOT_BYINO(args.mp, tp, ip,
3622
                        XFS_TRANS_DQ_BCOUNT, 1L);
3623
                flags |= XFS_ILOG_FEXT(whichfork);
3624
        } else {
3625
                ASSERT(XFS_IFORK_NEXTENTS(ip, whichfork) == 0);
3626
                xfs_bmap_forkoff_reset(ip->i_mount, ip, whichfork);
3627
        }
3628
        ifp->if_flags &= ~XFS_IFINLINE;
3629
        ifp->if_flags |= XFS_IFEXTENTS;
3630
        XFS_IFORK_FMT_SET(ip, whichfork, XFS_DINODE_FMT_EXTENTS);
3631
        flags |= XFS_ILOG_CORE;
3632
done:
3633
        *logflagsp = flags;
3634
        return error;
3635
}
3636
 
3637
/*
3638
 * Search the extent records for the entry containing block bno.
3639
 * If bno lies in a hole, point to the next entry.  If bno lies
3640
 * past eof, *eofp will be set, and *prevp will contain the last
3641
 * entry (null if none).  Else, *lastxp will be set to the index
3642
 * of the found entry; *gotp will contain the entry.
3643
 */
3644
xfs_bmbt_rec_host_t *                   /* pointer to found extent entry */
3645
xfs_bmap_search_multi_extents(
3646
        xfs_ifork_t     *ifp,           /* inode fork pointer */
3647
        xfs_fileoff_t   bno,            /* block number searched for */
3648
        int             *eofp,          /* out: end of file found */
3649
        xfs_extnum_t    *lastxp,        /* out: last extent index */
3650
        xfs_bmbt_irec_t *gotp,          /* out: extent entry found */
3651
        xfs_bmbt_irec_t *prevp)         /* out: previous extent entry found */
3652
{
3653
        xfs_bmbt_rec_host_t *ep;                /* extent record pointer */
3654
        xfs_extnum_t    lastx;          /* last extent index */
3655
 
3656
        /*
3657
         * Initialize the extent entry structure to catch access to
3658
         * uninitialized br_startblock field.
3659
         */
3660
        gotp->br_startoff = 0xffa5a5a5a5a5a5a5LL;
3661
        gotp->br_blockcount = 0xa55a5a5a5a5a5a5aLL;
3662
        gotp->br_state = XFS_EXT_INVALID;
3663
#if XFS_BIG_BLKNOS
3664
        gotp->br_startblock = 0xffffa5a5a5a5a5a5LL;
3665
#else
3666
        gotp->br_startblock = 0xffffa5a5;
3667
#endif
3668
        prevp->br_startoff = NULLFILEOFF;
3669
 
3670
        ep = xfs_iext_bno_to_ext(ifp, bno, &lastx);
3671
        if (lastx > 0) {
3672
                xfs_bmbt_get_all(xfs_iext_get_ext(ifp, lastx - 1), prevp);
3673
        }
3674
        if (lastx < (ifp->if_bytes / (uint)sizeof(xfs_bmbt_rec_t))) {
3675
                xfs_bmbt_get_all(ep, gotp);
3676
                *eofp = 0;
3677
        } else {
3678
                if (lastx > 0) {
3679
                        *gotp = *prevp;
3680
                }
3681
                *eofp = 1;
3682
                ep = NULL;
3683
        }
3684
        *lastxp = lastx;
3685
        return ep;
3686
}
3687
 
3688
/*
3689
 * Search the extents list for the inode, for the extent containing bno.
3690
 * If bno lies in a hole, point to the next entry.  If bno lies past eof,
3691
 * *eofp will be set, and *prevp will contain the last entry (null if none).
3692
 * Else, *lastxp will be set to the index of the found
3693
 * entry; *gotp will contain the entry.
3694
 */
3695
STATIC xfs_bmbt_rec_host_t *                 /* pointer to found extent entry */
3696
xfs_bmap_search_extents(
3697
        xfs_inode_t     *ip,            /* incore inode pointer */
3698
        xfs_fileoff_t   bno,            /* block number searched for */
3699
        int             fork,           /* data or attr fork */
3700
        int             *eofp,          /* out: end of file found */
3701
        xfs_extnum_t    *lastxp,        /* out: last extent index */
3702
        xfs_bmbt_irec_t *gotp,          /* out: extent entry found */
3703
        xfs_bmbt_irec_t *prevp)         /* out: previous extent entry found */
3704
{
3705
        xfs_ifork_t     *ifp;           /* inode fork pointer */
3706
        xfs_bmbt_rec_host_t  *ep;            /* extent record pointer */
3707
 
3708
        XFS_STATS_INC(xs_look_exlist);
3709
        ifp = XFS_IFORK_PTR(ip, fork);
3710
 
3711
        ep = xfs_bmap_search_multi_extents(ifp, bno, eofp, lastxp, gotp, prevp);
3712
 
3713
        if (unlikely(!(gotp->br_startblock) && (*lastxp != NULLEXTNUM) &&
3714
                     !(XFS_IS_REALTIME_INODE(ip) && fork == XFS_DATA_FORK))) {
3715
                xfs_cmn_err(XFS_PTAG_FSBLOCK_ZERO, CE_ALERT, ip->i_mount,
3716
                                "Access to block zero in inode %llu "
3717
                                "start_block: %llx start_off: %llx "
3718
                                "blkcnt: %llx extent-state: %x lastx: %x\n",
3719
                        (unsigned long long)ip->i_ino,
3720
                        (unsigned long long)gotp->br_startblock,
3721
                        (unsigned long long)gotp->br_startoff,
3722
                        (unsigned long long)gotp->br_blockcount,
3723
                        gotp->br_state, *lastxp);
3724
                *lastxp = NULLEXTNUM;
3725
                *eofp = 1;
3726
                return NULL;
3727
        }
3728
        return ep;
3729
}
3730
 
3731
 
3732
#ifdef XFS_BMAP_TRACE
3733
ktrace_t        *xfs_bmap_trace_buf;
3734
 
3735
/*
3736
 * Add a bmap trace buffer entry.  Base routine for the others.
3737
 */
3738
STATIC void
3739
xfs_bmap_trace_addentry(
3740
        int             opcode,         /* operation */
3741
        const char      *fname,         /* function name */
3742
        char            *desc,          /* operation description */
3743
        xfs_inode_t     *ip,            /* incore inode pointer */
3744
        xfs_extnum_t    idx,            /* index of entry(ies) */
3745
        xfs_extnum_t    cnt,            /* count of entries, 1 or 2 */
3746
        xfs_bmbt_rec_host_t *r1,        /* first record */
3747
        xfs_bmbt_rec_host_t *r2,        /* second record or null */
3748
        int             whichfork)      /* data or attr fork */
3749
{
3750
        xfs_bmbt_rec_host_t tr2;
3751
 
3752
        ASSERT(cnt == 1 || cnt == 2);
3753
        ASSERT(r1 != NULL);
3754
        if (cnt == 1) {
3755
                ASSERT(r2 == NULL);
3756
                r2 = &tr2;
3757
                memset(&tr2, 0, sizeof(tr2));
3758
        } else
3759
                ASSERT(r2 != NULL);
3760
        ktrace_enter(xfs_bmap_trace_buf,
3761
                (void *)(__psint_t)(opcode | (whichfork << 16)),
3762
                (void *)fname, (void *)desc, (void *)ip,
3763
                (void *)(__psint_t)idx,
3764
                (void *)(__psint_t)cnt,
3765
                (void *)(__psunsigned_t)(ip->i_ino >> 32),
3766
                (void *)(__psunsigned_t)(unsigned)ip->i_ino,
3767
                (void *)(__psunsigned_t)(r1->l0 >> 32),
3768
                (void *)(__psunsigned_t)(unsigned)(r1->l0),
3769
                (void *)(__psunsigned_t)(r1->l1 >> 32),
3770
                (void *)(__psunsigned_t)(unsigned)(r1->l1),
3771
                (void *)(__psunsigned_t)(r2->l0 >> 32),
3772
                (void *)(__psunsigned_t)(unsigned)(r2->l0),
3773
                (void *)(__psunsigned_t)(r2->l1 >> 32),
3774
                (void *)(__psunsigned_t)(unsigned)(r2->l1)
3775
                );
3776
        ASSERT(ip->i_xtrace);
3777
        ktrace_enter(ip->i_xtrace,
3778
                (void *)(__psint_t)(opcode | (whichfork << 16)),
3779
                (void *)fname, (void *)desc, (void *)ip,
3780
                (void *)(__psint_t)idx,
3781
                (void *)(__psint_t)cnt,
3782
                (void *)(__psunsigned_t)(ip->i_ino >> 32),
3783
                (void *)(__psunsigned_t)(unsigned)ip->i_ino,
3784
                (void *)(__psunsigned_t)(r1->l0 >> 32),
3785
                (void *)(__psunsigned_t)(unsigned)(r1->l0),
3786
                (void *)(__psunsigned_t)(r1->l1 >> 32),
3787
                (void *)(__psunsigned_t)(unsigned)(r1->l1),
3788
                (void *)(__psunsigned_t)(r2->l0 >> 32),
3789
                (void *)(__psunsigned_t)(unsigned)(r2->l0),
3790
                (void *)(__psunsigned_t)(r2->l1 >> 32),
3791
                (void *)(__psunsigned_t)(unsigned)(r2->l1)
3792
                );
3793
}
3794
 
3795
/*
3796
 * Add bmap trace entry prior to a call to xfs_iext_remove.
3797
 */
3798
STATIC void
3799
xfs_bmap_trace_delete(
3800
        const char      *fname,         /* function name */
3801
        char            *desc,          /* operation description */
3802
        xfs_inode_t     *ip,            /* incore inode pointer */
3803
        xfs_extnum_t    idx,            /* index of entry(entries) deleted */
3804
        xfs_extnum_t    cnt,            /* count of entries deleted, 1 or 2 */
3805
        int             whichfork)      /* data or attr fork */
3806
{
3807
        xfs_ifork_t     *ifp;           /* inode fork pointer */
3808
 
3809
        ifp = XFS_IFORK_PTR(ip, whichfork);
3810
        xfs_bmap_trace_addentry(XFS_BMAP_KTRACE_DELETE, fname, desc, ip, idx,
3811
                cnt, xfs_iext_get_ext(ifp, idx),
3812
                cnt == 2 ? xfs_iext_get_ext(ifp, idx + 1) : NULL,
3813
                whichfork);
3814
}
3815
 
3816
/*
3817
 * Add bmap trace entry prior to a call to xfs_iext_insert, or
3818
 * reading in the extents list from the disk (in the btree).
3819
 */
3820
STATIC void
3821
xfs_bmap_trace_insert(
3822
        const char      *fname,         /* function name */
3823
        char            *desc,          /* operation description */
3824
        xfs_inode_t     *ip,            /* incore inode pointer */
3825
        xfs_extnum_t    idx,            /* index of entry(entries) inserted */
3826
        xfs_extnum_t    cnt,            /* count of entries inserted, 1 or 2 */
3827
        xfs_bmbt_irec_t *r1,            /* inserted record 1 */
3828
        xfs_bmbt_irec_t *r2,            /* inserted record 2 or null */
3829
        int             whichfork)      /* data or attr fork */
3830
{
3831
        xfs_bmbt_rec_host_t tr1;        /* compressed record 1 */
3832
        xfs_bmbt_rec_host_t tr2;        /* compressed record 2 if needed */
3833
 
3834
        xfs_bmbt_set_all(&tr1, r1);
3835
        if (cnt == 2) {
3836
                ASSERT(r2 != NULL);
3837
                xfs_bmbt_set_all(&tr2, r2);
3838
        } else {
3839
                ASSERT(cnt == 1);
3840
                ASSERT(r2 == NULL);
3841
        }
3842
        xfs_bmap_trace_addentry(XFS_BMAP_KTRACE_INSERT, fname, desc, ip, idx,
3843
                cnt, &tr1, cnt == 2 ? &tr2 : NULL, whichfork);
3844
}
3845
 
3846
/*
3847
 * Add bmap trace entry after updating an extent record in place.
3848
 */
3849
STATIC void
3850
xfs_bmap_trace_post_update(
3851
        const char      *fname,         /* function name */
3852
        char            *desc,          /* operation description */
3853
        xfs_inode_t     *ip,            /* incore inode pointer */
3854
        xfs_extnum_t    idx,            /* index of entry updated */
3855
        int             whichfork)      /* data or attr fork */
3856
{
3857
        xfs_ifork_t     *ifp;           /* inode fork pointer */
3858
 
3859
        ifp = XFS_IFORK_PTR(ip, whichfork);
3860
        xfs_bmap_trace_addentry(XFS_BMAP_KTRACE_POST_UP, fname, desc, ip, idx,
3861
                1, xfs_iext_get_ext(ifp, idx), NULL, whichfork);
3862
}
3863
 
3864
/*
3865
 * Add bmap trace entry prior to updating an extent record in place.
3866
 */
3867
STATIC void
3868
xfs_bmap_trace_pre_update(
3869
        const char      *fname,         /* function name */
3870
        char            *desc,          /* operation description */
3871
        xfs_inode_t     *ip,            /* incore inode pointer */
3872
        xfs_extnum_t    idx,            /* index of entry to be updated */
3873
        int             whichfork)      /* data or attr fork */
3874
{
3875
        xfs_ifork_t     *ifp;           /* inode fork pointer */
3876
 
3877
        ifp = XFS_IFORK_PTR(ip, whichfork);
3878
        xfs_bmap_trace_addentry(XFS_BMAP_KTRACE_PRE_UP, fname, desc, ip, idx, 1,
3879
                xfs_iext_get_ext(ifp, idx), NULL, whichfork);
3880
}
3881
#endif  /* XFS_BMAP_TRACE */
3882
 
3883
/*
3884
 * Compute the worst-case number of indirect blocks that will be used
3885
 * for ip's delayed extent of length "len".
3886
 */
3887
STATIC xfs_filblks_t
3888
xfs_bmap_worst_indlen(
3889
        xfs_inode_t     *ip,            /* incore inode pointer */
3890
        xfs_filblks_t   len)            /* delayed extent length */
3891
{
3892
        int             level;          /* btree level number */
3893
        int             maxrecs;        /* maximum record count at this level */
3894
        xfs_mount_t     *mp;            /* mount structure */
3895
        xfs_filblks_t   rval;           /* return value */
3896
 
3897
        mp = ip->i_mount;
3898
        maxrecs = mp->m_bmap_dmxr[0];
3899
        for (level = 0, rval = 0;
3900
             level < XFS_BM_MAXLEVELS(mp, XFS_DATA_FORK);
3901
             level++) {
3902
                len += maxrecs - 1;
3903
                do_div(len, maxrecs);
3904
                rval += len;
3905
                if (len == 1)
3906
                        return rval + XFS_BM_MAXLEVELS(mp, XFS_DATA_FORK) -
3907
                                level - 1;
3908
                if (level == 0)
3909
                        maxrecs = mp->m_bmap_dmxr[1];
3910
        }
3911
        return rval;
3912
}
3913
 
3914
#if defined(XFS_RW_TRACE)
3915
STATIC void
3916
xfs_bunmap_trace(
3917
        xfs_inode_t             *ip,
3918
        xfs_fileoff_t           bno,
3919
        xfs_filblks_t           len,
3920
        int                     flags,
3921
        inst_t                  *ra)
3922
{
3923
        if (ip->i_rwtrace == NULL)
3924
                return;
3925
        ktrace_enter(ip->i_rwtrace,
3926
                (void *)(__psint_t)XFS_BUNMAP,
3927
                (void *)ip,
3928
                (void *)(__psint_t)((ip->i_d.di_size >> 32) & 0xffffffff),
3929
                (void *)(__psint_t)(ip->i_d.di_size & 0xffffffff),
3930
                (void *)(__psint_t)(((xfs_dfiloff_t)bno >> 32) & 0xffffffff),
3931
                (void *)(__psint_t)((xfs_dfiloff_t)bno & 0xffffffff),
3932
                (void *)(__psint_t)len,
3933
                (void *)(__psint_t)flags,
3934
                (void *)(unsigned long)current_cpu(),
3935
                (void *)ra,
3936
                (void *)0,
3937
                (void *)0,
3938
                (void *)0,
3939
                (void *)0,
3940
                (void *)0,
3941
                (void *)0);
3942
}
3943
#endif
3944
 
3945
/*
3946
 * Convert inode from non-attributed to attributed.
3947
 * Must not be in a transaction, ip must not be locked.
3948
 */
3949
int                                             /* error code */
3950
xfs_bmap_add_attrfork(
3951
        xfs_inode_t             *ip,            /* incore inode pointer */
3952
        int                     size,           /* space new attribute needs */
3953
        int                     rsvd)           /* xact may use reserved blks */
3954
{
3955
        xfs_fsblock_t           firstblock;     /* 1st block/ag allocated */
3956
        xfs_bmap_free_t         flist;          /* freed extent records */
3957
        xfs_mount_t             *mp;            /* mount structure */
3958
        xfs_trans_t             *tp;            /* transaction pointer */
3959
        unsigned long           s;              /* spinlock spl value */
3960
        int                     blks;           /* space reservation */
3961
        int                     version = 1;    /* superblock attr version */
3962
        int                     committed;      /* xaction was committed */
3963
        int                     logflags;       /* logging flags */
3964
        int                     error;          /* error return value */
3965
 
3966
        ASSERT(XFS_IFORK_Q(ip) == 0);
3967
        ASSERT(ip->i_df.if_ext_max ==
3968
               XFS_IFORK_DSIZE(ip) / (uint)sizeof(xfs_bmbt_rec_t));
3969
 
3970
        mp = ip->i_mount;
3971
        ASSERT(!XFS_NOT_DQATTACHED(mp, ip));
3972
        tp = xfs_trans_alloc(mp, XFS_TRANS_ADDAFORK);
3973
        blks = XFS_ADDAFORK_SPACE_RES(mp);
3974
        if (rsvd)
3975
                tp->t_flags |= XFS_TRANS_RESERVE;
3976
        if ((error = xfs_trans_reserve(tp, blks, XFS_ADDAFORK_LOG_RES(mp), 0,
3977
                        XFS_TRANS_PERM_LOG_RES, XFS_ADDAFORK_LOG_COUNT)))
3978
                goto error0;
3979
        xfs_ilock(ip, XFS_ILOCK_EXCL);
3980
        error = XFS_TRANS_RESERVE_QUOTA_NBLKS(mp, tp, ip, blks, 0, rsvd ?
3981
                        XFS_QMOPT_RES_REGBLKS | XFS_QMOPT_FORCE_RES :
3982
                        XFS_QMOPT_RES_REGBLKS);
3983
        if (error) {
3984
                xfs_iunlock(ip, XFS_ILOCK_EXCL);
3985
                xfs_trans_cancel(tp, XFS_TRANS_RELEASE_LOG_RES);
3986
                return error;
3987
        }
3988
        if (XFS_IFORK_Q(ip))
3989
                goto error1;
3990
        if (ip->i_d.di_aformat != XFS_DINODE_FMT_EXTENTS) {
3991
                /*
3992
                 * For inodes coming from pre-6.2 filesystems.
3993
                 */
3994
                ASSERT(ip->i_d.di_aformat == 0);
3995
                ip->i_d.di_aformat = XFS_DINODE_FMT_EXTENTS;
3996
        }
3997
        ASSERT(ip->i_d.di_anextents == 0);
3998
        VN_HOLD(XFS_ITOV(ip));
3999
        xfs_trans_ijoin(tp, ip, XFS_ILOCK_EXCL);
4000
        xfs_trans_log_inode(tp, ip, XFS_ILOG_CORE);
4001
        switch (ip->i_d.di_format) {
4002
        case XFS_DINODE_FMT_DEV:
4003
                ip->i_d.di_forkoff = roundup(sizeof(xfs_dev_t), 8) >> 3;
4004
                break;
4005
        case XFS_DINODE_FMT_UUID:
4006
                ip->i_d.di_forkoff = roundup(sizeof(uuid_t), 8) >> 3;
4007
                break;
4008
        case XFS_DINODE_FMT_LOCAL:
4009
        case XFS_DINODE_FMT_EXTENTS:
4010
        case XFS_DINODE_FMT_BTREE:
4011
                ip->i_d.di_forkoff = xfs_attr_shortform_bytesfit(ip, size);
4012
                if (!ip->i_d.di_forkoff)
4013
                        ip->i_d.di_forkoff = mp->m_attroffset >> 3;
4014
                else if (mp->m_flags & XFS_MOUNT_ATTR2)
4015
                        version = 2;
4016
                break;
4017
        default:
4018
                ASSERT(0);
4019
                error = XFS_ERROR(EINVAL);
4020
                goto error1;
4021
        }
4022
        ip->i_df.if_ext_max =
4023
                XFS_IFORK_DSIZE(ip) / (uint)sizeof(xfs_bmbt_rec_t);
4024
        ASSERT(ip->i_afp == NULL);
4025
        ip->i_afp = kmem_zone_zalloc(xfs_ifork_zone, KM_SLEEP);
4026
        ip->i_afp->if_ext_max =
4027
                XFS_IFORK_ASIZE(ip) / (uint)sizeof(xfs_bmbt_rec_t);
4028
        ip->i_afp->if_flags = XFS_IFEXTENTS;
4029
        logflags = 0;
4030
        XFS_BMAP_INIT(&flist, &firstblock);
4031
        switch (ip->i_d.di_format) {
4032
        case XFS_DINODE_FMT_LOCAL:
4033
                error = xfs_bmap_add_attrfork_local(tp, ip, &firstblock, &flist,
4034
                        &logflags);
4035
                break;
4036
        case XFS_DINODE_FMT_EXTENTS:
4037
                error = xfs_bmap_add_attrfork_extents(tp, ip, &firstblock,
4038
                        &flist, &logflags);
4039
                break;
4040
        case XFS_DINODE_FMT_BTREE:
4041
                error = xfs_bmap_add_attrfork_btree(tp, ip, &firstblock, &flist,
4042
                        &logflags);
4043
                break;
4044
        default:
4045
                error = 0;
4046
                break;
4047
        }
4048
        if (logflags)
4049
                xfs_trans_log_inode(tp, ip, logflags);
4050
        if (error)
4051
                goto error2;
4052
        if (!XFS_SB_VERSION_HASATTR(&mp->m_sb) ||
4053
           (!XFS_SB_VERSION_HASATTR2(&mp->m_sb) && version == 2)) {
4054
                __int64_t sbfields = 0;
4055
 
4056
                s = XFS_SB_LOCK(mp);
4057
                if (!XFS_SB_VERSION_HASATTR(&mp->m_sb)) {
4058
                        XFS_SB_VERSION_ADDATTR(&mp->m_sb);
4059
                        sbfields |= XFS_SB_VERSIONNUM;
4060
                }
4061
                if (!XFS_SB_VERSION_HASATTR2(&mp->m_sb) && version == 2) {
4062
                        XFS_SB_VERSION_ADDATTR2(&mp->m_sb);
4063
                        sbfields |= (XFS_SB_VERSIONNUM | XFS_SB_FEATURES2);
4064
                }
4065
                if (sbfields) {
4066
                        XFS_SB_UNLOCK(mp, s);
4067
                        xfs_mod_sb(tp, sbfields);
4068
                } else
4069
                        XFS_SB_UNLOCK(mp, s);
4070
        }
4071
        if ((error = xfs_bmap_finish(&tp, &flist, &committed)))
4072
                goto error2;
4073
        error = xfs_trans_commit(tp, XFS_TRANS_PERM_LOG_RES);
4074
        ASSERT(ip->i_df.if_ext_max ==
4075
               XFS_IFORK_DSIZE(ip) / (uint)sizeof(xfs_bmbt_rec_t));
4076
        return error;
4077
error2:
4078
        xfs_bmap_cancel(&flist);
4079
error1:
4080
        ASSERT(ismrlocked(&ip->i_lock,MR_UPDATE));
4081
        xfs_iunlock(ip, XFS_ILOCK_EXCL);
4082
error0:
4083
        xfs_trans_cancel(tp, XFS_TRANS_RELEASE_LOG_RES|XFS_TRANS_ABORT);
4084
        ASSERT(ip->i_df.if_ext_max ==
4085
               XFS_IFORK_DSIZE(ip) / (uint)sizeof(xfs_bmbt_rec_t));
4086
        return error;
4087
}
4088
 
4089
/*
4090
 * Add the extent to the list of extents to be free at transaction end.
4091
 * The list is maintained sorted (by block number).
4092
 */
4093
/* ARGSUSED */
4094
void
4095
xfs_bmap_add_free(
4096
        xfs_fsblock_t           bno,            /* fs block number of extent */
4097
        xfs_filblks_t           len,            /* length of extent */
4098
        xfs_bmap_free_t         *flist,         /* list of extents */
4099
        xfs_mount_t             *mp)            /* mount point structure */
4100
{
4101
        xfs_bmap_free_item_t    *cur;           /* current (next) element */
4102
        xfs_bmap_free_item_t    *new;           /* new element */
4103
        xfs_bmap_free_item_t    *prev;          /* previous element */
4104
#ifdef DEBUG
4105
        xfs_agnumber_t          agno;
4106
        xfs_agblock_t           agbno;
4107
 
4108
        ASSERT(bno != NULLFSBLOCK);
4109
        ASSERT(len > 0);
4110
        ASSERT(len <= MAXEXTLEN);
4111
        ASSERT(!ISNULLSTARTBLOCK(bno));
4112
        agno = XFS_FSB_TO_AGNO(mp, bno);
4113
        agbno = XFS_FSB_TO_AGBNO(mp, bno);
4114
        ASSERT(agno < mp->m_sb.sb_agcount);
4115
        ASSERT(agbno < mp->m_sb.sb_agblocks);
4116
        ASSERT(len < mp->m_sb.sb_agblocks);
4117
        ASSERT(agbno + len <= mp->m_sb.sb_agblocks);
4118
#endif
4119
        ASSERT(xfs_bmap_free_item_zone != NULL);
4120
        new = kmem_zone_alloc(xfs_bmap_free_item_zone, KM_SLEEP);
4121
        new->xbfi_startblock = bno;
4122
        new->xbfi_blockcount = (xfs_extlen_t)len;
4123
        for (prev = NULL, cur = flist->xbf_first;
4124
             cur != NULL;
4125
             prev = cur, cur = cur->xbfi_next) {
4126
                if (cur->xbfi_startblock >= bno)
4127
                        break;
4128
        }
4129
        if (prev)
4130
                prev->xbfi_next = new;
4131
        else
4132
                flist->xbf_first = new;
4133
        new->xbfi_next = cur;
4134
        flist->xbf_count++;
4135
}
4136
 
4137
/*
4138
 * Compute and fill in the value of the maximum depth of a bmap btree
4139
 * in this filesystem.  Done once, during mount.
4140
 */
4141
void
4142
xfs_bmap_compute_maxlevels(
4143
        xfs_mount_t     *mp,            /* file system mount structure */
4144
        int             whichfork)      /* data or attr fork */
4145
{
4146
        int             level;          /* btree level */
4147
        uint            maxblocks;      /* max blocks at this level */
4148
        uint            maxleafents;    /* max leaf entries possible */
4149
        int             maxrootrecs;    /* max records in root block */
4150
        int             minleafrecs;    /* min records in leaf block */
4151
        int             minnoderecs;    /* min records in node block */
4152
        int             sz;             /* root block size */
4153
 
4154
        /*
4155
         * The maximum number of extents in a file, hence the maximum
4156
         * number of leaf entries, is controlled by the type of di_nextents
4157
         * (a signed 32-bit number, xfs_extnum_t), or by di_anextents
4158
         * (a signed 16-bit number, xfs_aextnum_t).
4159
         */
4160
        if (whichfork == XFS_DATA_FORK) {
4161
                maxleafents = MAXEXTNUM;
4162
                sz = (mp->m_flags & XFS_MOUNT_ATTR2) ?
4163
                        XFS_BMDR_SPACE_CALC(MINDBTPTRS) : mp->m_attroffset;
4164
        } else {
4165
                maxleafents = MAXAEXTNUM;
4166
                sz = (mp->m_flags & XFS_MOUNT_ATTR2) ?
4167
                        XFS_BMDR_SPACE_CALC(MINABTPTRS) :
4168
                        mp->m_sb.sb_inodesize - mp->m_attroffset;
4169
        }
4170
        maxrootrecs = (int)XFS_BTREE_BLOCK_MAXRECS(sz, xfs_bmdr, 0);
4171
        minleafrecs = mp->m_bmap_dmnr[0];
4172
        minnoderecs = mp->m_bmap_dmnr[1];
4173
        maxblocks = (maxleafents + minleafrecs - 1) / minleafrecs;
4174
        for (level = 1; maxblocks > 1; level++) {
4175
                if (maxblocks <= maxrootrecs)
4176
                        maxblocks = 1;
4177
                else
4178
                        maxblocks = (maxblocks + minnoderecs - 1) / minnoderecs;
4179
        }
4180
        mp->m_bm_maxlevels[whichfork] = level;
4181
}
4182
 
4183
/*
4184
 * Routine to be called at transaction's end by xfs_bmapi, xfs_bunmapi
4185
 * caller.  Frees all the extents that need freeing, which must be done
4186
 * last due to locking considerations.  We never free any extents in
4187
 * the first transaction.  This is to allow the caller to make the first
4188
 * transaction a synchronous one so that the pointers to the data being
4189
 * broken in this transaction will be permanent before the data is actually
4190
 * freed.  This is necessary to prevent blocks from being reallocated
4191
 * and written to before the free and reallocation are actually permanent.
4192
 * We do not just make the first transaction synchronous here, because
4193
 * there are more efficient ways to gain the same protection in some cases
4194
 * (see the file truncation code).
4195
 *
4196
 * Return 1 if the given transaction was committed and a new one
4197
 * started, and 0 otherwise in the committed parameter.
4198
 */
4199
/*ARGSUSED*/
4200
int                                             /* error */
4201
xfs_bmap_finish(
4202
        xfs_trans_t             **tp,           /* transaction pointer addr */
4203
        xfs_bmap_free_t         *flist,         /* i/o: list extents to free */
4204
        int                     *committed)     /* xact committed or not */
4205
{
4206
        xfs_efd_log_item_t      *efd;           /* extent free data */
4207
        xfs_efi_log_item_t      *efi;           /* extent free intention */
4208
        int                     error;          /* error return value */
4209
        xfs_bmap_free_item_t    *free;          /* free extent item */
4210
        unsigned int            logres;         /* new log reservation */
4211
        unsigned int            logcount;       /* new log count */
4212
        xfs_mount_t             *mp;            /* filesystem mount structure */
4213
        xfs_bmap_free_item_t    *next;          /* next item on free list */
4214
        xfs_trans_t             *ntp;           /* new transaction pointer */
4215
 
4216
        ASSERT((*tp)->t_flags & XFS_TRANS_PERM_LOG_RES);
4217
        if (flist->xbf_count == 0) {
4218
                *committed = 0;
4219
                return 0;
4220
        }
4221
        ntp = *tp;
4222
        efi = xfs_trans_get_efi(ntp, flist->xbf_count);
4223
        for (free = flist->xbf_first; free; free = free->xbfi_next)
4224
                xfs_trans_log_efi_extent(ntp, efi, free->xbfi_startblock,
4225
                        free->xbfi_blockcount);
4226
        logres = ntp->t_log_res;
4227
        logcount = ntp->t_log_count;
4228
        ntp = xfs_trans_dup(*tp);
4229
        error = xfs_trans_commit(*tp, 0);
4230
        *tp = ntp;
4231
        *committed = 1;
4232
        /*
4233
         * We have a new transaction, so we should return committed=1,
4234
         * even though we're returning an error.
4235
         */
4236
        if (error) {
4237
                return error;
4238
        }
4239
        if ((error = xfs_trans_reserve(ntp, 0, logres, 0, XFS_TRANS_PERM_LOG_RES,
4240
                        logcount)))
4241
                return error;
4242
        efd = xfs_trans_get_efd(ntp, efi, flist->xbf_count);
4243
        for (free = flist->xbf_first; free != NULL; free = next) {
4244
                next = free->xbfi_next;
4245
                if ((error = xfs_free_extent(ntp, free->xbfi_startblock,
4246
                                free->xbfi_blockcount))) {
4247
                        /*
4248
                         * The bmap free list will be cleaned up at a
4249
                         * higher level.  The EFI will be canceled when
4250
                         * this transaction is aborted.
4251
                         * Need to force shutdown here to make sure it
4252
                         * happens, since this transaction may not be
4253
                         * dirty yet.
4254
                         */
4255
                        mp = ntp->t_mountp;
4256
                        if (!XFS_FORCED_SHUTDOWN(mp))
4257
                                xfs_force_shutdown(mp,
4258
                                                   (error == EFSCORRUPTED) ?
4259
                                                   SHUTDOWN_CORRUPT_INCORE :
4260
                                                   SHUTDOWN_META_IO_ERROR);
4261
                        return error;
4262
                }
4263
                xfs_trans_log_efd_extent(ntp, efd, free->xbfi_startblock,
4264
                        free->xbfi_blockcount);
4265
                xfs_bmap_del_free(flist, NULL, free);
4266
        }
4267
        return 0;
4268
}
4269
 
4270
/*
4271
 * Free up any items left in the list.
4272
 */
4273
void
4274
xfs_bmap_cancel(
4275
        xfs_bmap_free_t         *flist) /* list of bmap_free_items */
4276
{
4277
        xfs_bmap_free_item_t    *free;  /* free list item */
4278
        xfs_bmap_free_item_t    *next;
4279
 
4280
        if (flist->xbf_count == 0)
4281
                return;
4282
        ASSERT(flist->xbf_first != NULL);
4283
        for (free = flist->xbf_first; free; free = next) {
4284
                next = free->xbfi_next;
4285
                xfs_bmap_del_free(flist, NULL, free);
4286
        }
4287
        ASSERT(flist->xbf_count == 0);
4288
}
4289
 
4290
/*
4291
 * Returns the file-relative block number of the first unused block(s)
4292
 * in the file with at least "len" logically contiguous blocks free.
4293
 * This is the lowest-address hole if the file has holes, else the first block
4294
 * past the end of file.
4295
 * Return 0 if the file is currently local (in-inode).
4296
 */
4297
int                                             /* error */
4298
xfs_bmap_first_unused(
4299
        xfs_trans_t     *tp,                    /* transaction pointer */
4300
        xfs_inode_t     *ip,                    /* incore inode */
4301
        xfs_extlen_t    len,                    /* size of hole to find */
4302
        xfs_fileoff_t   *first_unused,          /* unused block */
4303
        int             whichfork)              /* data or attr fork */
4304
{
4305
        int             error;                  /* error return value */
4306
        int             idx;                    /* extent record index */
4307
        xfs_ifork_t     *ifp;                   /* inode fork pointer */
4308
        xfs_fileoff_t   lastaddr;               /* last block number seen */
4309
        xfs_fileoff_t   lowest;                 /* lowest useful block */
4310
        xfs_fileoff_t   max;                    /* starting useful block */
4311
        xfs_fileoff_t   off;                    /* offset for this block */
4312
        xfs_extnum_t    nextents;               /* number of extent entries */
4313
 
4314
        ASSERT(XFS_IFORK_FORMAT(ip, whichfork) == XFS_DINODE_FMT_BTREE ||
4315
               XFS_IFORK_FORMAT(ip, whichfork) == XFS_DINODE_FMT_EXTENTS ||
4316
               XFS_IFORK_FORMAT(ip, whichfork) == XFS_DINODE_FMT_LOCAL);
4317
        if (XFS_IFORK_FORMAT(ip, whichfork) == XFS_DINODE_FMT_LOCAL) {
4318
                *first_unused = 0;
4319
                return 0;
4320
        }
4321
        ifp = XFS_IFORK_PTR(ip, whichfork);
4322
        if (!(ifp->if_flags & XFS_IFEXTENTS) &&
4323
            (error = xfs_iread_extents(tp, ip, whichfork)))
4324
                return error;
4325
        lowest = *first_unused;
4326
        nextents = ifp->if_bytes / (uint)sizeof(xfs_bmbt_rec_t);
4327
        for (idx = 0, lastaddr = 0, max = lowest; idx < nextents; idx++) {
4328
                xfs_bmbt_rec_host_t *ep = xfs_iext_get_ext(ifp, idx);
4329
                off = xfs_bmbt_get_startoff(ep);
4330
                /*
4331
                 * See if the hole before this extent will work.
4332
                 */
4333
                if (off >= lowest + len && off - max >= len) {
4334
                        *first_unused = max;
4335
                        return 0;
4336
                }
4337
                lastaddr = off + xfs_bmbt_get_blockcount(ep);
4338
                max = XFS_FILEOFF_MAX(lastaddr, lowest);
4339
        }
4340
        *first_unused = max;
4341
        return 0;
4342
}
4343
 
4344
/*
4345
 * Returns the file-relative block number of the last block + 1 before
4346
 * last_block (input value) in the file.
4347
 * This is not based on i_size, it is based on the extent records.
4348
 * Returns 0 for local files, as they do not have extent records.
4349
 */
4350
int                                             /* error */
4351
xfs_bmap_last_before(
4352
        xfs_trans_t     *tp,                    /* transaction pointer */
4353
        xfs_inode_t     *ip,                    /* incore inode */
4354
        xfs_fileoff_t   *last_block,            /* last block */
4355
        int             whichfork)              /* data or attr fork */
4356
{
4357
        xfs_fileoff_t   bno;                    /* input file offset */
4358
        int             eof;                    /* hit end of file */
4359
        xfs_bmbt_rec_host_t *ep;                /* pointer to last extent */
4360
        int             error;                  /* error return value */
4361
        xfs_bmbt_irec_t got;                    /* current extent value */
4362
        xfs_ifork_t     *ifp;                   /* inode fork pointer */
4363
        xfs_extnum_t    lastx;                  /* last extent used */
4364
        xfs_bmbt_irec_t prev;                   /* previous extent value */
4365
 
4366
        if (XFS_IFORK_FORMAT(ip, whichfork) != XFS_DINODE_FMT_BTREE &&
4367
            XFS_IFORK_FORMAT(ip, whichfork) != XFS_DINODE_FMT_EXTENTS &&
4368
            XFS_IFORK_FORMAT(ip, whichfork) != XFS_DINODE_FMT_LOCAL)
4369
               return XFS_ERROR(EIO);
4370
        if (XFS_IFORK_FORMAT(ip, whichfork) == XFS_DINODE_FMT_LOCAL) {
4371
                *last_block = 0;
4372
                return 0;
4373
        }
4374
        ifp = XFS_IFORK_PTR(ip, whichfork);
4375
        if (!(ifp->if_flags & XFS_IFEXTENTS) &&
4376
            (error = xfs_iread_extents(tp, ip, whichfork)))
4377
                return error;
4378
        bno = *last_block - 1;
4379
        ep = xfs_bmap_search_extents(ip, bno, whichfork, &eof, &lastx, &got,
4380
                &prev);
4381
        if (eof || xfs_bmbt_get_startoff(ep) > bno) {
4382
                if (prev.br_startoff == NULLFILEOFF)
4383
                        *last_block = 0;
4384
                else
4385
                        *last_block = prev.br_startoff + prev.br_blockcount;
4386
        }
4387
        /*
4388
         * Otherwise *last_block is already the right answer.
4389
         */
4390
        return 0;
4391
}
4392
 
4393
/*
4394
 * Returns the file-relative block number of the first block past eof in
4395
 * the file.  This is not based on i_size, it is based on the extent records.
4396
 * Returns 0 for local files, as they do not have extent records.
4397
 */
4398
int                                             /* error */
4399
xfs_bmap_last_offset(
4400
        xfs_trans_t     *tp,                    /* transaction pointer */
4401
        xfs_inode_t     *ip,                    /* incore inode */
4402
        xfs_fileoff_t   *last_block,            /* last block */
4403
        int             whichfork)              /* data or attr fork */
4404
{
4405
        xfs_bmbt_rec_host_t *ep;                /* pointer to last extent */
4406
        int             error;                  /* error return value */
4407
        xfs_ifork_t     *ifp;                   /* inode fork pointer */
4408
        xfs_extnum_t    nextents;               /* number of extent entries */
4409
 
4410
        if (XFS_IFORK_FORMAT(ip, whichfork) != XFS_DINODE_FMT_BTREE &&
4411
            XFS_IFORK_FORMAT(ip, whichfork) != XFS_DINODE_FMT_EXTENTS &&
4412
            XFS_IFORK_FORMAT(ip, whichfork) != XFS_DINODE_FMT_LOCAL)
4413
               return XFS_ERROR(EIO);
4414
        if (XFS_IFORK_FORMAT(ip, whichfork) == XFS_DINODE_FMT_LOCAL) {
4415
                *last_block = 0;
4416
                return 0;
4417
        }
4418
        ifp = XFS_IFORK_PTR(ip, whichfork);
4419
        if (!(ifp->if_flags & XFS_IFEXTENTS) &&
4420
            (error = xfs_iread_extents(tp, ip, whichfork)))
4421
                return error;
4422
        nextents = ifp->if_bytes / (uint)sizeof(xfs_bmbt_rec_t);
4423
        if (!nextents) {
4424
                *last_block = 0;
4425
                return 0;
4426
        }
4427
        ep = xfs_iext_get_ext(ifp, nextents - 1);
4428
        *last_block = xfs_bmbt_get_startoff(ep) + xfs_bmbt_get_blockcount(ep);
4429
        return 0;
4430
}
4431
 
4432
/*
4433
 * Returns whether the selected fork of the inode has exactly one
4434
 * block or not.  For the data fork we check this matches di_size,
4435
 * implying the file's range is 0..bsize-1.
4436
 */
4437
int                                     /* 1=>1 block, 0=>otherwise */
4438
xfs_bmap_one_block(
4439
        xfs_inode_t     *ip,            /* incore inode */
4440
        int             whichfork)      /* data or attr fork */
4441
{
4442
        xfs_bmbt_rec_host_t *ep;        /* ptr to fork's extent */
4443
        xfs_ifork_t     *ifp;           /* inode fork pointer */
4444
        int             rval;           /* return value */
4445
        xfs_bmbt_irec_t s;              /* internal version of extent */
4446
 
4447
#ifndef DEBUG
4448
        if (whichfork == XFS_DATA_FORK) {
4449
                return ((ip->i_d.di_mode & S_IFMT) == S_IFREG) ?
4450
                        (ip->i_size == ip->i_mount->m_sb.sb_blocksize) :
4451
                        (ip->i_d.di_size == ip->i_mount->m_sb.sb_blocksize);
4452
        }
4453
#endif  /* !DEBUG */
4454
        if (XFS_IFORK_NEXTENTS(ip, whichfork) != 1)
4455
                return 0;
4456
        if (XFS_IFORK_FORMAT(ip, whichfork) != XFS_DINODE_FMT_EXTENTS)
4457
                return 0;
4458
        ifp = XFS_IFORK_PTR(ip, whichfork);
4459
        ASSERT(ifp->if_flags & XFS_IFEXTENTS);
4460
        ep = xfs_iext_get_ext(ifp, 0);
4461
        xfs_bmbt_get_all(ep, &s);
4462
        rval = s.br_startoff == 0 && s.br_blockcount == 1;
4463
        if (rval && whichfork == XFS_DATA_FORK)
4464
                ASSERT(ip->i_size == ip->i_mount->m_sb.sb_blocksize);
4465
        return rval;
4466
}
4467
 
4468
/*
4469
 * Read in the extents to if_extents.
4470
 * All inode fields are set up by caller, we just traverse the btree
4471
 * and copy the records in. If the file system cannot contain unwritten
4472
 * extents, the records are checked for no "state" flags.
4473
 */
4474
int                                     /* error */
4475
xfs_bmap_read_extents(
4476
        xfs_trans_t             *tp,    /* transaction pointer */
4477
        xfs_inode_t             *ip,    /* incore inode */
4478
        int                     whichfork) /* data or attr fork */
4479
{
4480
        xfs_bmbt_block_t        *block; /* current btree block */
4481
        xfs_fsblock_t           bno;    /* block # of "block" */
4482
        xfs_buf_t               *bp;    /* buffer for "block" */
4483
        int                     error;  /* error return value */
4484
        xfs_exntfmt_t           exntf;  /* XFS_EXTFMT_NOSTATE, if checking */
4485
        xfs_extnum_t            i, j;   /* index into the extents list */
4486
        xfs_ifork_t             *ifp;   /* fork structure */
4487
        int                     level;  /* btree level, for checking */
4488
        xfs_mount_t             *mp;    /* file system mount structure */
4489
        __be64                  *pp;    /* pointer to block address */
4490
        /* REFERENCED */
4491
        xfs_extnum_t            room;   /* number of entries there's room for */
4492
 
4493
        bno = NULLFSBLOCK;
4494
        mp = ip->i_mount;
4495
        ifp = XFS_IFORK_PTR(ip, whichfork);
4496
        exntf = (whichfork != XFS_DATA_FORK) ? XFS_EXTFMT_NOSTATE :
4497
                                        XFS_EXTFMT_INODE(ip);
4498
        block = ifp->if_broot;
4499
        /*
4500
         * Root level must use BMAP_BROOT_PTR_ADDR macro to get ptr out.
4501
         */
4502
        level = be16_to_cpu(block->bb_level);
4503
        ASSERT(level > 0);
4504
        pp = XFS_BMAP_BROOT_PTR_ADDR(block, 1, ifp->if_broot_bytes);
4505
        bno = be64_to_cpu(*pp);
4506
        ASSERT(bno != NULLDFSBNO);
4507
        ASSERT(XFS_FSB_TO_AGNO(mp, bno) < mp->m_sb.sb_agcount);
4508
        ASSERT(XFS_FSB_TO_AGBNO(mp, bno) < mp->m_sb.sb_agblocks);
4509
        /*
4510
         * Go down the tree until leaf level is reached, following the first
4511
         * pointer (leftmost) at each level.
4512
         */
4513
        while (level-- > 0) {
4514
                if ((error = xfs_btree_read_bufl(mp, tp, bno, 0, &bp,
4515
                                XFS_BMAP_BTREE_REF)))
4516
                        return error;
4517
                block = XFS_BUF_TO_BMBT_BLOCK(bp);
4518
                XFS_WANT_CORRUPTED_GOTO(
4519
                        XFS_BMAP_SANITY_CHECK(mp, block, level),
4520
                        error0);
4521
                if (level == 0)
4522
                        break;
4523
                pp = XFS_BTREE_PTR_ADDR(xfs_bmbt, block, 1, mp->m_bmap_dmxr[1]);
4524
                bno = be64_to_cpu(*pp);
4525
                XFS_WANT_CORRUPTED_GOTO(XFS_FSB_SANITY_CHECK(mp, bno), error0);
4526
                xfs_trans_brelse(tp, bp);
4527
        }
4528
        /*
4529
         * Here with bp and block set to the leftmost leaf node in the tree.
4530
         */
4531
        room = ifp->if_bytes / (uint)sizeof(xfs_bmbt_rec_t);
4532
        i = 0;
4533
        /*
4534
         * Loop over all leaf nodes.  Copy information to the extent records.
4535
         */
4536
        for (;;) {
4537
                xfs_bmbt_rec_t  *frp;
4538
                xfs_fsblock_t   nextbno;
4539
                xfs_extnum_t    num_recs;
4540
                xfs_extnum_t    start;
4541
 
4542
 
4543
                num_recs = be16_to_cpu(block->bb_numrecs);
4544
                if (unlikely(i + num_recs > room)) {
4545
                        ASSERT(i + num_recs <= room);
4546
                        xfs_fs_repair_cmn_err(CE_WARN, ip->i_mount,
4547
                                "corrupt dinode %Lu, (btree extents).",
4548
                                (unsigned long long) ip->i_ino);
4549
                        XFS_ERROR_REPORT("xfs_bmap_read_extents(1)",
4550
                                         XFS_ERRLEVEL_LOW,
4551
                                        ip->i_mount);
4552
                        goto error0;
4553
                }
4554
                XFS_WANT_CORRUPTED_GOTO(
4555
                        XFS_BMAP_SANITY_CHECK(mp, block, 0),
4556
                        error0);
4557
                /*
4558
                 * Read-ahead the next leaf block, if any.
4559
                 */
4560
                nextbno = be64_to_cpu(block->bb_rightsib);
4561
                if (nextbno != NULLFSBLOCK)
4562
                        xfs_btree_reada_bufl(mp, nextbno, 1);
4563
                /*
4564
                 * Copy records into the extent records.
4565
                 */
4566
                frp = XFS_BTREE_REC_ADDR(xfs_bmbt, block, 1);
4567
                start = i;
4568
                for (j = 0; j < num_recs; j++, i++, frp++) {
4569
                        xfs_bmbt_rec_host_t *trp = xfs_iext_get_ext(ifp, i);
4570
                        trp->l0 = be64_to_cpu(frp->l0);
4571
                        trp->l1 = be64_to_cpu(frp->l1);
4572
                }
4573
                if (exntf == XFS_EXTFMT_NOSTATE) {
4574
                        /*
4575
                         * Check all attribute bmap btree records and
4576
                         * any "older" data bmap btree records for a
4577
                         * set bit in the "extent flag" position.
4578
                         */
4579
                        if (unlikely(xfs_check_nostate_extents(ifp,
4580
                                        start, num_recs))) {
4581
                                XFS_ERROR_REPORT("xfs_bmap_read_extents(2)",
4582
                                                 XFS_ERRLEVEL_LOW,
4583
                                                 ip->i_mount);
4584
                                goto error0;
4585
                        }
4586
                }
4587
                xfs_trans_brelse(tp, bp);
4588
                bno = nextbno;
4589
                /*
4590
                 * If we've reached the end, stop.
4591
                 */
4592
                if (bno == NULLFSBLOCK)
4593
                        break;
4594
                if ((error = xfs_btree_read_bufl(mp, tp, bno, 0, &bp,
4595
                                XFS_BMAP_BTREE_REF)))
4596
                        return error;
4597
                block = XFS_BUF_TO_BMBT_BLOCK(bp);
4598
        }
4599
        ASSERT(i == (ifp->if_bytes / (uint)sizeof(xfs_bmbt_rec_t)));
4600
        ASSERT(i == XFS_IFORK_NEXTENTS(ip, whichfork));
4601
        XFS_BMAP_TRACE_EXLIST(ip, i, whichfork);
4602
        return 0;
4603
error0:
4604
        xfs_trans_brelse(tp, bp);
4605
        return XFS_ERROR(EFSCORRUPTED);
4606
}
4607
 
4608
#ifdef XFS_BMAP_TRACE
4609
/*
4610
 * Add bmap trace insert entries for all the contents of the extent records.
4611
 */
4612
void
4613
xfs_bmap_trace_exlist(
4614
        const char      *fname,         /* function name */
4615
        xfs_inode_t     *ip,            /* incore inode pointer */
4616
        xfs_extnum_t    cnt,            /* count of entries in the list */
4617
        int             whichfork)      /* data or attr fork */
4618
{
4619
        xfs_bmbt_rec_host_t *ep;        /* current extent record */
4620
        xfs_extnum_t    idx;            /* extent record index */
4621
        xfs_ifork_t     *ifp;           /* inode fork pointer */
4622
        xfs_bmbt_irec_t s;              /* file extent record */
4623
 
4624
        ifp = XFS_IFORK_PTR(ip, whichfork);
4625
        ASSERT(cnt == (ifp->if_bytes / (uint)sizeof(xfs_bmbt_rec_t)));
4626
        for (idx = 0; idx < cnt; idx++) {
4627
                ep = xfs_iext_get_ext(ifp, idx);
4628
                xfs_bmbt_get_all(ep, &s);
4629
                XFS_BMAP_TRACE_INSERT("exlist", ip, idx, 1, &s, NULL,
4630
                        whichfork);
4631
        }
4632
}
4633
#endif
4634
 
4635
#ifdef DEBUG
4636
/*
4637
 * Validate that the bmbt_irecs being returned from bmapi are valid
4638
 * given the callers original parameters.  Specifically check the
4639
 * ranges of the returned irecs to ensure that they only extent beyond
4640
 * the given parameters if the XFS_BMAPI_ENTIRE flag was set.
4641
 */
4642
STATIC void
4643
xfs_bmap_validate_ret(
4644
        xfs_fileoff_t           bno,
4645
        xfs_filblks_t           len,
4646
        int                     flags,
4647
        xfs_bmbt_irec_t         *mval,
4648
        int                     nmap,
4649
        int                     ret_nmap)
4650
{
4651
        int                     i;              /* index to map values */
4652
 
4653
        ASSERT(ret_nmap <= nmap);
4654
 
4655
        for (i = 0; i < ret_nmap; i++) {
4656
                ASSERT(mval[i].br_blockcount > 0);
4657
                if (!(flags & XFS_BMAPI_ENTIRE)) {
4658
                        ASSERT(mval[i].br_startoff >= bno);
4659
                        ASSERT(mval[i].br_blockcount <= len);
4660
                        ASSERT(mval[i].br_startoff + mval[i].br_blockcount <=
4661
                               bno + len);
4662
                } else {
4663
                        ASSERT(mval[i].br_startoff < bno + len);
4664
                        ASSERT(mval[i].br_startoff + mval[i].br_blockcount >
4665
                               bno);
4666
                }
4667
                ASSERT(i == 0 ||
4668
                       mval[i - 1].br_startoff + mval[i - 1].br_blockcount ==
4669
                       mval[i].br_startoff);
4670
                if ((flags & XFS_BMAPI_WRITE) && !(flags & XFS_BMAPI_DELAY))
4671
                        ASSERT(mval[i].br_startblock != DELAYSTARTBLOCK &&
4672
                               mval[i].br_startblock != HOLESTARTBLOCK);
4673
                ASSERT(mval[i].br_state == XFS_EXT_NORM ||
4674
                       mval[i].br_state == XFS_EXT_UNWRITTEN);
4675
        }
4676
}
4677
#endif /* DEBUG */
4678
 
4679
 
4680
/*
4681
 * Map file blocks to filesystem blocks.
4682
 * File range is given by the bno/len pair.
4683
 * Adds blocks to file if a write ("flags & XFS_BMAPI_WRITE" set)
4684
 * into a hole or past eof.
4685
 * Only allocates blocks from a single allocation group,
4686
 * to avoid locking problems.
4687
 * The returned value in "firstblock" from the first call in a transaction
4688
 * must be remembered and presented to subsequent calls in "firstblock".
4689
 * An upper bound for the number of blocks to be allocated is supplied to
4690
 * the first call in "total"; if no allocation group has that many free
4691
 * blocks then the call will fail (return NULLFSBLOCK in "firstblock").
4692
 */
4693
int                                     /* error */
4694
xfs_bmapi(
4695
        xfs_trans_t     *tp,            /* transaction pointer */
4696
        xfs_inode_t     *ip,            /* incore inode */
4697
        xfs_fileoff_t   bno,            /* starting file offs. mapped */
4698
        xfs_filblks_t   len,            /* length to map in file */
4699
        int             flags,          /* XFS_BMAPI_... */
4700
        xfs_fsblock_t   *firstblock,    /* first allocated block
4701
                                           controls a.g. for allocs */
4702
        xfs_extlen_t    total,          /* total blocks needed */
4703
        xfs_bmbt_irec_t *mval,          /* output: map values */
4704
        int             *nmap,          /* i/o: mval size/count */
4705
        xfs_bmap_free_t *flist,         /* i/o: list extents to free */
4706
        xfs_extdelta_t  *delta)         /* o: change made to incore extents */
4707
{
4708
        xfs_fsblock_t   abno;           /* allocated block number */
4709
        xfs_extlen_t    alen;           /* allocated extent length */
4710
        xfs_fileoff_t   aoff;           /* allocated file offset */
4711
        xfs_bmalloca_t  bma;            /* args for xfs_bmap_alloc */
4712
        xfs_btree_cur_t *cur;           /* bmap btree cursor */
4713
        xfs_fileoff_t   end;            /* end of mapped file region */
4714
        int             eof;            /* we've hit the end of extents */
4715
        xfs_bmbt_rec_host_t *ep;        /* extent record pointer */
4716
        int             error;          /* error return */
4717
        xfs_bmbt_irec_t got;            /* current file extent record */
4718
        xfs_ifork_t     *ifp;           /* inode fork pointer */
4719
        xfs_extlen_t    indlen;         /* indirect blocks length */
4720
        xfs_extnum_t    lastx;          /* last useful extent number */
4721
        int             logflags;       /* flags for transaction logging */
4722
        xfs_extlen_t    minleft;        /* min blocks left after allocation */
4723
        xfs_extlen_t    minlen;         /* min allocation size */
4724
        xfs_mount_t     *mp;            /* xfs mount structure */
4725
        int             n;              /* current extent index */
4726
        int             nallocs;        /* number of extents alloc\'d */
4727
        xfs_extnum_t    nextents;       /* number of extents in file */
4728
        xfs_fileoff_t   obno;           /* old block number (offset) */
4729
        xfs_bmbt_irec_t prev;           /* previous file extent record */
4730
        int             tmp_logflags;   /* temp flags holder */
4731
        int             whichfork;      /* data or attr fork */
4732
        char            inhole;         /* current location is hole in file */
4733
        char            wasdelay;       /* old extent was delayed */
4734
        char            wr;             /* this is a write request */
4735
        char            rt;             /* this is a realtime file */
4736
#ifdef DEBUG
4737
        xfs_fileoff_t   orig_bno;       /* original block number value */
4738
        int             orig_flags;     /* original flags arg value */
4739
        xfs_filblks_t   orig_len;       /* original value of len arg */
4740
        xfs_bmbt_irec_t *orig_mval;     /* original value of mval */
4741
        int             orig_nmap;      /* original value of *nmap */
4742
 
4743
        orig_bno = bno;
4744
        orig_len = len;
4745
        orig_flags = flags;
4746
        orig_mval = mval;
4747
        orig_nmap = *nmap;
4748
#endif
4749
        ASSERT(*nmap >= 1);
4750
        ASSERT(*nmap <= XFS_BMAP_MAX_NMAP || !(flags & XFS_BMAPI_WRITE));
4751
        whichfork = (flags & XFS_BMAPI_ATTRFORK) ?
4752
                XFS_ATTR_FORK : XFS_DATA_FORK;
4753
        mp = ip->i_mount;
4754
        if (unlikely(XFS_TEST_ERROR(
4755
            (XFS_IFORK_FORMAT(ip, whichfork) != XFS_DINODE_FMT_EXTENTS &&
4756
             XFS_IFORK_FORMAT(ip, whichfork) != XFS_DINODE_FMT_BTREE &&
4757
             XFS_IFORK_FORMAT(ip, whichfork) != XFS_DINODE_FMT_LOCAL),
4758
             mp, XFS_ERRTAG_BMAPIFORMAT, XFS_RANDOM_BMAPIFORMAT))) {
4759
                XFS_ERROR_REPORT("xfs_bmapi", XFS_ERRLEVEL_LOW, mp);
4760
                return XFS_ERROR(EFSCORRUPTED);
4761
        }
4762
        if (XFS_FORCED_SHUTDOWN(mp))
4763
                return XFS_ERROR(EIO);
4764
        rt = (whichfork == XFS_DATA_FORK) && XFS_IS_REALTIME_INODE(ip);
4765
        ifp = XFS_IFORK_PTR(ip, whichfork);
4766
        ASSERT(ifp->if_ext_max ==
4767
               XFS_IFORK_SIZE(ip, whichfork) / (uint)sizeof(xfs_bmbt_rec_t));
4768
        if ((wr = (flags & XFS_BMAPI_WRITE)) != 0)
4769
                XFS_STATS_INC(xs_blk_mapw);
4770
        else
4771
                XFS_STATS_INC(xs_blk_mapr);
4772
        /*
4773
         * IGSTATE flag is used to combine extents which
4774
         * differ only due to the state of the extents.
4775
         * This technique is used from xfs_getbmap()
4776
         * when the caller does not wish to see the
4777
         * separation (which is the default).
4778
         *
4779
         * This technique is also used when writing a
4780
         * buffer which has been partially written,
4781
         * (usually by being flushed during a chunkread),
4782
         * to ensure one write takes place. This also
4783
         * prevents a change in the xfs inode extents at
4784
         * this time, intentionally. This change occurs
4785
         * on completion of the write operation, in
4786
         * xfs_strat_comp(), where the xfs_bmapi() call
4787
         * is transactioned, and the extents combined.
4788
         */
4789
        if ((flags & XFS_BMAPI_IGSTATE) && wr)  /* if writing unwritten space */
4790
                wr = 0;                          /* no allocations are allowed */
4791
        ASSERT(wr || !(flags & XFS_BMAPI_DELAY));
4792
        logflags = 0;
4793
        nallocs = 0;
4794
        cur = NULL;
4795
        if (XFS_IFORK_FORMAT(ip, whichfork) == XFS_DINODE_FMT_LOCAL) {
4796
                ASSERT(wr && tp);
4797
                if ((error = xfs_bmap_local_to_extents(tp, ip,
4798
                                firstblock, total, &logflags, whichfork)))
4799
                        goto error0;
4800
        }
4801
        if (wr && *firstblock == NULLFSBLOCK) {
4802
                if (XFS_IFORK_FORMAT(ip, whichfork) == XFS_DINODE_FMT_BTREE)
4803
                        minleft = be16_to_cpu(ifp->if_broot->bb_level) + 1;
4804
                else
4805
                        minleft = 1;
4806
        } else
4807
                minleft = 0;
4808
        if (!(ifp->if_flags & XFS_IFEXTENTS) &&
4809
            (error = xfs_iread_extents(tp, ip, whichfork)))
4810
                goto error0;
4811
        ep = xfs_bmap_search_extents(ip, bno, whichfork, &eof, &lastx, &got,
4812
                &prev);
4813
        nextents = ifp->if_bytes / (uint)sizeof(xfs_bmbt_rec_t);
4814
        n = 0;
4815
        end = bno + len;
4816
        obno = bno;
4817
        bma.ip = NULL;
4818
        if (delta) {
4819
                delta->xed_startoff = NULLFILEOFF;
4820
                delta->xed_blockcount = 0;
4821
        }
4822
        while (bno < end && n < *nmap) {
4823
                /*
4824
                 * Reading past eof, act as though there's a hole
4825
                 * up to end.
4826
                 */
4827
                if (eof && !wr)
4828
                        got.br_startoff = end;
4829
                inhole = eof || got.br_startoff > bno;
4830
                wasdelay = wr && !inhole && !(flags & XFS_BMAPI_DELAY) &&
4831
                        ISNULLSTARTBLOCK(got.br_startblock);
4832
                /*
4833
                 * First, deal with the hole before the allocated space
4834
                 * that we found, if any.
4835
                 */
4836
                if (wr && (inhole || wasdelay)) {
4837
                        /*
4838
                         * For the wasdelay case, we could also just
4839
                         * allocate the stuff asked for in this bmap call
4840
                         * but that wouldn't be as good.
4841
                         */
4842
                        if (wasdelay && !(flags & XFS_BMAPI_EXACT)) {
4843
                                alen = (xfs_extlen_t)got.br_blockcount;
4844
                                aoff = got.br_startoff;
4845
                                if (lastx != NULLEXTNUM && lastx) {
4846
                                        ep = xfs_iext_get_ext(ifp, lastx - 1);
4847
                                        xfs_bmbt_get_all(ep, &prev);
4848
                                }
4849
                        } else if (wasdelay) {
4850
                                alen = (xfs_extlen_t)
4851
                                        XFS_FILBLKS_MIN(len,
4852
                                                (got.br_startoff +
4853
                                                 got.br_blockcount) - bno);
4854
                                aoff = bno;
4855
                        } else {
4856
                                alen = (xfs_extlen_t)
4857
                                        XFS_FILBLKS_MIN(len, MAXEXTLEN);
4858
                                if (!eof)
4859
                                        alen = (xfs_extlen_t)
4860
                                                XFS_FILBLKS_MIN(alen,
4861
                                                        got.br_startoff - bno);
4862
                                aoff = bno;
4863
                        }
4864
                        minlen = (flags & XFS_BMAPI_CONTIG) ? alen : 1;
4865
                        if (flags & XFS_BMAPI_DELAY) {
4866
                                xfs_extlen_t    extsz;
4867
 
4868
                                /* Figure out the extent size, adjust alen */
4869
                                extsz = xfs_get_extsz_hint(ip);
4870
                                if (extsz) {
4871
                                        error = xfs_bmap_extsize_align(mp,
4872
                                                        &got, &prev, extsz,
4873
                                                        rt, eof,
4874
                                                        flags&XFS_BMAPI_DELAY,
4875
                                                        flags&XFS_BMAPI_CONVERT,
4876
                                                        &aoff, &alen);
4877
                                        ASSERT(!error);
4878
                                }
4879
 
4880
                                if (rt)
4881
                                        extsz = alen / mp->m_sb.sb_rextsize;
4882
 
4883
                                /*
4884
                                 * Make a transaction-less quota reservation for
4885
                                 * delayed allocation blocks. This number gets
4886
                                 * adjusted later.  We return if we haven't
4887
                                 * allocated blocks already inside this loop.
4888
                                 */
4889
                                if ((error = XFS_TRANS_RESERVE_QUOTA_NBLKS(
4890
                                                mp, NULL, ip, (long)alen, 0,
4891
                                                rt ? XFS_QMOPT_RES_RTBLKS :
4892
                                                     XFS_QMOPT_RES_REGBLKS))) {
4893
                                        if (n == 0) {
4894
                                                *nmap = 0;
4895
                                                ASSERT(cur == NULL);
4896
                                                return error;
4897
                                        }
4898
                                        break;
4899
                                }
4900
 
4901
                                /*
4902
                                 * Split changing sb for alen and indlen since
4903
                                 * they could be coming from different places.
4904
                                 */
4905
                                indlen = (xfs_extlen_t)
4906
                                        xfs_bmap_worst_indlen(ip, alen);
4907
                                ASSERT(indlen > 0);
4908
 
4909
                                if (rt) {
4910
                                        error = xfs_mod_incore_sb(mp,
4911
                                                        XFS_SBS_FREXTENTS,
4912
                                                        -((int64_t)extsz), (flags &
4913
                                                        XFS_BMAPI_RSVBLOCKS));
4914
                                } else {
4915
                                        error = xfs_mod_incore_sb(mp,
4916
                                                        XFS_SBS_FDBLOCKS,
4917
                                                        -((int64_t)alen), (flags &
4918
                                                        XFS_BMAPI_RSVBLOCKS));
4919
                                }
4920
                                if (!error) {
4921
                                        error = xfs_mod_incore_sb(mp,
4922
                                                        XFS_SBS_FDBLOCKS,
4923
                                                        -((int64_t)indlen), (flags &
4924
                                                        XFS_BMAPI_RSVBLOCKS));
4925
                                        if (error && rt)
4926
                                                xfs_mod_incore_sb(mp,
4927
                                                        XFS_SBS_FREXTENTS,
4928
                                                        (int64_t)extsz, (flags &
4929
                                                        XFS_BMAPI_RSVBLOCKS));
4930
                                        else if (error)
4931
                                                xfs_mod_incore_sb(mp,
4932
                                                        XFS_SBS_FDBLOCKS,
4933
                                                        (int64_t)alen, (flags &
4934
                                                        XFS_BMAPI_RSVBLOCKS));
4935
                                }
4936
 
4937
                                if (error) {
4938
                                        if (XFS_IS_QUOTA_ON(mp))
4939
                                                /* unreserve the blocks now */
4940
                                                (void)
4941
                                                XFS_TRANS_UNRESERVE_QUOTA_NBLKS(
4942
                                                        mp, NULL, ip,
4943
                                                        (long)alen, 0, rt ?
4944
                                                        XFS_QMOPT_RES_RTBLKS :
4945
                                                        XFS_QMOPT_RES_REGBLKS);
4946
                                        break;
4947
                                }
4948
 
4949
                                ip->i_delayed_blks += alen;
4950
                                abno = NULLSTARTBLOCK(indlen);
4951
                        } else {
4952
                                /*
4953
                                 * If first time, allocate and fill in
4954
                                 * once-only bma fields.
4955
                                 */
4956
                                if (bma.ip == NULL) {
4957
                                        bma.tp = tp;
4958
                                        bma.ip = ip;
4959
                                        bma.prevp = &prev;
4960
                                        bma.gotp = &got;
4961
                                        bma.total = total;
4962
                                        bma.userdata = 0;
4963
                                }
4964
                                /* Indicate if this is the first user data
4965
                                 * in the file, or just any user data.
4966
                                 */
4967
                                if (!(flags & XFS_BMAPI_METADATA)) {
4968
                                        bma.userdata = (aoff == 0) ?
4969
                                                XFS_ALLOC_INITIAL_USER_DATA :
4970
                                                XFS_ALLOC_USERDATA;
4971
                                }
4972
                                /*
4973
                                 * Fill in changeable bma fields.
4974
                                 */
4975
                                bma.eof = eof;
4976
                                bma.firstblock = *firstblock;
4977
                                bma.alen = alen;
4978
                                bma.off = aoff;
4979
                                bma.conv = !!(flags & XFS_BMAPI_CONVERT);
4980
                                bma.wasdel = wasdelay;
4981
                                bma.minlen = minlen;
4982
                                bma.low = flist->xbf_low;
4983
                                bma.minleft = minleft;
4984
                                /*
4985
                                 * Only want to do the alignment at the
4986
                                 * eof if it is userdata and allocation length
4987
                                 * is larger than a stripe unit.
4988
                                 */
4989
                                if (mp->m_dalign && alen >= mp->m_dalign &&
4990
                                    (!(flags & XFS_BMAPI_METADATA)) &&
4991
                                    (whichfork == XFS_DATA_FORK)) {
4992
                                        if ((error = xfs_bmap_isaeof(ip, aoff,
4993
                                                        whichfork, &bma.aeof)))
4994
                                                goto error0;
4995
                                } else
4996
                                        bma.aeof = 0;
4997
                                /*
4998
                                 * Call allocator.
4999
                                 */
5000
                                if ((error = xfs_bmap_alloc(&bma)))
5001
                                        goto error0;
5002
                                /*
5003
                                 * Copy out result fields.
5004
                                 */
5005
                                abno = bma.rval;
5006
                                if ((flist->xbf_low = bma.low))
5007
                                        minleft = 0;
5008
                                alen = bma.alen;
5009
                                aoff = bma.off;
5010
                                ASSERT(*firstblock == NULLFSBLOCK ||
5011
                                       XFS_FSB_TO_AGNO(mp, *firstblock) ==
5012
                                       XFS_FSB_TO_AGNO(mp, bma.firstblock) ||
5013
                                       (flist->xbf_low &&
5014
                                        XFS_FSB_TO_AGNO(mp, *firstblock) <
5015
                                        XFS_FSB_TO_AGNO(mp, bma.firstblock)));
5016
                                *firstblock = bma.firstblock;
5017
                                if (cur)
5018
                                        cur->bc_private.b.firstblock =
5019
                                                *firstblock;
5020
                                if (abno == NULLFSBLOCK)
5021
                                        break;
5022
                                if ((ifp->if_flags & XFS_IFBROOT) && !cur) {
5023
                                        cur = xfs_btree_init_cursor(mp,
5024
                                                tp, NULL, 0, XFS_BTNUM_BMAP,
5025
                                                ip, whichfork);
5026
                                        cur->bc_private.b.firstblock =
5027
                                                *firstblock;
5028
                                        cur->bc_private.b.flist = flist;
5029
                                }
5030
                                /*
5031
                                 * Bump the number of extents we've allocated
5032
                                 * in this call.
5033
                                 */
5034
                                nallocs++;
5035
                        }
5036
                        if (cur)
5037
                                cur->bc_private.b.flags =
5038
                                        wasdelay ? XFS_BTCUR_BPRV_WASDEL : 0;
5039
                        got.br_startoff = aoff;
5040
                        got.br_startblock = abno;
5041
                        got.br_blockcount = alen;
5042
                        got.br_state = XFS_EXT_NORM;    /* assume normal */
5043
                        /*
5044
                         * Determine state of extent, and the filesystem.
5045
                         * A wasdelay extent has been initialized, so
5046
                         * shouldn't be flagged as unwritten.
5047
                         */
5048
                        if (wr && XFS_SB_VERSION_HASEXTFLGBIT(&mp->m_sb)) {
5049
                                if (!wasdelay && (flags & XFS_BMAPI_PREALLOC))
5050
                                        got.br_state = XFS_EXT_UNWRITTEN;
5051
                        }
5052
                        error = xfs_bmap_add_extent(ip, lastx, &cur, &got,
5053
                                firstblock, flist, &tmp_logflags, delta,
5054
                                whichfork, (flags & XFS_BMAPI_RSVBLOCKS));
5055
                        logflags |= tmp_logflags;
5056
                        if (error)
5057
                                goto error0;
5058
                        lastx = ifp->if_lastex;
5059
                        ep = xfs_iext_get_ext(ifp, lastx);
5060
                        nextents = ifp->if_bytes / (uint)sizeof(xfs_bmbt_rec_t);
5061
                        xfs_bmbt_get_all(ep, &got);
5062
                        ASSERT(got.br_startoff <= aoff);
5063
                        ASSERT(got.br_startoff + got.br_blockcount >=
5064
                                aoff + alen);
5065
#ifdef DEBUG
5066
                        if (flags & XFS_BMAPI_DELAY) {
5067
                                ASSERT(ISNULLSTARTBLOCK(got.br_startblock));
5068
                                ASSERT(STARTBLOCKVAL(got.br_startblock) > 0);
5069
                        }
5070
                        ASSERT(got.br_state == XFS_EXT_NORM ||
5071
                               got.br_state == XFS_EXT_UNWRITTEN);
5072
#endif
5073
                        /*
5074
                         * Fall down into the found allocated space case.
5075
                         */
5076
                } else if (inhole) {
5077
                        /*
5078
                         * Reading in a hole.
5079
                         */
5080
                        mval->br_startoff = bno;
5081
                        mval->br_startblock = HOLESTARTBLOCK;
5082
                        mval->br_blockcount =
5083
                                XFS_FILBLKS_MIN(len, got.br_startoff - bno);
5084
                        mval->br_state = XFS_EXT_NORM;
5085
                        bno += mval->br_blockcount;
5086
                        len -= mval->br_blockcount;
5087
                        mval++;
5088
                        n++;
5089
                        continue;
5090
                }
5091
                /*
5092
                 * Then deal with the allocated space we found.
5093
                 */
5094
                ASSERT(ep != NULL);
5095
                if (!(flags & XFS_BMAPI_ENTIRE) &&
5096
                    (got.br_startoff + got.br_blockcount > obno)) {
5097
                        if (obno > bno)
5098
                                bno = obno;
5099
                        ASSERT((bno >= obno) || (n == 0));
5100
                        ASSERT(bno < end);
5101
                        mval->br_startoff = bno;
5102
                        if (ISNULLSTARTBLOCK(got.br_startblock)) {
5103
                                ASSERT(!wr || (flags & XFS_BMAPI_DELAY));
5104
                                mval->br_startblock = DELAYSTARTBLOCK;
5105
                        } else
5106
                                mval->br_startblock =
5107
                                        got.br_startblock +
5108
                                        (bno - got.br_startoff);
5109
                        /*
5110
                         * Return the minimum of what we got and what we
5111
                         * asked for for the length.  We can use the len
5112
                         * variable here because it is modified below
5113
                         * and we could have been there before coming
5114
                         * here if the first part of the allocation
5115
                         * didn't overlap what was asked for.
5116
                         */
5117
                        mval->br_blockcount =
5118
                                XFS_FILBLKS_MIN(end - bno, got.br_blockcount -
5119
                                        (bno - got.br_startoff));
5120
                        mval->br_state = got.br_state;
5121
                        ASSERT(mval->br_blockcount <= len);
5122
                } else {
5123
                        *mval = got;
5124
                        if (ISNULLSTARTBLOCK(mval->br_startblock)) {
5125
                                ASSERT(!wr || (flags & XFS_BMAPI_DELAY));
5126
                                mval->br_startblock = DELAYSTARTBLOCK;
5127
                        }
5128
                }
5129
 
5130
                /*
5131
                 * Check if writing previously allocated but
5132
                 * unwritten extents.
5133
                 */
5134
                if (wr && mval->br_state == XFS_EXT_UNWRITTEN &&
5135
                    ((flags & (XFS_BMAPI_PREALLOC|XFS_BMAPI_DELAY)) == 0)) {
5136
                        /*
5137
                         * Modify (by adding) the state flag, if writing.
5138
                         */
5139
                        ASSERT(mval->br_blockcount <= len);
5140
                        if ((ifp->if_flags & XFS_IFBROOT) && !cur) {
5141
                                cur = xfs_btree_init_cursor(mp,
5142
                                        tp, NULL, 0, XFS_BTNUM_BMAP,
5143
                                        ip, whichfork);
5144
                                cur->bc_private.b.firstblock =
5145
                                        *firstblock;
5146
                                cur->bc_private.b.flist = flist;
5147
                        }
5148
                        mval->br_state = XFS_EXT_NORM;
5149
                        error = xfs_bmap_add_extent(ip, lastx, &cur, mval,
5150
                                firstblock, flist, &tmp_logflags, delta,
5151
                                whichfork, (flags & XFS_BMAPI_RSVBLOCKS));
5152
                        logflags |= tmp_logflags;
5153
                        if (error)
5154
                                goto error0;
5155
                        lastx = ifp->if_lastex;
5156
                        ep = xfs_iext_get_ext(ifp, lastx);
5157
                        nextents = ifp->if_bytes / (uint)sizeof(xfs_bmbt_rec_t);
5158
                        xfs_bmbt_get_all(ep, &got);
5159
                        /*
5160
                         * We may have combined previously unwritten
5161
                         * space with written space, so generate
5162
                         * another request.
5163
                         */
5164
                        if (mval->br_blockcount < len)
5165
                                continue;
5166
                }
5167
 
5168
                ASSERT((flags & XFS_BMAPI_ENTIRE) ||
5169
                       ((mval->br_startoff + mval->br_blockcount) <= end));
5170
                ASSERT((flags & XFS_BMAPI_ENTIRE) ||
5171
                       (mval->br_blockcount <= len) ||
5172
                       (mval->br_startoff < obno));
5173
                bno = mval->br_startoff + mval->br_blockcount;
5174
                len = end - bno;
5175
                if (n > 0 && mval->br_startoff == mval[-1].br_startoff) {
5176
                        ASSERT(mval->br_startblock == mval[-1].br_startblock);
5177
                        ASSERT(mval->br_blockcount > mval[-1].br_blockcount);
5178
                        ASSERT(mval->br_state == mval[-1].br_state);
5179
                        mval[-1].br_blockcount = mval->br_blockcount;
5180
                        mval[-1].br_state = mval->br_state;
5181
                } else if (n > 0 && mval->br_startblock != DELAYSTARTBLOCK &&
5182
                           mval[-1].br_startblock != DELAYSTARTBLOCK &&
5183
                           mval[-1].br_startblock != HOLESTARTBLOCK &&
5184
                           mval->br_startblock ==
5185
                           mval[-1].br_startblock + mval[-1].br_blockcount &&
5186
                           ((flags & XFS_BMAPI_IGSTATE) ||
5187
                                mval[-1].br_state == mval->br_state)) {
5188
                        ASSERT(mval->br_startoff ==
5189
                               mval[-1].br_startoff + mval[-1].br_blockcount);
5190
                        mval[-1].br_blockcount += mval->br_blockcount;
5191
                } else if (n > 0 &&
5192
                           mval->br_startblock == DELAYSTARTBLOCK &&
5193
                           mval[-1].br_startblock == DELAYSTARTBLOCK &&
5194
                           mval->br_startoff ==
5195
                           mval[-1].br_startoff + mval[-1].br_blockcount) {
5196
                        mval[-1].br_blockcount += mval->br_blockcount;
5197
                        mval[-1].br_state = mval->br_state;
5198
                } else if (!((n == 0) &&
5199
                             ((mval->br_startoff + mval->br_blockcount) <=
5200
                              obno))) {
5201
                        mval++;
5202
                        n++;
5203
                }
5204
                /*
5205
                 * If we're done, stop now.  Stop when we've allocated
5206
                 * XFS_BMAP_MAX_NMAP extents no matter what.  Otherwise
5207
                 * the transaction may get too big.
5208
                 */
5209
                if (bno >= end || n >= *nmap || nallocs >= *nmap)
5210
                        break;
5211
                /*
5212
                 * Else go on to the next record.
5213
                 */
5214
                ep = xfs_iext_get_ext(ifp, ++lastx);
5215
                prev = got;
5216
                if (lastx >= nextents)
5217
                        eof = 1;
5218
                else
5219
                        xfs_bmbt_get_all(ep, &got);
5220
        }
5221
        ifp->if_lastex = lastx;
5222
        *nmap = n;
5223
        /*
5224
         * Transform from btree to extents, give it cur.
5225
         */
5226
        if (tp && XFS_IFORK_FORMAT(ip, whichfork) == XFS_DINODE_FMT_BTREE &&
5227
            XFS_IFORK_NEXTENTS(ip, whichfork) <= ifp->if_ext_max) {
5228
                ASSERT(wr && cur);
5229
                error = xfs_bmap_btree_to_extents(tp, ip, cur,
5230
                        &tmp_logflags, whichfork);
5231
                logflags |= tmp_logflags;
5232
                if (error)
5233
                        goto error0;
5234
        }
5235
        ASSERT(ifp->if_ext_max ==
5236
               XFS_IFORK_SIZE(ip, whichfork) / (uint)sizeof(xfs_bmbt_rec_t));
5237
        ASSERT(XFS_IFORK_FORMAT(ip, whichfork) != XFS_DINODE_FMT_BTREE ||
5238
               XFS_IFORK_NEXTENTS(ip, whichfork) > ifp->if_ext_max);
5239
        error = 0;
5240
        if (delta && delta->xed_startoff != NULLFILEOFF) {
5241
                /* A change was actually made.
5242
                 * Note that delta->xed_blockount is an offset at this
5243
                 * point and needs to be converted to a block count.
5244
                 */
5245
                ASSERT(delta->xed_blockcount > delta->xed_startoff);
5246
                delta->xed_blockcount -= delta->xed_startoff;
5247
        }
5248
error0:
5249
        /*
5250
         * Log everything.  Do this after conversion, there's no point in
5251
         * logging the extent records if we've converted to btree format.
5252
         */
5253
        if ((logflags & XFS_ILOG_FEXT(whichfork)) &&
5254
            XFS_IFORK_FORMAT(ip, whichfork) != XFS_DINODE_FMT_EXTENTS)
5255
                logflags &= ~XFS_ILOG_FEXT(whichfork);
5256
        else if ((logflags & XFS_ILOG_FBROOT(whichfork)) &&
5257
                 XFS_IFORK_FORMAT(ip, whichfork) != XFS_DINODE_FMT_BTREE)
5258
                logflags &= ~XFS_ILOG_FBROOT(whichfork);
5259
        /*
5260
         * Log whatever the flags say, even if error.  Otherwise we might miss
5261
         * detecting a case where the data is changed, there's an error,
5262
         * and it's not logged so we don't shutdown when we should.
5263
         */
5264
        if (logflags) {
5265
                ASSERT(tp && wr);
5266
                xfs_trans_log_inode(tp, ip, logflags);
5267
        }
5268
        if (cur) {
5269
                if (!error) {
5270
                        ASSERT(*firstblock == NULLFSBLOCK ||
5271
                               XFS_FSB_TO_AGNO(mp, *firstblock) ==
5272
                               XFS_FSB_TO_AGNO(mp,
5273
                                       cur->bc_private.b.firstblock) ||
5274
                               (flist->xbf_low &&
5275
                                XFS_FSB_TO_AGNO(mp, *firstblock) <
5276
                                XFS_FSB_TO_AGNO(mp,
5277
                                        cur->bc_private.b.firstblock)));
5278
                        *firstblock = cur->bc_private.b.firstblock;
5279
                }
5280
                xfs_btree_del_cursor(cur,
5281
                        error ? XFS_BTREE_ERROR : XFS_BTREE_NOERROR);
5282
        }
5283
        if (!error)
5284
                xfs_bmap_validate_ret(orig_bno, orig_len, orig_flags, orig_mval,
5285
                        orig_nmap, *nmap);
5286
        return error;
5287
}
5288
 
5289
/*
5290
 * Map file blocks to filesystem blocks, simple version.
5291
 * One block (extent) only, read-only.
5292
 * For flags, only the XFS_BMAPI_ATTRFORK flag is examined.
5293
 * For the other flag values, the effect is as if XFS_BMAPI_METADATA
5294
 * was set and all the others were clear.
5295
 */
5296
int                                             /* error */
5297
xfs_bmapi_single(
5298
        xfs_trans_t     *tp,            /* transaction pointer */
5299
        xfs_inode_t     *ip,            /* incore inode */
5300
        int             whichfork,      /* data or attr fork */
5301
        xfs_fsblock_t   *fsb,           /* output: mapped block */
5302
        xfs_fileoff_t   bno)            /* starting file offs. mapped */
5303
{
5304
        int             eof;            /* we've hit the end of extents */
5305
        int             error;          /* error return */
5306
        xfs_bmbt_irec_t got;            /* current file extent record */
5307
        xfs_ifork_t     *ifp;           /* inode fork pointer */
5308
        xfs_extnum_t    lastx;          /* last useful extent number */
5309
        xfs_bmbt_irec_t prev;           /* previous file extent record */
5310
 
5311
        ifp = XFS_IFORK_PTR(ip, whichfork);
5312
        if (unlikely(
5313
            XFS_IFORK_FORMAT(ip, whichfork) != XFS_DINODE_FMT_BTREE &&
5314
            XFS_IFORK_FORMAT(ip, whichfork) != XFS_DINODE_FMT_EXTENTS)) {
5315
               XFS_ERROR_REPORT("xfs_bmapi_single", XFS_ERRLEVEL_LOW,
5316
                                ip->i_mount);
5317
               return XFS_ERROR(EFSCORRUPTED);
5318
        }
5319
        if (XFS_FORCED_SHUTDOWN(ip->i_mount))
5320
                return XFS_ERROR(EIO);
5321
        XFS_STATS_INC(xs_blk_mapr);
5322
        if (!(ifp->if_flags & XFS_IFEXTENTS) &&
5323
            (error = xfs_iread_extents(tp, ip, whichfork)))
5324
                return error;
5325
        (void)xfs_bmap_search_extents(ip, bno, whichfork, &eof, &lastx, &got,
5326
                &prev);
5327
        /*
5328
         * Reading past eof, act as though there's a hole
5329
         * up to end.
5330
         */
5331
        if (eof || got.br_startoff > bno) {
5332
                *fsb = NULLFSBLOCK;
5333
                return 0;
5334
        }
5335
        ASSERT(!ISNULLSTARTBLOCK(got.br_startblock));
5336
        ASSERT(bno < got.br_startoff + got.br_blockcount);
5337
        *fsb = got.br_startblock + (bno - got.br_startoff);
5338
        ifp->if_lastex = lastx;
5339
        return 0;
5340
}
5341
 
5342
/*
5343
 * Unmap (remove) blocks from a file.
5344
 * If nexts is nonzero then the number of extents to remove is limited to
5345
 * that value.  If not all extents in the block range can be removed then
5346
 * *done is set.
5347
 */
5348
int                                             /* error */
5349
xfs_bunmapi(
5350
        xfs_trans_t             *tp,            /* transaction pointer */
5351
        struct xfs_inode        *ip,            /* incore inode */
5352
        xfs_fileoff_t           bno,            /* starting offset to unmap */
5353
        xfs_filblks_t           len,            /* length to unmap in file */
5354
        int                     flags,          /* misc flags */
5355
        xfs_extnum_t            nexts,          /* number of extents max */
5356
        xfs_fsblock_t           *firstblock,    /* first allocated block
5357
                                                   controls a.g. for allocs */
5358
        xfs_bmap_free_t         *flist,         /* i/o: list extents to free */
5359
        xfs_extdelta_t          *delta,         /* o: change made to incore
5360
                                                   extents */
5361
        int                     *done)          /* set if not done yet */
5362
{
5363
        xfs_btree_cur_t         *cur;           /* bmap btree cursor */
5364
        xfs_bmbt_irec_t         del;            /* extent being deleted */
5365
        int                     eof;            /* is deleting at eof */
5366
        xfs_bmbt_rec_host_t     *ep;            /* extent record pointer */
5367
        int                     error;          /* error return value */
5368
        xfs_extnum_t            extno;          /* extent number in list */
5369
        xfs_bmbt_irec_t         got;            /* current extent record */
5370
        xfs_ifork_t             *ifp;           /* inode fork pointer */
5371
        int                     isrt;           /* freeing in rt area */
5372
        xfs_extnum_t            lastx;          /* last extent index used */
5373
        int                     logflags;       /* transaction logging flags */
5374
        xfs_extlen_t            mod;            /* rt extent offset */
5375
        xfs_mount_t             *mp;            /* mount structure */
5376
        xfs_extnum_t            nextents;       /* number of file extents */
5377
        xfs_bmbt_irec_t         prev;           /* previous extent record */
5378
        xfs_fileoff_t           start;          /* first file offset deleted */
5379
        int                     tmp_logflags;   /* partial logging flags */
5380
        int                     wasdel;         /* was a delayed alloc extent */
5381
        int                     whichfork;      /* data or attribute fork */
5382
        int                     rsvd;           /* OK to allocate reserved blocks */
5383
        xfs_fsblock_t           sum;
5384
 
5385
        xfs_bunmap_trace(ip, bno, len, flags, (inst_t *)__return_address);
5386
        whichfork = (flags & XFS_BMAPI_ATTRFORK) ?
5387
                XFS_ATTR_FORK : XFS_DATA_FORK;
5388
        ifp = XFS_IFORK_PTR(ip, whichfork);
5389
        if (unlikely(
5390
            XFS_IFORK_FORMAT(ip, whichfork) != XFS_DINODE_FMT_EXTENTS &&
5391
            XFS_IFORK_FORMAT(ip, whichfork) != XFS_DINODE_FMT_BTREE)) {
5392
                XFS_ERROR_REPORT("xfs_bunmapi", XFS_ERRLEVEL_LOW,
5393
                                 ip->i_mount);
5394
                return XFS_ERROR(EFSCORRUPTED);
5395
        }
5396
        mp = ip->i_mount;
5397
        if (XFS_FORCED_SHUTDOWN(mp))
5398
                return XFS_ERROR(EIO);
5399
        rsvd = (flags & XFS_BMAPI_RSVBLOCKS) != 0;
5400
        ASSERT(len > 0);
5401
        ASSERT(nexts >= 0);
5402
        ASSERT(ifp->if_ext_max ==
5403
               XFS_IFORK_SIZE(ip, whichfork) / (uint)sizeof(xfs_bmbt_rec_t));
5404
        if (!(ifp->if_flags & XFS_IFEXTENTS) &&
5405
            (error = xfs_iread_extents(tp, ip, whichfork)))
5406
                return error;
5407
        nextents = ifp->if_bytes / (uint)sizeof(xfs_bmbt_rec_t);
5408
        if (nextents == 0) {
5409
                *done = 1;
5410
                return 0;
5411
        }
5412
        XFS_STATS_INC(xs_blk_unmap);
5413
        isrt = (whichfork == XFS_DATA_FORK) && XFS_IS_REALTIME_INODE(ip);
5414
        start = bno;
5415
        bno = start + len - 1;
5416
        ep = xfs_bmap_search_extents(ip, bno, whichfork, &eof, &lastx, &got,
5417
                &prev);
5418
        if (delta) {
5419
                delta->xed_startoff = NULLFILEOFF;
5420
                delta->xed_blockcount = 0;
5421
        }
5422
        /*
5423
         * Check to see if the given block number is past the end of the
5424
         * file, back up to the last block if so...
5425
         */
5426
        if (eof) {
5427
                ep = xfs_iext_get_ext(ifp, --lastx);
5428
                xfs_bmbt_get_all(ep, &got);
5429
                bno = got.br_startoff + got.br_blockcount - 1;
5430
        }
5431
        logflags = 0;
5432
        if (ifp->if_flags & XFS_IFBROOT) {
5433
                ASSERT(XFS_IFORK_FORMAT(ip, whichfork) == XFS_DINODE_FMT_BTREE);
5434
                cur = xfs_btree_init_cursor(mp, tp, NULL, 0, XFS_BTNUM_BMAP, ip,
5435
                        whichfork);
5436
                cur->bc_private.b.firstblock = *firstblock;
5437
                cur->bc_private.b.flist = flist;
5438
                cur->bc_private.b.flags = 0;
5439
        } else
5440
                cur = NULL;
5441
        extno = 0;
5442
        while (bno != (xfs_fileoff_t)-1 && bno >= start && lastx >= 0 &&
5443
               (nexts == 0 || extno < nexts)) {
5444
                /*
5445
                 * Is the found extent after a hole in which bno lives?
5446
                 * Just back up to the previous extent, if so.
5447
                 */
5448
                if (got.br_startoff > bno) {
5449
                        if (--lastx < 0)
5450
                                break;
5451
                        ep = xfs_iext_get_ext(ifp, lastx);
5452
                        xfs_bmbt_get_all(ep, &got);
5453
                }
5454
                /*
5455
                 * Is the last block of this extent before the range
5456
                 * we're supposed to delete?  If so, we're done.
5457
                 */
5458
                bno = XFS_FILEOFF_MIN(bno,
5459
                        got.br_startoff + got.br_blockcount - 1);
5460
                if (bno < start)
5461
                        break;
5462
                /*
5463
                 * Then deal with the (possibly delayed) allocated space
5464
                 * we found.
5465
                 */
5466
                ASSERT(ep != NULL);
5467
                del = got;
5468
                wasdel = ISNULLSTARTBLOCK(del.br_startblock);
5469
                if (got.br_startoff < start) {
5470
                        del.br_startoff = start;
5471
                        del.br_blockcount -= start - got.br_startoff;
5472
                        if (!wasdel)
5473
                                del.br_startblock += start - got.br_startoff;
5474
                }
5475
                if (del.br_startoff + del.br_blockcount > bno + 1)
5476
                        del.br_blockcount = bno + 1 - del.br_startoff;
5477
                sum = del.br_startblock + del.br_blockcount;
5478
                if (isrt &&
5479
                    (mod = do_mod(sum, mp->m_sb.sb_rextsize))) {
5480
                        /*
5481
                         * Realtime extent not lined up at the end.
5482
                         * The extent could have been split into written
5483
                         * and unwritten pieces, or we could just be
5484
                         * unmapping part of it.  But we can't really
5485
                         * get rid of part of a realtime extent.
5486
                         */
5487
                        if (del.br_state == XFS_EXT_UNWRITTEN ||
5488
                            !XFS_SB_VERSION_HASEXTFLGBIT(&mp->m_sb)) {
5489
                                /*
5490
                                 * This piece is unwritten, or we're not
5491
                                 * using unwritten extents.  Skip over it.
5492
                                 */
5493
                                ASSERT(bno >= mod);
5494
                                bno -= mod > del.br_blockcount ?
5495
                                        del.br_blockcount : mod;
5496
                                if (bno < got.br_startoff) {
5497
                                        if (--lastx >= 0)
5498
                                                xfs_bmbt_get_all(xfs_iext_get_ext(
5499
                                                        ifp, lastx), &got);
5500
                                }
5501
                                continue;
5502
                        }
5503
                        /*
5504
                         * It's written, turn it unwritten.
5505
                         * This is better than zeroing it.
5506
                         */
5507
                        ASSERT(del.br_state == XFS_EXT_NORM);
5508
                        ASSERT(xfs_trans_get_block_res(tp) > 0);
5509
                        /*
5510
                         * If this spans a realtime extent boundary,
5511
                         * chop it back to the start of the one we end at.
5512
                         */
5513
                        if (del.br_blockcount > mod) {
5514
                                del.br_startoff += del.br_blockcount - mod;
5515
                                del.br_startblock += del.br_blockcount - mod;
5516
                                del.br_blockcount = mod;
5517
                        }
5518
                        del.br_state = XFS_EXT_UNWRITTEN;
5519
                        error = xfs_bmap_add_extent(ip, lastx, &cur, &del,
5520
                                firstblock, flist, &logflags, delta,
5521
                                XFS_DATA_FORK, 0);
5522
                        if (error)
5523
                                goto error0;
5524
                        goto nodelete;
5525
                }
5526
                if (isrt && (mod = do_mod(del.br_startblock, mp->m_sb.sb_rextsize))) {
5527
                        /*
5528
                         * Realtime extent is lined up at the end but not
5529
                         * at the front.  We'll get rid of full extents if
5530
                         * we can.
5531
                         */
5532
                        mod = mp->m_sb.sb_rextsize - mod;
5533
                        if (del.br_blockcount > mod) {
5534
                                del.br_blockcount -= mod;
5535
                                del.br_startoff += mod;
5536
                                del.br_startblock += mod;
5537
                        } else if ((del.br_startoff == start &&
5538
                                    (del.br_state == XFS_EXT_UNWRITTEN ||
5539
                                     xfs_trans_get_block_res(tp) == 0)) ||
5540
                                   !XFS_SB_VERSION_HASEXTFLGBIT(&mp->m_sb)) {
5541
                                /*
5542
                                 * Can't make it unwritten.  There isn't
5543
                                 * a full extent here so just skip it.
5544
                                 */
5545
                                ASSERT(bno >= del.br_blockcount);
5546
                                bno -= del.br_blockcount;
5547
                                if (bno < got.br_startoff) {
5548
                                        if (--lastx >= 0)
5549
                                                xfs_bmbt_get_all(--ep, &got);
5550
                                }
5551
                                continue;
5552
                        } else if (del.br_state == XFS_EXT_UNWRITTEN) {
5553
                                /*
5554
                                 * This one is already unwritten.
5555
                                 * It must have a written left neighbor.
5556
                                 * Unwrite the killed part of that one and
5557
                                 * try again.
5558
                                 */
5559
                                ASSERT(lastx > 0);
5560
                                xfs_bmbt_get_all(xfs_iext_get_ext(ifp,
5561
                                                lastx - 1), &prev);
5562
                                ASSERT(prev.br_state == XFS_EXT_NORM);
5563
                                ASSERT(!ISNULLSTARTBLOCK(prev.br_startblock));
5564
                                ASSERT(del.br_startblock ==
5565
                                       prev.br_startblock + prev.br_blockcount);
5566
                                if (prev.br_startoff < start) {
5567
                                        mod = start - prev.br_startoff;
5568
                                        prev.br_blockcount -= mod;
5569
                                        prev.br_startblock += mod;
5570
                                        prev.br_startoff = start;
5571
                                }
5572
                                prev.br_state = XFS_EXT_UNWRITTEN;
5573
                                error = xfs_bmap_add_extent(ip, lastx - 1, &cur,
5574
                                        &prev, firstblock, flist, &logflags,
5575
                                        delta, XFS_DATA_FORK, 0);
5576
                                if (error)
5577
                                        goto error0;
5578
                                goto nodelete;
5579
                        } else {
5580
                                ASSERT(del.br_state == XFS_EXT_NORM);
5581
                                del.br_state = XFS_EXT_UNWRITTEN;
5582
                                error = xfs_bmap_add_extent(ip, lastx, &cur,
5583
                                        &del, firstblock, flist, &logflags,
5584
                                        delta, XFS_DATA_FORK, 0);
5585
                                if (error)
5586
                                        goto error0;
5587
                                goto nodelete;
5588
                        }
5589
                }
5590
                if (wasdel) {
5591
                        ASSERT(STARTBLOCKVAL(del.br_startblock) > 0);
5592
                        /* Update realtime/data freespace, unreserve quota */
5593
                        if (isrt) {
5594
                                xfs_filblks_t rtexts;
5595
 
5596
                                rtexts = XFS_FSB_TO_B(mp, del.br_blockcount);
5597
                                do_div(rtexts, mp->m_sb.sb_rextsize);
5598
                                xfs_mod_incore_sb(mp, XFS_SBS_FREXTENTS,
5599
                                                (int64_t)rtexts, rsvd);
5600
                                (void)XFS_TRANS_RESERVE_QUOTA_NBLKS(mp,
5601
                                        NULL, ip, -((long)del.br_blockcount), 0,
5602
                                        XFS_QMOPT_RES_RTBLKS);
5603
                        } else {
5604
                                xfs_mod_incore_sb(mp, XFS_SBS_FDBLOCKS,
5605
                                                (int64_t)del.br_blockcount, rsvd);
5606
                                (void)XFS_TRANS_RESERVE_QUOTA_NBLKS(mp,
5607
                                        NULL, ip, -((long)del.br_blockcount), 0,
5608
                                        XFS_QMOPT_RES_REGBLKS);
5609
                        }
5610
                        ip->i_delayed_blks -= del.br_blockcount;
5611
                        if (cur)
5612
                                cur->bc_private.b.flags |=
5613
                                        XFS_BTCUR_BPRV_WASDEL;
5614
                } else if (cur)
5615
                        cur->bc_private.b.flags &= ~XFS_BTCUR_BPRV_WASDEL;
5616
                /*
5617
                 * If it's the case where the directory code is running
5618
                 * with no block reservation, and the deleted block is in
5619
                 * the middle of its extent, and the resulting insert
5620
                 * of an extent would cause transformation to btree format,
5621
                 * then reject it.  The calling code will then swap
5622
                 * blocks around instead.
5623
                 * We have to do this now, rather than waiting for the
5624
                 * conversion to btree format, since the transaction
5625
                 * will be dirty.
5626
                 */
5627
                if (!wasdel && xfs_trans_get_block_res(tp) == 0 &&
5628
                    XFS_IFORK_FORMAT(ip, whichfork) == XFS_DINODE_FMT_EXTENTS &&
5629
                    XFS_IFORK_NEXTENTS(ip, whichfork) >= ifp->if_ext_max &&
5630
                    del.br_startoff > got.br_startoff &&
5631
                    del.br_startoff + del.br_blockcount <
5632
                    got.br_startoff + got.br_blockcount) {
5633
                        error = XFS_ERROR(ENOSPC);
5634
                        goto error0;
5635
                }
5636
                error = xfs_bmap_del_extent(ip, tp, lastx, flist, cur, &del,
5637
                                &tmp_logflags, delta, whichfork, rsvd);
5638
                logflags |= tmp_logflags;
5639
                if (error)
5640
                        goto error0;
5641
                bno = del.br_startoff - 1;
5642
nodelete:
5643
                lastx = ifp->if_lastex;
5644
                /*
5645
                 * If not done go on to the next (previous) record.
5646
                 * Reset ep in case the extents array was re-alloced.
5647
                 */
5648
                ep = xfs_iext_get_ext(ifp, lastx);
5649
                if (bno != (xfs_fileoff_t)-1 && bno >= start) {
5650
                        if (lastx >= XFS_IFORK_NEXTENTS(ip, whichfork) ||
5651
                            xfs_bmbt_get_startoff(ep) > bno) {
5652
                                if (--lastx >= 0)
5653
                                        ep = xfs_iext_get_ext(ifp, lastx);
5654
                        }
5655
                        if (lastx >= 0)
5656
                                xfs_bmbt_get_all(ep, &got);
5657
                        extno++;
5658
                }
5659
        }
5660
        ifp->if_lastex = lastx;
5661
        *done = bno == (xfs_fileoff_t)-1 || bno < start || lastx < 0;
5662
        ASSERT(ifp->if_ext_max ==
5663
               XFS_IFORK_SIZE(ip, whichfork) / (uint)sizeof(xfs_bmbt_rec_t));
5664
        /*
5665
         * Convert to a btree if necessary.
5666
         */
5667
        if (XFS_IFORK_FORMAT(ip, whichfork) == XFS_DINODE_FMT_EXTENTS &&
5668
            XFS_IFORK_NEXTENTS(ip, whichfork) > ifp->if_ext_max) {
5669
                ASSERT(cur == NULL);
5670
                error = xfs_bmap_extents_to_btree(tp, ip, firstblock, flist,
5671
                        &cur, 0, &tmp_logflags, whichfork);
5672
                logflags |= tmp_logflags;
5673
                if (error)
5674
                        goto error0;
5675
        }
5676
        /*
5677
         * transform from btree to extents, give it cur
5678
         */
5679
        else if (XFS_IFORK_FORMAT(ip, whichfork) == XFS_DINODE_FMT_BTREE &&
5680
                 XFS_IFORK_NEXTENTS(ip, whichfork) <= ifp->if_ext_max) {
5681
                ASSERT(cur != NULL);
5682
                error = xfs_bmap_btree_to_extents(tp, ip, cur, &tmp_logflags,
5683
                        whichfork);
5684
                logflags |= tmp_logflags;
5685
                if (error)
5686
                        goto error0;
5687
        }
5688
        /*
5689
         * transform from extents to local?
5690
         */
5691
        ASSERT(ifp->if_ext_max ==
5692
               XFS_IFORK_SIZE(ip, whichfork) / (uint)sizeof(xfs_bmbt_rec_t));
5693
        error = 0;
5694
        if (delta && delta->xed_startoff != NULLFILEOFF) {
5695
                /* A change was actually made.
5696
                 * Note that delta->xed_blockount is an offset at this
5697
                 * point and needs to be converted to a block count.
5698
                 */
5699
                ASSERT(delta->xed_blockcount > delta->xed_startoff);
5700
                delta->xed_blockcount -= delta->xed_startoff;
5701
        }
5702
error0:
5703
        /*
5704
         * Log everything.  Do this after conversion, there's no point in
5705
         * logging the extent records if we've converted to btree format.
5706
         */
5707
        if ((logflags & XFS_ILOG_FEXT(whichfork)) &&
5708
            XFS_IFORK_FORMAT(ip, whichfork) != XFS_DINODE_FMT_EXTENTS)
5709
                logflags &= ~XFS_ILOG_FEXT(whichfork);
5710
        else if ((logflags & XFS_ILOG_FBROOT(whichfork)) &&
5711
                 XFS_IFORK_FORMAT(ip, whichfork) != XFS_DINODE_FMT_BTREE)
5712
                logflags &= ~XFS_ILOG_FBROOT(whichfork);
5713
        /*
5714
         * Log inode even in the error case, if the transaction
5715
         * is dirty we'll need to shut down the filesystem.
5716
         */
5717
        if (logflags)
5718
                xfs_trans_log_inode(tp, ip, logflags);
5719
        if (cur) {
5720
                if (!error) {
5721
                        *firstblock = cur->bc_private.b.firstblock;
5722
                        cur->bc_private.b.allocated = 0;
5723
                }
5724
                xfs_btree_del_cursor(cur,
5725
                        error ? XFS_BTREE_ERROR : XFS_BTREE_NOERROR);
5726
        }
5727
        return error;
5728
}
5729
 
5730
/*
5731
 * returns 1 for success, 0 if we failed to map the extent.
5732
 */
5733
STATIC int
5734
xfs_getbmapx_fix_eof_hole(
5735
        xfs_inode_t             *ip,            /* xfs incore inode pointer */
5736
        struct getbmap          *out,           /* output structure */
5737
        int                     prealloced,     /* this is a file with
5738
                                                * preallocated data space */
5739
        __int64_t               end,            /* last block requested */
5740
        xfs_fsblock_t           startblock)
5741
{
5742
        __int64_t               fixlen;
5743
        xfs_mount_t             *mp;            /* file system mount point */
5744
 
5745
        if (startblock == HOLESTARTBLOCK) {
5746
                mp = ip->i_mount;
5747
                out->bmv_block = -1;
5748
                fixlen = XFS_FSB_TO_BB(mp, XFS_B_TO_FSB(mp, ip->i_size));
5749
                fixlen -= out->bmv_offset;
5750
                if (prealloced && out->bmv_offset + out->bmv_length == end) {
5751
                        /* Came to hole at EOF. Trim it. */
5752
                        if (fixlen <= 0)
5753
                                return 0;
5754
                        out->bmv_length = fixlen;
5755
                }
5756
        } else {
5757
                out->bmv_block = XFS_FSB_TO_DB(ip, startblock);
5758
        }
5759
 
5760
        return 1;
5761
}
5762
 
5763
/*
5764
 * Fcntl interface to xfs_bmapi.
5765
 */
5766
int                                             /* error code */
5767
xfs_getbmap(
5768
        xfs_inode_t             *ip,
5769
        struct getbmap          *bmv,           /* user bmap structure */
5770
        void                    __user *ap,     /* pointer to user's array */
5771
        int                     interface)      /* interface flags */
5772
{
5773
        __int64_t               bmvend;         /* last block requested */
5774
        int                     error;          /* return value */
5775
        __int64_t               fixlen;         /* length for -1 case */
5776
        int                     i;              /* extent number */
5777
        bhv_vnode_t             *vp;            /* corresponding vnode */
5778
        int                     lock;           /* lock state */
5779
        xfs_bmbt_irec_t         *map;           /* buffer for user's data */
5780
        xfs_mount_t             *mp;            /* file system mount point */
5781
        int                     nex;            /* # of user extents can do */
5782
        int                     nexleft;        /* # of user extents left */
5783
        int                     subnex;         /* # of bmapi's can do */
5784
        int                     nmap;           /* number of map entries */
5785
        struct getbmap          out;            /* output structure */
5786
        int                     whichfork;      /* data or attr fork */
5787
        int                     prealloced;     /* this is a file with
5788
                                                 * preallocated data space */
5789
        int                     sh_unwritten;   /* true, if unwritten */
5790
                                                /* extents listed separately */
5791
        int                     bmapi_flags;    /* flags for xfs_bmapi */
5792
        __int32_t               oflags;         /* getbmapx bmv_oflags field */
5793
 
5794
        vp = XFS_ITOV(ip);
5795
        mp = ip->i_mount;
5796
 
5797
        whichfork = interface & BMV_IF_ATTRFORK ? XFS_ATTR_FORK : XFS_DATA_FORK;
5798
        sh_unwritten = (interface & BMV_IF_PREALLOC) != 0;
5799
 
5800
        /*      If the BMV_IF_NO_DMAPI_READ interface bit specified, do not
5801
         *      generate a DMAPI read event.  Otherwise, if the DM_EVENT_READ
5802
         *      bit is set for the file, generate a read event in order
5803
         *      that the DMAPI application may do its thing before we return
5804
         *      the extents.  Usually this means restoring user file data to
5805
         *      regions of the file that look like holes.
5806
         *
5807
         *      The "old behavior" (from XFS_IOC_GETBMAP) is to not specify
5808
         *      BMV_IF_NO_DMAPI_READ so that read events are generated.
5809
         *      If this were not true, callers of ioctl( XFS_IOC_GETBMAP )
5810
         *      could misinterpret holes in a DMAPI file as true holes,
5811
         *      when in fact they may represent offline user data.
5812
         */
5813
        if ((interface & BMV_IF_NO_DMAPI_READ) == 0 &&
5814
            DM_EVENT_ENABLED(ip, DM_EVENT_READ) &&
5815
            whichfork == XFS_DATA_FORK) {
5816
                error = XFS_SEND_DATA(mp, DM_EVENT_READ, vp, 0, 0, 0, NULL);
5817
                if (error)
5818
                        return XFS_ERROR(error);
5819
        }
5820
 
5821
        if (whichfork == XFS_ATTR_FORK) {
5822
                if (XFS_IFORK_Q(ip)) {
5823
                        if (ip->i_d.di_aformat != XFS_DINODE_FMT_EXTENTS &&
5824
                            ip->i_d.di_aformat != XFS_DINODE_FMT_BTREE &&
5825
                            ip->i_d.di_aformat != XFS_DINODE_FMT_LOCAL)
5826
                                return XFS_ERROR(EINVAL);
5827
                } else if (unlikely(
5828
                           ip->i_d.di_aformat != 0 &&
5829
                           ip->i_d.di_aformat != XFS_DINODE_FMT_EXTENTS)) {
5830
                        XFS_ERROR_REPORT("xfs_getbmap", XFS_ERRLEVEL_LOW,
5831
                                         ip->i_mount);
5832
                        return XFS_ERROR(EFSCORRUPTED);
5833
                }
5834
        } else if (ip->i_d.di_format != XFS_DINODE_FMT_EXTENTS &&
5835
                   ip->i_d.di_format != XFS_DINODE_FMT_BTREE &&
5836
                   ip->i_d.di_format != XFS_DINODE_FMT_LOCAL)
5837
                return XFS_ERROR(EINVAL);
5838
        if (whichfork == XFS_DATA_FORK) {
5839
                if (xfs_get_extsz_hint(ip) ||
5840
                    ip->i_d.di_flags & (XFS_DIFLAG_PREALLOC|XFS_DIFLAG_APPEND)){
5841
                        prealloced = 1;
5842
                        fixlen = XFS_MAXIOFFSET(mp);
5843
                } else {
5844
                        prealloced = 0;
5845
                        fixlen = ip->i_size;
5846
                }
5847
        } else {
5848
                prealloced = 0;
5849
                fixlen = 1LL << 32;
5850
        }
5851
 
5852
        if (bmv->bmv_length == -1) {
5853
                fixlen = XFS_FSB_TO_BB(mp, XFS_B_TO_FSB(mp, fixlen));
5854
                bmv->bmv_length = MAX( (__int64_t)(fixlen - bmv->bmv_offset),
5855
                                        (__int64_t)0);
5856
        } else if (bmv->bmv_length < 0)
5857
                return XFS_ERROR(EINVAL);
5858
        if (bmv->bmv_length == 0) {
5859
                bmv->bmv_entries = 0;
5860
                return 0;
5861
        }
5862
        nex = bmv->bmv_count - 1;
5863
        if (nex <= 0)
5864
                return XFS_ERROR(EINVAL);
5865
        bmvend = bmv->bmv_offset + bmv->bmv_length;
5866
 
5867
        xfs_ilock(ip, XFS_IOLOCK_SHARED);
5868
 
5869
        if (whichfork == XFS_DATA_FORK &&
5870
                (ip->i_delayed_blks || ip->i_size > ip->i_d.di_size)) {
5871
                /* xfs_fsize_t last_byte = xfs_file_last_byte(ip); */
5872
                error = xfs_flush_pages(ip, (xfs_off_t)0,
5873
                                               -1, 0, FI_REMAPF);
5874
        }
5875
 
5876
        ASSERT(whichfork == XFS_ATTR_FORK || ip->i_delayed_blks == 0);
5877
 
5878
        lock = xfs_ilock_map_shared(ip);
5879
 
5880
        /*
5881
         * Don't let nex be bigger than the number of extents
5882
         * we can have assuming alternating holes and real extents.
5883
         */
5884
        if (nex > XFS_IFORK_NEXTENTS(ip, whichfork) * 2 + 1)
5885
                nex = XFS_IFORK_NEXTENTS(ip, whichfork) * 2 + 1;
5886
 
5887
        bmapi_flags = XFS_BMAPI_AFLAG(whichfork) |
5888
                        ((sh_unwritten) ? 0 : XFS_BMAPI_IGSTATE);
5889
 
5890
        /*
5891
         * Allocate enough space to handle "subnex" maps at a time.
5892
         */
5893
        subnex = 16;
5894
        map = kmem_alloc(subnex * sizeof(*map), KM_SLEEP);
5895
 
5896
        bmv->bmv_entries = 0;
5897
 
5898
        if (XFS_IFORK_NEXTENTS(ip, whichfork) == 0) {
5899
                error = 0;
5900
                goto unlock_and_return;
5901
        }
5902
 
5903
        nexleft = nex;
5904
 
5905
        do {
5906
                nmap = (nexleft > subnex) ? subnex : nexleft;
5907
                error = xfs_bmapi(NULL, ip, XFS_BB_TO_FSBT(mp, bmv->bmv_offset),
5908
                                  XFS_BB_TO_FSB(mp, bmv->bmv_length),
5909
                                  bmapi_flags, NULL, 0, map, &nmap,
5910
                                  NULL, NULL);
5911
                if (error)
5912
                        goto unlock_and_return;
5913
                ASSERT(nmap <= subnex);
5914
 
5915
                for (i = 0; i < nmap && nexleft && bmv->bmv_length; i++) {
5916
                        nexleft--;
5917
                        oflags = (map[i].br_state == XFS_EXT_UNWRITTEN) ?
5918
                                        BMV_OF_PREALLOC : 0;
5919
                        out.bmv_offset = XFS_FSB_TO_BB(mp, map[i].br_startoff);
5920
                        out.bmv_length = XFS_FSB_TO_BB(mp, map[i].br_blockcount);
5921
                        ASSERT(map[i].br_startblock != DELAYSTARTBLOCK);
5922
                        if (map[i].br_startblock == HOLESTARTBLOCK &&
5923
                            whichfork == XFS_ATTR_FORK) {
5924
                                /* came to the end of attribute fork */
5925
                                goto unlock_and_return;
5926
                        } else {
5927
                                if (!xfs_getbmapx_fix_eof_hole(ip, &out,
5928
                                                        prealloced, bmvend,
5929
                                                        map[i].br_startblock)) {
5930
                                        goto unlock_and_return;
5931
                                }
5932
 
5933
                                /* return either getbmap/getbmapx structure. */
5934
                                if (interface & BMV_IF_EXTENDED) {
5935
                                        struct  getbmapx        outx;
5936
 
5937
                                        GETBMAP_CONVERT(out,outx);
5938
                                        outx.bmv_oflags = oflags;
5939
                                        outx.bmv_unused1 = outx.bmv_unused2 = 0;
5940
                                        if (copy_to_user(ap, &outx,
5941
                                                        sizeof(outx))) {
5942
                                                error = XFS_ERROR(EFAULT);
5943
                                                goto unlock_and_return;
5944
                                        }
5945
                                } else {
5946
                                        if (copy_to_user(ap, &out,
5947
                                                        sizeof(out))) {
5948
                                                error = XFS_ERROR(EFAULT);
5949
                                                goto unlock_and_return;
5950
                                        }
5951
                                }
5952
                                bmv->bmv_offset =
5953
                                        out.bmv_offset + out.bmv_length;
5954
                                bmv->bmv_length = MAX((__int64_t)0,
5955
                                        (__int64_t)(bmvend - bmv->bmv_offset));
5956
                                bmv->bmv_entries++;
5957
                                ap = (interface & BMV_IF_EXTENDED) ?
5958
                                                (void __user *)
5959
                                        ((struct getbmapx __user *)ap + 1) :
5960
                                                (void __user *)
5961
                                        ((struct getbmap __user *)ap + 1);
5962
                        }
5963
                }
5964
        } while (nmap && nexleft && bmv->bmv_length);
5965
 
5966
unlock_and_return:
5967
        xfs_iunlock_map_shared(ip, lock);
5968
        xfs_iunlock(ip, XFS_IOLOCK_SHARED);
5969
 
5970
        kmem_free(map, subnex * sizeof(*map));
5971
 
5972
        return error;
5973
}
5974
 
5975
/*
5976
 * Check the last inode extent to determine whether this allocation will result
5977
 * in blocks being allocated at the end of the file. When we allocate new data
5978
 * blocks at the end of the file which do not start at the previous data block,
5979
 * we will try to align the new blocks at stripe unit boundaries.
5980
 */
5981
STATIC int                              /* error */
5982
xfs_bmap_isaeof(
5983
        xfs_inode_t     *ip,            /* incore inode pointer */
5984
        xfs_fileoff_t   off,            /* file offset in fsblocks */
5985
        int             whichfork,      /* data or attribute fork */
5986
        char            *aeof)          /* return value */
5987
{
5988
        int             error;          /* error return value */
5989
        xfs_ifork_t     *ifp;           /* inode fork pointer */
5990
        xfs_bmbt_rec_host_t *lastrec;   /* extent record pointer */
5991
        xfs_extnum_t    nextents;       /* number of file extents */
5992
        xfs_bmbt_irec_t s;              /* expanded extent record */
5993
 
5994
        ASSERT(whichfork == XFS_DATA_FORK);
5995
        ifp = XFS_IFORK_PTR(ip, whichfork);
5996
        if (!(ifp->if_flags & XFS_IFEXTENTS) &&
5997
            (error = xfs_iread_extents(NULL, ip, whichfork)))
5998
                return error;
5999
        nextents = ifp->if_bytes / (uint)sizeof(xfs_bmbt_rec_t);
6000
        if (nextents == 0) {
6001
                *aeof = 1;
6002
                return 0;
6003
        }
6004
        /*
6005
         * Go to the last extent
6006
         */
6007
        lastrec = xfs_iext_get_ext(ifp, nextents - 1);
6008
        xfs_bmbt_get_all(lastrec, &s);
6009
        /*
6010
         * Check we are allocating in the last extent (for delayed allocations)
6011
         * or past the last extent for non-delayed allocations.
6012
         */
6013
        *aeof = (off >= s.br_startoff &&
6014
                 off < s.br_startoff + s.br_blockcount &&
6015
                 ISNULLSTARTBLOCK(s.br_startblock)) ||
6016
                off >= s.br_startoff + s.br_blockcount;
6017
        return 0;
6018
}
6019
 
6020
/*
6021
 * Check if the endoff is outside the last extent. If so the caller will grow
6022
 * the allocation to a stripe unit boundary.
6023
 */
6024
int                                     /* error */
6025
xfs_bmap_eof(
6026
        xfs_inode_t     *ip,            /* incore inode pointer */
6027
        xfs_fileoff_t   endoff,         /* file offset in fsblocks */
6028
        int             whichfork,      /* data or attribute fork */
6029
        int             *eof)           /* result value */
6030
{
6031
        xfs_fsblock_t   blockcount;     /* extent block count */
6032
        int             error;          /* error return value */
6033
        xfs_ifork_t     *ifp;           /* inode fork pointer */
6034
        xfs_bmbt_rec_host_t *lastrec;   /* extent record pointer */
6035
        xfs_extnum_t    nextents;       /* number of file extents */
6036
        xfs_fileoff_t   startoff;       /* extent starting file offset */
6037
 
6038
        ASSERT(whichfork == XFS_DATA_FORK);
6039
        ifp = XFS_IFORK_PTR(ip, whichfork);
6040
        if (!(ifp->if_flags & XFS_IFEXTENTS) &&
6041
            (error = xfs_iread_extents(NULL, ip, whichfork)))
6042
                return error;
6043
        nextents = ifp->if_bytes / (uint)sizeof(xfs_bmbt_rec_t);
6044
        if (nextents == 0) {
6045
                *eof = 1;
6046
                return 0;
6047
        }
6048
        /*
6049
         * Go to the last extent
6050
         */
6051
        lastrec = xfs_iext_get_ext(ifp, nextents - 1);
6052
        startoff = xfs_bmbt_get_startoff(lastrec);
6053
        blockcount = xfs_bmbt_get_blockcount(lastrec);
6054
        *eof = endoff >= startoff + blockcount;
6055
        return 0;
6056
}
6057
 
6058
#ifdef DEBUG
6059
STATIC
6060
xfs_buf_t *
6061
xfs_bmap_get_bp(
6062
        xfs_btree_cur_t         *cur,
6063
        xfs_fsblock_t           bno)
6064
{
6065
        int i;
6066
        xfs_buf_t *bp;
6067
 
6068
        if (!cur)
6069
                return(NULL);
6070
 
6071
        bp = NULL;
6072
        for(i = 0; i < XFS_BTREE_MAXLEVELS; i++) {
6073
                bp = cur->bc_bufs[i];
6074
                if (!bp) break;
6075
                if (XFS_BUF_ADDR(bp) == bno)
6076
                        break;  /* Found it */
6077
        }
6078
        if (i == XFS_BTREE_MAXLEVELS)
6079
                bp = NULL;
6080
 
6081
        if (!bp) { /* Chase down all the log items to see if the bp is there */
6082
                xfs_log_item_chunk_t    *licp;
6083
                xfs_trans_t             *tp;
6084
 
6085
                tp = cur->bc_tp;
6086
                licp = &tp->t_items;
6087
                while (!bp && licp != NULL) {
6088
                        if (XFS_LIC_ARE_ALL_FREE(licp)) {
6089
                                licp = licp->lic_next;
6090
                                continue;
6091
                        }
6092
                        for (i = 0; i < licp->lic_unused; i++) {
6093
                                xfs_log_item_desc_t     *lidp;
6094
                                xfs_log_item_t          *lip;
6095
                                xfs_buf_log_item_t      *bip;
6096
                                xfs_buf_t               *lbp;
6097
 
6098
                                if (XFS_LIC_ISFREE(licp, i)) {
6099
                                        continue;
6100
                                }
6101
 
6102
                                lidp = XFS_LIC_SLOT(licp, i);
6103
                                lip = lidp->lid_item;
6104
                                if (lip->li_type != XFS_LI_BUF)
6105
                                        continue;
6106
 
6107
                                bip = (xfs_buf_log_item_t *)lip;
6108
                                lbp = bip->bli_buf;
6109
 
6110
                                if (XFS_BUF_ADDR(lbp) == bno) {
6111
                                        bp = lbp;
6112
                                        break; /* Found it */
6113
                                }
6114
                        }
6115
                        licp = licp->lic_next;
6116
                }
6117
        }
6118
        return(bp);
6119
}
6120
 
6121
void
6122
xfs_check_block(
6123
        xfs_bmbt_block_t        *block,
6124
        xfs_mount_t             *mp,
6125
        int                     root,
6126
        short                   sz)
6127
{
6128
        int                     i, j, dmxr;
6129
        __be64                  *pp, *thispa;   /* pointer to block address */
6130
        xfs_bmbt_key_t          *prevp, *keyp;
6131
 
6132
        ASSERT(be16_to_cpu(block->bb_level) > 0);
6133
 
6134
        prevp = NULL;
6135
        for( i = 1; i <= be16_to_cpu(block->bb_numrecs); i++) {
6136
                dmxr = mp->m_bmap_dmxr[0];
6137
 
6138
                if (root) {
6139
                        keyp = XFS_BMAP_BROOT_KEY_ADDR(block, i, sz);
6140
                } else {
6141
                        keyp = XFS_BTREE_KEY_ADDR(xfs_bmbt, block, i);
6142
                }
6143
 
6144
                if (prevp) {
6145
                        xfs_btree_check_key(XFS_BTNUM_BMAP, prevp, keyp);
6146
                }
6147
                prevp = keyp;
6148
 
6149
                /*
6150
                 * Compare the block numbers to see if there are dups.
6151
                 */
6152
 
6153
                if (root) {
6154
                        pp = XFS_BMAP_BROOT_PTR_ADDR(block, i, sz);
6155
                } else {
6156
                        pp = XFS_BTREE_PTR_ADDR(xfs_bmbt, block, i, dmxr);
6157
                }
6158
                for (j = i+1; j <= be16_to_cpu(block->bb_numrecs); j++) {
6159
                        if (root) {
6160
                                thispa = XFS_BMAP_BROOT_PTR_ADDR(block, j, sz);
6161
                        } else {
6162
                                thispa = XFS_BTREE_PTR_ADDR(xfs_bmbt, block, j,
6163
                                                            dmxr);
6164
                        }
6165
                        if (*thispa == *pp) {
6166
                                cmn_err(CE_WARN, "%s: thispa(%d) == pp(%d) %Ld",
6167
                                        __FUNCTION__, j, i,
6168
                                        (unsigned long long)be64_to_cpu(*thispa));
6169
                                panic("%s: ptrs are equal in node\n",
6170
                                        __FUNCTION__);
6171
                        }
6172
                }
6173
        }
6174
}
6175
 
6176
/*
6177
 * Check that the extents for the inode ip are in the right order in all
6178
 * btree leaves.
6179
 */
6180
 
6181
STATIC void
6182
xfs_bmap_check_leaf_extents(
6183
        xfs_btree_cur_t         *cur,   /* btree cursor or null */
6184
        xfs_inode_t             *ip,            /* incore inode pointer */
6185
        int                     whichfork)      /* data or attr fork */
6186
{
6187
        xfs_bmbt_block_t        *block; /* current btree block */
6188
        xfs_fsblock_t           bno;    /* block # of "block" */
6189
        xfs_buf_t               *bp;    /* buffer for "block" */
6190
        int                     error;  /* error return value */
6191
        xfs_extnum_t            i=0, j;  /* index into the extents list */
6192
        xfs_ifork_t             *ifp;   /* fork structure */
6193
        int                     level;  /* btree level, for checking */
6194
        xfs_mount_t             *mp;    /* file system mount structure */
6195
        __be64                  *pp;    /* pointer to block address */
6196
        xfs_bmbt_rec_t          *ep;    /* pointer to current extent */
6197
        xfs_bmbt_rec_t          *lastp; /* pointer to previous extent */
6198
        xfs_bmbt_rec_t          *nextp; /* pointer to next extent */
6199
        int                     bp_release = 0;
6200
 
6201
        if (XFS_IFORK_FORMAT(ip, whichfork) != XFS_DINODE_FMT_BTREE) {
6202
                return;
6203
        }
6204
 
6205
        bno = NULLFSBLOCK;
6206
        mp = ip->i_mount;
6207
        ifp = XFS_IFORK_PTR(ip, whichfork);
6208
        block = ifp->if_broot;
6209
        /*
6210
         * Root level must use BMAP_BROOT_PTR_ADDR macro to get ptr out.
6211
         */
6212
        level = be16_to_cpu(block->bb_level);
6213
        ASSERT(level > 0);
6214
        xfs_check_block(block, mp, 1, ifp->if_broot_bytes);
6215
        pp = XFS_BMAP_BROOT_PTR_ADDR(block, 1, ifp->if_broot_bytes);
6216
        bno = be64_to_cpu(*pp);
6217
 
6218
        ASSERT(bno != NULLDFSBNO);
6219
        ASSERT(XFS_FSB_TO_AGNO(mp, bno) < mp->m_sb.sb_agcount);
6220
        ASSERT(XFS_FSB_TO_AGBNO(mp, bno) < mp->m_sb.sb_agblocks);
6221
 
6222
        /*
6223
         * Go down the tree until leaf level is reached, following the first
6224
         * pointer (leftmost) at each level.
6225
         */
6226
        while (level-- > 0) {
6227
                /* See if buf is in cur first */
6228
                bp = xfs_bmap_get_bp(cur, XFS_FSB_TO_DADDR(mp, bno));
6229
                if (bp) {
6230
                        bp_release = 0;
6231
                } else {
6232
                        bp_release = 1;
6233
                }
6234
                if (!bp && (error = xfs_btree_read_bufl(mp, NULL, bno, 0, &bp,
6235
                                XFS_BMAP_BTREE_REF)))
6236
                        goto error_norelse;
6237
                block = XFS_BUF_TO_BMBT_BLOCK(bp);
6238
                XFS_WANT_CORRUPTED_GOTO(
6239
                        XFS_BMAP_SANITY_CHECK(mp, block, level),
6240
                        error0);
6241
                if (level == 0)
6242
                        break;
6243
 
6244
                /*
6245
                 * Check this block for basic sanity (increasing keys and
6246
                 * no duplicate blocks).
6247
                 */
6248
 
6249
                xfs_check_block(block, mp, 0, 0);
6250
                pp = XFS_BTREE_PTR_ADDR(xfs_bmbt, block, 1, mp->m_bmap_dmxr[1]);
6251
                bno = be64_to_cpu(*pp);
6252
                XFS_WANT_CORRUPTED_GOTO(XFS_FSB_SANITY_CHECK(mp, bno), error0);
6253
                if (bp_release) {
6254
                        bp_release = 0;
6255
                        xfs_trans_brelse(NULL, bp);
6256
                }
6257
        }
6258
 
6259
        /*
6260
         * Here with bp and block set to the leftmost leaf node in the tree.
6261
         */
6262
        i = 0;
6263
 
6264
        /*
6265
         * Loop over all leaf nodes checking that all extents are in the right order.
6266
         */
6267
        lastp = NULL;
6268
        for (;;) {
6269
                xfs_fsblock_t   nextbno;
6270
                xfs_extnum_t    num_recs;
6271
 
6272
 
6273
                num_recs = be16_to_cpu(block->bb_numrecs);
6274
 
6275
                /*
6276
                 * Read-ahead the next leaf block, if any.
6277
                 */
6278
 
6279
                nextbno = be64_to_cpu(block->bb_rightsib);
6280
 
6281
                /*
6282
                 * Check all the extents to make sure they are OK.
6283
                 * If we had a previous block, the last entry should
6284
                 * conform with the first entry in this one.
6285
                 */
6286
 
6287
                ep = XFS_BTREE_REC_ADDR(xfs_bmbt, block, 1);
6288
                for (j = 1; j < num_recs; j++) {
6289
                        nextp = XFS_BTREE_REC_ADDR(xfs_bmbt, block, j + 1);
6290
                        if (lastp) {
6291
                                xfs_btree_check_rec(XFS_BTNUM_BMAP,
6292
                                        (void *)lastp, (void *)ep);
6293
                        }
6294
                        xfs_btree_check_rec(XFS_BTNUM_BMAP, (void *)ep,
6295
                                (void *)(nextp));
6296
                        lastp = ep;
6297
                        ep = nextp;
6298
                }
6299
 
6300
                i += num_recs;
6301
                if (bp_release) {
6302
                        bp_release = 0;
6303
                        xfs_trans_brelse(NULL, bp);
6304
                }
6305
                bno = nextbno;
6306
                /*
6307
                 * If we've reached the end, stop.
6308
                 */
6309
                if (bno == NULLFSBLOCK)
6310
                        break;
6311
 
6312
                bp = xfs_bmap_get_bp(cur, XFS_FSB_TO_DADDR(mp, bno));
6313
                if (bp) {
6314
                        bp_release = 0;
6315
                } else {
6316
                        bp_release = 1;
6317
                }
6318
                if (!bp && (error = xfs_btree_read_bufl(mp, NULL, bno, 0, &bp,
6319
                                XFS_BMAP_BTREE_REF)))
6320
                        goto error_norelse;
6321
                block = XFS_BUF_TO_BMBT_BLOCK(bp);
6322
        }
6323
        if (bp_release) {
6324
                bp_release = 0;
6325
                xfs_trans_brelse(NULL, bp);
6326
        }
6327
        return;
6328
 
6329
error0:
6330
        cmn_err(CE_WARN, "%s: at error0", __FUNCTION__);
6331
        if (bp_release)
6332
                xfs_trans_brelse(NULL, bp);
6333
error_norelse:
6334
        cmn_err(CE_WARN, "%s: BAD after btree leaves for %d extents",
6335
                __FUNCTION__, i);
6336
        panic("%s: CORRUPTED BTREE OR SOMETHING", __FUNCTION__);
6337
        return;
6338
}
6339
#endif
6340
 
6341
/*
6342
 * Count fsblocks of the given fork.
6343
 */
6344
int                                             /* error */
6345
xfs_bmap_count_blocks(
6346
        xfs_trans_t             *tp,            /* transaction pointer */
6347
        xfs_inode_t             *ip,            /* incore inode */
6348
        int                     whichfork,      /* data or attr fork */
6349
        int                     *count)         /* out: count of blocks */
6350
{
6351
        xfs_bmbt_block_t        *block; /* current btree block */
6352
        xfs_fsblock_t           bno;    /* block # of "block" */
6353
        xfs_ifork_t             *ifp;   /* fork structure */
6354
        int                     level;  /* btree level, for checking */
6355
        xfs_mount_t             *mp;    /* file system mount structure */
6356
        __be64                  *pp;    /* pointer to block address */
6357
 
6358
        bno = NULLFSBLOCK;
6359
        mp = ip->i_mount;
6360
        ifp = XFS_IFORK_PTR(ip, whichfork);
6361
        if ( XFS_IFORK_FORMAT(ip, whichfork) == XFS_DINODE_FMT_EXTENTS ) {
6362
                if (unlikely(xfs_bmap_count_leaves(ifp, 0,
6363
                        ifp->if_bytes / (uint)sizeof(xfs_bmbt_rec_t),
6364
                        count) < 0)) {
6365
                        XFS_ERROR_REPORT("xfs_bmap_count_blocks(1)",
6366
                                         XFS_ERRLEVEL_LOW, mp);
6367
                        return XFS_ERROR(EFSCORRUPTED);
6368
                }
6369
                return 0;
6370
        }
6371
 
6372
        /*
6373
         * Root level must use BMAP_BROOT_PTR_ADDR macro to get ptr out.
6374
         */
6375
        block = ifp->if_broot;
6376
        level = be16_to_cpu(block->bb_level);
6377
        ASSERT(level > 0);
6378
        pp = XFS_BMAP_BROOT_PTR_ADDR(block, 1, ifp->if_broot_bytes);
6379
        bno = be64_to_cpu(*pp);
6380
        ASSERT(bno != NULLDFSBNO);
6381
        ASSERT(XFS_FSB_TO_AGNO(mp, bno) < mp->m_sb.sb_agcount);
6382
        ASSERT(XFS_FSB_TO_AGBNO(mp, bno) < mp->m_sb.sb_agblocks);
6383
 
6384
        if (unlikely(xfs_bmap_count_tree(mp, tp, ifp, bno, level, count) < 0)) {
6385
                XFS_ERROR_REPORT("xfs_bmap_count_blocks(2)", XFS_ERRLEVEL_LOW,
6386
                                 mp);
6387
                return XFS_ERROR(EFSCORRUPTED);
6388
        }
6389
 
6390
        return 0;
6391
}
6392
 
6393
/*
6394
 * Recursively walks each level of a btree
6395
 * to count total fsblocks is use.
6396
 */
6397
int                                     /* error */
6398
xfs_bmap_count_tree(
6399
        xfs_mount_t     *mp,            /* file system mount point */
6400
        xfs_trans_t     *tp,            /* transaction pointer */
6401
        xfs_ifork_t     *ifp,           /* inode fork pointer */
6402
        xfs_fsblock_t   blockno,        /* file system block number */
6403
        int             levelin,        /* level in btree */
6404
        int             *count)         /* Count of blocks */
6405
{
6406
        int                     error;
6407
        xfs_buf_t               *bp, *nbp;
6408
        int                     level = levelin;
6409
        __be64                  *pp;
6410
        xfs_fsblock_t           bno = blockno;
6411
        xfs_fsblock_t           nextbno;
6412
        xfs_bmbt_block_t        *block, *nextblock;
6413
        int                     numrecs;
6414
 
6415
        if ((error = xfs_btree_read_bufl(mp, tp, bno, 0, &bp, XFS_BMAP_BTREE_REF)))
6416
                return error;
6417
        *count += 1;
6418
        block = XFS_BUF_TO_BMBT_BLOCK(bp);
6419
 
6420
        if (--level) {
6421
                /* Not at node above leafs, count this level of nodes */
6422
                nextbno = be64_to_cpu(block->bb_rightsib);
6423
                while (nextbno != NULLFSBLOCK) {
6424
                        if ((error = xfs_btree_read_bufl(mp, tp, nextbno,
6425
                                0, &nbp, XFS_BMAP_BTREE_REF)))
6426
                                return error;
6427
                        *count += 1;
6428
                        nextblock = XFS_BUF_TO_BMBT_BLOCK(nbp);
6429
                        nextbno = be64_to_cpu(nextblock->bb_rightsib);
6430
                        xfs_trans_brelse(tp, nbp);
6431
                }
6432
 
6433
                /* Dive to the next level */
6434
                pp = XFS_BTREE_PTR_ADDR(xfs_bmbt, block, 1, mp->m_bmap_dmxr[1]);
6435
                bno = be64_to_cpu(*pp);
6436
                if (unlikely((error =
6437
                     xfs_bmap_count_tree(mp, tp, ifp, bno, level, count)) < 0)) {
6438
                        xfs_trans_brelse(tp, bp);
6439
                        XFS_ERROR_REPORT("xfs_bmap_count_tree(1)",
6440
                                         XFS_ERRLEVEL_LOW, mp);
6441
                        return XFS_ERROR(EFSCORRUPTED);
6442
                }
6443
                xfs_trans_brelse(tp, bp);
6444
        } else {
6445
                /* count all level 1 nodes and their leaves */
6446
                for (;;) {
6447
                        nextbno = be64_to_cpu(block->bb_rightsib);
6448
                        numrecs = be16_to_cpu(block->bb_numrecs);
6449
                        if (unlikely(xfs_bmap_disk_count_leaves(0,
6450
                                        block, numrecs, count) < 0)) {
6451
                                xfs_trans_brelse(tp, bp);
6452
                                XFS_ERROR_REPORT("xfs_bmap_count_tree(2)",
6453
                                                 XFS_ERRLEVEL_LOW, mp);
6454
                                return XFS_ERROR(EFSCORRUPTED);
6455
                        }
6456
                        xfs_trans_brelse(tp, bp);
6457
                        if (nextbno == NULLFSBLOCK)
6458
                                break;
6459
                        bno = nextbno;
6460
                        if ((error = xfs_btree_read_bufl(mp, tp, bno, 0, &bp,
6461
                                XFS_BMAP_BTREE_REF)))
6462
                                return error;
6463
                        *count += 1;
6464
                        block = XFS_BUF_TO_BMBT_BLOCK(bp);
6465
                }
6466
        }
6467
        return 0;
6468
}
6469
 
6470
/*
6471
 * Count leaf blocks given a range of extent records.
6472
 */
6473
int
6474
xfs_bmap_count_leaves(
6475
        xfs_ifork_t             *ifp,
6476
        xfs_extnum_t            idx,
6477
        int                     numrecs,
6478
        int                     *count)
6479
{
6480
        int             b;
6481
 
6482
        for (b = 0; b < numrecs; b++) {
6483
                xfs_bmbt_rec_host_t *frp = xfs_iext_get_ext(ifp, idx + b);
6484
                *count += xfs_bmbt_get_blockcount(frp);
6485
        }
6486
        return 0;
6487
}
6488
 
6489
/*
6490
 * Count leaf blocks given a range of extent records originally
6491
 * in btree format.
6492
 */
6493
int
6494
xfs_bmap_disk_count_leaves(
6495
        xfs_extnum_t            idx,
6496
        xfs_bmbt_block_t        *block,
6497
        int                     numrecs,
6498
        int                     *count)
6499
{
6500
        int             b;
6501
        xfs_bmbt_rec_t  *frp;
6502
 
6503
        for (b = 1; b <= numrecs; b++) {
6504
                frp = XFS_BTREE_REC_ADDR(xfs_bmbt, block, idx + b);
6505
                *count += xfs_bmbt_disk_get_blockcount(frp);
6506
        }
6507
        return 0;
6508
}

powered by: WebSVN 2.1.0

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