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