brintos

brintos / linux-shallow public Read only

0
0
Text · 33.6 KiB · a16b05c Raw
1252 lines · c
1// SPDX-License-Identifier: GPL-2.02/*3 * Copyright (c) 2000-2002,2005 Silicon Graphics, Inc.4 * Copyright (c) 2013 Red Hat, Inc.5 * All Rights Reserved.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_dir2.h"16#include "xfs_dir2_priv.h"17#include "xfs_error.h"18#include "xfs_trans.h"19#include "xfs_buf_item.h"20#include "xfs_log.h"21#include "xfs_health.h"22 23static xfs_failaddr_t xfs_dir2_data_freefind_verify(24		struct xfs_dir2_data_hdr *hdr, struct xfs_dir2_data_free *bf,25		struct xfs_dir2_data_unused *dup,26		struct xfs_dir2_data_free **bf_ent);27 28struct xfs_dir2_data_free *29xfs_dir2_data_bestfree_p(30	struct xfs_mount		*mp,31	struct xfs_dir2_data_hdr	*hdr)32{33	if (xfs_has_crc(mp))34		return ((struct xfs_dir3_data_hdr *)hdr)->best_free;35	return hdr->bestfree;36}37 38/*39 * Pointer to an entry's tag word.40 */41__be16 *42xfs_dir2_data_entry_tag_p(43	struct xfs_mount		*mp,44	struct xfs_dir2_data_entry	*dep)45{46	return (__be16 *)((char *)dep +47		xfs_dir2_data_entsize(mp, dep->namelen) - sizeof(__be16));48}49 50uint8_t51xfs_dir2_data_get_ftype(52	struct xfs_mount		*mp,53	struct xfs_dir2_data_entry	*dep)54{55	if (xfs_has_ftype(mp)) {56		uint8_t			ftype = dep->name[dep->namelen];57 58		if (likely(ftype < XFS_DIR3_FT_MAX))59			return ftype;60	}61 62	return XFS_DIR3_FT_UNKNOWN;63}64 65void66xfs_dir2_data_put_ftype(67	struct xfs_mount		*mp,68	struct xfs_dir2_data_entry	*dep,69	uint8_t				ftype)70{71	ASSERT(ftype < XFS_DIR3_FT_MAX);72	ASSERT(dep->namelen != 0);73 74	if (xfs_has_ftype(mp))75		dep->name[dep->namelen] = ftype;76}77 78/*79 * The number of leaf entries is limited by the size of the block and the amount80 * of space used by the data entries.  We don't know how much space is used by81 * the data entries yet, so just ensure that the count falls somewhere inside82 * the block right now.83 */84static inline unsigned int85xfs_dir2_data_max_leaf_entries(86	struct xfs_da_geometry		*geo)87{88	return (geo->blksize - sizeof(struct xfs_dir2_block_tail) -89		geo->data_entry_offset) /90			sizeof(struct xfs_dir2_leaf_entry);91}92 93/*94 * Check the consistency of the data block.95 * The input can also be a block-format directory.96 * Return NULL if the buffer is good, otherwise the address of the error.97 */98xfs_failaddr_t99__xfs_dir3_data_check(100	struct xfs_inode	*dp,		/* incore inode pointer */101	struct xfs_buf		*bp)		/* data block's buffer */102{103	xfs_dir2_dataptr_t	addr;		/* addr for leaf lookup */104	xfs_dir2_data_free_t	*bf;		/* bestfree table */105	xfs_dir2_block_tail_t	*btp=NULL;	/* block tail */106	int			count;		/* count of entries found */107	xfs_dir2_data_hdr_t	*hdr;		/* data block header */108	xfs_dir2_data_free_t	*dfp;		/* bestfree entry */109	int			freeseen;	/* mask of bestfrees seen */110	xfs_dahash_t		hash;		/* hash of current name */111	int			i;		/* leaf index */112	int			lastfree;	/* last entry was unused */113	xfs_dir2_leaf_entry_t	*lep=NULL;	/* block leaf entries */114	struct xfs_mount	*mp = bp->b_mount;115	int			stale;		/* count of stale leaves */116	struct xfs_name		name;117	unsigned int		offset;118	unsigned int		end;119	struct xfs_da_geometry	*geo = mp->m_dir_geo;120 121	/*122	 * If this isn't a directory, something is seriously wrong.  Bail out.123	 */124	if (dp && !S_ISDIR(VFS_I(dp)->i_mode))125		return __this_address;126 127	hdr = bp->b_addr;128	offset = geo->data_entry_offset;129 130	switch (hdr->magic) {131	case cpu_to_be32(XFS_DIR3_BLOCK_MAGIC):132	case cpu_to_be32(XFS_DIR2_BLOCK_MAGIC):133		btp = xfs_dir2_block_tail_p(geo, hdr);134		lep = xfs_dir2_block_leaf_p(btp);135 136		if (be32_to_cpu(btp->count) >=137		    xfs_dir2_data_max_leaf_entries(geo))138			return __this_address;139		break;140	case cpu_to_be32(XFS_DIR3_DATA_MAGIC):141	case cpu_to_be32(XFS_DIR2_DATA_MAGIC):142		break;143	default:144		return __this_address;145	}146	end = xfs_dir3_data_end_offset(geo, hdr);147	if (!end)148		return __this_address;149 150	/*151	 * Account for zero bestfree entries.152	 */153	bf = xfs_dir2_data_bestfree_p(mp, hdr);154	count = lastfree = freeseen = 0;155	if (!bf[0].length) {156		if (bf[0].offset)157			return __this_address;158		freeseen |= 1 << 0;159	}160	if (!bf[1].length) {161		if (bf[1].offset)162			return __this_address;163		freeseen |= 1 << 1;164	}165	if (!bf[2].length) {166		if (bf[2].offset)167			return __this_address;168		freeseen |= 1 << 2;169	}170 171	if (be16_to_cpu(bf[0].length) < be16_to_cpu(bf[1].length))172		return __this_address;173	if (be16_to_cpu(bf[1].length) < be16_to_cpu(bf[2].length))174		return __this_address;175	/*176	 * Loop over the data/unused entries.177	 */178	while (offset < end) {179		struct xfs_dir2_data_unused	*dup = bp->b_addr + offset;180		struct xfs_dir2_data_entry	*dep = bp->b_addr + offset;181		unsigned int	reclen;182 183		/*184		 * Are the remaining bytes large enough to hold an185		 * unused entry?186		 */187		if (offset > end - xfs_dir2_data_unusedsize(1))188			return __this_address;189 190		/*191		 * If it's unused, look for the space in the bestfree table.192		 * If we find it, account for that, else make sure it193		 * doesn't need to be there.194		 */195		if (be16_to_cpu(dup->freetag) == XFS_DIR2_DATA_FREE_TAG) {196			xfs_failaddr_t	fa;197 198			reclen = xfs_dir2_data_unusedsize(199					be16_to_cpu(dup->length));200			if (lastfree != 0)201				return __this_address;202			if (be16_to_cpu(dup->length) != reclen)203				return __this_address;204			if (offset + reclen > end)205				return __this_address;206			if (be16_to_cpu(*xfs_dir2_data_unused_tag_p(dup)) !=207			    offset)208				return __this_address;209			fa = xfs_dir2_data_freefind_verify(hdr, bf, dup, &dfp);210			if (fa)211				return fa;212			if (dfp) {213				i = (int)(dfp - bf);214				if ((freeseen & (1 << i)) != 0)215					return __this_address;216				freeseen |= 1 << i;217			} else {218				if (be16_to_cpu(dup->length) >219				    be16_to_cpu(bf[2].length))220					return __this_address;221			}222			offset += reclen;223			lastfree = 1;224			continue;225		}226 227		/*228		 * This is not an unused entry. Are the remaining bytes229		 * large enough for a dirent with a single-byte name?230		 */231		if (offset > end - xfs_dir2_data_entsize(mp, 1))232			return __this_address;233 234		/*235		 * It's a real entry.  Validate the fields.236		 * If this is a block directory then make sure it's237		 * in the leaf section of the block.238		 * The linear search is crude but this is DEBUG code.239		 */240		if (dep->namelen == 0)241			return __this_address;242		reclen = xfs_dir2_data_entsize(mp, dep->namelen);243		if (offset + reclen > end)244			return __this_address;245		if (!xfs_verify_dir_ino(mp, be64_to_cpu(dep->inumber)))246			return __this_address;247		if (be16_to_cpu(*xfs_dir2_data_entry_tag_p(mp, dep)) != offset)248			return __this_address;249		if (xfs_dir2_data_get_ftype(mp, dep) >= XFS_DIR3_FT_MAX)250			return __this_address;251		count++;252		lastfree = 0;253		if (hdr->magic == cpu_to_be32(XFS_DIR2_BLOCK_MAGIC) ||254		    hdr->magic == cpu_to_be32(XFS_DIR3_BLOCK_MAGIC)) {255			addr = xfs_dir2_db_off_to_dataptr(geo, geo->datablk,256						(xfs_dir2_data_aoff_t)257						((char *)dep - (char *)hdr));258			name.name = dep->name;259			name.len = dep->namelen;260			hash = xfs_dir2_hashname(mp, &name);261			for (i = 0; i < be32_to_cpu(btp->count); i++) {262				if (be32_to_cpu(lep[i].address) == addr &&263				    be32_to_cpu(lep[i].hashval) == hash)264					break;265			}266			if (i >= be32_to_cpu(btp->count))267				return __this_address;268		}269		offset += reclen;270	}271	/*272	 * Need to have seen all the entries and all the bestfree slots.273	 */274	if (freeseen != 7)275		return __this_address;276	if (hdr->magic == cpu_to_be32(XFS_DIR2_BLOCK_MAGIC) ||277	    hdr->magic == cpu_to_be32(XFS_DIR3_BLOCK_MAGIC)) {278		for (i = stale = 0; i < be32_to_cpu(btp->count); i++) {279			if (lep[i].address ==280			    cpu_to_be32(XFS_DIR2_NULL_DATAPTR))281				stale++;282			if (i > 0 && be32_to_cpu(lep[i].hashval) <283				     be32_to_cpu(lep[i - 1].hashval))284				return __this_address;285		}286		if (count != be32_to_cpu(btp->count) - be32_to_cpu(btp->stale))287			return __this_address;288		if (stale != be32_to_cpu(btp->stale))289			return __this_address;290	}291	return NULL;292}293 294#ifdef DEBUG295void296xfs_dir3_data_check(297	struct xfs_inode	*dp,298	struct xfs_buf		*bp)299{300	xfs_failaddr_t		fa;301 302	fa = __xfs_dir3_data_check(dp, bp);303	if (!fa)304		return;305	xfs_corruption_error(__func__, XFS_ERRLEVEL_LOW, dp->i_mount,306			bp->b_addr, BBTOB(bp->b_length), __FILE__, __LINE__,307			fa);308	ASSERT(0);309}310#endif311 312static xfs_failaddr_t313xfs_dir3_data_verify(314	struct xfs_buf		*bp)315{316	struct xfs_mount	*mp = bp->b_mount;317	struct xfs_dir3_blk_hdr	*hdr3 = bp->b_addr;318 319	if (!xfs_verify_magic(bp, hdr3->magic))320		return __this_address;321 322	if (xfs_has_crc(mp)) {323		if (!uuid_equal(&hdr3->uuid, &mp->m_sb.sb_meta_uuid))324			return __this_address;325		if (be64_to_cpu(hdr3->blkno) != xfs_buf_daddr(bp))326			return __this_address;327		if (!xfs_log_check_lsn(mp, be64_to_cpu(hdr3->lsn)))328			return __this_address;329	}330	return __xfs_dir3_data_check(NULL, bp);331}332 333/*334 * Readahead of the first block of the directory when it is opened is completely335 * oblivious to the format of the directory. Hence we can either get a block336 * format buffer or a data format buffer on readahead.337 */338static void339xfs_dir3_data_reada_verify(340	struct xfs_buf		*bp)341{342	struct xfs_dir2_data_hdr *hdr = bp->b_addr;343 344	switch (hdr->magic) {345	case cpu_to_be32(XFS_DIR2_BLOCK_MAGIC):346	case cpu_to_be32(XFS_DIR3_BLOCK_MAGIC):347		bp->b_ops = &xfs_dir3_block_buf_ops;348		bp->b_ops->verify_read(bp);349		return;350	case cpu_to_be32(XFS_DIR2_DATA_MAGIC):351	case cpu_to_be32(XFS_DIR3_DATA_MAGIC):352		bp->b_ops = &xfs_dir3_data_buf_ops;353		bp->b_ops->verify_read(bp);354		return;355	default:356		xfs_verifier_error(bp, -EFSCORRUPTED, __this_address);357		break;358	}359}360 361static void362xfs_dir3_data_read_verify(363	struct xfs_buf	*bp)364{365	struct xfs_mount	*mp = bp->b_mount;366	xfs_failaddr_t		fa;367 368	if (xfs_has_crc(mp) &&369	    !xfs_buf_verify_cksum(bp, XFS_DIR3_DATA_CRC_OFF))370		xfs_verifier_error(bp, -EFSBADCRC, __this_address);371	else {372		fa = xfs_dir3_data_verify(bp);373		if (fa)374			xfs_verifier_error(bp, -EFSCORRUPTED, fa);375	}376}377 378static void379xfs_dir3_data_write_verify(380	struct xfs_buf	*bp)381{382	struct xfs_mount	*mp = bp->b_mount;383	struct xfs_buf_log_item	*bip = bp->b_log_item;384	struct xfs_dir3_blk_hdr	*hdr3 = bp->b_addr;385	xfs_failaddr_t		fa;386 387	fa = xfs_dir3_data_verify(bp);388	if (fa) {389		xfs_verifier_error(bp, -EFSCORRUPTED, fa);390		return;391	}392 393	if (!xfs_has_crc(mp))394		return;395 396	if (bip)397		hdr3->lsn = cpu_to_be64(bip->bli_item.li_lsn);398 399	xfs_buf_update_cksum(bp, XFS_DIR3_DATA_CRC_OFF);400}401 402const struct xfs_buf_ops xfs_dir3_data_buf_ops = {403	.name = "xfs_dir3_data",404	.magic = { cpu_to_be32(XFS_DIR2_DATA_MAGIC),405		   cpu_to_be32(XFS_DIR3_DATA_MAGIC) },406	.verify_read = xfs_dir3_data_read_verify,407	.verify_write = xfs_dir3_data_write_verify,408	.verify_struct = xfs_dir3_data_verify,409};410 411static const struct xfs_buf_ops xfs_dir3_data_reada_buf_ops = {412	.name = "xfs_dir3_data_reada",413	.magic = { cpu_to_be32(XFS_DIR2_DATA_MAGIC),414		   cpu_to_be32(XFS_DIR3_DATA_MAGIC) },415	.verify_read = xfs_dir3_data_reada_verify,416	.verify_write = xfs_dir3_data_write_verify,417};418 419xfs_failaddr_t420xfs_dir3_data_header_check(421	struct xfs_buf		*bp,422	xfs_ino_t		owner)423{424	struct xfs_mount	*mp = bp->b_mount;425 426	if (xfs_has_crc(mp)) {427		struct xfs_dir3_data_hdr *hdr3 = bp->b_addr;428 429		if (hdr3->hdr.magic != cpu_to_be32(XFS_DIR3_DATA_MAGIC))430			return __this_address;431 432		if (be64_to_cpu(hdr3->hdr.owner) != owner)433			return __this_address;434	}435 436	return NULL;437}438 439int440xfs_dir3_data_read(441	struct xfs_trans	*tp,442	struct xfs_inode	*dp,443	xfs_ino_t		owner,444	xfs_dablk_t		bno,445	unsigned int		flags,446	struct xfs_buf		**bpp)447{448	xfs_failaddr_t		fa;449	int			err;450 451	err = xfs_da_read_buf(tp, dp, bno, flags, bpp, XFS_DATA_FORK,452			&xfs_dir3_data_buf_ops);453	if (err || !*bpp)454		return err;455 456	/* Check things that we can't do in the verifier. */457	fa = xfs_dir3_data_header_check(*bpp, owner);458	if (fa) {459		__xfs_buf_mark_corrupt(*bpp, fa);460		xfs_trans_brelse(tp, *bpp);461		*bpp = NULL;462		xfs_dirattr_mark_sick(dp, XFS_DATA_FORK);463		return -EFSCORRUPTED;464	}465 466	xfs_trans_buf_set_type(tp, *bpp, XFS_BLFT_DIR_DATA_BUF);467	return err;468}469 470int471xfs_dir3_data_readahead(472	struct xfs_inode	*dp,473	xfs_dablk_t		bno,474	unsigned int		flags)475{476	return xfs_da_reada_buf(dp, bno, flags, XFS_DATA_FORK,477				&xfs_dir3_data_reada_buf_ops);478}479 480/*481 * Find the bestfree entry that exactly coincides with unused directory space482 * or a verifier error because the bestfree data are bad.483 */484static xfs_failaddr_t485xfs_dir2_data_freefind_verify(486	struct xfs_dir2_data_hdr	*hdr,487	struct xfs_dir2_data_free	*bf,488	struct xfs_dir2_data_unused	*dup,489	struct xfs_dir2_data_free	**bf_ent)490{491	struct xfs_dir2_data_free	*dfp;492	xfs_dir2_data_aoff_t		off;493	bool				matched = false;494	bool				seenzero = false;495 496	*bf_ent = NULL;497	off = (xfs_dir2_data_aoff_t)((char *)dup - (char *)hdr);498 499	/*500	 * Validate some consistency in the bestfree table.501	 * Check order, non-overlapping entries, and if we find the502	 * one we're looking for it has to be exact.503	 */504	for (dfp = &bf[0]; dfp < &bf[XFS_DIR2_DATA_FD_COUNT]; dfp++) {505		if (!dfp->offset) {506			if (dfp->length)507				return __this_address;508			seenzero = true;509			continue;510		}511		if (seenzero)512			return __this_address;513		if (be16_to_cpu(dfp->offset) == off) {514			matched = true;515			if (dfp->length != dup->length)516				return __this_address;517		} else if (be16_to_cpu(dfp->offset) > off) {518			if (off + be16_to_cpu(dup->length) >519					be16_to_cpu(dfp->offset))520				return __this_address;521		} else {522			if (be16_to_cpu(dfp->offset) +523					be16_to_cpu(dfp->length) > off)524				return __this_address;525		}526		if (!matched &&527		    be16_to_cpu(dfp->length) < be16_to_cpu(dup->length))528			return __this_address;529		if (dfp > &bf[0] &&530		    be16_to_cpu(dfp[-1].length) < be16_to_cpu(dfp[0].length))531			return __this_address;532	}533 534	/* Looks ok so far; now try to match up with a bestfree entry. */535	*bf_ent = xfs_dir2_data_freefind(hdr, bf, dup);536	return NULL;537}538 539/*540 * Given a data block and an unused entry from that block,541 * return the bestfree entry if any that corresponds to it.542 */543xfs_dir2_data_free_t *544xfs_dir2_data_freefind(545	struct xfs_dir2_data_hdr *hdr,		/* data block header */546	struct xfs_dir2_data_free *bf,		/* bestfree table pointer */547	struct xfs_dir2_data_unused *dup)	/* unused space */548{549	xfs_dir2_data_free_t	*dfp;		/* bestfree entry */550	xfs_dir2_data_aoff_t	off;		/* offset value needed */551 552	off = (xfs_dir2_data_aoff_t)((char *)dup - (char *)hdr);553 554	/*555	 * If this is smaller than the smallest bestfree entry,556	 * it can't be there since they're sorted.557	 */558	if (be16_to_cpu(dup->length) <559	    be16_to_cpu(bf[XFS_DIR2_DATA_FD_COUNT - 1].length))560		return NULL;561	/*562	 * Look at the three bestfree entries for our guy.563	 */564	for (dfp = &bf[0]; dfp < &bf[XFS_DIR2_DATA_FD_COUNT]; dfp++) {565		if (!dfp->offset)566			return NULL;567		if (be16_to_cpu(dfp->offset) == off)568			return dfp;569	}570	/*571	 * Didn't find it.  This only happens if there are duplicate lengths.572	 */573	return NULL;574}575 576/*577 * Insert an unused-space entry into the bestfree table.578 */579xfs_dir2_data_free_t *				/* entry inserted */580xfs_dir2_data_freeinsert(581	struct xfs_dir2_data_hdr *hdr,		/* data block pointer */582	struct xfs_dir2_data_free *dfp,		/* bestfree table pointer */583	struct xfs_dir2_data_unused *dup,	/* unused space */584	int			*loghead)	/* log the data header (out) */585{586	xfs_dir2_data_free_t	new;		/* new bestfree entry */587 588	ASSERT(hdr->magic == cpu_to_be32(XFS_DIR2_DATA_MAGIC) ||589	       hdr->magic == cpu_to_be32(XFS_DIR2_BLOCK_MAGIC) ||590	       hdr->magic == cpu_to_be32(XFS_DIR3_DATA_MAGIC) ||591	       hdr->magic == cpu_to_be32(XFS_DIR3_BLOCK_MAGIC));592 593	new.length = dup->length;594	new.offset = cpu_to_be16((char *)dup - (char *)hdr);595 596	/*597	 * Insert at position 0, 1, or 2; or not at all.598	 */599	if (be16_to_cpu(new.length) > be16_to_cpu(dfp[0].length)) {600		dfp[2] = dfp[1];601		dfp[1] = dfp[0];602		dfp[0] = new;603		*loghead = 1;604		return &dfp[0];605	}606	if (be16_to_cpu(new.length) > be16_to_cpu(dfp[1].length)) {607		dfp[2] = dfp[1];608		dfp[1] = new;609		*loghead = 1;610		return &dfp[1];611	}612	if (be16_to_cpu(new.length) > be16_to_cpu(dfp[2].length)) {613		dfp[2] = new;614		*loghead = 1;615		return &dfp[2];616	}617	return NULL;618}619 620/*621 * Remove a bestfree entry from the table.622 */623STATIC void624xfs_dir2_data_freeremove(625	struct xfs_dir2_data_hdr *hdr,		/* data block header */626	struct xfs_dir2_data_free *bf,		/* bestfree table pointer */627	struct xfs_dir2_data_free *dfp,		/* bestfree entry pointer */628	int			*loghead)	/* out: log data header */629{630 631	ASSERT(hdr->magic == cpu_to_be32(XFS_DIR2_DATA_MAGIC) ||632	       hdr->magic == cpu_to_be32(XFS_DIR2_BLOCK_MAGIC) ||633	       hdr->magic == cpu_to_be32(XFS_DIR3_DATA_MAGIC) ||634	       hdr->magic == cpu_to_be32(XFS_DIR3_BLOCK_MAGIC));635 636	/*637	 * It's the first entry, slide the next 2 up.638	 */639	if (dfp == &bf[0]) {640		bf[0] = bf[1];641		bf[1] = bf[2];642	}643	/*644	 * It's the second entry, slide the 3rd entry up.645	 */646	else if (dfp == &bf[1])647		bf[1] = bf[2];648	/*649	 * Must be the last entry.650	 */651	else652		ASSERT(dfp == &bf[2]);653	/*654	 * Clear the 3rd entry, must be zero now.655	 */656	bf[2].length = 0;657	bf[2].offset = 0;658	*loghead = 1;659}660 661/*662 * Given a data block, reconstruct its bestfree map.663 */664void665xfs_dir2_data_freescan(666	struct xfs_mount		*mp,667	struct xfs_dir2_data_hdr	*hdr,668	int				*loghead)669{670	struct xfs_da_geometry		*geo = mp->m_dir_geo;671	struct xfs_dir2_data_free	*bf = xfs_dir2_data_bestfree_p(mp, hdr);672	void				*addr = hdr;673	unsigned int			offset = geo->data_entry_offset;674	unsigned int			end;675 676	ASSERT(hdr->magic == cpu_to_be32(XFS_DIR2_DATA_MAGIC) ||677	       hdr->magic == cpu_to_be32(XFS_DIR3_DATA_MAGIC) ||678	       hdr->magic == cpu_to_be32(XFS_DIR2_BLOCK_MAGIC) ||679	       hdr->magic == cpu_to_be32(XFS_DIR3_BLOCK_MAGIC));680 681	/*682	 * Start by clearing the table.683	 */684	memset(bf, 0, sizeof(*bf) * XFS_DIR2_DATA_FD_COUNT);685	*loghead = 1;686 687	end = xfs_dir3_data_end_offset(geo, addr);688	while (offset < end) {689		struct xfs_dir2_data_unused	*dup = addr + offset;690		struct xfs_dir2_data_entry	*dep = addr + offset;691 692		/*693		 * If it's a free entry, insert it.694		 */695		if (be16_to_cpu(dup->freetag) == XFS_DIR2_DATA_FREE_TAG) {696			ASSERT(offset ==697			       be16_to_cpu(*xfs_dir2_data_unused_tag_p(dup)));698			xfs_dir2_data_freeinsert(hdr, bf, dup, loghead);699			offset += be16_to_cpu(dup->length);700			continue;701		}702 703		/*704		 * For active entries, check their tags and skip them.705		 */706		ASSERT(offset ==707		       be16_to_cpu(*xfs_dir2_data_entry_tag_p(mp, dep)));708		offset += xfs_dir2_data_entsize(mp, dep->namelen);709	}710}711 712/*713 * Initialize a data block at the given block number in the directory.714 * Give back the buffer for the created block.715 */716int						/* error */717xfs_dir3_data_init(718	struct xfs_da_args		*args,	/* directory operation args */719	xfs_dir2_db_t			blkno,	/* logical dir block number */720	struct xfs_buf			**bpp)	/* output block buffer */721{722	struct xfs_trans		*tp = args->trans;723	struct xfs_inode		*dp = args->dp;724	struct xfs_mount		*mp = dp->i_mount;725	struct xfs_da_geometry		*geo = args->geo;726	struct xfs_buf			*bp;727	struct xfs_dir2_data_hdr	*hdr;728	struct xfs_dir2_data_unused	*dup;729	struct xfs_dir2_data_free 	*bf;730	int				error;731	int				i;732 733	/*734	 * Get the buffer set up for the block.735	 */736	error = xfs_da_get_buf(tp, dp, xfs_dir2_db_to_da(args->geo, blkno),737			       &bp, XFS_DATA_FORK);738	if (error)739		return error;740	bp->b_ops = &xfs_dir3_data_buf_ops;741	xfs_trans_buf_set_type(tp, bp, XFS_BLFT_DIR_DATA_BUF);742 743	/*744	 * Initialize the header.745	 */746	hdr = bp->b_addr;747	if (xfs_has_crc(mp)) {748		struct xfs_dir3_blk_hdr *hdr3 = bp->b_addr;749 750		memset(hdr3, 0, sizeof(*hdr3));751		hdr3->magic = cpu_to_be32(XFS_DIR3_DATA_MAGIC);752		hdr3->blkno = cpu_to_be64(xfs_buf_daddr(bp));753		hdr3->owner = cpu_to_be64(args->owner);754		uuid_copy(&hdr3->uuid, &mp->m_sb.sb_meta_uuid);755 756	} else757		hdr->magic = cpu_to_be32(XFS_DIR2_DATA_MAGIC);758 759	bf = xfs_dir2_data_bestfree_p(mp, hdr);760	bf[0].offset = cpu_to_be16(geo->data_entry_offset);761	bf[0].length = cpu_to_be16(geo->blksize - geo->data_entry_offset);762	for (i = 1; i < XFS_DIR2_DATA_FD_COUNT; i++) {763		bf[i].length = 0;764		bf[i].offset = 0;765	}766 767	/*768	 * Set up an unused entry for the block's body.769	 */770	dup = bp->b_addr + geo->data_entry_offset;771	dup->freetag = cpu_to_be16(XFS_DIR2_DATA_FREE_TAG);772	dup->length = bf[0].length;773	*xfs_dir2_data_unused_tag_p(dup) = cpu_to_be16((char *)dup - (char *)hdr);774 775	/*776	 * Log it and return it.777	 */778	xfs_dir2_data_log_header(args, bp);779	xfs_dir2_data_log_unused(args, bp, dup);780	*bpp = bp;781	return 0;782}783 784/*785 * Log an active data entry from the block.786 */787void788xfs_dir2_data_log_entry(789	struct xfs_da_args	*args,790	struct xfs_buf		*bp,791	xfs_dir2_data_entry_t	*dep)		/* data entry pointer */792{793	struct xfs_mount	*mp = bp->b_mount;794	struct xfs_dir2_data_hdr *hdr = bp->b_addr;795 796	ASSERT(hdr->magic == cpu_to_be32(XFS_DIR2_DATA_MAGIC) ||797	       hdr->magic == cpu_to_be32(XFS_DIR3_DATA_MAGIC) ||798	       hdr->magic == cpu_to_be32(XFS_DIR2_BLOCK_MAGIC) ||799	       hdr->magic == cpu_to_be32(XFS_DIR3_BLOCK_MAGIC));800 801	xfs_trans_log_buf(args->trans, bp, (uint)((char *)dep - (char *)hdr),802		(uint)((char *)(xfs_dir2_data_entry_tag_p(mp, dep) + 1) -803		       (char *)hdr - 1));804}805 806/*807 * Log a data block header.808 */809void810xfs_dir2_data_log_header(811	struct xfs_da_args	*args,812	struct xfs_buf		*bp)813{814#ifdef DEBUG815	struct xfs_dir2_data_hdr *hdr = bp->b_addr;816 817	ASSERT(hdr->magic == cpu_to_be32(XFS_DIR2_DATA_MAGIC) ||818	       hdr->magic == cpu_to_be32(XFS_DIR3_DATA_MAGIC) ||819	       hdr->magic == cpu_to_be32(XFS_DIR2_BLOCK_MAGIC) ||820	       hdr->magic == cpu_to_be32(XFS_DIR3_BLOCK_MAGIC));821#endif822 823	xfs_trans_log_buf(args->trans, bp, 0, args->geo->data_entry_offset - 1);824}825 826/*827 * Log a data unused entry.828 */829void830xfs_dir2_data_log_unused(831	struct xfs_da_args	*args,832	struct xfs_buf		*bp,833	xfs_dir2_data_unused_t	*dup)		/* data unused pointer */834{835	xfs_dir2_data_hdr_t	*hdr = bp->b_addr;836 837	ASSERT(hdr->magic == cpu_to_be32(XFS_DIR2_DATA_MAGIC) ||838	       hdr->magic == cpu_to_be32(XFS_DIR3_DATA_MAGIC) ||839	       hdr->magic == cpu_to_be32(XFS_DIR2_BLOCK_MAGIC) ||840	       hdr->magic == cpu_to_be32(XFS_DIR3_BLOCK_MAGIC));841 842	/*843	 * Log the first part of the unused entry.844	 */845	xfs_trans_log_buf(args->trans, bp, (uint)((char *)dup - (char *)hdr),846		(uint)((char *)&dup->length + sizeof(dup->length) -847		       1 - (char *)hdr));848	/*849	 * Log the end (tag) of the unused entry.850	 */851	xfs_trans_log_buf(args->trans, bp,852		(uint)((char *)xfs_dir2_data_unused_tag_p(dup) - (char *)hdr),853		(uint)((char *)xfs_dir2_data_unused_tag_p(dup) - (char *)hdr +854		       sizeof(xfs_dir2_data_off_t) - 1));855}856 857/*858 * Make a byte range in the data block unused.859 * Its current contents are unimportant.860 */861void862xfs_dir2_data_make_free(863	struct xfs_da_args	*args,864	struct xfs_buf		*bp,865	xfs_dir2_data_aoff_t	offset,		/* starting byte offset */866	xfs_dir2_data_aoff_t	len,		/* length in bytes */867	int			*needlogp,	/* out: log header */868	int			*needscanp)	/* out: regen bestfree */869{870	xfs_dir2_data_hdr_t	*hdr;		/* data block pointer */871	xfs_dir2_data_free_t	*dfp;		/* bestfree pointer */872	int			needscan;	/* need to regen bestfree */873	xfs_dir2_data_unused_t	*newdup;	/* new unused entry */874	xfs_dir2_data_unused_t	*postdup;	/* unused entry after us */875	xfs_dir2_data_unused_t	*prevdup;	/* unused entry before us */876	unsigned int		end;877	struct xfs_dir2_data_free *bf;878 879	hdr = bp->b_addr;880 881	/*882	 * Figure out where the end of the data area is.883	 */884	end = xfs_dir3_data_end_offset(args->geo, hdr);885	ASSERT(end != 0);886 887	/*888	 * If this isn't the start of the block, then back up to889	 * the previous entry and see if it's free.890	 */891	if (offset > args->geo->data_entry_offset) {892		__be16			*tagp;	/* tag just before us */893 894		tagp = (__be16 *)((char *)hdr + offset) - 1;895		prevdup = (xfs_dir2_data_unused_t *)((char *)hdr + be16_to_cpu(*tagp));896		if (be16_to_cpu(prevdup->freetag) != XFS_DIR2_DATA_FREE_TAG)897			prevdup = NULL;898	} else899		prevdup = NULL;900	/*901	 * If this isn't the end of the block, see if the entry after902	 * us is free.903	 */904	if (offset + len < end) {905		postdup =906			(xfs_dir2_data_unused_t *)((char *)hdr + offset + len);907		if (be16_to_cpu(postdup->freetag) != XFS_DIR2_DATA_FREE_TAG)908			postdup = NULL;909	} else910		postdup = NULL;911	ASSERT(*needscanp == 0);912	needscan = 0;913	/*914	 * Previous and following entries are both free,915	 * merge everything into a single free entry.916	 */917	bf = xfs_dir2_data_bestfree_p(args->dp->i_mount, hdr);918	if (prevdup && postdup) {919		xfs_dir2_data_free_t	*dfp2;	/* another bestfree pointer */920 921		/*922		 * See if prevdup and/or postdup are in bestfree table.923		 */924		dfp = xfs_dir2_data_freefind(hdr, bf, prevdup);925		dfp2 = xfs_dir2_data_freefind(hdr, bf, postdup);926		/*927		 * We need a rescan unless there are exactly 2 free entries928		 * namely our two.  Then we know what's happening, otherwise929		 * since the third bestfree is there, there might be more930		 * entries.931		 */932		needscan = (bf[2].length != 0);933		/*934		 * Fix up the new big freespace.935		 */936		be16_add_cpu(&prevdup->length, len + be16_to_cpu(postdup->length));937		*xfs_dir2_data_unused_tag_p(prevdup) =938			cpu_to_be16((char *)prevdup - (char *)hdr);939		xfs_dir2_data_log_unused(args, bp, prevdup);940		if (!needscan) {941			/*942			 * Has to be the case that entries 0 and 1 are943			 * dfp and dfp2 (don't know which is which), and944			 * entry 2 is empty.945			 * Remove entry 1 first then entry 0.946			 */947			ASSERT(dfp && dfp2);948			if (dfp == &bf[1]) {949				dfp = &bf[0];950				ASSERT(dfp2 == dfp);951				dfp2 = &bf[1];952			}953			xfs_dir2_data_freeremove(hdr, bf, dfp2, needlogp);954			xfs_dir2_data_freeremove(hdr, bf, dfp, needlogp);955			/*956			 * Now insert the new entry.957			 */958			dfp = xfs_dir2_data_freeinsert(hdr, bf, prevdup,959						       needlogp);960			ASSERT(dfp == &bf[0]);961			ASSERT(dfp->length == prevdup->length);962			ASSERT(!dfp[1].length);963			ASSERT(!dfp[2].length);964		}965	}966	/*967	 * The entry before us is free, merge with it.968	 */969	else if (prevdup) {970		dfp = xfs_dir2_data_freefind(hdr, bf, prevdup);971		be16_add_cpu(&prevdup->length, len);972		*xfs_dir2_data_unused_tag_p(prevdup) =973			cpu_to_be16((char *)prevdup - (char *)hdr);974		xfs_dir2_data_log_unused(args, bp, prevdup);975		/*976		 * If the previous entry was in the table, the new entry977		 * is longer, so it will be in the table too.  Remove978		 * the old one and add the new one.979		 */980		if (dfp) {981			xfs_dir2_data_freeremove(hdr, bf, dfp, needlogp);982			xfs_dir2_data_freeinsert(hdr, bf, prevdup, needlogp);983		}984		/*985		 * Otherwise we need a scan if the new entry is big enough.986		 */987		else {988			needscan = be16_to_cpu(prevdup->length) >989				   be16_to_cpu(bf[2].length);990		}991	}992	/*993	 * The following entry is free, merge with it.994	 */995	else if (postdup) {996		dfp = xfs_dir2_data_freefind(hdr, bf, postdup);997		newdup = (xfs_dir2_data_unused_t *)((char *)hdr + offset);998		newdup->freetag = cpu_to_be16(XFS_DIR2_DATA_FREE_TAG);999		newdup->length = cpu_to_be16(len + be16_to_cpu(postdup->length));1000		*xfs_dir2_data_unused_tag_p(newdup) =1001			cpu_to_be16((char *)newdup - (char *)hdr);1002		xfs_dir2_data_log_unused(args, bp, newdup);1003		/*1004		 * If the following entry was in the table, the new entry1005		 * is longer, so it will be in the table too.  Remove1006		 * the old one and add the new one.1007		 */1008		if (dfp) {1009			xfs_dir2_data_freeremove(hdr, bf, dfp, needlogp);1010			xfs_dir2_data_freeinsert(hdr, bf, newdup, needlogp);1011		}1012		/*1013		 * Otherwise we need a scan if the new entry is big enough.1014		 */1015		else {1016			needscan = be16_to_cpu(newdup->length) >1017				   be16_to_cpu(bf[2].length);1018		}1019	}1020	/*1021	 * Neither neighbor is free.  Make a new entry.1022	 */1023	else {1024		newdup = (xfs_dir2_data_unused_t *)((char *)hdr + offset);1025		newdup->freetag = cpu_to_be16(XFS_DIR2_DATA_FREE_TAG);1026		newdup->length = cpu_to_be16(len);1027		*xfs_dir2_data_unused_tag_p(newdup) =1028			cpu_to_be16((char *)newdup - (char *)hdr);1029		xfs_dir2_data_log_unused(args, bp, newdup);1030		xfs_dir2_data_freeinsert(hdr, bf, newdup, needlogp);1031	}1032	*needscanp = needscan;1033}1034 1035/* Check our free data for obvious signs of corruption. */1036static inline xfs_failaddr_t1037xfs_dir2_data_check_free(1038	struct xfs_dir2_data_hdr	*hdr,1039	struct xfs_dir2_data_unused	*dup,1040	xfs_dir2_data_aoff_t		offset,1041	xfs_dir2_data_aoff_t		len)1042{1043	if (hdr->magic != cpu_to_be32(XFS_DIR2_DATA_MAGIC) &&1044	    hdr->magic != cpu_to_be32(XFS_DIR3_DATA_MAGIC) &&1045	    hdr->magic != cpu_to_be32(XFS_DIR2_BLOCK_MAGIC) &&1046	    hdr->magic != cpu_to_be32(XFS_DIR3_BLOCK_MAGIC))1047		return __this_address;1048	if (be16_to_cpu(dup->freetag) != XFS_DIR2_DATA_FREE_TAG)1049		return __this_address;1050	if (offset < (char *)dup - (char *)hdr)1051		return __this_address;1052	if (offset + len > (char *)dup + be16_to_cpu(dup->length) - (char *)hdr)1053		return __this_address;1054	if ((char *)dup - (char *)hdr !=1055			be16_to_cpu(*xfs_dir2_data_unused_tag_p(dup)))1056		return __this_address;1057	return NULL;1058}1059 1060/* Sanity-check a new bestfree entry. */1061static inline xfs_failaddr_t1062xfs_dir2_data_check_new_free(1063	struct xfs_dir2_data_hdr	*hdr,1064	struct xfs_dir2_data_free	*dfp,1065	struct xfs_dir2_data_unused	*newdup)1066{1067	if (dfp == NULL)1068		return __this_address;1069	if (dfp->length != newdup->length)1070		return __this_address;1071	if (be16_to_cpu(dfp->offset) != (char *)newdup - (char *)hdr)1072		return __this_address;1073	return NULL;1074}1075 1076/*1077 * Take a byte range out of an existing unused space and make it un-free.1078 */1079int1080xfs_dir2_data_use_free(1081	struct xfs_da_args	*args,1082	struct xfs_buf		*bp,1083	xfs_dir2_data_unused_t	*dup,		/* unused entry */1084	xfs_dir2_data_aoff_t	offset,		/* starting offset to use */1085	xfs_dir2_data_aoff_t	len,		/* length to use */1086	int			*needlogp,	/* out: need to log header */1087	int			*needscanp)	/* out: need regen bestfree */1088{1089	xfs_dir2_data_hdr_t	*hdr;		/* data block header */1090	xfs_dir2_data_free_t	*dfp;		/* bestfree pointer */1091	xfs_dir2_data_unused_t	*newdup;	/* new unused entry */1092	xfs_dir2_data_unused_t	*newdup2;	/* another new unused entry */1093	struct xfs_dir2_data_free *bf;1094	xfs_failaddr_t		fa;1095	int			matchback;	/* matches end of freespace */1096	int			matchfront;	/* matches start of freespace */1097	int			needscan;	/* need to regen bestfree */1098	int			oldlen;		/* old unused entry's length */1099 1100	hdr = bp->b_addr;1101	fa = xfs_dir2_data_check_free(hdr, dup, offset, len);1102	if (fa)1103		goto corrupt;1104	/*1105	 * Look up the entry in the bestfree table.1106	 */1107	oldlen = be16_to_cpu(dup->length);1108	bf = xfs_dir2_data_bestfree_p(args->dp->i_mount, hdr);1109	dfp = xfs_dir2_data_freefind(hdr, bf, dup);1110	ASSERT(dfp || oldlen <= be16_to_cpu(bf[2].length));1111	/*1112	 * Check for alignment with front and back of the entry.1113	 */1114	matchfront = (char *)dup - (char *)hdr == offset;1115	matchback = (char *)dup + oldlen - (char *)hdr == offset + len;1116	ASSERT(*needscanp == 0);1117	needscan = 0;1118	/*1119	 * If we matched it exactly we just need to get rid of it from1120	 * the bestfree table.1121	 */1122	if (matchfront && matchback) {1123		if (dfp) {1124			needscan = (bf[2].offset != 0);1125			if (!needscan)1126				xfs_dir2_data_freeremove(hdr, bf, dfp,1127							 needlogp);1128		}1129	}1130	/*1131	 * We match the first part of the entry.1132	 * Make a new entry with the remaining freespace.1133	 */1134	else if (matchfront) {1135		newdup = (xfs_dir2_data_unused_t *)((char *)hdr + offset + len);1136		newdup->freetag = cpu_to_be16(XFS_DIR2_DATA_FREE_TAG);1137		newdup->length = cpu_to_be16(oldlen - len);1138		*xfs_dir2_data_unused_tag_p(newdup) =1139			cpu_to_be16((char *)newdup - (char *)hdr);1140		xfs_dir2_data_log_unused(args, bp, newdup);1141		/*1142		 * If it was in the table, remove it and add the new one.1143		 */1144		if (dfp) {1145			xfs_dir2_data_freeremove(hdr, bf, dfp, needlogp);1146			dfp = xfs_dir2_data_freeinsert(hdr, bf, newdup,1147						       needlogp);1148			fa = xfs_dir2_data_check_new_free(hdr, dfp, newdup);1149			if (fa)1150				goto corrupt;1151			/*1152			 * If we got inserted at the last slot,1153			 * that means we don't know if there was a better1154			 * choice for the last slot, or not.  Rescan.1155			 */1156			needscan = dfp == &bf[2];1157		}1158	}1159	/*1160	 * We match the last part of the entry.1161	 * Trim the allocated space off the tail of the entry.1162	 */1163	else if (matchback) {1164		newdup = dup;1165		newdup->length = cpu_to_be16(((char *)hdr + offset) - (char *)newdup);1166		*xfs_dir2_data_unused_tag_p(newdup) =1167			cpu_to_be16((char *)newdup - (char *)hdr);1168		xfs_dir2_data_log_unused(args, bp, newdup);1169		/*1170		 * If it was in the table, remove it and add the new one.1171		 */1172		if (dfp) {1173			xfs_dir2_data_freeremove(hdr, bf, dfp, needlogp);1174			dfp = xfs_dir2_data_freeinsert(hdr, bf, newdup,1175						       needlogp);1176			fa = xfs_dir2_data_check_new_free(hdr, dfp, newdup);1177			if (fa)1178				goto corrupt;1179			/*1180			 * If we got inserted at the last slot,1181			 * that means we don't know if there was a better1182			 * choice for the last slot, or not.  Rescan.1183			 */1184			needscan = dfp == &bf[2];1185		}1186	}1187	/*1188	 * Poking out the middle of an entry.1189	 * Make two new entries.1190	 */1191	else {1192		newdup = dup;1193		newdup->length = cpu_to_be16(((char *)hdr + offset) - (char *)newdup);1194		*xfs_dir2_data_unused_tag_p(newdup) =1195			cpu_to_be16((char *)newdup - (char *)hdr);1196		xfs_dir2_data_log_unused(args, bp, newdup);1197		newdup2 = (xfs_dir2_data_unused_t *)((char *)hdr + offset + len);1198		newdup2->freetag = cpu_to_be16(XFS_DIR2_DATA_FREE_TAG);1199		newdup2->length = cpu_to_be16(oldlen - len - be16_to_cpu(newdup->length));1200		*xfs_dir2_data_unused_tag_p(newdup2) =1201			cpu_to_be16((char *)newdup2 - (char *)hdr);1202		xfs_dir2_data_log_unused(args, bp, newdup2);1203		/*1204		 * If the old entry was in the table, we need to scan1205		 * if the 3rd entry was valid, since these entries1206		 * are smaller than the old one.1207		 * If we don't need to scan that means there were 1 or 21208		 * entries in the table, and removing the old and adding1209		 * the 2 new will work.1210		 */1211		if (dfp) {1212			needscan = (bf[2].length != 0);1213			if (!needscan) {1214				xfs_dir2_data_freeremove(hdr, bf, dfp,1215							 needlogp);1216				xfs_dir2_data_freeinsert(hdr, bf, newdup,1217							 needlogp);1218				xfs_dir2_data_freeinsert(hdr, bf, newdup2,1219							 needlogp);1220			}1221		}1222	}1223	*needscanp = needscan;1224	return 0;1225corrupt:1226	xfs_corruption_error(__func__, XFS_ERRLEVEL_LOW, args->dp->i_mount,1227			hdr, sizeof(*hdr), __FILE__, __LINE__, fa);1228	xfs_da_mark_sick(args);1229	return -EFSCORRUPTED;1230}1231 1232/* Find the end of the entry data in a data/block format dir block. */1233unsigned int1234xfs_dir3_data_end_offset(1235	struct xfs_da_geometry		*geo,1236	struct xfs_dir2_data_hdr	*hdr)1237{1238	void				*p;1239 1240	switch (hdr->magic) {1241	case cpu_to_be32(XFS_DIR3_BLOCK_MAGIC):1242	case cpu_to_be32(XFS_DIR2_BLOCK_MAGIC):1243		p = xfs_dir2_block_leaf_p(xfs_dir2_block_tail_p(geo, hdr));1244		return p - (void *)hdr;1245	case cpu_to_be32(XFS_DIR3_DATA_MAGIC):1246	case cpu_to_be32(XFS_DIR2_DATA_MAGIC):1247		return geo->blksize;1248	default:1249		return 0;1250	}1251}1252