Linux Audio

Check our new training course

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