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

📄 xfs_attr_leaf.c

📁 linux 内核源代码
💻 C
📖 第 1 页 / 共 5 页
字号:
{	xfs_attr_leafblock_t *leaf;	xfs_da_intnode_t *node;	xfs_inode_t *dp;	xfs_dabuf_t *bp1, *bp2;	xfs_dablk_t blkno;	int error;	dp = args->dp;	bp1 = bp2 = NULL;	error = xfs_da_grow_inode(args, &blkno);	if (error)		goto out;	error = xfs_da_read_buf(args->trans, args->dp, 0, -1, &bp1,					     XFS_ATTR_FORK);	if (error)		goto out;	ASSERT(bp1 != NULL);	bp2 = NULL;	error = xfs_da_get_buf(args->trans, args->dp, blkno, -1, &bp2,					    XFS_ATTR_FORK);	if (error)		goto out;	ASSERT(bp2 != NULL);	memcpy(bp2->data, bp1->data, XFS_LBSIZE(dp->i_mount));	xfs_da_buf_done(bp1);	bp1 = NULL;	xfs_da_log_buf(args->trans, bp2, 0, XFS_LBSIZE(dp->i_mount) - 1);	/*	 * Set up the new root node.	 */	error = xfs_da_node_create(args, 0, 1, &bp1, XFS_ATTR_FORK);	if (error)		goto out;	node = bp1->data;	leaf = bp2->data;	ASSERT(be16_to_cpu(leaf->hdr.info.magic) == XFS_ATTR_LEAF_MAGIC);	/* both on-disk, don't endian-flip twice */	node->btree[0].hashval =		leaf->entries[be16_to_cpu(leaf->hdr.count)-1 ].hashval;	node->btree[0].before = cpu_to_be32(blkno);	node->hdr.count = cpu_to_be16(1);	xfs_da_log_buf(args->trans, bp1, 0, XFS_LBSIZE(dp->i_mount) - 1);	error = 0;out:	if (bp1)		xfs_da_buf_done(bp1);	if (bp2)		xfs_da_buf_done(bp2);	return(error);}/*======================================================================== * Routines used for growing the Btree. *========================================================================*//* * Create the initial contents of a leaf attribute list * or a leaf in a node attribute list. */STATIC intxfs_attr_leaf_create(xfs_da_args_t *args, xfs_dablk_t blkno, xfs_dabuf_t **bpp){	xfs_attr_leafblock_t *leaf;	xfs_attr_leaf_hdr_t *hdr;	xfs_inode_t *dp;	xfs_dabuf_t *bp;	int error;	dp = args->dp;	ASSERT(dp != NULL);	error = xfs_da_get_buf(args->trans, args->dp, blkno, -1, &bp,					    XFS_ATTR_FORK);	if (error)		return(error);	ASSERT(bp != NULL);	leaf = bp->data;	memset((char *)leaf, 0, XFS_LBSIZE(dp->i_mount));	hdr = &leaf->hdr;	hdr->info.magic = cpu_to_be16(XFS_ATTR_LEAF_MAGIC);	hdr->firstused = cpu_to_be16(XFS_LBSIZE(dp->i_mount));	if (!hdr->firstused) {		hdr->firstused = cpu_to_be16(			XFS_LBSIZE(dp->i_mount) - XFS_ATTR_LEAF_NAME_ALIGN);	}	hdr->freemap[0].base = cpu_to_be16(sizeof(xfs_attr_leaf_hdr_t));	hdr->freemap[0].size = cpu_to_be16(be16_to_cpu(hdr->firstused) -					   sizeof(xfs_attr_leaf_hdr_t));	xfs_da_log_buf(args->trans, bp, 0, XFS_LBSIZE(dp->i_mount) - 1);	*bpp = bp;	return(0);}/* * Split the leaf node, rebalance, then add the new entry. */intxfs_attr_leaf_split(xfs_da_state_t *state, xfs_da_state_blk_t *oldblk,				   xfs_da_state_blk_t *newblk){	xfs_dablk_t blkno;	int error;	/*	 * Allocate space for a new leaf node.	 */	ASSERT(oldblk->magic == XFS_ATTR_LEAF_MAGIC);	error = xfs_da_grow_inode(state->args, &blkno);	if (error)		return(error);	error = xfs_attr_leaf_create(state->args, blkno, &newblk->bp);	if (error)		return(error);	newblk->blkno = blkno;	newblk->magic = XFS_ATTR_LEAF_MAGIC;	/*	 * Rebalance the entries across the two leaves.	 * NOTE: rebalance() currently depends on the 2nd block being empty.	 */	xfs_attr_leaf_rebalance(state, oldblk, newblk);	error = xfs_da_blk_link(state, oldblk, newblk);	if (error)		return(error);	/*	 * Save info on "old" attribute for "atomic rename" ops, leaf_add()	 * modifies the index/blkno/rmtblk/rmtblkcnt fields to show the	 * "new" attrs info.  Will need the "old" info to remove it later.	 *	 * Insert the "new" entry in the correct block.	 */	if (state->inleaf)		error = xfs_attr_leaf_add(oldblk->bp, state->args);	else		error = xfs_attr_leaf_add(newblk->bp, state->args);	/*	 * Update last hashval in each block since we added the name.	 */	oldblk->hashval = xfs_attr_leaf_lasthash(oldblk->bp, NULL);	newblk->hashval = xfs_attr_leaf_lasthash(newblk->bp, NULL);	return(error);}/* * Add a name to the leaf attribute list structure. */intxfs_attr_leaf_add(xfs_dabuf_t *bp, xfs_da_args_t *args){	xfs_attr_leafblock_t *leaf;	xfs_attr_leaf_hdr_t *hdr;	xfs_attr_leaf_map_t *map;	int tablesize, entsize, sum, tmp, i;	leaf = bp->data;	ASSERT(be16_to_cpu(leaf->hdr.info.magic) == XFS_ATTR_LEAF_MAGIC);	ASSERT((args->index >= 0)		&& (args->index <= be16_to_cpu(leaf->hdr.count)));	hdr = &leaf->hdr;	entsize = xfs_attr_leaf_newentsize(args->namelen, args->valuelen,			   args->trans->t_mountp->m_sb.sb_blocksize, NULL);	/*	 * Search through freemap for first-fit on new name length.	 * (may need to figure in size of entry struct too)	 */	tablesize = (be16_to_cpu(hdr->count) + 1)					* sizeof(xfs_attr_leaf_entry_t)					+ sizeof(xfs_attr_leaf_hdr_t);	map = &hdr->freemap[XFS_ATTR_LEAF_MAPSIZE-1];	for (sum = 0, i = XFS_ATTR_LEAF_MAPSIZE-1; i >= 0; map--, i--) {		if (tablesize > be16_to_cpu(hdr->firstused)) {			sum += be16_to_cpu(map->size);			continue;		}		if (!map->size)			continue;	/* no space in this map */		tmp = entsize;		if (be16_to_cpu(map->base) < be16_to_cpu(hdr->firstused))			tmp += sizeof(xfs_attr_leaf_entry_t);		if (be16_to_cpu(map->size) >= tmp) {			tmp = xfs_attr_leaf_add_work(bp, args, i);			return(tmp);		}		sum += be16_to_cpu(map->size);	}	/*	 * If there are no holes in the address space of the block,	 * and we don't have enough freespace, then compaction will do us	 * no good and we should just give up.	 */	if (!hdr->holes && (sum < entsize))		return(XFS_ERROR(ENOSPC));	/*	 * Compact the entries to coalesce free space.	 * This may change the hdr->count via dropping INCOMPLETE entries.	 */	xfs_attr_leaf_compact(args->trans, bp);	/*	 * After compaction, the block is guaranteed to have only one	 * free region, in freemap[0].  If it is not big enough, give up.	 */	if (be16_to_cpu(hdr->freemap[0].size)				< (entsize + sizeof(xfs_attr_leaf_entry_t)))		return(XFS_ERROR(ENOSPC));	return(xfs_attr_leaf_add_work(bp, args, 0));}/* * Add a name to a leaf attribute list structure. */STATIC intxfs_attr_leaf_add_work(xfs_dabuf_t *bp, xfs_da_args_t *args, int mapindex){	xfs_attr_leafblock_t *leaf;	xfs_attr_leaf_hdr_t *hdr;	xfs_attr_leaf_entry_t *entry;	xfs_attr_leaf_name_local_t *name_loc;	xfs_attr_leaf_name_remote_t *name_rmt;	xfs_attr_leaf_map_t *map;	xfs_mount_t *mp;	int tmp, i;	leaf = bp->data;	ASSERT(be16_to_cpu(leaf->hdr.info.magic) == XFS_ATTR_LEAF_MAGIC);	hdr = &leaf->hdr;	ASSERT((mapindex >= 0) && (mapindex < XFS_ATTR_LEAF_MAPSIZE));	ASSERT((args->index >= 0) && (args->index <= be16_to_cpu(hdr->count)));	/*	 * Force open some space in the entry array and fill it in.	 */	entry = &leaf->entries[args->index];	if (args->index < be16_to_cpu(hdr->count)) {		tmp  = be16_to_cpu(hdr->count) - args->index;		tmp *= sizeof(xfs_attr_leaf_entry_t);		memmove((char *)(entry+1), (char *)entry, tmp);		xfs_da_log_buf(args->trans, bp,		    XFS_DA_LOGRANGE(leaf, entry, tmp + sizeof(*entry)));	}	be16_add(&hdr->count, 1);	/*	 * Allocate space for the new string (at the end of the run).	 */	map = &hdr->freemap[mapindex];	mp = args->trans->t_mountp;	ASSERT(be16_to_cpu(map->base) < XFS_LBSIZE(mp));	ASSERT((be16_to_cpu(map->base) & 0x3) == 0);	ASSERT(be16_to_cpu(map->size) >=		xfs_attr_leaf_newentsize(args->namelen, args->valuelen,					 mp->m_sb.sb_blocksize, NULL));	ASSERT(be16_to_cpu(map->size) < XFS_LBSIZE(mp));	ASSERT((be16_to_cpu(map->size) & 0x3) == 0);	be16_add(&map->size,		-xfs_attr_leaf_newentsize(args->namelen, args->valuelen,					  mp->m_sb.sb_blocksize, &tmp));	entry->nameidx = cpu_to_be16(be16_to_cpu(map->base) +				     be16_to_cpu(map->size));	entry->hashval = cpu_to_be32(args->hashval);	entry->flags = tmp ? XFS_ATTR_LOCAL : 0;	entry->flags |= XFS_ATTR_NSP_ARGS_TO_ONDISK(args->flags);	if (args->rename) {		entry->flags |= XFS_ATTR_INCOMPLETE;		if ((args->blkno2 == args->blkno) &&		    (args->index2 <= args->index)) {			args->index2++;		}	}	xfs_da_log_buf(args->trans, bp,			  XFS_DA_LOGRANGE(leaf, entry, sizeof(*entry)));	ASSERT((args->index == 0) ||	       (be32_to_cpu(entry->hashval) >= be32_to_cpu((entry-1)->hashval)));	ASSERT((args->index == be16_to_cpu(hdr->count)-1) ||	       (be32_to_cpu(entry->hashval) <= be32_to_cpu((entry+1)->hashval)));	/*	 * Copy the attribute name and value into the new space.	 *	 * For "remote" attribute values, simply note that we need to	 * allocate space for the "remote" value.  We can't actually	 * allocate the extents in this transaction, and we can't decide	 * which blocks they should be as we might allocate more blocks	 * as part of this transaction (a split operation for example).	 */	if (entry->flags & XFS_ATTR_LOCAL) {		name_loc = XFS_ATTR_LEAF_NAME_LOCAL(leaf, args->index);		name_loc->namelen = args->namelen;		name_loc->valuelen = cpu_to_be16(args->valuelen);		memcpy((char *)name_loc->nameval, args->name, args->namelen);		memcpy((char *)&name_loc->nameval[args->namelen], args->value,				   be16_to_cpu(name_loc->valuelen));	} else {		name_rmt = XFS_ATTR_LEAF_NAME_REMOTE(leaf, args->index);		name_rmt->namelen = args->namelen;		memcpy((char *)name_rmt->name, args->name, args->namelen);		entry->flags |= XFS_ATTR_INCOMPLETE;		/* just in case */		name_rmt->valuelen = 0;		name_rmt->valueblk = 0;		args->rmtblkno = 1;		args->rmtblkcnt = XFS_B_TO_FSB(mp, args->valuelen);	}	xfs_da_log_buf(args->trans, bp,	     XFS_DA_LOGRANGE(leaf, XFS_ATTR_LEAF_NAME(leaf, args->index),				   xfs_attr_leaf_entsize(leaf, args->index)));	/*	 * Update the control info for this leaf node	 */	if (be16_to_cpu(entry->nameidx) < be16_to_cpu(hdr->firstused)) {		/* both on-disk, don't endian-flip twice */		hdr->firstused = entry->nameidx;	}	ASSERT(be16_to_cpu(hdr->firstused) >=	       ((be16_to_cpu(hdr->count) * sizeof(*entry)) + sizeof(*hdr)));	tmp = (be16_to_cpu(hdr->count)-1) * sizeof(xfs_attr_leaf_entry_t)					+ sizeof(xfs_attr_leaf_hdr_t);	map = &hdr->freemap[0];	for (i = 0; i < XFS_ATTR_LEAF_MAPSIZE; map++, i++) {		if (be16_to_cpu(map->base) == tmp) {			be16_add(&map->base, sizeof(xfs_attr_leaf_entry_t));			be16_add(&map->size,				 -((int)sizeof(xfs_attr_leaf_entry_t)));		}	}	be16_add(&hdr->usedbytes, xfs_attr_leaf_entsize(leaf, args->index));	xfs_da_log_buf(args->trans, bp,		XFS_DA_LOGRANGE(leaf, hdr, sizeof(*hdr)));	return(0);}/* * Garbage collect a leaf attribute list block by copying it to a new buffer. */STATIC voidxfs_attr_leaf_compact(xfs_trans_t *trans, xfs_dabuf_t *bp){	xfs_attr_leafblock_t *leaf_s, *leaf_d;	xfs_attr_leaf_hdr_t *hdr_s, *hdr_d;	xfs_mount_t *mp;	char *tmpbuffer;	mp = trans->t_mountp;	tmpbuffer = kmem_alloc(XFS_LBSIZE(mp), KM_SLEEP);	ASSERT(tmpbuffer != NULL);	memcpy(tmpbuffer, bp->data, XFS_LBSIZE(mp));	memset(bp->data, 0, XFS_LBSIZE(mp));	/*	 * Copy basic information	 */	leaf_s = (xfs_attr_leafblock_t *)tmpbuffer;	leaf_d = bp->data;	hdr_s = &leaf_s->hdr;	hdr_d = &leaf_d->hdr;	hdr_d->info = hdr_s->info;	/* struct copy */	hdr_d->firstused = cpu_to_be16(XFS_LBSIZE(mp));	/* handle truncation gracefully */	if (!hdr_d->firstused) {		hdr_d->firstused = cpu_to_be16(				XFS_LBSIZE(mp) - XFS_ATTR_LEAF_NAME_ALIGN);	}	hdr_d->usedbytes = 0;	hdr_d->count = 0;	hdr_d->holes = 0;	hdr_d->freemap[0].base = cpu_to_be16(sizeof(xfs_attr_leaf_hdr_t));	hdr_d->freemap[0].size = cpu_to_be16(be16_to_cpu(hdr_d->firstused) -					     sizeof(xfs_attr_leaf_hdr_t));	/*	 * Copy all entry's in the same (sorted) order,	 * but allocate name/value pairs packed and in sequence.	 */	xfs_attr_leaf_moveents(leaf_s, 0, leaf_d, 0,				be16_to_cpu(hdr_s->count), mp);	xfs_da_log_buf(trans, bp, 0, XFS_LBSIZE(mp) - 1);	kmem_free(tmpbuffer, XFS_LBSIZE(mp));}/* * Redistribute the attribute list entries between two leaf nodes, * taking into account the size of the new entry. * * NOTE: if new block is empty, then it will get the upper half of the * old block.  At present, all (one) callers pass in an empty second block. * * This code adjusts the args->index/blkno and args->index2/blkno2 fields * to match what it is doing in splitting the attribute leaf block.  Those * values are used in "atomic rename" operations on attributes.  Note that * the "new" and "old" values can end up in different blocks. */STATIC voidxfs_attr_leaf_rebalance(xfs_da_state_t *state, xfs_da_state_blk_t *blk1,				       xfs_da_state_blk_t *blk2){	xfs_da_args_t *args;	xfs_da_state_blk_t *tmp_blk;	xfs_attr_leafblock_t *leaf1, *leaf2;	xfs_attr_leaf_hdr_t *hdr1, *hdr2;	int count, totallen, max, space, swap;	/*	 * Set up environment.	 */	ASSERT(blk1->magic == XFS_ATTR_LEAF_MAGIC);	ASSERT(blk2->magic == XFS_ATTR_LEAF_MAGIC);	leaf1 = blk1->bp->data;	leaf2 = blk2->bp->data;	ASSERT(be16_to_cpu(leaf1->hdr.info.magic) == XFS_ATTR_LEAF_MAGIC);	ASSERT(be16_to_cpu(leaf2->hdr.info.magic) == XFS_ATTR_LEAF_MAGIC);	args = state->args;	/*	 * Check ordering of blocks, reverse if it makes things simpler.	 *	 * NOTE: Given that all (current) callers pass in an empty	 * second block, this code should never set "swap".	 */	swap = 0;	if (xfs_attr_leaf_order(blk1->bp, blk2->bp)) {		tmp_blk = blk1;		blk1 = blk2;		blk2 = tmp_blk;		leaf1 = blk1->bp->data;		leaf2 = blk2->bp->data;		swap = 1;	}	hdr1 = &leaf1->hdr;	hdr2 = &leaf2->hdr;

⌨️ 快捷键说明

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