642ef9ed5f5735461049467e82a67a603f1911dd
[linux-2.6-microblaze.git] / fs / xfs / libxfs / xfs_inode_fork.c
1 // SPDX-License-Identifier: GPL-2.0
2 /*
3  * Copyright (c) 2000-2006 Silicon Graphics, Inc.
4  * All Rights Reserved.
5  */
6 #include <linux/log2.h>
7
8 #include "xfs.h"
9 #include "xfs_fs.h"
10 #include "xfs_shared.h"
11 #include "xfs_format.h"
12 #include "xfs_log_format.h"
13 #include "xfs_trans_resv.h"
14 #include "xfs_mount.h"
15 #include "xfs_inode.h"
16 #include "xfs_trans.h"
17 #include "xfs_inode_item.h"
18 #include "xfs_btree.h"
19 #include "xfs_bmap_btree.h"
20 #include "xfs_bmap.h"
21 #include "xfs_error.h"
22 #include "xfs_trace.h"
23 #include "xfs_attr_sf.h"
24 #include "xfs_da_format.h"
25 #include "xfs_da_btree.h"
26 #include "xfs_dir2_priv.h"
27 #include "xfs_attr_leaf.h"
28 #include "xfs_shared.h"
29
30 kmem_zone_t *xfs_ifork_zone;
31
32 STATIC int xfs_iformat_local(xfs_inode_t *, xfs_dinode_t *, int, int);
33 STATIC int xfs_iformat_extents(xfs_inode_t *, xfs_dinode_t *, int);
34 STATIC int xfs_iformat_btree(xfs_inode_t *, xfs_dinode_t *, int);
35
36 /*
37  * Copy inode type and data and attr format specific information from the
38  * on-disk inode to the in-core inode and fork structures.  For fifos, devices,
39  * and sockets this means set i_rdev to the proper value.  For files,
40  * directories, and symlinks this means to bring in the in-line data or extent
41  * pointers as well as the attribute fork.  For a fork in B-tree format, only
42  * the root is immediately brought in-core.  The rest will be read in later when
43  * first referenced (see xfs_iread_extents()).
44  */
45 int
46 xfs_iformat_fork(
47         struct xfs_inode        *ip,
48         struct xfs_dinode       *dip)
49 {
50         struct inode            *inode = VFS_I(ip);
51         struct xfs_attr_shortform *atp;
52         int                     size;
53         int                     error = 0;
54         xfs_fsize_t             di_size;
55
56         switch (inode->i_mode & S_IFMT) {
57         case S_IFIFO:
58         case S_IFCHR:
59         case S_IFBLK:
60         case S_IFSOCK:
61                 ip->i_d.di_size = 0;
62                 inode->i_rdev = xfs_to_linux_dev_t(xfs_dinode_get_rdev(dip));
63                 break;
64
65         case S_IFREG:
66         case S_IFLNK:
67         case S_IFDIR:
68                 switch (dip->di_format) {
69                 case XFS_DINODE_FMT_LOCAL:
70                         di_size = be64_to_cpu(dip->di_size);
71                         size = (int)di_size;
72                         error = xfs_iformat_local(ip, dip, XFS_DATA_FORK, size);
73                         break;
74                 case XFS_DINODE_FMT_EXTENTS:
75                         error = xfs_iformat_extents(ip, dip, XFS_DATA_FORK);
76                         break;
77                 case XFS_DINODE_FMT_BTREE:
78                         error = xfs_iformat_btree(ip, dip, XFS_DATA_FORK);
79                         break;
80                 default:
81                         return -EFSCORRUPTED;
82                 }
83                 break;
84
85         default:
86                 return -EFSCORRUPTED;
87         }
88         if (error)
89                 return error;
90
91         if (xfs_is_reflink_inode(ip)) {
92                 ASSERT(ip->i_cowfp == NULL);
93                 xfs_ifork_init_cow(ip);
94         }
95
96         if (!XFS_DFORK_Q(dip))
97                 return 0;
98
99         ASSERT(ip->i_afp == NULL);
100         ip->i_afp = kmem_zone_zalloc(xfs_ifork_zone, KM_SLEEP | KM_NOFS);
101
102         switch (dip->di_aformat) {
103         case XFS_DINODE_FMT_LOCAL:
104                 atp = (xfs_attr_shortform_t *)XFS_DFORK_APTR(dip);
105                 size = be16_to_cpu(atp->hdr.totsize);
106
107                 error = xfs_iformat_local(ip, dip, XFS_ATTR_FORK, size);
108                 break;
109         case XFS_DINODE_FMT_EXTENTS:
110                 error = xfs_iformat_extents(ip, dip, XFS_ATTR_FORK);
111                 break;
112         case XFS_DINODE_FMT_BTREE:
113                 error = xfs_iformat_btree(ip, dip, XFS_ATTR_FORK);
114                 break;
115         default:
116                 error = -EFSCORRUPTED;
117                 break;
118         }
119         if (error) {
120                 kmem_zone_free(xfs_ifork_zone, ip->i_afp);
121                 ip->i_afp = NULL;
122                 if (ip->i_cowfp)
123                         kmem_zone_free(xfs_ifork_zone, ip->i_cowfp);
124                 ip->i_cowfp = NULL;
125                 xfs_idestroy_fork(ip, XFS_DATA_FORK);
126         }
127         return error;
128 }
129
130 void
131 xfs_init_local_fork(
132         struct xfs_inode        *ip,
133         int                     whichfork,
134         const void              *data,
135         int                     size)
136 {
137         struct xfs_ifork        *ifp = XFS_IFORK_PTR(ip, whichfork);
138         int                     mem_size = size, real_size = 0;
139         bool                    zero_terminate;
140
141         /*
142          * If we are using the local fork to store a symlink body we need to
143          * zero-terminate it so that we can pass it back to the VFS directly.
144          * Overallocate the in-memory fork by one for that and add a zero
145          * to terminate it below.
146          */
147         zero_terminate = S_ISLNK(VFS_I(ip)->i_mode);
148         if (zero_terminate)
149                 mem_size++;
150
151         if (size) {
152                 real_size = roundup(mem_size, 4);
153                 ifp->if_u1.if_data = kmem_alloc(real_size, KM_SLEEP | KM_NOFS);
154                 memcpy(ifp->if_u1.if_data, data, size);
155                 if (zero_terminate)
156                         ifp->if_u1.if_data[size] = '\0';
157         } else {
158                 ifp->if_u1.if_data = NULL;
159         }
160
161         ifp->if_bytes = size;
162         ifp->if_flags &= ~(XFS_IFEXTENTS | XFS_IFBROOT);
163         ifp->if_flags |= XFS_IFINLINE;
164 }
165
166 /*
167  * The file is in-lined in the on-disk inode.
168  */
169 STATIC int
170 xfs_iformat_local(
171         xfs_inode_t     *ip,
172         xfs_dinode_t    *dip,
173         int             whichfork,
174         int             size)
175 {
176         /*
177          * If the size is unreasonable, then something
178          * is wrong and we just bail out rather than crash in
179          * kmem_alloc() or memcpy() below.
180          */
181         if (unlikely(size > XFS_DFORK_SIZE(dip, ip->i_mount, whichfork))) {
182                 xfs_warn(ip->i_mount,
183         "corrupt inode %Lu (bad size %d for local fork, size = %d).",
184                         (unsigned long long) ip->i_ino, size,
185                         XFS_DFORK_SIZE(dip, ip->i_mount, whichfork));
186                 xfs_inode_verifier_error(ip, -EFSCORRUPTED,
187                                 "xfs_iformat_local", dip, sizeof(*dip),
188                                 __this_address);
189                 return -EFSCORRUPTED;
190         }
191
192         xfs_init_local_fork(ip, whichfork, XFS_DFORK_PTR(dip, whichfork), size);
193         return 0;
194 }
195
196 /*
197  * The file consists of a set of extents all of which fit into the on-disk
198  * inode.
199  */
200 STATIC int
201 xfs_iformat_extents(
202         struct xfs_inode        *ip,
203         struct xfs_dinode       *dip,
204         int                     whichfork)
205 {
206         struct xfs_mount        *mp = ip->i_mount;
207         struct xfs_ifork        *ifp = XFS_IFORK_PTR(ip, whichfork);
208         int                     state = xfs_bmap_fork_to_state(whichfork);
209         int                     nex = XFS_DFORK_NEXTENTS(dip, whichfork);
210         int                     size = nex * sizeof(xfs_bmbt_rec_t);
211         struct xfs_iext_cursor  icur;
212         struct xfs_bmbt_rec     *dp;
213         struct xfs_bmbt_irec    new;
214         int                     i;
215
216         /*
217          * If the number of extents is unreasonable, then something is wrong and
218          * we just bail out rather than crash in kmem_alloc() or memcpy() below.
219          */
220         if (unlikely(size < 0 || size > XFS_DFORK_SIZE(dip, mp, whichfork))) {
221                 xfs_warn(ip->i_mount, "corrupt inode %Lu ((a)extents = %d).",
222                         (unsigned long long) ip->i_ino, nex);
223                 xfs_inode_verifier_error(ip, -EFSCORRUPTED,
224                                 "xfs_iformat_extents(1)", dip, sizeof(*dip),
225                                 __this_address);
226                 return -EFSCORRUPTED;
227         }
228
229         ifp->if_bytes = 0;
230         ifp->if_u1.if_root = NULL;
231         ifp->if_height = 0;
232         if (size) {
233                 dp = (xfs_bmbt_rec_t *) XFS_DFORK_PTR(dip, whichfork);
234
235                 xfs_iext_first(ifp, &icur);
236                 for (i = 0; i < nex; i++, dp++) {
237                         xfs_failaddr_t  fa;
238
239                         xfs_bmbt_disk_get_all(dp, &new);
240                         fa = xfs_bmap_validate_extent(ip, whichfork, &new);
241                         if (fa) {
242                                 xfs_inode_verifier_error(ip, -EFSCORRUPTED,
243                                                 "xfs_iformat_extents(2)",
244                                                 dp, sizeof(*dp), fa);
245                                 return -EFSCORRUPTED;
246                         }
247
248                         xfs_iext_insert(ip, &icur, &new, state);
249                         trace_xfs_read_extent(ip, &icur, state, _THIS_IP_);
250                         xfs_iext_next(ifp, &icur);
251                 }
252         }
253         ifp->if_flags |= XFS_IFEXTENTS;
254         return 0;
255 }
256
257 /*
258  * The file has too many extents to fit into
259  * the inode, so they are in B-tree format.
260  * Allocate a buffer for the root of the B-tree
261  * and copy the root into it.  The i_extents
262  * field will remain NULL until all of the
263  * extents are read in (when they are needed).
264  */
265 STATIC int
266 xfs_iformat_btree(
267         xfs_inode_t             *ip,
268         xfs_dinode_t            *dip,
269         int                     whichfork)
270 {
271         struct xfs_mount        *mp = ip->i_mount;
272         xfs_bmdr_block_t        *dfp;
273         struct xfs_ifork        *ifp;
274         /* REFERENCED */
275         int                     nrecs;
276         int                     size;
277         int                     level;
278
279         ifp = XFS_IFORK_PTR(ip, whichfork);
280         dfp = (xfs_bmdr_block_t *)XFS_DFORK_PTR(dip, whichfork);
281         size = XFS_BMAP_BROOT_SPACE(mp, dfp);
282         nrecs = be16_to_cpu(dfp->bb_numrecs);
283         level = be16_to_cpu(dfp->bb_level);
284
285         /*
286          * blow out if -- fork has less extents than can fit in
287          * fork (fork shouldn't be a btree format), root btree
288          * block has more records than can fit into the fork,
289          * or the number of extents is greater than the number of
290          * blocks.
291          */
292         if (unlikely(XFS_IFORK_NEXTENTS(ip, whichfork) <=
293                                         XFS_IFORK_MAXEXT(ip, whichfork) ||
294                      nrecs == 0 ||
295                      XFS_BMDR_SPACE_CALC(nrecs) >
296                                         XFS_DFORK_SIZE(dip, mp, whichfork) ||
297                      XFS_IFORK_NEXTENTS(ip, whichfork) > ip->i_d.di_nblocks) ||
298                      level == 0 || level > XFS_BTREE_MAXLEVELS) {
299                 xfs_warn(mp, "corrupt inode %Lu (btree).",
300                                         (unsigned long long) ip->i_ino);
301                 xfs_inode_verifier_error(ip, -EFSCORRUPTED,
302                                 "xfs_iformat_btree", dfp, size,
303                                 __this_address);
304                 return -EFSCORRUPTED;
305         }
306
307         ifp->if_broot_bytes = size;
308         ifp->if_broot = kmem_alloc(size, KM_SLEEP | KM_NOFS);
309         ASSERT(ifp->if_broot != NULL);
310         /*
311          * Copy and convert from the on-disk structure
312          * to the in-memory structure.
313          */
314         xfs_bmdr_to_bmbt(ip, dfp, XFS_DFORK_SIZE(dip, ip->i_mount, whichfork),
315                          ifp->if_broot, size);
316         ifp->if_flags &= ~XFS_IFEXTENTS;
317         ifp->if_flags |= XFS_IFBROOT;
318
319         ifp->if_bytes = 0;
320         ifp->if_u1.if_root = NULL;
321         ifp->if_height = 0;
322         return 0;
323 }
324
325 /*
326  * Reallocate the space for if_broot based on the number of records
327  * being added or deleted as indicated in rec_diff.  Move the records
328  * and pointers in if_broot to fit the new size.  When shrinking this
329  * will eliminate holes between the records and pointers created by
330  * the caller.  When growing this will create holes to be filled in
331  * by the caller.
332  *
333  * The caller must not request to add more records than would fit in
334  * the on-disk inode root.  If the if_broot is currently NULL, then
335  * if we are adding records, one will be allocated.  The caller must also
336  * not request that the number of records go below zero, although
337  * it can go to zero.
338  *
339  * ip -- the inode whose if_broot area is changing
340  * ext_diff -- the change in the number of records, positive or negative,
341  *       requested for the if_broot array.
342  */
343 void
344 xfs_iroot_realloc(
345         xfs_inode_t             *ip,
346         int                     rec_diff,
347         int                     whichfork)
348 {
349         struct xfs_mount        *mp = ip->i_mount;
350         int                     cur_max;
351         struct xfs_ifork        *ifp;
352         struct xfs_btree_block  *new_broot;
353         int                     new_max;
354         size_t                  new_size;
355         char                    *np;
356         char                    *op;
357
358         /*
359          * Handle the degenerate case quietly.
360          */
361         if (rec_diff == 0) {
362                 return;
363         }
364
365         ifp = XFS_IFORK_PTR(ip, whichfork);
366         if (rec_diff > 0) {
367                 /*
368                  * If there wasn't any memory allocated before, just
369                  * allocate it now and get out.
370                  */
371                 if (ifp->if_broot_bytes == 0) {
372                         new_size = XFS_BMAP_BROOT_SPACE_CALC(mp, rec_diff);
373                         ifp->if_broot = kmem_alloc(new_size, KM_SLEEP | KM_NOFS);
374                         ifp->if_broot_bytes = (int)new_size;
375                         return;
376                 }
377
378                 /*
379                  * If there is already an existing if_broot, then we need
380                  * to realloc() it and shift the pointers to their new
381                  * location.  The records don't change location because
382                  * they are kept butted up against the btree block header.
383                  */
384                 cur_max = xfs_bmbt_maxrecs(mp, ifp->if_broot_bytes, 0);
385                 new_max = cur_max + rec_diff;
386                 new_size = XFS_BMAP_BROOT_SPACE_CALC(mp, new_max);
387                 ifp->if_broot = kmem_realloc(ifp->if_broot, new_size,
388                                 KM_SLEEP | KM_NOFS);
389                 op = (char *)XFS_BMAP_BROOT_PTR_ADDR(mp, ifp->if_broot, 1,
390                                                      ifp->if_broot_bytes);
391                 np = (char *)XFS_BMAP_BROOT_PTR_ADDR(mp, ifp->if_broot, 1,
392                                                      (int)new_size);
393                 ifp->if_broot_bytes = (int)new_size;
394                 ASSERT(XFS_BMAP_BMDR_SPACE(ifp->if_broot) <=
395                         XFS_IFORK_SIZE(ip, whichfork));
396                 memmove(np, op, cur_max * (uint)sizeof(xfs_fsblock_t));
397                 return;
398         }
399
400         /*
401          * rec_diff is less than 0.  In this case, we are shrinking the
402          * if_broot buffer.  It must already exist.  If we go to zero
403          * records, just get rid of the root and clear the status bit.
404          */
405         ASSERT((ifp->if_broot != NULL) && (ifp->if_broot_bytes > 0));
406         cur_max = xfs_bmbt_maxrecs(mp, ifp->if_broot_bytes, 0);
407         new_max = cur_max + rec_diff;
408         ASSERT(new_max >= 0);
409         if (new_max > 0)
410                 new_size = XFS_BMAP_BROOT_SPACE_CALC(mp, new_max);
411         else
412                 new_size = 0;
413         if (new_size > 0) {
414                 new_broot = kmem_alloc(new_size, KM_SLEEP | KM_NOFS);
415                 /*
416                  * First copy over the btree block header.
417                  */
418                 memcpy(new_broot, ifp->if_broot,
419                         XFS_BMBT_BLOCK_LEN(ip->i_mount));
420         } else {
421                 new_broot = NULL;
422                 ifp->if_flags &= ~XFS_IFBROOT;
423         }
424
425         /*
426          * Only copy the records and pointers if there are any.
427          */
428         if (new_max > 0) {
429                 /*
430                  * First copy the records.
431                  */
432                 op = (char *)XFS_BMBT_REC_ADDR(mp, ifp->if_broot, 1);
433                 np = (char *)XFS_BMBT_REC_ADDR(mp, new_broot, 1);
434                 memcpy(np, op, new_max * (uint)sizeof(xfs_bmbt_rec_t));
435
436                 /*
437                  * Then copy the pointers.
438                  */
439                 op = (char *)XFS_BMAP_BROOT_PTR_ADDR(mp, ifp->if_broot, 1,
440                                                      ifp->if_broot_bytes);
441                 np = (char *)XFS_BMAP_BROOT_PTR_ADDR(mp, new_broot, 1,
442                                                      (int)new_size);
443                 memcpy(np, op, new_max * (uint)sizeof(xfs_fsblock_t));
444         }
445         kmem_free(ifp->if_broot);
446         ifp->if_broot = new_broot;
447         ifp->if_broot_bytes = (int)new_size;
448         if (ifp->if_broot)
449                 ASSERT(XFS_BMAP_BMDR_SPACE(ifp->if_broot) <=
450                         XFS_IFORK_SIZE(ip, whichfork));
451         return;
452 }
453
454
455 /*
456  * This is called when the amount of space needed for if_data
457  * is increased or decreased.  The change in size is indicated by
458  * the number of bytes that need to be added or deleted in the
459  * byte_diff parameter.
460  *
461  * If the amount of space needed has decreased below the size of the
462  * inline buffer, then switch to using the inline buffer.  Otherwise,
463  * use kmem_realloc() or kmem_alloc() to adjust the size of the buffer
464  * to what is needed.
465  *
466  * ip -- the inode whose if_data area is changing
467  * byte_diff -- the change in the number of bytes, positive or negative,
468  *       requested for the if_data array.
469  */
470 void
471 xfs_idata_realloc(
472         struct xfs_inode        *ip,
473         int                     byte_diff,
474         int                     whichfork)
475 {
476         struct xfs_ifork        *ifp = XFS_IFORK_PTR(ip, whichfork);
477         int                     new_size = (int)ifp->if_bytes + byte_diff;
478
479         ASSERT(new_size >= 0);
480         ASSERT(new_size <= XFS_IFORK_SIZE(ip, whichfork));
481
482         if (byte_diff == 0)
483                 return;
484
485         if (new_size == 0) {
486                 kmem_free(ifp->if_u1.if_data);
487                 ifp->if_u1.if_data = NULL;
488                 ifp->if_bytes = 0;
489                 return;
490         }
491
492         /*
493          * For inline data, the underlying buffer must be a multiple of 4 bytes
494          * in size so that it can be logged and stay on word boundaries.
495          * We enforce that here.
496          */
497         ifp->if_u1.if_data = kmem_realloc(ifp->if_u1.if_data,
498                         roundup(new_size, 4), KM_SLEEP | KM_NOFS);
499         ifp->if_bytes = new_size;
500 }
501
502 void
503 xfs_idestroy_fork(
504         xfs_inode_t     *ip,
505         int             whichfork)
506 {
507         struct xfs_ifork        *ifp;
508
509         ifp = XFS_IFORK_PTR(ip, whichfork);
510         if (ifp->if_broot != NULL) {
511                 kmem_free(ifp->if_broot);
512                 ifp->if_broot = NULL;
513         }
514
515         /*
516          * If the format is local, then we can't have an extents
517          * array so just look for an inline data array.  If we're
518          * not local then we may or may not have an extents list,
519          * so check and free it up if we do.
520          */
521         if (XFS_IFORK_FORMAT(ip, whichfork) == XFS_DINODE_FMT_LOCAL) {
522                 if (ifp->if_u1.if_data != NULL) {
523                         kmem_free(ifp->if_u1.if_data);
524                         ifp->if_u1.if_data = NULL;
525                 }
526         } else if ((ifp->if_flags & XFS_IFEXTENTS) && ifp->if_height) {
527                 xfs_iext_destroy(ifp);
528         }
529
530         if (whichfork == XFS_ATTR_FORK) {
531                 kmem_zone_free(xfs_ifork_zone, ip->i_afp);
532                 ip->i_afp = NULL;
533         } else if (whichfork == XFS_COW_FORK) {
534                 kmem_zone_free(xfs_ifork_zone, ip->i_cowfp);
535                 ip->i_cowfp = NULL;
536         }
537 }
538
539 /*
540  * Convert in-core extents to on-disk form
541  *
542  * In the case of the data fork, the in-core and on-disk fork sizes can be
543  * different due to delayed allocation extents. We only copy on-disk extents
544  * here, so callers must always use the physical fork size to determine the
545  * size of the buffer passed to this routine.  We will return the size actually
546  * used.
547  */
548 int
549 xfs_iextents_copy(
550         struct xfs_inode        *ip,
551         struct xfs_bmbt_rec     *dp,
552         int                     whichfork)
553 {
554         int                     state = xfs_bmap_fork_to_state(whichfork);
555         struct xfs_ifork        *ifp = XFS_IFORK_PTR(ip, whichfork);
556         struct xfs_iext_cursor  icur;
557         struct xfs_bmbt_irec    rec;
558         int                     copied = 0;
559
560         ASSERT(xfs_isilocked(ip, XFS_ILOCK_EXCL | XFS_ILOCK_SHARED));
561         ASSERT(ifp->if_bytes > 0);
562
563         for_each_xfs_iext(ifp, &icur, &rec) {
564                 if (isnullstartblock(rec.br_startblock))
565                         continue;
566                 ASSERT(xfs_bmap_validate_extent(ip, whichfork, &rec) == NULL);
567                 xfs_bmbt_disk_set_all(dp, &rec);
568                 trace_xfs_write_extent(ip, &icur, state, _RET_IP_);
569                 copied += sizeof(struct xfs_bmbt_rec);
570                 dp++;
571         }
572
573         ASSERT(copied > 0);
574         ASSERT(copied <= ifp->if_bytes);
575         return copied;
576 }
577
578 /*
579  * Each of the following cases stores data into the same region
580  * of the on-disk inode, so only one of them can be valid at
581  * any given time. While it is possible to have conflicting formats
582  * and log flags, e.g. having XFS_ILOG_?DATA set when the fork is
583  * in EXTENTS format, this can only happen when the fork has
584  * changed formats after being modified but before being flushed.
585  * In these cases, the format always takes precedence, because the
586  * format indicates the current state of the fork.
587  */
588 void
589 xfs_iflush_fork(
590         xfs_inode_t             *ip,
591         xfs_dinode_t            *dip,
592         xfs_inode_log_item_t    *iip,
593         int                     whichfork)
594 {
595         char                    *cp;
596         struct xfs_ifork        *ifp;
597         xfs_mount_t             *mp;
598         static const short      brootflag[2] =
599                 { XFS_ILOG_DBROOT, XFS_ILOG_ABROOT };
600         static const short      dataflag[2] =
601                 { XFS_ILOG_DDATA, XFS_ILOG_ADATA };
602         static const short      extflag[2] =
603                 { XFS_ILOG_DEXT, XFS_ILOG_AEXT };
604
605         if (!iip)
606                 return;
607         ifp = XFS_IFORK_PTR(ip, whichfork);
608         /*
609          * This can happen if we gave up in iformat in an error path,
610          * for the attribute fork.
611          */
612         if (!ifp) {
613                 ASSERT(whichfork == XFS_ATTR_FORK);
614                 return;
615         }
616         cp = XFS_DFORK_PTR(dip, whichfork);
617         mp = ip->i_mount;
618         switch (XFS_IFORK_FORMAT(ip, whichfork)) {
619         case XFS_DINODE_FMT_LOCAL:
620                 if ((iip->ili_fields & dataflag[whichfork]) &&
621                     (ifp->if_bytes > 0)) {
622                         ASSERT(ifp->if_u1.if_data != NULL);
623                         ASSERT(ifp->if_bytes <= XFS_IFORK_SIZE(ip, whichfork));
624                         memcpy(cp, ifp->if_u1.if_data, ifp->if_bytes);
625                 }
626                 break;
627
628         case XFS_DINODE_FMT_EXTENTS:
629                 ASSERT((ifp->if_flags & XFS_IFEXTENTS) ||
630                        !(iip->ili_fields & extflag[whichfork]));
631                 if ((iip->ili_fields & extflag[whichfork]) &&
632                     (ifp->if_bytes > 0)) {
633                         ASSERT(XFS_IFORK_NEXTENTS(ip, whichfork) > 0);
634                         (void)xfs_iextents_copy(ip, (xfs_bmbt_rec_t *)cp,
635                                 whichfork);
636                 }
637                 break;
638
639         case XFS_DINODE_FMT_BTREE:
640                 if ((iip->ili_fields & brootflag[whichfork]) &&
641                     (ifp->if_broot_bytes > 0)) {
642                         ASSERT(ifp->if_broot != NULL);
643                         ASSERT(XFS_BMAP_BMDR_SPACE(ifp->if_broot) <=
644                                 XFS_IFORK_SIZE(ip, whichfork));
645                         xfs_bmbt_to_bmdr(mp, ifp->if_broot, ifp->if_broot_bytes,
646                                 (xfs_bmdr_block_t *)cp,
647                                 XFS_DFORK_SIZE(dip, mp, whichfork));
648                 }
649                 break;
650
651         case XFS_DINODE_FMT_DEV:
652                 if (iip->ili_fields & XFS_ILOG_DEV) {
653                         ASSERT(whichfork == XFS_DATA_FORK);
654                         xfs_dinode_put_rdev(dip,
655                                         linux_to_xfs_dev_t(VFS_I(ip)->i_rdev));
656                 }
657                 break;
658
659         default:
660                 ASSERT(0);
661                 break;
662         }
663 }
664
665 /* Convert bmap state flags to an inode fork. */
666 struct xfs_ifork *
667 xfs_iext_state_to_fork(
668         struct xfs_inode        *ip,
669         int                     state)
670 {
671         if (state & BMAP_COWFORK)
672                 return ip->i_cowfp;
673         else if (state & BMAP_ATTRFORK)
674                 return ip->i_afp;
675         return &ip->i_df;
676 }
677
678 /*
679  * Initialize an inode's copy-on-write fork.
680  */
681 void
682 xfs_ifork_init_cow(
683         struct xfs_inode        *ip)
684 {
685         if (ip->i_cowfp)
686                 return;
687
688         ip->i_cowfp = kmem_zone_zalloc(xfs_ifork_zone,
689                                        KM_SLEEP | KM_NOFS);
690         ip->i_cowfp->if_flags = XFS_IFEXTENTS;
691         ip->i_cformat = XFS_DINODE_FMT_EXTENTS;
692         ip->i_cnextents = 0;
693 }
694
695 /* Default fork content verifiers. */
696 struct xfs_ifork_ops xfs_default_ifork_ops = {
697         .verify_attr    = xfs_attr_shortform_verify,
698         .verify_dir     = xfs_dir2_sf_verify,
699         .verify_symlink = xfs_symlink_shortform_verify,
700 };
701
702 /* Verify the inline contents of the data fork of an inode. */
703 xfs_failaddr_t
704 xfs_ifork_verify_data(
705         struct xfs_inode        *ip,
706         struct xfs_ifork_ops    *ops)
707 {
708         /* Non-local data fork, we're done. */
709         if (ip->i_d.di_format != XFS_DINODE_FMT_LOCAL)
710                 return NULL;
711
712         /* Check the inline data fork if there is one. */
713         switch (VFS_I(ip)->i_mode & S_IFMT) {
714         case S_IFDIR:
715                 return ops->verify_dir(ip);
716         case S_IFLNK:
717                 return ops->verify_symlink(ip);
718         default:
719                 return NULL;
720         }
721 }
722
723 /* Verify the inline contents of the attr fork of an inode. */
724 xfs_failaddr_t
725 xfs_ifork_verify_attr(
726         struct xfs_inode        *ip,
727         struct xfs_ifork_ops    *ops)
728 {
729         /* There has to be an attr fork allocated if aformat is local. */
730         if (ip->i_d.di_aformat != XFS_DINODE_FMT_LOCAL)
731                 return NULL;
732         if (!XFS_IFORK_PTR(ip, XFS_ATTR_FORK))
733                 return __this_address;
734         return ops->verify_attr(ip);
735 }