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