2 * Copyright (c) 2000-2006 Silicon Graphics, Inc.
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.
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.
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
18 #include <linux/log2.h>
22 #include "xfs_format.h"
23 #include "xfs_log_format.h"
24 #include "xfs_trans_resv.h"
25 #include "xfs_mount.h"
26 #include "xfs_inode.h"
27 #include "xfs_trans.h"
28 #include "xfs_inode_item.h"
29 #include "xfs_btree.h"
30 #include "xfs_bmap_btree.h"
32 #include "xfs_error.h"
33 #include "xfs_trace.h"
34 #include "xfs_attr_sf.h"
35 #include "xfs_da_format.h"
36 #include "xfs_da_btree.h"
37 #include "xfs_dir2_priv.h"
39 kmem_zone_t
*xfs_ifork_zone
;
41 STATIC
int xfs_iformat_local(xfs_inode_t
*, xfs_dinode_t
*, int, int);
42 STATIC
int xfs_iformat_extents(xfs_inode_t
*, xfs_dinode_t
*, int);
43 STATIC
int xfs_iformat_btree(xfs_inode_t
*, xfs_dinode_t
*, int);
46 * Copy inode type and data and attr format specific information from the
47 * on-disk inode to the in-core inode and fork structures. For fifos, devices,
48 * and sockets this means set i_rdev to the proper value. For files,
49 * directories, and symlinks this means to bring in the in-line data or extent
50 * pointers as well as the attribute fork. For a fork in B-tree format, only
51 * the root is immediately brought in-core. The rest will be read in later when
52 * first referenced (see xfs_iread_extents()).
57 struct xfs_dinode
*dip
)
59 struct inode
*inode
= VFS_I(ip
);
60 struct xfs_attr_shortform
*atp
;
65 if (unlikely(be32_to_cpu(dip
->di_nextents
) +
66 be16_to_cpu(dip
->di_anextents
) >
67 be64_to_cpu(dip
->di_nblocks
))) {
69 "corrupt dinode %Lu, extent total = %d, nblocks = %Lu.",
70 (unsigned long long)ip
->i_ino
,
71 (int)(be32_to_cpu(dip
->di_nextents
) +
72 be16_to_cpu(dip
->di_anextents
)),
74 be64_to_cpu(dip
->di_nblocks
));
75 XFS_CORRUPTION_ERROR("xfs_iformat(1)", XFS_ERRLEVEL_LOW
,
80 if (unlikely(dip
->di_forkoff
> ip
->i_mount
->m_sb
.sb_inodesize
)) {
81 xfs_warn(ip
->i_mount
, "corrupt dinode %Lu, forkoff = 0x%x.",
82 (unsigned long long)ip
->i_ino
,
84 XFS_CORRUPTION_ERROR("xfs_iformat(2)", XFS_ERRLEVEL_LOW
,
89 if (unlikely((ip
->i_d
.di_flags
& XFS_DIFLAG_REALTIME
) &&
90 !ip
->i_mount
->m_rtdev_targp
)) {
92 "corrupt dinode %Lu, has realtime flag set.",
94 XFS_CORRUPTION_ERROR("xfs_iformat(realtime)",
95 XFS_ERRLEVEL_LOW
, ip
->i_mount
, dip
);
99 if (unlikely(xfs_is_reflink_inode(ip
) && !S_ISREG(inode
->i_mode
))) {
100 xfs_warn(ip
->i_mount
,
101 "corrupt dinode %llu, wrong file type for reflink.",
103 XFS_CORRUPTION_ERROR("xfs_iformat(reflink)",
104 XFS_ERRLEVEL_LOW
, ip
->i_mount
, dip
);
105 return -EFSCORRUPTED
;
108 if (unlikely(xfs_is_reflink_inode(ip
) &&
109 (ip
->i_d
.di_flags
& XFS_DIFLAG_REALTIME
))) {
110 xfs_warn(ip
->i_mount
,
111 "corrupt dinode %llu, has reflink+realtime flag set.",
113 XFS_CORRUPTION_ERROR("xfs_iformat(reflink)",
114 XFS_ERRLEVEL_LOW
, ip
->i_mount
, dip
);
115 return -EFSCORRUPTED
;
118 switch (inode
->i_mode
& S_IFMT
) {
123 if (unlikely(dip
->di_format
!= XFS_DINODE_FMT_DEV
)) {
124 XFS_CORRUPTION_ERROR("xfs_iformat(3)", XFS_ERRLEVEL_LOW
,
126 return -EFSCORRUPTED
;
129 inode
->i_rdev
= xfs_to_linux_dev_t(xfs_dinode_get_rdev(dip
));
135 switch (dip
->di_format
) {
136 case XFS_DINODE_FMT_LOCAL
:
138 * no local regular files yet
140 if (unlikely(S_ISREG(be16_to_cpu(dip
->di_mode
)))) {
141 xfs_warn(ip
->i_mount
,
142 "corrupt inode %Lu (local format for regular file).",
143 (unsigned long long) ip
->i_ino
);
144 XFS_CORRUPTION_ERROR("xfs_iformat(4)",
147 return -EFSCORRUPTED
;
150 di_size
= be64_to_cpu(dip
->di_size
);
151 if (unlikely(di_size
< 0 ||
152 di_size
> XFS_DFORK_DSIZE(dip
, ip
->i_mount
))) {
153 xfs_warn(ip
->i_mount
,
154 "corrupt inode %Lu (bad size %Ld for local inode).",
155 (unsigned long long) ip
->i_ino
,
156 (long long) di_size
);
157 XFS_CORRUPTION_ERROR("xfs_iformat(5)",
160 return -EFSCORRUPTED
;
164 error
= xfs_iformat_local(ip
, dip
, XFS_DATA_FORK
, size
);
166 case XFS_DINODE_FMT_EXTENTS
:
167 error
= xfs_iformat_extents(ip
, dip
, XFS_DATA_FORK
);
169 case XFS_DINODE_FMT_BTREE
:
170 error
= xfs_iformat_btree(ip
, dip
, XFS_DATA_FORK
);
173 XFS_ERROR_REPORT("xfs_iformat(6)", XFS_ERRLEVEL_LOW
,
175 return -EFSCORRUPTED
;
180 XFS_ERROR_REPORT("xfs_iformat(7)", XFS_ERRLEVEL_LOW
, ip
->i_mount
);
181 return -EFSCORRUPTED
;
186 /* Check inline dir contents. */
187 if (S_ISDIR(inode
->i_mode
) && dip
->di_format
== XFS_DINODE_FMT_LOCAL
) {
188 error
= xfs_dir2_sf_verify(ip
);
190 xfs_idestroy_fork(ip
, XFS_DATA_FORK
);
195 if (xfs_is_reflink_inode(ip
)) {
196 ASSERT(ip
->i_cowfp
== NULL
);
197 xfs_ifork_init_cow(ip
);
200 if (!XFS_DFORK_Q(dip
))
203 ASSERT(ip
->i_afp
== NULL
);
204 ip
->i_afp
= kmem_zone_zalloc(xfs_ifork_zone
, KM_SLEEP
| KM_NOFS
);
206 switch (dip
->di_aformat
) {
207 case XFS_DINODE_FMT_LOCAL
:
208 atp
= (xfs_attr_shortform_t
*)XFS_DFORK_APTR(dip
);
209 size
= be16_to_cpu(atp
->hdr
.totsize
);
211 if (unlikely(size
< sizeof(struct xfs_attr_sf_hdr
))) {
212 xfs_warn(ip
->i_mount
,
213 "corrupt inode %Lu (bad attr fork size %Ld).",
214 (unsigned long long) ip
->i_ino
,
216 XFS_CORRUPTION_ERROR("xfs_iformat(8)",
219 error
= -EFSCORRUPTED
;
223 error
= xfs_iformat_local(ip
, dip
, XFS_ATTR_FORK
, size
);
225 case XFS_DINODE_FMT_EXTENTS
:
226 error
= xfs_iformat_extents(ip
, dip
, XFS_ATTR_FORK
);
228 case XFS_DINODE_FMT_BTREE
:
229 error
= xfs_iformat_btree(ip
, dip
, XFS_ATTR_FORK
);
232 error
= -EFSCORRUPTED
;
236 kmem_zone_free(xfs_ifork_zone
, ip
->i_afp
);
239 kmem_zone_free(xfs_ifork_zone
, ip
->i_cowfp
);
241 xfs_idestroy_fork(ip
, XFS_DATA_FORK
);
248 struct xfs_inode
*ip
,
253 struct xfs_ifork
*ifp
= XFS_IFORK_PTR(ip
, whichfork
);
254 int mem_size
= size
, real_size
= 0;
258 * If we are using the local fork to store a symlink body we need to
259 * zero-terminate it so that we can pass it back to the VFS directly.
260 * Overallocate the in-memory fork by one for that and add a zero
261 * to terminate it below.
263 zero_terminate
= S_ISLNK(VFS_I(ip
)->i_mode
);
268 real_size
= roundup(mem_size
, 4);
269 ifp
->if_u1
.if_data
= kmem_alloc(real_size
, KM_SLEEP
| KM_NOFS
);
270 memcpy(ifp
->if_u1
.if_data
, data
, size
);
272 ifp
->if_u1
.if_data
[size
] = '\0';
274 ifp
->if_u1
.if_data
= NULL
;
277 ifp
->if_bytes
= size
;
278 ifp
->if_real_bytes
= real_size
;
279 ifp
->if_flags
&= ~(XFS_IFEXTENTS
| XFS_IFBROOT
);
280 ifp
->if_flags
|= XFS_IFINLINE
;
284 * The file is in-lined in the on-disk inode.
294 * If the size is unreasonable, then something
295 * is wrong and we just bail out rather than crash in
296 * kmem_alloc() or memcpy() below.
298 if (unlikely(size
> XFS_DFORK_SIZE(dip
, ip
->i_mount
, whichfork
))) {
299 xfs_warn(ip
->i_mount
,
300 "corrupt inode %Lu (bad size %d for local fork, size = %d).",
301 (unsigned long long) ip
->i_ino
, size
,
302 XFS_DFORK_SIZE(dip
, ip
->i_mount
, whichfork
));
303 XFS_CORRUPTION_ERROR("xfs_iformat_local", XFS_ERRLEVEL_LOW
,
305 return -EFSCORRUPTED
;
308 xfs_init_local_fork(ip
, whichfork
, XFS_DFORK_PTR(dip
, whichfork
), size
);
313 * The file consists of a set of extents all of which fit into the on-disk
318 struct xfs_inode
*ip
,
319 struct xfs_dinode
*dip
,
322 struct xfs_mount
*mp
= ip
->i_mount
;
323 struct xfs_ifork
*ifp
= XFS_IFORK_PTR(ip
, whichfork
);
324 int state
= xfs_bmap_fork_to_state(whichfork
);
325 int nex
= XFS_DFORK_NEXTENTS(dip
, whichfork
);
326 int size
= nex
* sizeof(xfs_bmbt_rec_t
);
327 struct xfs_iext_cursor icur
;
328 struct xfs_bmbt_rec
*dp
;
329 struct xfs_bmbt_irec
new;
333 * If the number of extents is unreasonable, then something is wrong and
334 * we just bail out rather than crash in kmem_alloc() or memcpy() below.
336 if (unlikely(size
< 0 || size
> XFS_DFORK_SIZE(dip
, mp
, whichfork
))) {
337 xfs_warn(ip
->i_mount
, "corrupt inode %Lu ((a)extents = %d).",
338 (unsigned long long) ip
->i_ino
, nex
);
339 XFS_CORRUPTION_ERROR("xfs_iformat_extents(1)", XFS_ERRLEVEL_LOW
,
341 return -EFSCORRUPTED
;
344 ifp
->if_real_bytes
= 0;
346 ifp
->if_u1
.if_root
= NULL
;
349 dp
= (xfs_bmbt_rec_t
*) XFS_DFORK_PTR(dip
, whichfork
);
351 xfs_iext_first(ifp
, &icur
);
352 for (i
= 0; i
< nex
; i
++, dp
++) {
353 xfs_bmbt_disk_get_all(dp
, &new);
354 if (!xfs_bmbt_validate_extent(mp
, whichfork
, &new)) {
355 XFS_ERROR_REPORT("xfs_iformat_extents(2)",
356 XFS_ERRLEVEL_LOW
, mp
);
357 return -EFSCORRUPTED
;
360 xfs_iext_insert(ip
, &icur
, &new, state
);
361 trace_xfs_read_extent(ip
, &icur
, state
, _THIS_IP_
);
362 xfs_iext_next(ifp
, &icur
);
365 ifp
->if_flags
|= XFS_IFEXTENTS
;
370 * The file has too many extents to fit into
371 * the inode, so they are in B-tree format.
372 * Allocate a buffer for the root of the B-tree
373 * and copy the root into it. The i_extents
374 * field will remain NULL until all of the
375 * extents are read in (when they are needed).
383 struct xfs_mount
*mp
= ip
->i_mount
;
384 xfs_bmdr_block_t
*dfp
;
391 ifp
= XFS_IFORK_PTR(ip
, whichfork
);
392 dfp
= (xfs_bmdr_block_t
*)XFS_DFORK_PTR(dip
, whichfork
);
393 size
= XFS_BMAP_BROOT_SPACE(mp
, dfp
);
394 nrecs
= be16_to_cpu(dfp
->bb_numrecs
);
395 level
= be16_to_cpu(dfp
->bb_level
);
398 * blow out if -- fork has less extents than can fit in
399 * fork (fork shouldn't be a btree format), root btree
400 * block has more records than can fit into the fork,
401 * or the number of extents is greater than the number of
404 if (unlikely(XFS_IFORK_NEXTENTS(ip
, whichfork
) <=
405 XFS_IFORK_MAXEXT(ip
, whichfork
) ||
406 XFS_BMDR_SPACE_CALC(nrecs
) >
407 XFS_DFORK_SIZE(dip
, mp
, whichfork
) ||
408 XFS_IFORK_NEXTENTS(ip
, whichfork
) > ip
->i_d
.di_nblocks
) ||
409 level
== 0 || level
> XFS_BTREE_MAXLEVELS
) {
410 xfs_warn(mp
, "corrupt inode %Lu (btree).",
411 (unsigned long long) ip
->i_ino
);
412 XFS_CORRUPTION_ERROR("xfs_iformat_btree", XFS_ERRLEVEL_LOW
,
414 return -EFSCORRUPTED
;
417 ifp
->if_broot_bytes
= size
;
418 ifp
->if_broot
= kmem_alloc(size
, KM_SLEEP
| KM_NOFS
);
419 ASSERT(ifp
->if_broot
!= NULL
);
421 * Copy and convert from the on-disk structure
422 * to the in-memory structure.
424 xfs_bmdr_to_bmbt(ip
, dfp
, XFS_DFORK_SIZE(dip
, ip
->i_mount
, whichfork
),
425 ifp
->if_broot
, size
);
426 ifp
->if_flags
&= ~XFS_IFEXTENTS
;
427 ifp
->if_flags
|= XFS_IFBROOT
;
429 ifp
->if_real_bytes
= 0;
431 ifp
->if_u1
.if_root
= NULL
;
437 * Reallocate the space for if_broot based on the number of records
438 * being added or deleted as indicated in rec_diff. Move the records
439 * and pointers in if_broot to fit the new size. When shrinking this
440 * will eliminate holes between the records and pointers created by
441 * the caller. When growing this will create holes to be filled in
444 * The caller must not request to add more records than would fit in
445 * the on-disk inode root. If the if_broot is currently NULL, then
446 * if we are adding records, one will be allocated. The caller must also
447 * not request that the number of records go below zero, although
450 * ip -- the inode whose if_broot area is changing
451 * ext_diff -- the change in the number of records, positive or negative,
452 * requested for the if_broot array.
460 struct xfs_mount
*mp
= ip
->i_mount
;
463 struct xfs_btree_block
*new_broot
;
470 * Handle the degenerate case quietly.
476 ifp
= XFS_IFORK_PTR(ip
, whichfork
);
479 * If there wasn't any memory allocated before, just
480 * allocate it now and get out.
482 if (ifp
->if_broot_bytes
== 0) {
483 new_size
= XFS_BMAP_BROOT_SPACE_CALC(mp
, rec_diff
);
484 ifp
->if_broot
= kmem_alloc(new_size
, KM_SLEEP
| KM_NOFS
);
485 ifp
->if_broot_bytes
= (int)new_size
;
490 * If there is already an existing if_broot, then we need
491 * to realloc() it and shift the pointers to their new
492 * location. The records don't change location because
493 * they are kept butted up against the btree block header.
495 cur_max
= xfs_bmbt_maxrecs(mp
, ifp
->if_broot_bytes
, 0);
496 new_max
= cur_max
+ rec_diff
;
497 new_size
= XFS_BMAP_BROOT_SPACE_CALC(mp
, new_max
);
498 ifp
->if_broot
= kmem_realloc(ifp
->if_broot
, new_size
,
500 op
= (char *)XFS_BMAP_BROOT_PTR_ADDR(mp
, ifp
->if_broot
, 1,
501 ifp
->if_broot_bytes
);
502 np
= (char *)XFS_BMAP_BROOT_PTR_ADDR(mp
, ifp
->if_broot
, 1,
504 ifp
->if_broot_bytes
= (int)new_size
;
505 ASSERT(XFS_BMAP_BMDR_SPACE(ifp
->if_broot
) <=
506 XFS_IFORK_SIZE(ip
, whichfork
));
507 memmove(np
, op
, cur_max
* (uint
)sizeof(xfs_fsblock_t
));
512 * rec_diff is less than 0. In this case, we are shrinking the
513 * if_broot buffer. It must already exist. If we go to zero
514 * records, just get rid of the root and clear the status bit.
516 ASSERT((ifp
->if_broot
!= NULL
) && (ifp
->if_broot_bytes
> 0));
517 cur_max
= xfs_bmbt_maxrecs(mp
, ifp
->if_broot_bytes
, 0);
518 new_max
= cur_max
+ rec_diff
;
519 ASSERT(new_max
>= 0);
521 new_size
= XFS_BMAP_BROOT_SPACE_CALC(mp
, new_max
);
525 new_broot
= kmem_alloc(new_size
, KM_SLEEP
| KM_NOFS
);
527 * First copy over the btree block header.
529 memcpy(new_broot
, ifp
->if_broot
,
530 XFS_BMBT_BLOCK_LEN(ip
->i_mount
));
533 ifp
->if_flags
&= ~XFS_IFBROOT
;
537 * Only copy the records and pointers if there are any.
541 * First copy the records.
543 op
= (char *)XFS_BMBT_REC_ADDR(mp
, ifp
->if_broot
, 1);
544 np
= (char *)XFS_BMBT_REC_ADDR(mp
, new_broot
, 1);
545 memcpy(np
, op
, new_max
* (uint
)sizeof(xfs_bmbt_rec_t
));
548 * Then copy the pointers.
550 op
= (char *)XFS_BMAP_BROOT_PTR_ADDR(mp
, ifp
->if_broot
, 1,
551 ifp
->if_broot_bytes
);
552 np
= (char *)XFS_BMAP_BROOT_PTR_ADDR(mp
, new_broot
, 1,
554 memcpy(np
, op
, new_max
* (uint
)sizeof(xfs_fsblock_t
));
556 kmem_free(ifp
->if_broot
);
557 ifp
->if_broot
= new_broot
;
558 ifp
->if_broot_bytes
= (int)new_size
;
560 ASSERT(XFS_BMAP_BMDR_SPACE(ifp
->if_broot
) <=
561 XFS_IFORK_SIZE(ip
, whichfork
));
567 * This is called when the amount of space needed for if_data
568 * is increased or decreased. The change in size is indicated by
569 * the number of bytes that need to be added or deleted in the
570 * byte_diff parameter.
572 * If the amount of space needed has decreased below the size of the
573 * inline buffer, then switch to using the inline buffer. Otherwise,
574 * use kmem_realloc() or kmem_alloc() to adjust the size of the buffer
577 * ip -- the inode whose if_data area is changing
578 * byte_diff -- the change in the number of bytes, positive or negative,
579 * requested for the if_data array.
591 if (byte_diff
== 0) {
595 ifp
= XFS_IFORK_PTR(ip
, whichfork
);
596 new_size
= (int)ifp
->if_bytes
+ byte_diff
;
597 ASSERT(new_size
>= 0);
600 kmem_free(ifp
->if_u1
.if_data
);
601 ifp
->if_u1
.if_data
= NULL
;
605 * Stuck with malloc/realloc.
606 * For inline data, the underlying buffer must be
607 * a multiple of 4 bytes in size so that it can be
608 * logged and stay on word boundaries. We enforce
611 real_size
= roundup(new_size
, 4);
612 if (ifp
->if_u1
.if_data
== NULL
) {
613 ASSERT(ifp
->if_real_bytes
== 0);
614 ifp
->if_u1
.if_data
= kmem_alloc(real_size
,
618 * Only do the realloc if the underlying size
619 * is really changing.
621 if (ifp
->if_real_bytes
!= real_size
) {
623 kmem_realloc(ifp
->if_u1
.if_data
,
629 ifp
->if_real_bytes
= real_size
;
630 ifp
->if_bytes
= new_size
;
631 ASSERT(ifp
->if_bytes
<= XFS_IFORK_SIZE(ip
, whichfork
));
641 ifp
= XFS_IFORK_PTR(ip
, whichfork
);
642 if (ifp
->if_broot
!= NULL
) {
643 kmem_free(ifp
->if_broot
);
644 ifp
->if_broot
= NULL
;
648 * If the format is local, then we can't have an extents
649 * array so just look for an inline data array. If we're
650 * not local then we may or may not have an extents list,
651 * so check and free it up if we do.
653 if (XFS_IFORK_FORMAT(ip
, whichfork
) == XFS_DINODE_FMT_LOCAL
) {
654 if (ifp
->if_u1
.if_data
!= NULL
) {
655 ASSERT(ifp
->if_real_bytes
!= 0);
656 kmem_free(ifp
->if_u1
.if_data
);
657 ifp
->if_u1
.if_data
= NULL
;
658 ifp
->if_real_bytes
= 0;
660 } else if ((ifp
->if_flags
& XFS_IFEXTENTS
) && ifp
->if_height
) {
661 xfs_iext_destroy(ifp
);
664 ASSERT(ifp
->if_real_bytes
== 0);
666 if (whichfork
== XFS_ATTR_FORK
) {
667 kmem_zone_free(xfs_ifork_zone
, ip
->i_afp
);
669 } else if (whichfork
== XFS_COW_FORK
) {
670 kmem_zone_free(xfs_ifork_zone
, ip
->i_cowfp
);
676 * Convert in-core extents to on-disk form
678 * In the case of the data fork, the in-core and on-disk fork sizes can be
679 * different due to delayed allocation extents. We only copy on-disk extents
680 * here, so callers must always use the physical fork size to determine the
681 * size of the buffer passed to this routine. We will return the size actually
686 struct xfs_inode
*ip
,
687 struct xfs_bmbt_rec
*dp
,
690 int state
= xfs_bmap_fork_to_state(whichfork
);
691 struct xfs_ifork
*ifp
= XFS_IFORK_PTR(ip
, whichfork
);
692 struct xfs_iext_cursor icur
;
693 struct xfs_bmbt_irec rec
;
696 ASSERT(xfs_isilocked(ip
, XFS_ILOCK_EXCL
| XFS_ILOCK_SHARED
));
697 ASSERT(ifp
->if_bytes
> 0);
699 for_each_xfs_iext(ifp
, &icur
, &rec
) {
700 if (isnullstartblock(rec
.br_startblock
))
702 ASSERT(xfs_bmbt_validate_extent(ip
->i_mount
, whichfork
, &rec
));
703 xfs_bmbt_disk_set_all(dp
, &rec
);
704 trace_xfs_write_extent(ip
, &icur
, state
, _RET_IP_
);
705 copied
+= sizeof(struct xfs_bmbt_rec
);
710 ASSERT(copied
<= ifp
->if_bytes
);
715 * Each of the following cases stores data into the same region
716 * of the on-disk inode, so only one of them can be valid at
717 * any given time. While it is possible to have conflicting formats
718 * and log flags, e.g. having XFS_ILOG_?DATA set when the fork is
719 * in EXTENTS format, this can only happen when the fork has
720 * changed formats after being modified but before being flushed.
721 * In these cases, the format always takes precedence, because the
722 * format indicates the current state of the fork.
728 xfs_inode_log_item_t
*iip
,
734 static const short brootflag
[2] =
735 { XFS_ILOG_DBROOT
, XFS_ILOG_ABROOT
};
736 static const short dataflag
[2] =
737 { XFS_ILOG_DDATA
, XFS_ILOG_ADATA
};
738 static const short extflag
[2] =
739 { XFS_ILOG_DEXT
, XFS_ILOG_AEXT
};
743 ifp
= XFS_IFORK_PTR(ip
, whichfork
);
745 * This can happen if we gave up in iformat in an error path,
746 * for the attribute fork.
749 ASSERT(whichfork
== XFS_ATTR_FORK
);
752 cp
= XFS_DFORK_PTR(dip
, whichfork
);
754 switch (XFS_IFORK_FORMAT(ip
, whichfork
)) {
755 case XFS_DINODE_FMT_LOCAL
:
756 if ((iip
->ili_fields
& dataflag
[whichfork
]) &&
757 (ifp
->if_bytes
> 0)) {
758 ASSERT(ifp
->if_u1
.if_data
!= NULL
);
759 ASSERT(ifp
->if_bytes
<= XFS_IFORK_SIZE(ip
, whichfork
));
760 memcpy(cp
, ifp
->if_u1
.if_data
, ifp
->if_bytes
);
764 case XFS_DINODE_FMT_EXTENTS
:
765 ASSERT((ifp
->if_flags
& XFS_IFEXTENTS
) ||
766 !(iip
->ili_fields
& extflag
[whichfork
]));
767 if ((iip
->ili_fields
& extflag
[whichfork
]) &&
768 (ifp
->if_bytes
> 0)) {
769 ASSERT(XFS_IFORK_NEXTENTS(ip
, whichfork
) > 0);
770 (void)xfs_iextents_copy(ip
, (xfs_bmbt_rec_t
*)cp
,
775 case XFS_DINODE_FMT_BTREE
:
776 if ((iip
->ili_fields
& brootflag
[whichfork
]) &&
777 (ifp
->if_broot_bytes
> 0)) {
778 ASSERT(ifp
->if_broot
!= NULL
);
779 ASSERT(XFS_BMAP_BMDR_SPACE(ifp
->if_broot
) <=
780 XFS_IFORK_SIZE(ip
, whichfork
));
781 xfs_bmbt_to_bmdr(mp
, ifp
->if_broot
, ifp
->if_broot_bytes
,
782 (xfs_bmdr_block_t
*)cp
,
783 XFS_DFORK_SIZE(dip
, mp
, whichfork
));
787 case XFS_DINODE_FMT_DEV
:
788 if (iip
->ili_fields
& XFS_ILOG_DEV
) {
789 ASSERT(whichfork
== XFS_DATA_FORK
);
790 xfs_dinode_put_rdev(dip
,
791 linux_to_xfs_dev_t(VFS_I(ip
)->i_rdev
));
801 /* Convert bmap state flags to an inode fork. */
803 xfs_iext_state_to_fork(
804 struct xfs_inode
*ip
,
807 if (state
& BMAP_COWFORK
)
809 else if (state
& BMAP_ATTRFORK
)
815 * Initialize an inode's copy-on-write fork.
819 struct xfs_inode
*ip
)
824 ip
->i_cowfp
= kmem_zone_zalloc(xfs_ifork_zone
,
826 ip
->i_cowfp
->if_flags
= XFS_IFEXTENTS
;
827 ip
->i_cformat
= XFS_DINODE_FMT_EXTENTS
;