cachepc-linux

Fork of AMDESE/linux with modifications for CachePC side-channel attack
git clone https://git.sinitax.com/sinitax/cachepc-linux
Log | Files | Refs | README | LICENSE | sfeed.txt

xfs_inode_fork.c (19837B)


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