⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 xfs_dir2_data.c

📁 linux 内核源代码
💻 C
📖 第 1 页 / 共 2 页
字号:
	for (i = 1; i < XFS_DIR2_DATA_FD_COUNT; i++) {		d->hdr.bestfree[i].length = 0;		d->hdr.bestfree[i].offset = 0;	}	/*	 * Set up an unused entry for the block's body.	 */	dup = &d->u[0].unused;	dup->freetag = cpu_to_be16(XFS_DIR2_DATA_FREE_TAG);	t=mp->m_dirblksize - (uint)sizeof(d->hdr);	d->hdr.bestfree[0].length = cpu_to_be16(t);	dup->length = cpu_to_be16(t);	*xfs_dir2_data_unused_tag_p(dup) = cpu_to_be16((char *)dup - (char *)d);	/*	 * Log it and return it.	 */	xfs_dir2_data_log_header(tp, bp);	xfs_dir2_data_log_unused(tp, bp, dup);	*bpp = bp;	return 0;}/* * Log an active data entry from the block. */voidxfs_dir2_data_log_entry(	xfs_trans_t		*tp,		/* transaction pointer */	xfs_dabuf_t		*bp,		/* block buffer */	xfs_dir2_data_entry_t	*dep)		/* data entry pointer */{	xfs_dir2_data_t		*d;		/* data block pointer */	d = bp->data;	ASSERT(be32_to_cpu(d->hdr.magic) == XFS_DIR2_DATA_MAGIC ||	       be32_to_cpu(d->hdr.magic) == XFS_DIR2_BLOCK_MAGIC);	xfs_da_log_buf(tp, bp, (uint)((char *)dep - (char *)d),		(uint)((char *)(xfs_dir2_data_entry_tag_p(dep) + 1) -		       (char *)d - 1));}/* * Log a data block header. */voidxfs_dir2_data_log_header(	xfs_trans_t		*tp,		/* transaction pointer */	xfs_dabuf_t		*bp)		/* block buffer */{	xfs_dir2_data_t		*d;		/* data block pointer */	d = bp->data;	ASSERT(be32_to_cpu(d->hdr.magic) == XFS_DIR2_DATA_MAGIC ||	       be32_to_cpu(d->hdr.magic) == XFS_DIR2_BLOCK_MAGIC);	xfs_da_log_buf(tp, bp, (uint)((char *)&d->hdr - (char *)d),		(uint)(sizeof(d->hdr) - 1));}/* * Log a data unused entry. */voidxfs_dir2_data_log_unused(	xfs_trans_t		*tp,		/* transaction pointer */	xfs_dabuf_t		*bp,		/* block buffer */	xfs_dir2_data_unused_t	*dup)		/* data unused pointer */{	xfs_dir2_data_t		*d;		/* data block pointer */	d = bp->data;	ASSERT(be32_to_cpu(d->hdr.magic) == XFS_DIR2_DATA_MAGIC ||	       be32_to_cpu(d->hdr.magic) == XFS_DIR2_BLOCK_MAGIC);	/*	 * Log the first part of the unused entry.	 */	xfs_da_log_buf(tp, bp, (uint)((char *)dup - (char *)d),		(uint)((char *)&dup->length + sizeof(dup->length) -		       1 - (char *)d));	/*	 * Log the end (tag) of the unused entry.	 */	xfs_da_log_buf(tp, bp,		(uint)((char *)xfs_dir2_data_unused_tag_p(dup) - (char *)d),		(uint)((char *)xfs_dir2_data_unused_tag_p(dup) - (char *)d +		       sizeof(xfs_dir2_data_off_t) - 1));}/* * Make a byte range in the data block unused. * Its current contents are unimportant. */voidxfs_dir2_data_make_free(	xfs_trans_t		*tp,		/* transaction pointer */	xfs_dabuf_t		*bp,		/* block buffer */	xfs_dir2_data_aoff_t	offset,		/* starting byte offset */	xfs_dir2_data_aoff_t	len,		/* length in bytes */	int			*needlogp,	/* out: log header */	int			*needscanp)	/* out: regen bestfree */{	xfs_dir2_data_t		*d;		/* data block pointer */	xfs_dir2_data_free_t	*dfp;		/* bestfree pointer */	char			*endptr;	/* end of data area */	xfs_mount_t		*mp;		/* filesystem mount point */	int			needscan;	/* need to regen bestfree */	xfs_dir2_data_unused_t	*newdup;	/* new unused entry */	xfs_dir2_data_unused_t	*postdup;	/* unused entry after us */	xfs_dir2_data_unused_t	*prevdup;	/* unused entry before us */	mp = tp->t_mountp;	d = bp->data;	/*	 * Figure out where the end of the data area is.	 */	if (be32_to_cpu(d->hdr.magic) == XFS_DIR2_DATA_MAGIC)		endptr = (char *)d + mp->m_dirblksize;	else {		xfs_dir2_block_tail_t	*btp;	/* block tail */		ASSERT(be32_to_cpu(d->hdr.magic) == XFS_DIR2_BLOCK_MAGIC);		btp = xfs_dir2_block_tail_p(mp, (xfs_dir2_block_t *)d);		endptr = (char *)xfs_dir2_block_leaf_p(btp);	}	/*	 * If this isn't the start of the block, then back up to	 * the previous entry and see if it's free.	 */	if (offset > sizeof(d->hdr)) {		__be16			*tagp;	/* tag just before us */		tagp = (__be16 *)((char *)d + offset) - 1;		prevdup = (xfs_dir2_data_unused_t *)((char *)d + be16_to_cpu(*tagp));		if (be16_to_cpu(prevdup->freetag) != XFS_DIR2_DATA_FREE_TAG)			prevdup = NULL;	} else		prevdup = NULL;	/*	 * If this isn't the end of the block, see if the entry after	 * us is free.	 */	if ((char *)d + offset + len < endptr) {		postdup =			(xfs_dir2_data_unused_t *)((char *)d + offset + len);		if (be16_to_cpu(postdup->freetag) != XFS_DIR2_DATA_FREE_TAG)			postdup = NULL;	} else		postdup = NULL;	ASSERT(*needscanp == 0);	needscan = 0;	/*	 * Previous and following entries are both free,	 * merge everything into a single free entry.	 */	if (prevdup && postdup) {		xfs_dir2_data_free_t	*dfp2;	/* another bestfree pointer */		/*		 * See if prevdup and/or postdup are in bestfree table.		 */		dfp = xfs_dir2_data_freefind(d, prevdup);		dfp2 = xfs_dir2_data_freefind(d, postdup);		/*		 * We need a rescan unless there are exactly 2 free entries		 * namely our two.  Then we know what's happening, otherwise		 * since the third bestfree is there, there might be more		 * entries.		 */		needscan = (d->hdr.bestfree[2].length != 0);		/*		 * Fix up the new big freespace.		 */		be16_add(&prevdup->length, len + be16_to_cpu(postdup->length));		*xfs_dir2_data_unused_tag_p(prevdup) =			cpu_to_be16((char *)prevdup - (char *)d);		xfs_dir2_data_log_unused(tp, bp, prevdup);		if (!needscan) {			/*			 * Has to be the case that entries 0 and 1 are			 * dfp and dfp2 (don't know which is which), and			 * entry 2 is empty.			 * Remove entry 1 first then entry 0.			 */			ASSERT(dfp && dfp2);			if (dfp == &d->hdr.bestfree[1]) {				dfp = &d->hdr.bestfree[0];				ASSERT(dfp2 == dfp);				dfp2 = &d->hdr.bestfree[1];			}			xfs_dir2_data_freeremove(d, dfp2, needlogp);			xfs_dir2_data_freeremove(d, dfp, needlogp);			/*			 * Now insert the new entry.			 */			dfp = xfs_dir2_data_freeinsert(d, prevdup, needlogp);			ASSERT(dfp == &d->hdr.bestfree[0]);			ASSERT(dfp->length == prevdup->length);			ASSERT(!dfp[1].length);			ASSERT(!dfp[2].length);		}	}	/*	 * The entry before us is free, merge with it.	 */	else if (prevdup) {		dfp = xfs_dir2_data_freefind(d, prevdup);		be16_add(&prevdup->length, len);		*xfs_dir2_data_unused_tag_p(prevdup) =			cpu_to_be16((char *)prevdup - (char *)d);		xfs_dir2_data_log_unused(tp, bp, prevdup);		/*		 * If the previous entry was in the table, the new entry		 * is longer, so it will be in the table too.  Remove		 * the old one and add the new one.		 */		if (dfp) {			xfs_dir2_data_freeremove(d, dfp, needlogp);			(void)xfs_dir2_data_freeinsert(d, prevdup, needlogp);		}		/*		 * Otherwise we need a scan if the new entry is big enough.		 */		else {			needscan = be16_to_cpu(prevdup->length) >				   be16_to_cpu(d->hdr.bestfree[2].length);		}	}	/*	 * The following entry is free, merge with it.	 */	else if (postdup) {		dfp = xfs_dir2_data_freefind(d, postdup);		newdup = (xfs_dir2_data_unused_t *)((char *)d + offset);		newdup->freetag = cpu_to_be16(XFS_DIR2_DATA_FREE_TAG);		newdup->length = cpu_to_be16(len + be16_to_cpu(postdup->length));		*xfs_dir2_data_unused_tag_p(newdup) =			cpu_to_be16((char *)newdup - (char *)d);		xfs_dir2_data_log_unused(tp, bp, newdup);		/*		 * If the following entry was in the table, the new entry		 * is longer, so it will be in the table too.  Remove		 * the old one and add the new one.		 */		if (dfp) {			xfs_dir2_data_freeremove(d, dfp, needlogp);			(void)xfs_dir2_data_freeinsert(d, newdup, needlogp);		}		/*		 * Otherwise we need a scan if the new entry is big enough.		 */		else {			needscan = be16_to_cpu(newdup->length) >				   be16_to_cpu(d->hdr.bestfree[2].length);		}	}	/*	 * Neither neighbor is free.  Make a new entry.	 */	else {		newdup = (xfs_dir2_data_unused_t *)((char *)d + offset);		newdup->freetag = cpu_to_be16(XFS_DIR2_DATA_FREE_TAG);		newdup->length = cpu_to_be16(len);		*xfs_dir2_data_unused_tag_p(newdup) =			cpu_to_be16((char *)newdup - (char *)d);		xfs_dir2_data_log_unused(tp, bp, newdup);		(void)xfs_dir2_data_freeinsert(d, newdup, needlogp);	}	*needscanp = needscan;}/* * Take a byte range out of an existing unused space and make it un-free. */voidxfs_dir2_data_use_free(	xfs_trans_t		*tp,		/* transaction pointer */	xfs_dabuf_t		*bp,		/* data block buffer */	xfs_dir2_data_unused_t	*dup,		/* unused entry */	xfs_dir2_data_aoff_t	offset,		/* starting offset to use */	xfs_dir2_data_aoff_t	len,		/* length to use */	int			*needlogp,	/* out: need to log header */	int			*needscanp)	/* out: need regen bestfree */{	xfs_dir2_data_t		*d;		/* data block */	xfs_dir2_data_free_t	*dfp;		/* bestfree pointer */	int			matchback;	/* matches end of freespace */	int			matchfront;	/* matches start of freespace */	int			needscan;	/* need to regen bestfree */	xfs_dir2_data_unused_t	*newdup;	/* new unused entry */	xfs_dir2_data_unused_t	*newdup2;	/* another new unused entry */	int			oldlen;		/* old unused entry's length */	d = bp->data;	ASSERT(be32_to_cpu(d->hdr.magic) == XFS_DIR2_DATA_MAGIC ||	       be32_to_cpu(d->hdr.magic) == XFS_DIR2_BLOCK_MAGIC);	ASSERT(be16_to_cpu(dup->freetag) == XFS_DIR2_DATA_FREE_TAG);	ASSERT(offset >= (char *)dup - (char *)d);	ASSERT(offset + len <= (char *)dup + be16_to_cpu(dup->length) - (char *)d);	ASSERT((char *)dup - (char *)d == be16_to_cpu(*xfs_dir2_data_unused_tag_p(dup)));	/*	 * Look up the entry in the bestfree table.	 */	dfp = xfs_dir2_data_freefind(d, dup);	oldlen = be16_to_cpu(dup->length);	ASSERT(dfp || oldlen <= be16_to_cpu(d->hdr.bestfree[2].length));	/*	 * Check for alignment with front and back of the entry.	 */	matchfront = (char *)dup - (char *)d == offset;	matchback = (char *)dup + oldlen - (char *)d == offset + len;	ASSERT(*needscanp == 0);	needscan = 0;	/*	 * If we matched it exactly we just need to get rid of it from	 * the bestfree table.	 */	if (matchfront && matchback) {		if (dfp) {			needscan = (d->hdr.bestfree[2].offset != 0);			if (!needscan)				xfs_dir2_data_freeremove(d, dfp, needlogp);		}	}	/*	 * We match the first part of the entry.	 * Make a new entry with the remaining freespace.	 */	else if (matchfront) {		newdup = (xfs_dir2_data_unused_t *)((char *)d + offset + len);		newdup->freetag = cpu_to_be16(XFS_DIR2_DATA_FREE_TAG);		newdup->length = cpu_to_be16(oldlen - len);		*xfs_dir2_data_unused_tag_p(newdup) =			cpu_to_be16((char *)newdup - (char *)d);		xfs_dir2_data_log_unused(tp, bp, newdup);		/*		 * If it was in the table, remove it and add the new one.		 */		if (dfp) {			xfs_dir2_data_freeremove(d, dfp, needlogp);			dfp = xfs_dir2_data_freeinsert(d, newdup, needlogp);			ASSERT(dfp != NULL);			ASSERT(dfp->length == newdup->length);			ASSERT(be16_to_cpu(dfp->offset) == (char *)newdup - (char *)d);			/*			 * If we got inserted at the last slot,			 * that means we don't know if there was a better			 * choice for the last slot, or not.  Rescan.			 */			needscan = dfp == &d->hdr.bestfree[2];		}	}	/*	 * We match the last part of the entry.	 * Trim the allocated space off the tail of the entry.	 */	else if (matchback) {		newdup = dup;		newdup->length = cpu_to_be16(((char *)d + offset) - (char *)newdup);		*xfs_dir2_data_unused_tag_p(newdup) =			cpu_to_be16((char *)newdup - (char *)d);		xfs_dir2_data_log_unused(tp, bp, newdup);		/*		 * If it was in the table, remove it and add the new one.		 */		if (dfp) {			xfs_dir2_data_freeremove(d, dfp, needlogp);			dfp = xfs_dir2_data_freeinsert(d, newdup, needlogp);			ASSERT(dfp != NULL);			ASSERT(dfp->length == newdup->length);			ASSERT(be16_to_cpu(dfp->offset) == (char *)newdup - (char *)d);			/*			 * If we got inserted at the last slot,			 * that means we don't know if there was a better			 * choice for the last slot, or not.  Rescan.			 */			needscan = dfp == &d->hdr.bestfree[2];		}	}	/*	 * Poking out the middle of an entry.	 * Make two new entries.	 */	else {		newdup = dup;		newdup->length = cpu_to_be16(((char *)d + offset) - (char *)newdup);		*xfs_dir2_data_unused_tag_p(newdup) =			cpu_to_be16((char *)newdup - (char *)d);		xfs_dir2_data_log_unused(tp, bp, newdup);		newdup2 = (xfs_dir2_data_unused_t *)((char *)d + offset + len);		newdup2->freetag = cpu_to_be16(XFS_DIR2_DATA_FREE_TAG);		newdup2->length = cpu_to_be16(oldlen - len - be16_to_cpu(newdup->length));		*xfs_dir2_data_unused_tag_p(newdup2) =			cpu_to_be16((char *)newdup2 - (char *)d);		xfs_dir2_data_log_unused(tp, bp, newdup2);		/*		 * If the old entry was in the table, we need to scan		 * if the 3rd entry was valid, since these entries		 * are smaller than the old one.		 * If we don't need to scan that means there were 1 or 2		 * entries in the table, and removing the old and adding		 * the 2 new will work.		 */		if (dfp) {			needscan = (d->hdr.bestfree[2].length != 0);			if (!needscan) {				xfs_dir2_data_freeremove(d, dfp, needlogp);				(void)xfs_dir2_data_freeinsert(d, newdup,					needlogp);				(void)xfs_dir2_data_freeinsert(d, newdup2,					needlogp);			}		}	}	*needscanp = needscan;}

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -