crypto: s5p-sss - Fix kernel Oops in AES-ECB mode
[linux/fpc-iii.git] / fs / xfs / libxfs / xfs_inode_fork.c
blobc79a1616b79d7530f50746aecd26800d95d4fd48
1 /*
2 * Copyright (c) 2000-2006 Silicon Graphics, Inc.
3 * All Rights Reserved.
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>
20 #include "xfs.h"
21 #include "xfs_fs.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"
31 #include "xfs_bmap.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()).
54 int
55 xfs_iformat_fork(
56 struct xfs_inode *ip,
57 struct xfs_dinode *dip)
59 struct inode *inode = VFS_I(ip);
60 struct xfs_attr_shortform *atp;
61 int size;
62 int error = 0;
63 xfs_fsize_t di_size;
65 if (unlikely(be32_to_cpu(dip->di_nextents) +
66 be16_to_cpu(dip->di_anextents) >
67 be64_to_cpu(dip->di_nblocks))) {
68 xfs_warn(ip->i_mount,
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)),
73 (unsigned long long)
74 be64_to_cpu(dip->di_nblocks));
75 XFS_CORRUPTION_ERROR("xfs_iformat(1)", XFS_ERRLEVEL_LOW,
76 ip->i_mount, dip);
77 return -EFSCORRUPTED;
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,
83 dip->di_forkoff);
84 XFS_CORRUPTION_ERROR("xfs_iformat(2)", XFS_ERRLEVEL_LOW,
85 ip->i_mount, dip);
86 return -EFSCORRUPTED;
89 if (unlikely((ip->i_d.di_flags & XFS_DIFLAG_REALTIME) &&
90 !ip->i_mount->m_rtdev_targp)) {
91 xfs_warn(ip->i_mount,
92 "corrupt dinode %Lu, has realtime flag set.",
93 ip->i_ino);
94 XFS_CORRUPTION_ERROR("xfs_iformat(realtime)",
95 XFS_ERRLEVEL_LOW, ip->i_mount, dip);
96 return -EFSCORRUPTED;
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.",
102 ip->i_ino);
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.",
112 ip->i_ino);
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) {
119 case S_IFIFO:
120 case S_IFCHR:
121 case S_IFBLK:
122 case S_IFSOCK:
123 if (unlikely(dip->di_format != XFS_DINODE_FMT_DEV)) {
124 XFS_CORRUPTION_ERROR("xfs_iformat(3)", XFS_ERRLEVEL_LOW,
125 ip->i_mount, dip);
126 return -EFSCORRUPTED;
128 ip->i_d.di_size = 0;
129 inode->i_rdev = xfs_to_linux_dev_t(xfs_dinode_get_rdev(dip));
130 break;
132 case S_IFREG:
133 case S_IFLNK:
134 case S_IFDIR:
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)",
145 XFS_ERRLEVEL_LOW,
146 ip->i_mount, dip);
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)",
158 XFS_ERRLEVEL_LOW,
159 ip->i_mount, dip);
160 return -EFSCORRUPTED;
163 size = (int)di_size;
164 error = xfs_iformat_local(ip, dip, XFS_DATA_FORK, size);
165 break;
166 case XFS_DINODE_FMT_EXTENTS:
167 error = xfs_iformat_extents(ip, dip, XFS_DATA_FORK);
168 break;
169 case XFS_DINODE_FMT_BTREE:
170 error = xfs_iformat_btree(ip, dip, XFS_DATA_FORK);
171 break;
172 default:
173 XFS_ERROR_REPORT("xfs_iformat(6)", XFS_ERRLEVEL_LOW,
174 ip->i_mount);
175 return -EFSCORRUPTED;
177 break;
179 default:
180 XFS_ERROR_REPORT("xfs_iformat(7)", XFS_ERRLEVEL_LOW, ip->i_mount);
181 return -EFSCORRUPTED;
183 if (error)
184 return error;
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);
189 if (error) {
190 xfs_idestroy_fork(ip, XFS_DATA_FORK);
191 return error;
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))
201 return 0;
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,
215 (long long) size);
216 XFS_CORRUPTION_ERROR("xfs_iformat(8)",
217 XFS_ERRLEVEL_LOW,
218 ip->i_mount, dip);
219 error = -EFSCORRUPTED;
220 break;
223 error = xfs_iformat_local(ip, dip, XFS_ATTR_FORK, size);
224 break;
225 case XFS_DINODE_FMT_EXTENTS:
226 error = xfs_iformat_extents(ip, dip, XFS_ATTR_FORK);
227 break;
228 case XFS_DINODE_FMT_BTREE:
229 error = xfs_iformat_btree(ip, dip, XFS_ATTR_FORK);
230 break;
231 default:
232 error = -EFSCORRUPTED;
233 break;
235 if (error) {
236 kmem_zone_free(xfs_ifork_zone, ip->i_afp);
237 ip->i_afp = NULL;
238 if (ip->i_cowfp)
239 kmem_zone_free(xfs_ifork_zone, ip->i_cowfp);
240 ip->i_cowfp = NULL;
241 xfs_idestroy_fork(ip, XFS_DATA_FORK);
243 return error;
246 void
247 xfs_init_local_fork(
248 struct xfs_inode *ip,
249 int whichfork,
250 const void *data,
251 int size)
253 struct xfs_ifork *ifp = XFS_IFORK_PTR(ip, whichfork);
254 int mem_size = size, real_size = 0;
255 bool zero_terminate;
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);
264 if (zero_terminate)
265 mem_size++;
267 if (size) {
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);
271 if (zero_terminate)
272 ifp->if_u1.if_data[size] = '\0';
273 } else {
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.
286 STATIC int
287 xfs_iformat_local(
288 xfs_inode_t *ip,
289 xfs_dinode_t *dip,
290 int whichfork,
291 int size)
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,
304 ip->i_mount, dip);
305 return -EFSCORRUPTED;
308 xfs_init_local_fork(ip, whichfork, XFS_DFORK_PTR(dip, whichfork), size);
309 return 0;
313 * The file consists of a set of extents all of which fit into the on-disk
314 * inode.
316 STATIC int
317 xfs_iformat_extents(
318 struct xfs_inode *ip,
319 struct xfs_dinode *dip,
320 int whichfork)
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;
330 int i;
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,
340 mp, dip);
341 return -EFSCORRUPTED;
344 ifp->if_real_bytes = 0;
345 ifp->if_bytes = 0;
346 ifp->if_u1.if_root = NULL;
347 ifp->if_height = 0;
348 if (size) {
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;
366 return 0;
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).
377 STATIC int
378 xfs_iformat_btree(
379 xfs_inode_t *ip,
380 xfs_dinode_t *dip,
381 int whichfork)
383 struct xfs_mount *mp = ip->i_mount;
384 xfs_bmdr_block_t *dfp;
385 xfs_ifork_t *ifp;
386 /* REFERENCED */
387 int nrecs;
388 int size;
389 int level;
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
402 * blocks.
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,
413 mp, dip);
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;
430 ifp->if_bytes = 0;
431 ifp->if_u1.if_root = NULL;
432 ifp->if_height = 0;
433 return 0;
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
442 * by the caller.
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
448 * it can go to zero.
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.
454 void
455 xfs_iroot_realloc(
456 xfs_inode_t *ip,
457 int rec_diff,
458 int whichfork)
460 struct xfs_mount *mp = ip->i_mount;
461 int cur_max;
462 xfs_ifork_t *ifp;
463 struct xfs_btree_block *new_broot;
464 int new_max;
465 size_t new_size;
466 char *np;
467 char *op;
470 * Handle the degenerate case quietly.
472 if (rec_diff == 0) {
473 return;
476 ifp = XFS_IFORK_PTR(ip, whichfork);
477 if (rec_diff > 0) {
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;
486 return;
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,
499 KM_SLEEP | KM_NOFS);
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,
503 (int)new_size);
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));
508 return;
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);
520 if (new_max > 0)
521 new_size = XFS_BMAP_BROOT_SPACE_CALC(mp, new_max);
522 else
523 new_size = 0;
524 if (new_size > 0) {
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));
531 } else {
532 new_broot = NULL;
533 ifp->if_flags &= ~XFS_IFBROOT;
537 * Only copy the records and pointers if there are any.
539 if (new_max > 0) {
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,
553 (int)new_size);
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;
559 if (ifp->if_broot)
560 ASSERT(XFS_BMAP_BMDR_SPACE(ifp->if_broot) <=
561 XFS_IFORK_SIZE(ip, whichfork));
562 return;
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
575 * to what is needed.
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.
581 void
582 xfs_idata_realloc(
583 xfs_inode_t *ip,
584 int byte_diff,
585 int whichfork)
587 xfs_ifork_t *ifp;
588 int new_size;
589 int real_size;
591 if (byte_diff == 0) {
592 return;
595 ifp = XFS_IFORK_PTR(ip, whichfork);
596 new_size = (int)ifp->if_bytes + byte_diff;
597 ASSERT(new_size >= 0);
599 if (new_size == 0) {
600 kmem_free(ifp->if_u1.if_data);
601 ifp->if_u1.if_data = NULL;
602 real_size = 0;
603 } else {
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
609 * that here.
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,
615 KM_SLEEP | KM_NOFS);
616 } else {
618 * Only do the realloc if the underlying size
619 * is really changing.
621 if (ifp->if_real_bytes != real_size) {
622 ifp->if_u1.if_data =
623 kmem_realloc(ifp->if_u1.if_data,
624 real_size,
625 KM_SLEEP | KM_NOFS);
629 ifp->if_real_bytes = real_size;
630 ifp->if_bytes = new_size;
631 ASSERT(ifp->if_bytes <= XFS_IFORK_SIZE(ip, whichfork));
634 void
635 xfs_idestroy_fork(
636 xfs_inode_t *ip,
637 int whichfork)
639 xfs_ifork_t *ifp;
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);
668 ip->i_afp = NULL;
669 } else if (whichfork == XFS_COW_FORK) {
670 kmem_zone_free(xfs_ifork_zone, ip->i_cowfp);
671 ip->i_cowfp = NULL;
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
682 * used.
685 xfs_iextents_copy(
686 struct xfs_inode *ip,
687 struct xfs_bmbt_rec *dp,
688 int whichfork)
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;
694 int copied = 0;
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))
701 continue;
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);
706 dp++;
709 ASSERT(copied > 0);
710 ASSERT(copied <= ifp->if_bytes);
711 return copied;
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.
724 void
725 xfs_iflush_fork(
726 xfs_inode_t *ip,
727 xfs_dinode_t *dip,
728 xfs_inode_log_item_t *iip,
729 int whichfork)
731 char *cp;
732 xfs_ifork_t *ifp;
733 xfs_mount_t *mp;
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 };
741 if (!iip)
742 return;
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.
748 if (!ifp) {
749 ASSERT(whichfork == XFS_ATTR_FORK);
750 return;
752 cp = XFS_DFORK_PTR(dip, whichfork);
753 mp = ip->i_mount;
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);
762 break;
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,
771 whichfork);
773 break;
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));
785 break;
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));
793 break;
795 default:
796 ASSERT(0);
797 break;
801 /* Convert bmap state flags to an inode fork. */
802 struct xfs_ifork *
803 xfs_iext_state_to_fork(
804 struct xfs_inode *ip,
805 int state)
807 if (state & BMAP_COWFORK)
808 return ip->i_cowfp;
809 else if (state & BMAP_ATTRFORK)
810 return ip->i_afp;
811 return &ip->i_df;
815 * Initialize an inode's copy-on-write fork.
817 void
818 xfs_ifork_init_cow(
819 struct xfs_inode *ip)
821 if (ip->i_cowfp)
822 return;
824 ip->i_cowfp = kmem_zone_zalloc(xfs_ifork_zone,
825 KM_SLEEP | KM_NOFS);
826 ip->i_cowfp->if_flags = XFS_IFEXTENTS;
827 ip->i_cformat = XFS_DINODE_FMT_EXTENTS;
828 ip->i_cnextents = 0;