blob: 5b8030561d78385e8385953b52952be29916f622 [file] [log] [blame]
Linus Torvalds1da177e2005-04-16 15:20:36 -07001/*
Nathan Scott7b718762005-11-02 14:58:39 +11002 * Copyright (c) 2000-2003,2005 Silicon Graphics, Inc.
3 * All Rights Reserved.
Linus Torvalds1da177e2005-04-16 15:20:36 -07004 *
Nathan Scott7b718762005-11-02 14:58:39 +11005 * This program is free software; you can redistribute it and/or
6 * modify it under the terms of the GNU General Public License as
Linus Torvalds1da177e2005-04-16 15:20:36 -07007 * published by the Free Software Foundation.
8 *
Nathan Scott7b718762005-11-02 14:58:39 +11009 * 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.
Linus Torvalds1da177e2005-04-16 15:20:36 -070013 *
Nathan Scott7b718762005-11-02 14:58:39 +110014 * 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
Linus Torvalds1da177e2005-04-16 15:20:36 -070017 */
Linus Torvalds1da177e2005-04-16 15:20:36 -070018#include "xfs.h"
Nathan Scotta844f452005-11-02 14:38:42 +110019#include "xfs_fs.h"
Linus Torvalds1da177e2005-04-16 15:20:36 -070020#include "xfs_types.h"
Nathan Scotta844f452005-11-02 14:38:42 +110021#include "xfs_bit.h"
Linus Torvalds1da177e2005-04-16 15:20:36 -070022#include "xfs_log.h"
Nathan Scotta844f452005-11-02 14:38:42 +110023#include "xfs_inum.h"
Linus Torvalds1da177e2005-04-16 15:20:36 -070024#include "xfs_trans.h"
25#include "xfs_sb.h"
26#include "xfs_ag.h"
Linus Torvalds1da177e2005-04-16 15:20:36 -070027#include "xfs_dir2.h"
28#include "xfs_dmapi.h"
29#include "xfs_mount.h"
Linus Torvalds1da177e2005-04-16 15:20:36 -070030#include "xfs_bmap_btree.h"
Nathan Scotta844f452005-11-02 14:38:42 +110031#include "xfs_alloc_btree.h"
Linus Torvalds1da177e2005-04-16 15:20:36 -070032#include "xfs_ialloc_btree.h"
Nathan Scotta844f452005-11-02 14:38:42 +110033#include "xfs_dir2_sf.h"
34#include "xfs_attr_sf.h"
35#include "xfs_dinode.h"
36#include "xfs_inode.h"
37#include "xfs_inode_item.h"
38#include "xfs_alloc.h"
Linus Torvalds1da177e2005-04-16 15:20:36 -070039#include "xfs_btree.h"
Christoph Hellwig8c4ed632008-10-30 16:55:13 +110040#include "xfs_btree_trace.h"
Linus Torvalds1da177e2005-04-16 15:20:36 -070041#include "xfs_ialloc.h"
42#include "xfs_itable.h"
Linus Torvalds1da177e2005-04-16 15:20:36 -070043#include "xfs_bmap.h"
44#include "xfs_error.h"
45#include "xfs_quota.h"
46
Linus Torvalds1da177e2005-04-16 15:20:36 -070047#undef EXIT
Christoph Hellwig8c4ed632008-10-30 16:55:13 +110048
49#define ENTRY XBT_ENTRY
50#define ERROR XBT_ERROR
51#define EXIT XBT_EXIT
Linus Torvalds1da177e2005-04-16 15:20:36 -070052
53/*
Christoph Hellwig8c4ed632008-10-30 16:55:13 +110054 * Keep the XFS_BMBT_TRACE_ names around for now until all code using them
55 * is converted to be generic and thus switches to the XFS_BTREE_TRACE_ names.
Linus Torvalds1da177e2005-04-16 15:20:36 -070056 */
Christoph Hellwig8c4ed632008-10-30 16:55:13 +110057#define XFS_BMBT_TRACE_ARGBI(c,b,i) \
58 XFS_BTREE_TRACE_ARGBI(c,b,i)
59#define XFS_BMBT_TRACE_ARGBII(c,b,i,j) \
60 XFS_BTREE_TRACE_ARGBII(c,b,i,j)
61#define XFS_BMBT_TRACE_ARGFFFI(c,o,b,i,j) \
62 XFS_BTREE_TRACE_ARGFFFI(c,o,b,i,j)
63#define XFS_BMBT_TRACE_ARGI(c,i) \
64 XFS_BTREE_TRACE_ARGI(c,i)
65#define XFS_BMBT_TRACE_ARGIFK(c,i,f,s) \
66 XFS_BTREE_TRACE_ARGIPK(c,i,(union xfs_btree_ptr)f,s)
67#define XFS_BMBT_TRACE_ARGIFR(c,i,f,r) \
68 XFS_BTREE_TRACE_ARGIPR(c,i, \
69 (union xfs_btree_ptr)f, (union xfs_btree_rec *)r)
70#define XFS_BMBT_TRACE_ARGIK(c,i,k) \
71 XFS_BTREE_TRACE_ARGIK(c,i,(union xfs_btree_key *)k)
72#define XFS_BMBT_TRACE_CURSOR(c,s) \
73 XFS_BTREE_TRACE_CURSOR(c,s)
Linus Torvalds1da177e2005-04-16 15:20:36 -070074
Linus Torvalds1da177e2005-04-16 15:20:36 -070075/*
Linus Torvalds1da177e2005-04-16 15:20:36 -070076 * Determine the extent state.
77 */
78/* ARGSUSED */
79STATIC xfs_exntst_t
80xfs_extent_state(
81 xfs_filblks_t blks,
82 int extent_flag)
83{
84 if (extent_flag) {
85 ASSERT(blks != 0); /* saved for DMIG */
86 return XFS_EXT_UNWRITTEN;
87 }
88 return XFS_EXT_NORM;
89}
90
Linus Torvalds1da177e2005-04-16 15:20:36 -070091/*
92 * Convert on-disk form of btree root to in-memory form.
93 */
94void
95xfs_bmdr_to_bmbt(
96 xfs_bmdr_block_t *dblock,
97 int dblocklen,
98 xfs_bmbt_block_t *rblock,
99 int rblocklen)
100{
101 int dmxr;
102 xfs_bmbt_key_t *fkp;
Christoph Hellwig576039c2006-09-28 10:58:06 +1000103 __be64 *fpp;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700104 xfs_bmbt_key_t *tkp;
Christoph Hellwig576039c2006-09-28 10:58:06 +1000105 __be64 *tpp;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700106
Christoph Hellwig16259e72005-11-02 15:11:25 +1100107 rblock->bb_magic = cpu_to_be32(XFS_BMAP_MAGIC);
108 rblock->bb_level = dblock->bb_level;
109 ASSERT(be16_to_cpu(rblock->bb_level) > 0);
110 rblock->bb_numrecs = dblock->bb_numrecs;
111 rblock->bb_leftsib = cpu_to_be64(NULLDFSBNO);
112 rblock->bb_rightsib = cpu_to_be64(NULLDFSBNO);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700113 dmxr = (int)XFS_BTREE_BLOCK_MAXRECS(dblocklen, xfs_bmdr, 0);
Eric Sandeen2c36dde2007-02-10 18:37:33 +1100114 fkp = XFS_BTREE_KEY_ADDR(xfs_bmdr, dblock, 1);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700115 tkp = XFS_BMAP_BROOT_KEY_ADDR(rblock, 1, rblocklen);
Eric Sandeen2c36dde2007-02-10 18:37:33 +1100116 fpp = XFS_BTREE_PTR_ADDR(xfs_bmdr, dblock, 1, dmxr);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700117 tpp = XFS_BMAP_BROOT_PTR_ADDR(rblock, 1, rblocklen);
Christoph Hellwig16259e72005-11-02 15:11:25 +1100118 dmxr = be16_to_cpu(dblock->bb_numrecs);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700119 memcpy(tkp, fkp, sizeof(*fkp) * dmxr);
Christoph Hellwig576039c2006-09-28 10:58:06 +1000120 memcpy(tpp, fpp, sizeof(*fpp) * dmxr);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700121}
122
123/*
Linus Torvalds1da177e2005-04-16 15:20:36 -0700124 * Convert a compressed bmap extent record to an uncompressed form.
125 * This code must be in sync with the routines xfs_bmbt_get_startoff,
126 * xfs_bmbt_get_startblock, xfs_bmbt_get_blockcount and xfs_bmbt_get_state.
127 */
128
David Chinner7989cb82007-02-10 18:34:56 +1100129STATIC_INLINE void
Linus Torvalds1da177e2005-04-16 15:20:36 -0700130__xfs_bmbt_get_all(
131 __uint64_t l0,
132 __uint64_t l1,
133 xfs_bmbt_irec_t *s)
134{
135 int ext_flag;
136 xfs_exntst_t st;
137
138 ext_flag = (int)(l0 >> (64 - BMBT_EXNTFLAG_BITLEN));
139 s->br_startoff = ((xfs_fileoff_t)l0 &
140 XFS_MASK64LO(64 - BMBT_EXNTFLAG_BITLEN)) >> 9;
141#if XFS_BIG_BLKNOS
142 s->br_startblock = (((xfs_fsblock_t)l0 & XFS_MASK64LO(9)) << 43) |
143 (((xfs_fsblock_t)l1) >> 21);
144#else
145#ifdef DEBUG
146 {
147 xfs_dfsbno_t b;
148
149 b = (((xfs_dfsbno_t)l0 & XFS_MASK64LO(9)) << 43) |
150 (((xfs_dfsbno_t)l1) >> 21);
151 ASSERT((b >> 32) == 0 || ISNULLDSTARTBLOCK(b));
152 s->br_startblock = (xfs_fsblock_t)b;
153 }
154#else /* !DEBUG */
155 s->br_startblock = (xfs_fsblock_t)(((xfs_dfsbno_t)l1) >> 21);
156#endif /* DEBUG */
157#endif /* XFS_BIG_BLKNOS */
158 s->br_blockcount = (xfs_filblks_t)(l1 & XFS_MASK64LO(21));
159 /* This is xfs_extent_state() in-line */
160 if (ext_flag) {
161 ASSERT(s->br_blockcount != 0); /* saved for DMIG */
162 st = XFS_EXT_UNWRITTEN;
163 } else
164 st = XFS_EXT_NORM;
165 s->br_state = st;
166}
167
168void
169xfs_bmbt_get_all(
Christoph Hellwiga6f64d42007-08-16 16:23:40 +1000170 xfs_bmbt_rec_host_t *r,
Linus Torvalds1da177e2005-04-16 15:20:36 -0700171 xfs_bmbt_irec_t *s)
172{
173 __xfs_bmbt_get_all(r->l0, r->l1, s);
174}
175
176/*
Linus Torvalds1da177e2005-04-16 15:20:36 -0700177 * Extract the blockcount field from an in memory bmap extent record.
178 */
179xfs_filblks_t
180xfs_bmbt_get_blockcount(
Christoph Hellwiga6f64d42007-08-16 16:23:40 +1000181 xfs_bmbt_rec_host_t *r)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700182{
183 return (xfs_filblks_t)(r->l1 & XFS_MASK64LO(21));
184}
185
186/*
187 * Extract the startblock field from an in memory bmap extent record.
188 */
189xfs_fsblock_t
190xfs_bmbt_get_startblock(
Christoph Hellwiga6f64d42007-08-16 16:23:40 +1000191 xfs_bmbt_rec_host_t *r)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700192{
193#if XFS_BIG_BLKNOS
194 return (((xfs_fsblock_t)r->l0 & XFS_MASK64LO(9)) << 43) |
195 (((xfs_fsblock_t)r->l1) >> 21);
196#else
197#ifdef DEBUG
198 xfs_dfsbno_t b;
199
200 b = (((xfs_dfsbno_t)r->l0 & XFS_MASK64LO(9)) << 43) |
201 (((xfs_dfsbno_t)r->l1) >> 21);
202 ASSERT((b >> 32) == 0 || ISNULLDSTARTBLOCK(b));
203 return (xfs_fsblock_t)b;
204#else /* !DEBUG */
205 return (xfs_fsblock_t)(((xfs_dfsbno_t)r->l1) >> 21);
206#endif /* DEBUG */
207#endif /* XFS_BIG_BLKNOS */
208}
209
210/*
211 * Extract the startoff field from an in memory bmap extent record.
212 */
213xfs_fileoff_t
214xfs_bmbt_get_startoff(
Christoph Hellwiga6f64d42007-08-16 16:23:40 +1000215 xfs_bmbt_rec_host_t *r)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700216{
217 return ((xfs_fileoff_t)r->l0 &
218 XFS_MASK64LO(64 - BMBT_EXNTFLAG_BITLEN)) >> 9;
219}
220
221xfs_exntst_t
222xfs_bmbt_get_state(
Christoph Hellwiga6f64d42007-08-16 16:23:40 +1000223 xfs_bmbt_rec_host_t *r)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700224{
225 int ext_flag;
226
227 ext_flag = (int)((r->l0) >> (64 - BMBT_EXNTFLAG_BITLEN));
228 return xfs_extent_state(xfs_bmbt_get_blockcount(r),
229 ext_flag);
230}
231
Linus Torvalds1da177e2005-04-16 15:20:36 -0700232/* Endian flipping versions of the bmbt extraction functions */
233void
234xfs_bmbt_disk_get_all(
235 xfs_bmbt_rec_t *r,
236 xfs_bmbt_irec_t *s)
237{
Christoph Hellwigcd8b0a92007-08-16 16:24:15 +1000238 __xfs_bmbt_get_all(be64_to_cpu(r->l0), be64_to_cpu(r->l1), s);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700239}
240
241/*
242 * Extract the blockcount field from an on disk bmap extent record.
243 */
244xfs_filblks_t
245xfs_bmbt_disk_get_blockcount(
246 xfs_bmbt_rec_t *r)
247{
Christoph Hellwigcd8b0a92007-08-16 16:24:15 +1000248 return (xfs_filblks_t)(be64_to_cpu(r->l1) & XFS_MASK64LO(21));
Linus Torvalds1da177e2005-04-16 15:20:36 -0700249}
250
251/*
Linus Torvalds1da177e2005-04-16 15:20:36 -0700252 * Extract the startoff field from a disk format bmap extent record.
253 */
254xfs_fileoff_t
255xfs_bmbt_disk_get_startoff(
256 xfs_bmbt_rec_t *r)
257{
Christoph Hellwigcd8b0a92007-08-16 16:24:15 +1000258 return ((xfs_fileoff_t)be64_to_cpu(r->l0) &
Linus Torvalds1da177e2005-04-16 15:20:36 -0700259 XFS_MASK64LO(64 - BMBT_EXNTFLAG_BITLEN)) >> 9;
260}
Linus Torvalds1da177e2005-04-16 15:20:36 -0700261
262/*
Linus Torvalds1da177e2005-04-16 15:20:36 -0700263 * Log fields from the btree block header.
264 */
265void
266xfs_bmbt_log_block(
267 xfs_btree_cur_t *cur,
268 xfs_buf_t *bp,
269 int fields)
270{
271 int first;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700272 int last;
273 xfs_trans_t *tp;
274 static const short offsets[] = {
275 offsetof(xfs_bmbt_block_t, bb_magic),
276 offsetof(xfs_bmbt_block_t, bb_level),
277 offsetof(xfs_bmbt_block_t, bb_numrecs),
278 offsetof(xfs_bmbt_block_t, bb_leftsib),
279 offsetof(xfs_bmbt_block_t, bb_rightsib),
280 sizeof(xfs_bmbt_block_t)
281 };
282
283 XFS_BMBT_TRACE_CURSOR(cur, ENTRY);
284 XFS_BMBT_TRACE_ARGBI(cur, bp, fields);
285 tp = cur->bc_tp;
286 if (bp) {
287 xfs_btree_offsets(fields, offsets, XFS_BB_NUM_BITS, &first,
288 &last);
289 xfs_trans_log_buf(tp, bp, first, last);
290 } else
291 xfs_trans_log_inode(tp, cur->bc_private.b.ip,
292 XFS_ILOG_FBROOT(cur->bc_private.b.whichfork));
293 XFS_BMBT_TRACE_CURSOR(cur, EXIT);
294}
295
296/*
297 * Log record values from the btree block.
298 */
299void
300xfs_bmbt_log_recs(
301 xfs_btree_cur_t *cur,
302 xfs_buf_t *bp,
303 int rfirst,
304 int rlast)
305{
306 xfs_bmbt_block_t *block;
307 int first;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700308 int last;
309 xfs_bmbt_rec_t *rp;
310 xfs_trans_t *tp;
311
312 XFS_BMBT_TRACE_CURSOR(cur, ENTRY);
313 XFS_BMBT_TRACE_ARGBII(cur, bp, rfirst, rlast);
314 ASSERT(bp);
315 tp = cur->bc_tp;
316 block = XFS_BUF_TO_BMBT_BLOCK(bp);
317 rp = XFS_BMAP_REC_DADDR(block, 1, cur);
318 first = (int)((xfs_caddr_t)&rp[rfirst - 1] - (xfs_caddr_t)block);
319 last = (int)(((xfs_caddr_t)&rp[rlast] - 1) - (xfs_caddr_t)block);
320 xfs_trans_log_buf(tp, bp, first, last);
321 XFS_BMBT_TRACE_CURSOR(cur, EXIT);
322}
323
Linus Torvalds1da177e2005-04-16 15:20:36 -0700324/*
Christoph Hellwig8cba4342007-08-16 16:23:53 +1000325 * Set all the fields in a bmap extent record from the arguments.
326 */
327void
328xfs_bmbt_set_allf(
329 xfs_bmbt_rec_host_t *r,
330 xfs_fileoff_t startoff,
331 xfs_fsblock_t startblock,
332 xfs_filblks_t blockcount,
333 xfs_exntst_t state)
334{
335 int extent_flag = (state == XFS_EXT_NORM) ? 0 : 1;
336
337 ASSERT(state == XFS_EXT_NORM || state == XFS_EXT_UNWRITTEN);
338 ASSERT((startoff & XFS_MASK64HI(64-BMBT_STARTOFF_BITLEN)) == 0);
339 ASSERT((blockcount & XFS_MASK64HI(64-BMBT_BLOCKCOUNT_BITLEN)) == 0);
340
341#if XFS_BIG_BLKNOS
342 ASSERT((startblock & XFS_MASK64HI(64-BMBT_STARTBLOCK_BITLEN)) == 0);
343
344 r->l0 = ((xfs_bmbt_rec_base_t)extent_flag << 63) |
345 ((xfs_bmbt_rec_base_t)startoff << 9) |
346 ((xfs_bmbt_rec_base_t)startblock >> 43);
347 r->l1 = ((xfs_bmbt_rec_base_t)startblock << 21) |
348 ((xfs_bmbt_rec_base_t)blockcount &
349 (xfs_bmbt_rec_base_t)XFS_MASK64LO(21));
350#else /* !XFS_BIG_BLKNOS */
Michal Piotrowskiddc6d3b2007-08-23 16:20:10 +1000351 if (ISNULLSTARTBLOCK(startblock)) {
Christoph Hellwig8cba4342007-08-16 16:23:53 +1000352 r->l0 = ((xfs_bmbt_rec_base_t)extent_flag << 63) |
353 ((xfs_bmbt_rec_base_t)startoff << 9) |
354 (xfs_bmbt_rec_base_t)XFS_MASK64LO(9);
355 r->l1 = XFS_MASK64HI(11) |
356 ((xfs_bmbt_rec_base_t)startblock << 21) |
357 ((xfs_bmbt_rec_base_t)blockcount &
358 (xfs_bmbt_rec_base_t)XFS_MASK64LO(21));
359 } else {
360 r->l0 = ((xfs_bmbt_rec_base_t)extent_flag << 63) |
361 ((xfs_bmbt_rec_base_t)startoff << 9);
362 r->l1 = ((xfs_bmbt_rec_base_t)startblock << 21) |
363 ((xfs_bmbt_rec_base_t)blockcount &
364 (xfs_bmbt_rec_base_t)XFS_MASK64LO(21));
365 }
366#endif /* XFS_BIG_BLKNOS */
367}
368
369/*
Linus Torvalds1da177e2005-04-16 15:20:36 -0700370 * Set all the fields in a bmap extent record from the uncompressed form.
371 */
372void
373xfs_bmbt_set_all(
Christoph Hellwiga6f64d42007-08-16 16:23:40 +1000374 xfs_bmbt_rec_host_t *r,
Linus Torvalds1da177e2005-04-16 15:20:36 -0700375 xfs_bmbt_irec_t *s)
376{
Christoph Hellwig8cba4342007-08-16 16:23:53 +1000377 xfs_bmbt_set_allf(r, s->br_startoff, s->br_startblock,
378 s->br_blockcount, s->br_state);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700379}
380
Linus Torvalds1da177e2005-04-16 15:20:36 -0700381
Linus Torvalds1da177e2005-04-16 15:20:36 -0700382/*
Christoph Hellwig8cba4342007-08-16 16:23:53 +1000383 * Set all the fields in a disk format bmap extent record from the arguments.
384 */
385void
386xfs_bmbt_disk_set_allf(
387 xfs_bmbt_rec_t *r,
388 xfs_fileoff_t startoff,
389 xfs_fsblock_t startblock,
390 xfs_filblks_t blockcount,
391 xfs_exntst_t state)
392{
393 int extent_flag = (state == XFS_EXT_NORM) ? 0 : 1;
394
395 ASSERT(state == XFS_EXT_NORM || state == XFS_EXT_UNWRITTEN);
396 ASSERT((startoff & XFS_MASK64HI(64-BMBT_STARTOFF_BITLEN)) == 0);
397 ASSERT((blockcount & XFS_MASK64HI(64-BMBT_BLOCKCOUNT_BITLEN)) == 0);
398
399#if XFS_BIG_BLKNOS
400 ASSERT((startblock & XFS_MASK64HI(64-BMBT_STARTBLOCK_BITLEN)) == 0);
401
Christoph Hellwigcd8b0a92007-08-16 16:24:15 +1000402 r->l0 = cpu_to_be64(
Christoph Hellwig8cba4342007-08-16 16:23:53 +1000403 ((xfs_bmbt_rec_base_t)extent_flag << 63) |
404 ((xfs_bmbt_rec_base_t)startoff << 9) |
405 ((xfs_bmbt_rec_base_t)startblock >> 43));
Christoph Hellwigcd8b0a92007-08-16 16:24:15 +1000406 r->l1 = cpu_to_be64(
Christoph Hellwig8cba4342007-08-16 16:23:53 +1000407 ((xfs_bmbt_rec_base_t)startblock << 21) |
408 ((xfs_bmbt_rec_base_t)blockcount &
409 (xfs_bmbt_rec_base_t)XFS_MASK64LO(21)));
410#else /* !XFS_BIG_BLKNOS */
Michal Piotrowskiddc6d3b2007-08-23 16:20:10 +1000411 if (ISNULLSTARTBLOCK(startblock)) {
Christoph Hellwigcd8b0a92007-08-16 16:24:15 +1000412 r->l0 = cpu_to_be64(
Christoph Hellwig8cba4342007-08-16 16:23:53 +1000413 ((xfs_bmbt_rec_base_t)extent_flag << 63) |
414 ((xfs_bmbt_rec_base_t)startoff << 9) |
415 (xfs_bmbt_rec_base_t)XFS_MASK64LO(9));
Christoph Hellwigcd8b0a92007-08-16 16:24:15 +1000416 r->l1 = cpu_to_be64(XFS_MASK64HI(11) |
Christoph Hellwig8cba4342007-08-16 16:23:53 +1000417 ((xfs_bmbt_rec_base_t)startblock << 21) |
418 ((xfs_bmbt_rec_base_t)blockcount &
419 (xfs_bmbt_rec_base_t)XFS_MASK64LO(21)));
420 } else {
Christoph Hellwigcd8b0a92007-08-16 16:24:15 +1000421 r->l0 = cpu_to_be64(
Christoph Hellwig8cba4342007-08-16 16:23:53 +1000422 ((xfs_bmbt_rec_base_t)extent_flag << 63) |
423 ((xfs_bmbt_rec_base_t)startoff << 9));
Christoph Hellwigcd8b0a92007-08-16 16:24:15 +1000424 r->l1 = cpu_to_be64(
Christoph Hellwig8cba4342007-08-16 16:23:53 +1000425 ((xfs_bmbt_rec_base_t)startblock << 21) |
426 ((xfs_bmbt_rec_base_t)blockcount &
427 (xfs_bmbt_rec_base_t)XFS_MASK64LO(21)));
428 }
429#endif /* XFS_BIG_BLKNOS */
430}
431
432/*
Linus Torvalds1da177e2005-04-16 15:20:36 -0700433 * Set all the fields in a bmap extent record from the uncompressed form.
434 */
435void
436xfs_bmbt_disk_set_all(
437 xfs_bmbt_rec_t *r,
438 xfs_bmbt_irec_t *s)
439{
Christoph Hellwig8cba4342007-08-16 16:23:53 +1000440 xfs_bmbt_disk_set_allf(r, s->br_startoff, s->br_startblock,
441 s->br_blockcount, s->br_state);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700442}
Linus Torvalds1da177e2005-04-16 15:20:36 -0700443
444/*
445 * Set the blockcount field in a bmap extent record.
446 */
447void
448xfs_bmbt_set_blockcount(
Christoph Hellwiga6f64d42007-08-16 16:23:40 +1000449 xfs_bmbt_rec_host_t *r,
Linus Torvalds1da177e2005-04-16 15:20:36 -0700450 xfs_filblks_t v)
451{
452 ASSERT((v & XFS_MASK64HI(43)) == 0);
453 r->l1 = (r->l1 & (xfs_bmbt_rec_base_t)XFS_MASK64HI(43)) |
454 (xfs_bmbt_rec_base_t)(v & XFS_MASK64LO(21));
455}
456
457/*
458 * Set the startblock field in a bmap extent record.
459 */
460void
461xfs_bmbt_set_startblock(
Christoph Hellwiga6f64d42007-08-16 16:23:40 +1000462 xfs_bmbt_rec_host_t *r,
Linus Torvalds1da177e2005-04-16 15:20:36 -0700463 xfs_fsblock_t v)
464{
465#if XFS_BIG_BLKNOS
466 ASSERT((v & XFS_MASK64HI(12)) == 0);
467 r->l0 = (r->l0 & (xfs_bmbt_rec_base_t)XFS_MASK64HI(55)) |
468 (xfs_bmbt_rec_base_t)(v >> 43);
469 r->l1 = (r->l1 & (xfs_bmbt_rec_base_t)XFS_MASK64LO(21)) |
470 (xfs_bmbt_rec_base_t)(v << 21);
471#else /* !XFS_BIG_BLKNOS */
472 if (ISNULLSTARTBLOCK(v)) {
473 r->l0 |= (xfs_bmbt_rec_base_t)XFS_MASK64LO(9);
474 r->l1 = (xfs_bmbt_rec_base_t)XFS_MASK64HI(11) |
475 ((xfs_bmbt_rec_base_t)v << 21) |
476 (r->l1 & (xfs_bmbt_rec_base_t)XFS_MASK64LO(21));
477 } else {
478 r->l0 &= ~(xfs_bmbt_rec_base_t)XFS_MASK64LO(9);
479 r->l1 = ((xfs_bmbt_rec_base_t)v << 21) |
480 (r->l1 & (xfs_bmbt_rec_base_t)XFS_MASK64LO(21));
481 }
482#endif /* XFS_BIG_BLKNOS */
483}
484
485/*
486 * Set the startoff field in a bmap extent record.
487 */
488void
489xfs_bmbt_set_startoff(
Christoph Hellwiga6f64d42007-08-16 16:23:40 +1000490 xfs_bmbt_rec_host_t *r,
Linus Torvalds1da177e2005-04-16 15:20:36 -0700491 xfs_fileoff_t v)
492{
493 ASSERT((v & XFS_MASK64HI(9)) == 0);
494 r->l0 = (r->l0 & (xfs_bmbt_rec_base_t) XFS_MASK64HI(1)) |
495 ((xfs_bmbt_rec_base_t)v << 9) |
496 (r->l0 & (xfs_bmbt_rec_base_t)XFS_MASK64LO(9));
497}
498
499/*
500 * Set the extent state field in a bmap extent record.
501 */
502void
503xfs_bmbt_set_state(
Christoph Hellwiga6f64d42007-08-16 16:23:40 +1000504 xfs_bmbt_rec_host_t *r,
Linus Torvalds1da177e2005-04-16 15:20:36 -0700505 xfs_exntst_t v)
506{
507 ASSERT(v == XFS_EXT_NORM || v == XFS_EXT_UNWRITTEN);
508 if (v == XFS_EXT_NORM)
509 r->l0 &= XFS_MASK64LO(64 - BMBT_EXNTFLAG_BITLEN);
510 else
511 r->l0 |= XFS_MASK64HI(BMBT_EXNTFLAG_BITLEN);
512}
513
514/*
515 * Convert in-memory form of btree root to on-disk form.
516 */
517void
518xfs_bmbt_to_bmdr(
519 xfs_bmbt_block_t *rblock,
520 int rblocklen,
521 xfs_bmdr_block_t *dblock,
522 int dblocklen)
523{
524 int dmxr;
525 xfs_bmbt_key_t *fkp;
Christoph Hellwig576039c2006-09-28 10:58:06 +1000526 __be64 *fpp;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700527 xfs_bmbt_key_t *tkp;
Christoph Hellwig576039c2006-09-28 10:58:06 +1000528 __be64 *tpp;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700529
Christoph Hellwig16259e72005-11-02 15:11:25 +1100530 ASSERT(be32_to_cpu(rblock->bb_magic) == XFS_BMAP_MAGIC);
531 ASSERT(be64_to_cpu(rblock->bb_leftsib) == NULLDFSBNO);
532 ASSERT(be64_to_cpu(rblock->bb_rightsib) == NULLDFSBNO);
533 ASSERT(be16_to_cpu(rblock->bb_level) > 0);
534 dblock->bb_level = rblock->bb_level;
535 dblock->bb_numrecs = rblock->bb_numrecs;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700536 dmxr = (int)XFS_BTREE_BLOCK_MAXRECS(dblocklen, xfs_bmdr, 0);
537 fkp = XFS_BMAP_BROOT_KEY_ADDR(rblock, 1, rblocklen);
Eric Sandeen2c36dde2007-02-10 18:37:33 +1100538 tkp = XFS_BTREE_KEY_ADDR(xfs_bmdr, dblock, 1);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700539 fpp = XFS_BMAP_BROOT_PTR_ADDR(rblock, 1, rblocklen);
Eric Sandeen2c36dde2007-02-10 18:37:33 +1100540 tpp = XFS_BTREE_PTR_ADDR(xfs_bmdr, dblock, 1, dmxr);
Christoph Hellwig16259e72005-11-02 15:11:25 +1100541 dmxr = be16_to_cpu(dblock->bb_numrecs);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700542 memcpy(tkp, fkp, sizeof(*fkp) * dmxr);
Christoph Hellwig576039c2006-09-28 10:58:06 +1000543 memcpy(tpp, fpp, sizeof(*fpp) * dmxr);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700544}
545
546/*
Mandy Kirkconnell4eea22f2006-03-14 13:29:52 +1100547 * Check extent records, which have just been read, for
Linus Torvalds1da177e2005-04-16 15:20:36 -0700548 * any bit in the extent flag field. ASSERT on debug
549 * kernels, as this condition should not occur.
550 * Return an error condition (1) if any flags found,
551 * otherwise return 0.
552 */
553
554int
555xfs_check_nostate_extents(
Mandy Kirkconnell4eea22f2006-03-14 13:29:52 +1100556 xfs_ifork_t *ifp,
557 xfs_extnum_t idx,
Linus Torvalds1da177e2005-04-16 15:20:36 -0700558 xfs_extnum_t num)
559{
Mandy Kirkconnell4eea22f2006-03-14 13:29:52 +1100560 for (; num > 0; num--, idx++) {
Christoph Hellwiga6f64d42007-08-16 16:23:40 +1000561 xfs_bmbt_rec_host_t *ep = xfs_iext_get_ext(ifp, idx);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700562 if ((ep->l0 >>
563 (64 - BMBT_EXNTFLAG_BITLEN)) != 0) {
564 ASSERT(0);
565 return 1;
566 }
567 }
568 return 0;
569}
Christoph Hellwig561f7d12008-10-30 16:53:59 +1100570
571
572STATIC struct xfs_btree_cur *
573xfs_bmbt_dup_cursor(
574 struct xfs_btree_cur *cur)
575{
576 struct xfs_btree_cur *new;
577
578 new = xfs_bmbt_init_cursor(cur->bc_mp, cur->bc_tp,
579 cur->bc_private.b.ip, cur->bc_private.b.whichfork);
580
581 /*
582 * Copy the firstblock, flist, and flags values,
583 * since init cursor doesn't get them.
584 */
585 new->bc_private.b.firstblock = cur->bc_private.b.firstblock;
586 new->bc_private.b.flist = cur->bc_private.b.flist;
587 new->bc_private.b.flags = cur->bc_private.b.flags;
588
589 return new;
590}
591
Christoph Hellwig4b22a572008-10-30 16:57:40 +1100592STATIC void
593xfs_bmbt_update_cursor(
594 struct xfs_btree_cur *src,
595 struct xfs_btree_cur *dst)
596{
597 ASSERT((dst->bc_private.b.firstblock != NULLFSBLOCK) ||
598 (dst->bc_private.b.ip->i_d.di_flags & XFS_DIFLAG_REALTIME));
599 ASSERT(dst->bc_private.b.flist == src->bc_private.b.flist);
600
601 dst->bc_private.b.allocated += src->bc_private.b.allocated;
602 dst->bc_private.b.firstblock = src->bc_private.b.firstblock;
603
604 src->bc_private.b.allocated = 0;
605}
606
Christoph Hellwigce5e42d2008-10-30 16:55:23 +1100607STATIC int
Christoph Hellwigf5eb8e72008-10-30 16:57:03 +1100608xfs_bmbt_alloc_block(
609 struct xfs_btree_cur *cur,
610 union xfs_btree_ptr *start,
611 union xfs_btree_ptr *new,
612 int length,
613 int *stat)
614{
615 xfs_alloc_arg_t args; /* block allocation args */
616 int error; /* error return value */
617
618 memset(&args, 0, sizeof(args));
619 args.tp = cur->bc_tp;
620 args.mp = cur->bc_mp;
621 args.fsbno = cur->bc_private.b.firstblock;
622 args.firstblock = args.fsbno;
623
624 if (args.fsbno == NULLFSBLOCK) {
625 args.fsbno = be64_to_cpu(start->l);
626 args.type = XFS_ALLOCTYPE_START_BNO;
627 /*
628 * Make sure there is sufficient room left in the AG to
629 * complete a full tree split for an extent insert. If
630 * we are converting the middle part of an extent then
631 * we may need space for two tree splits.
632 *
633 * We are relying on the caller to make the correct block
634 * reservation for this operation to succeed. If the
635 * reservation amount is insufficient then we may fail a
636 * block allocation here and corrupt the filesystem.
637 */
638 args.minleft = xfs_trans_get_block_res(args.tp);
639 } else if (cur->bc_private.b.flist->xbf_low) {
640 args.type = XFS_ALLOCTYPE_START_BNO;
641 } else {
642 args.type = XFS_ALLOCTYPE_NEAR_BNO;
643 }
644
645 args.minlen = args.maxlen = args.prod = 1;
646 args.wasdel = cur->bc_private.b.flags & XFS_BTCUR_BPRV_WASDEL;
647 if (!args.wasdel && xfs_trans_get_block_res(args.tp) == 0) {
648 error = XFS_ERROR(ENOSPC);
649 goto error0;
650 }
651 error = xfs_alloc_vextent(&args);
652 if (error)
653 goto error0;
654
655 if (args.fsbno == NULLFSBLOCK && args.minleft) {
656 /*
657 * Could not find an AG with enough free space to satisfy
658 * a full btree split. Try again without minleft and if
659 * successful activate the lowspace algorithm.
660 */
661 args.fsbno = 0;
662 args.type = XFS_ALLOCTYPE_FIRST_AG;
663 args.minleft = 0;
664 error = xfs_alloc_vextent(&args);
665 if (error)
666 goto error0;
667 cur->bc_private.b.flist->xbf_low = 1;
668 }
669 if (args.fsbno == NULLFSBLOCK) {
670 XFS_BTREE_TRACE_CURSOR(cur, XBT_EXIT);
671 *stat = 0;
672 return 0;
673 }
674 ASSERT(args.len == 1);
675 cur->bc_private.b.firstblock = args.fsbno;
676 cur->bc_private.b.allocated++;
677 cur->bc_private.b.ip->i_d.di_nblocks++;
678 xfs_trans_log_inode(args.tp, cur->bc_private.b.ip, XFS_ILOG_CORE);
679 XFS_TRANS_MOD_DQUOT_BYINO(args.mp, args.tp, cur->bc_private.b.ip,
680 XFS_TRANS_DQ_BCOUNT, 1L);
681
682 new->l = cpu_to_be64(args.fsbno);
683
684 XFS_BTREE_TRACE_CURSOR(cur, XBT_EXIT);
685 *stat = 1;
686 return 0;
687
688 error0:
689 XFS_BTREE_TRACE_CURSOR(cur, XBT_ERROR);
690 return error;
691}
692
693STATIC int
Christoph Hellwigd4b3a4b2008-10-30 16:57:51 +1100694xfs_bmbt_free_block(
695 struct xfs_btree_cur *cur,
696 struct xfs_buf *bp)
697{
698 struct xfs_mount *mp = cur->bc_mp;
699 struct xfs_inode *ip = cur->bc_private.b.ip;
700 struct xfs_trans *tp = cur->bc_tp;
701 xfs_fsblock_t fsbno = XFS_DADDR_TO_FSB(mp, XFS_BUF_ADDR(bp));
702
703 xfs_bmap_add_free(fsbno, 1, cur->bc_private.b.flist, mp);
704 ip->i_d.di_nblocks--;
705
706 xfs_trans_log_inode(tp, ip, XFS_ILOG_CORE);
707 XFS_TRANS_MOD_DQUOT_BYINO(mp, tp, ip, XFS_TRANS_DQ_BCOUNT, -1L);
708 xfs_trans_binval(tp, bp);
709 return 0;
710}
711
712STATIC int
Christoph Hellwig91cca5df2008-10-30 16:58:01 +1100713xfs_bmbt_get_minrecs(
714 struct xfs_btree_cur *cur,
715 int level)
716{
717 return XFS_BMAP_BLOCK_IMINRECS(level, cur);
718}
719
720STATIC int
Christoph Hellwigce5e42d2008-10-30 16:55:23 +1100721xfs_bmbt_get_maxrecs(
722 struct xfs_btree_cur *cur,
723 int level)
724{
725 return XFS_BMAP_BLOCK_IMAXRECS(level, cur);
726}
727
Christoph Hellwig4b22a572008-10-30 16:57:40 +1100728/*
729 * Get the maximum records we could store in the on-disk format.
730 *
731 * For non-root nodes this is equivalent to xfs_bmbt_get_maxrecs, but
732 * for the root node this checks the available space in the dinode fork
733 * so that we can resize the in-memory buffer to match it. After a
734 * resize to the maximum size this function returns the same value
735 * as xfs_bmbt_get_maxrecs for the root node, too.
736 */
737STATIC int
738xfs_bmbt_get_dmaxrecs(
739 struct xfs_btree_cur *cur,
740 int level)
741{
742 return XFS_BMAP_BLOCK_DMAXRECS(level, cur);
743}
744
Christoph Hellwigfe033cc2008-10-30 16:56:09 +1100745STATIC void
746xfs_bmbt_init_key_from_rec(
747 union xfs_btree_key *key,
748 union xfs_btree_rec *rec)
749{
750 key->bmbt.br_startoff =
751 cpu_to_be64(xfs_bmbt_disk_get_startoff(&rec->bmbt));
752}
753
754STATIC void
Christoph Hellwig4b22a572008-10-30 16:57:40 +1100755xfs_bmbt_init_rec_from_key(
756 union xfs_btree_key *key,
757 union xfs_btree_rec *rec)
758{
759 ASSERT(key->bmbt.br_startoff != 0);
760
761 xfs_bmbt_disk_set_allf(&rec->bmbt, be64_to_cpu(key->bmbt.br_startoff),
762 0, 0, XFS_EXT_NORM);
763}
764
765STATIC void
766xfs_bmbt_init_rec_from_cur(
767 struct xfs_btree_cur *cur,
768 union xfs_btree_rec *rec)
769{
770 xfs_bmbt_disk_set_all(&rec->bmbt, &cur->bc_rec.b);
771}
772
773STATIC void
Christoph Hellwigfe033cc2008-10-30 16:56:09 +1100774xfs_bmbt_init_ptr_from_cur(
775 struct xfs_btree_cur *cur,
776 union xfs_btree_ptr *ptr)
777{
778 ptr->l = 0;
779}
780
781STATIC __int64_t
782xfs_bmbt_key_diff(
783 struct xfs_btree_cur *cur,
784 union xfs_btree_key *key)
785{
786 return (__int64_t)be64_to_cpu(key->bmbt.br_startoff) -
787 cur->bc_rec.b.br_startoff;
788}
789
Christoph Hellwig8c4ed632008-10-30 16:55:13 +1100790#ifdef XFS_BTREE_TRACE
791ktrace_t *xfs_bmbt_trace_buf;
792
793STATIC void
794xfs_bmbt_trace_enter(
795 struct xfs_btree_cur *cur,
796 const char *func,
797 char *s,
798 int type,
799 int line,
800 __psunsigned_t a0,
801 __psunsigned_t a1,
802 __psunsigned_t a2,
803 __psunsigned_t a3,
804 __psunsigned_t a4,
805 __psunsigned_t a5,
806 __psunsigned_t a6,
807 __psunsigned_t a7,
808 __psunsigned_t a8,
809 __psunsigned_t a9,
810 __psunsigned_t a10)
811{
812 struct xfs_inode *ip = cur->bc_private.b.ip;
813 int whichfork = cur->bc_private.b.whichfork;
814
815 ktrace_enter(xfs_bmbt_trace_buf,
816 (void *)((__psint_t)type | (whichfork << 8) | (line << 16)),
817 (void *)func, (void *)s, (void *)ip, (void *)cur,
818 (void *)a0, (void *)a1, (void *)a2, (void *)a3,
819 (void *)a4, (void *)a5, (void *)a6, (void *)a7,
820 (void *)a8, (void *)a9, (void *)a10);
821 ktrace_enter(ip->i_btrace,
822 (void *)((__psint_t)type | (whichfork << 8) | (line << 16)),
823 (void *)func, (void *)s, (void *)ip, (void *)cur,
824 (void *)a0, (void *)a1, (void *)a2, (void *)a3,
825 (void *)a4, (void *)a5, (void *)a6, (void *)a7,
826 (void *)a8, (void *)a9, (void *)a10);
827}
828
829STATIC void
830xfs_bmbt_trace_cursor(
831 struct xfs_btree_cur *cur,
832 __uint32_t *s0,
833 __uint64_t *l0,
834 __uint64_t *l1)
835{
836 struct xfs_bmbt_rec_host r;
837
838 xfs_bmbt_set_all(&r, &cur->bc_rec.b);
839
840 *s0 = (cur->bc_nlevels << 24) |
841 (cur->bc_private.b.flags << 16) |
842 cur->bc_private.b.allocated;
843 *l0 = r.l0;
844 *l1 = r.l1;
845}
846
847STATIC void
848xfs_bmbt_trace_key(
849 struct xfs_btree_cur *cur,
850 union xfs_btree_key *key,
851 __uint64_t *l0,
852 __uint64_t *l1)
853{
854 *l0 = be64_to_cpu(key->bmbt.br_startoff);
855 *l1 = 0;
856}
857
858STATIC void
859xfs_bmbt_trace_record(
860 struct xfs_btree_cur *cur,
861 union xfs_btree_rec *rec,
862 __uint64_t *l0,
863 __uint64_t *l1,
864 __uint64_t *l2)
865{
866 struct xfs_bmbt_irec irec;
867
868 xfs_bmbt_disk_get_all(&rec->bmbt, &irec);
869 *l0 = irec.br_startoff;
870 *l1 = irec.br_startblock;
871 *l2 = irec.br_blockcount;
872}
873#endif /* XFS_BTREE_TRACE */
874
Christoph Hellwig561f7d12008-10-30 16:53:59 +1100875static const struct xfs_btree_ops xfs_bmbt_ops = {
Christoph Hellwig65f1eae2008-10-30 16:55:34 +1100876 .rec_len = sizeof(xfs_bmbt_rec_t),
877 .key_len = sizeof(xfs_bmbt_key_t),
878
Christoph Hellwig561f7d12008-10-30 16:53:59 +1100879 .dup_cursor = xfs_bmbt_dup_cursor,
Christoph Hellwig4b22a572008-10-30 16:57:40 +1100880 .update_cursor = xfs_bmbt_update_cursor,
Christoph Hellwigf5eb8e72008-10-30 16:57:03 +1100881 .alloc_block = xfs_bmbt_alloc_block,
Christoph Hellwigd4b3a4b2008-10-30 16:57:51 +1100882 .free_block = xfs_bmbt_free_block,
Christoph Hellwigce5e42d2008-10-30 16:55:23 +1100883 .get_maxrecs = xfs_bmbt_get_maxrecs,
Christoph Hellwig91cca5df2008-10-30 16:58:01 +1100884 .get_minrecs = xfs_bmbt_get_minrecs,
Christoph Hellwig4b22a572008-10-30 16:57:40 +1100885 .get_dmaxrecs = xfs_bmbt_get_dmaxrecs,
Christoph Hellwigfe033cc2008-10-30 16:56:09 +1100886 .init_key_from_rec = xfs_bmbt_init_key_from_rec,
Christoph Hellwig4b22a572008-10-30 16:57:40 +1100887 .init_rec_from_key = xfs_bmbt_init_rec_from_key,
888 .init_rec_from_cur = xfs_bmbt_init_rec_from_cur,
Christoph Hellwigfe033cc2008-10-30 16:56:09 +1100889 .init_ptr_from_cur = xfs_bmbt_init_ptr_from_cur,
890 .key_diff = xfs_bmbt_key_diff,
Christoph Hellwig8c4ed632008-10-30 16:55:13 +1100891
892#ifdef XFS_BTREE_TRACE
893 .trace_enter = xfs_bmbt_trace_enter,
894 .trace_cursor = xfs_bmbt_trace_cursor,
895 .trace_key = xfs_bmbt_trace_key,
896 .trace_record = xfs_bmbt_trace_record,
897#endif
Christoph Hellwig561f7d12008-10-30 16:53:59 +1100898};
899
900/*
901 * Allocate a new bmap btree cursor.
902 */
903struct xfs_btree_cur * /* new bmap btree cursor */
904xfs_bmbt_init_cursor(
905 struct xfs_mount *mp, /* file system mount point */
906 struct xfs_trans *tp, /* transaction pointer */
907 struct xfs_inode *ip, /* inode owning the btree */
908 int whichfork) /* data or attr fork */
909{
910 struct xfs_ifork *ifp = XFS_IFORK_PTR(ip, whichfork);
911 struct xfs_btree_cur *cur;
912
913 cur = kmem_zone_zalloc(xfs_btree_cur_zone, KM_SLEEP);
914
915 cur->bc_tp = tp;
916 cur->bc_mp = mp;
917 cur->bc_nlevels = be16_to_cpu(ifp->if_broot->bb_level) + 1;
918 cur->bc_btnum = XFS_BTNUM_BMAP;
919 cur->bc_blocklog = mp->m_sb.sb_blocklog;
920
921 cur->bc_ops = &xfs_bmbt_ops;
Christoph Hellwige99ab902008-10-30 16:54:33 +1100922 cur->bc_flags = XFS_BTREE_LONG_PTRS | XFS_BTREE_ROOT_IN_INODE;
Christoph Hellwig561f7d12008-10-30 16:53:59 +1100923
924 cur->bc_private.b.forksize = XFS_IFORK_SIZE(ip, whichfork);
925 cur->bc_private.b.ip = ip;
926 cur->bc_private.b.firstblock = NULLFSBLOCK;
927 cur->bc_private.b.flist = NULL;
928 cur->bc_private.b.allocated = 0;
929 cur->bc_private.b.flags = 0;
930 cur->bc_private.b.whichfork = whichfork;
931
932 return cur;
933}