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