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

📄 xfs_attr_leaf.c

📁 linux 内核源代码
💻 C
📖 第 1 页 / 共 5 页
字号:
		 */		map = &hdr->freemap[smallest];		if (be16_to_cpu(map->size) < entsize) {			map->base = cpu_to_be16(be16_to_cpu(entry->nameidx));			map->size = cpu_to_be16(entsize);		}	}	/*	 * Did we remove the first entry?	 */	if (be16_to_cpu(entry->nameidx) == be16_to_cpu(hdr->firstused))		smallest = 1;	else		smallest = 0;	/*	 * Compress the remaining entries and zero out the removed stuff.	 */	memset(XFS_ATTR_LEAF_NAME(leaf, args->index), 0, entsize);	be16_add(&hdr->usedbytes, -entsize);	xfs_da_log_buf(args->trans, bp,	     XFS_DA_LOGRANGE(leaf, XFS_ATTR_LEAF_NAME(leaf, args->index),				   entsize));	tmp = (be16_to_cpu(hdr->count) - args->index)					* sizeof(xfs_attr_leaf_entry_t);	memmove((char *)entry, (char *)(entry+1), tmp);	be16_add(&hdr->count, -1);	xfs_da_log_buf(args->trans, bp,	    XFS_DA_LOGRANGE(leaf, entry, tmp + sizeof(*entry)));	entry = &leaf->entries[be16_to_cpu(hdr->count)];	memset((char *)entry, 0, sizeof(xfs_attr_leaf_entry_t));	/*	 * If we removed the first entry, re-find the first used byte	 * in the name area.  Note that if the entry was the "firstused",	 * then we don't have a "hole" in our block resulting from	 * removing the name.	 */	if (smallest) {		tmp = XFS_LBSIZE(mp);		entry = &leaf->entries[0];		for (i = be16_to_cpu(hdr->count)-1; i >= 0; entry++, i--) {			ASSERT(be16_to_cpu(entry->nameidx) >=			       be16_to_cpu(hdr->firstused));			ASSERT(be16_to_cpu(entry->nameidx) < XFS_LBSIZE(mp));			if (be16_to_cpu(entry->nameidx) < tmp)				tmp = be16_to_cpu(entry->nameidx);		}		hdr->firstused = cpu_to_be16(tmp);		if (!hdr->firstused) {			hdr->firstused = cpu_to_be16(					tmp - XFS_ATTR_LEAF_NAME_ALIGN);		}	} else {		hdr->holes = 1;		/* mark as needing compaction */	}	xfs_da_log_buf(args->trans, bp,			  XFS_DA_LOGRANGE(leaf, hdr, sizeof(*hdr)));	/*	 * Check if leaf is less than 50% full, caller may want to	 * "join" the leaf with a sibling if so.	 */	tmp  = sizeof(xfs_attr_leaf_hdr_t);	tmp += be16_to_cpu(leaf->hdr.count) * sizeof(xfs_attr_leaf_entry_t);	tmp += be16_to_cpu(leaf->hdr.usedbytes);	return(tmp < mp->m_attr_magicpct); /* leaf is < 37% full */}/* * Move all the attribute list entries from drop_leaf into save_leaf. */voidxfs_attr_leaf_unbalance(xfs_da_state_t *state, xfs_da_state_blk_t *drop_blk,				       xfs_da_state_blk_t *save_blk){	xfs_attr_leafblock_t *drop_leaf, *save_leaf, *tmp_leaf;	xfs_attr_leaf_hdr_t *drop_hdr, *save_hdr, *tmp_hdr;	xfs_mount_t *mp;	char *tmpbuffer;	/*	 * Set up environment.	 */	mp = state->mp;	ASSERT(drop_blk->magic == XFS_ATTR_LEAF_MAGIC);	ASSERT(save_blk->magic == XFS_ATTR_LEAF_MAGIC);	drop_leaf = drop_blk->bp->data;	save_leaf = save_blk->bp->data;	ASSERT(be16_to_cpu(drop_leaf->hdr.info.magic) == XFS_ATTR_LEAF_MAGIC);	ASSERT(be16_to_cpu(save_leaf->hdr.info.magic) == XFS_ATTR_LEAF_MAGIC);	drop_hdr = &drop_leaf->hdr;	save_hdr = &save_leaf->hdr;	/*	 * Save last hashval from dying block for later Btree fixup.	 */	drop_blk->hashval = be32_to_cpu(		drop_leaf->entries[be16_to_cpu(drop_leaf->hdr.count)-1].hashval);	/*	 * Check if we need a temp buffer, or can we do it in place.	 * Note that we don't check "leaf" for holes because we will	 * always be dropping it, toosmall() decided that for us already.	 */	if (save_hdr->holes == 0) {		/*		 * dest leaf has no holes, so we add there.  May need		 * to make some room in the entry array.		 */		if (xfs_attr_leaf_order(save_blk->bp, drop_blk->bp)) {			xfs_attr_leaf_moveents(drop_leaf, 0, save_leaf, 0,			     be16_to_cpu(drop_hdr->count), mp);		} else {			xfs_attr_leaf_moveents(drop_leaf, 0, save_leaf,				  be16_to_cpu(save_hdr->count),				  be16_to_cpu(drop_hdr->count), mp);		}	} else {		/*		 * Destination has holes, so we make a temporary copy		 * of the leaf and add them both to that.		 */		tmpbuffer = kmem_alloc(state->blocksize, KM_SLEEP);		ASSERT(tmpbuffer != NULL);		memset(tmpbuffer, 0, state->blocksize);		tmp_leaf = (xfs_attr_leafblock_t *)tmpbuffer;		tmp_hdr = &tmp_leaf->hdr;		tmp_hdr->info = save_hdr->info;	/* struct copy */		tmp_hdr->count = 0;		tmp_hdr->firstused = cpu_to_be16(state->blocksize);		if (!tmp_hdr->firstused) {			tmp_hdr->firstused = cpu_to_be16(				state->blocksize - XFS_ATTR_LEAF_NAME_ALIGN);		}		tmp_hdr->usedbytes = 0;		if (xfs_attr_leaf_order(save_blk->bp, drop_blk->bp)) {			xfs_attr_leaf_moveents(drop_leaf, 0, tmp_leaf, 0,				be16_to_cpu(drop_hdr->count), mp);			xfs_attr_leaf_moveents(save_leaf, 0, tmp_leaf,				  be16_to_cpu(tmp_leaf->hdr.count),				  be16_to_cpu(save_hdr->count), mp);		} else {			xfs_attr_leaf_moveents(save_leaf, 0, tmp_leaf, 0,				be16_to_cpu(save_hdr->count), mp);			xfs_attr_leaf_moveents(drop_leaf, 0, tmp_leaf,				be16_to_cpu(tmp_leaf->hdr.count),				be16_to_cpu(drop_hdr->count), mp);		}		memcpy((char *)save_leaf, (char *)tmp_leaf, state->blocksize);		kmem_free(tmpbuffer, state->blocksize);	}	xfs_da_log_buf(state->args->trans, save_blk->bp, 0,					   state->blocksize - 1);	/*	 * Copy out last hashval in each block for B-tree code.	 */	save_blk->hashval = be32_to_cpu(		save_leaf->entries[be16_to_cpu(save_leaf->hdr.count)-1].hashval);}/*======================================================================== * Routines used for finding things in the Btree. *========================================================================*//* * Look up a name in a leaf attribute list structure. * This is the internal routine, it uses the caller's buffer. * * Note that duplicate keys are allowed, but only check within the * current leaf node.  The Btree code must check in adjacent leaf nodes. * * Return in args->index the index into the entry[] array of either * the found entry, or where the entry should have been (insert before * that entry). * * Don't change the args->value unless we find the attribute. */intxfs_attr_leaf_lookup_int(xfs_dabuf_t *bp, xfs_da_args_t *args){	xfs_attr_leafblock_t *leaf;	xfs_attr_leaf_entry_t *entry;	xfs_attr_leaf_name_local_t *name_loc;	xfs_attr_leaf_name_remote_t *name_rmt;	int probe, span;	xfs_dahash_t hashval;	leaf = bp->data;	ASSERT(be16_to_cpu(leaf->hdr.info.magic) == XFS_ATTR_LEAF_MAGIC);	ASSERT(be16_to_cpu(leaf->hdr.count)					< (XFS_LBSIZE(args->dp->i_mount)/8));	/*	 * Binary search.  (note: small blocks will skip this loop)	 */	hashval = args->hashval;	probe = span = be16_to_cpu(leaf->hdr.count) / 2;	for (entry = &leaf->entries[probe]; span > 4;		   entry = &leaf->entries[probe]) {		span /= 2;		if (be32_to_cpu(entry->hashval) < hashval)			probe += span;		else if (be32_to_cpu(entry->hashval) > hashval)			probe -= span;		else			break;	}	ASSERT((probe >= 0) &&	       (!leaf->hdr.count	       || (probe < be16_to_cpu(leaf->hdr.count))));	ASSERT((span <= 4) || (be32_to_cpu(entry->hashval) == hashval));	/*	 * Since we may have duplicate hashval's, find the first matching	 * hashval in the leaf.	 */	while ((probe > 0) && (be32_to_cpu(entry->hashval) >= hashval)) {		entry--;		probe--;	}	while ((probe < be16_to_cpu(leaf->hdr.count)) &&	       (be32_to_cpu(entry->hashval) < hashval)) {		entry++;		probe++;	}	if ((probe == be16_to_cpu(leaf->hdr.count)) ||	    (be32_to_cpu(entry->hashval) != hashval)) {		args->index = probe;		return(XFS_ERROR(ENOATTR));	}	/*	 * Duplicate keys may be present, so search all of them for a match.	 */	for (  ; (probe < be16_to_cpu(leaf->hdr.count)) &&			(be32_to_cpu(entry->hashval) == hashval);			entry++, probe++) {/* * GROT: Add code to remove incomplete entries. */		/*		 * If we are looking for INCOMPLETE entries, show only those.		 * If we are looking for complete entries, show only those.		 */		if ((args->flags & XFS_ATTR_INCOMPLETE) !=		    (entry->flags & XFS_ATTR_INCOMPLETE)) {			continue;		}		if (entry->flags & XFS_ATTR_LOCAL) {			name_loc = XFS_ATTR_LEAF_NAME_LOCAL(leaf, probe);			if (name_loc->namelen != args->namelen)				continue;			if (memcmp(args->name, (char *)name_loc->nameval, args->namelen) != 0)				continue;			if (!xfs_attr_namesp_match(args->flags, entry->flags))				continue;			args->index = probe;			return(XFS_ERROR(EEXIST));		} else {			name_rmt = XFS_ATTR_LEAF_NAME_REMOTE(leaf, probe);			if (name_rmt->namelen != args->namelen)				continue;			if (memcmp(args->name, (char *)name_rmt->name,					     args->namelen) != 0)				continue;			if (!xfs_attr_namesp_match(args->flags, entry->flags))				continue;			args->index = probe;			args->rmtblkno = be32_to_cpu(name_rmt->valueblk);			args->rmtblkcnt = XFS_B_TO_FSB(args->dp->i_mount,						   be32_to_cpu(name_rmt->valuelen));			return(XFS_ERROR(EEXIST));		}	}	args->index = probe;	return(XFS_ERROR(ENOATTR));}/* * Get the value associated with an attribute name from a leaf attribute * list structure. */intxfs_attr_leaf_getvalue(xfs_dabuf_t *bp, xfs_da_args_t *args){	int valuelen;	xfs_attr_leafblock_t *leaf;	xfs_attr_leaf_entry_t *entry;	xfs_attr_leaf_name_local_t *name_loc;	xfs_attr_leaf_name_remote_t *name_rmt;	leaf = bp->data;	ASSERT(be16_to_cpu(leaf->hdr.info.magic) == XFS_ATTR_LEAF_MAGIC);	ASSERT(be16_to_cpu(leaf->hdr.count)					< (XFS_LBSIZE(args->dp->i_mount)/8));	ASSERT(args->index < be16_to_cpu(leaf->hdr.count));	entry = &leaf->entries[args->index];	if (entry->flags & XFS_ATTR_LOCAL) {		name_loc = XFS_ATTR_LEAF_NAME_LOCAL(leaf, args->index);		ASSERT(name_loc->namelen == args->namelen);		ASSERT(memcmp(args->name, name_loc->nameval, args->namelen) == 0);		valuelen = be16_to_cpu(name_loc->valuelen);		if (args->flags & ATTR_KERNOVAL) {			args->valuelen = valuelen;			return(0);		}		if (args->valuelen < valuelen) {			args->valuelen = valuelen;			return(XFS_ERROR(ERANGE));		}		args->valuelen = valuelen;		memcpy(args->value, &name_loc->nameval[args->namelen], valuelen);	} else {		name_rmt = XFS_ATTR_LEAF_NAME_REMOTE(leaf, args->index);		ASSERT(name_rmt->namelen == args->namelen);		ASSERT(memcmp(args->name, name_rmt->name, args->namelen) == 0);		valuelen = be32_to_cpu(name_rmt->valuelen);		args->rmtblkno = be32_to_cpu(name_rmt->valueblk);		args->rmtblkcnt = XFS_B_TO_FSB(args->dp->i_mount, valuelen);		if (args->flags & ATTR_KERNOVAL) {			args->valuelen = valuelen;			return(0);		}		if (args->valuelen < valuelen) {			args->valuelen = valuelen;			return(XFS_ERROR(ERANGE));		}		args->valuelen = valuelen;	}	return(0);}/*======================================================================== * Utility routines. *========================================================================*//* * Move the indicated entries from one leaf to another. * NOTE: this routine modifies both source and destination leaves. *//*ARGSUSED*/STATIC voidxfs_attr_leaf_moveents(xfs_attr_leafblock_t *leaf_s, int start_s,			xfs_attr_leafblock_t *leaf_d, int start_d,			int count, xfs_mount_t *mp){	xfs_attr_leaf_hdr_t *hdr_s, *hdr_d;	xfs_attr_leaf_entry_t *entry_s, *entry_d;	int desti, tmp, i;	/*	 * Check for nothing to do.	 */	if (count == 0)		return;	/*	 * Set up environment.	 */	ASSERT(be16_to_cpu(leaf_s->hdr.info.magic) == XFS_ATTR_LEAF_MAGIC);	ASSERT(be16_to_cpu(leaf_d->hdr.info.magic) == XFS_ATTR_LEAF_MAGIC);	hdr_s = &leaf_s->hdr;	hdr_d = &leaf_d->hdr;	ASSERT((be16_to_cpu(hdr_s->count) > 0) &&	       (be16_to_cpu(hdr_s->count) < (XFS_LBSIZE(mp)/8)));	ASSERT(be16_to_cpu(hdr_s->firstused) >=		((be16_to_cpu(hdr_s->count)					* sizeof(*entry_s))+sizeof(*hdr_s)));	ASSERT(be16_to_cpu(hdr_d->count) < (XFS_LBSIZE(mp)/8));	ASSERT(be16_to_cpu(hdr_d->firstused) >=		((be16_to_cpu(hdr_d->count)					* sizeof(*entry_d))+sizeof(*hdr_d)));	ASSERT(start_s < be16_to_cpu(hdr_s->count));	ASSERT(start_d <= be16_to_cpu(hdr_d->count));	ASSERT(count <= be16_to_cpu(hdr_s->count));	/*	 * Move the entries in the destination leaf up to make a hole?	 */	if (start_d < be16_to_cpu(hdr_d->count)) {		tmp  = be16_to_cpu(hdr_d->count) - start_d;		tmp *= sizeof(xfs_attr_leaf_entry_t);		entry_s = &leaf_d->entries[start_d];		entry_d = &leaf_d->entries[start_d + count];		memmove((char *)entry_d, (char *)entry_s, tmp);	}	/*	 * Copy all entry's in the same (sorted) order,	 * but allocate attribute info packed and in sequence.	 */	entry_s = &leaf_s->entries[start_s];	entry_d = &leaf_d->entries[start_d];	desti = start_d;	for (i = 0; i < count; entry_s++, entry_d++, desti++, i++) {		ASSERT(be16_to_cpu(entry_s->nameidx)				>= be16_to_cpu(hdr_s->firstused));		tmp = xfs_attr_leaf_entsize(leaf_s, start_s + i);#ifdef GROT		/*		 * Code to drop INCOMPLETE entries.  Difficult to use as we		 * may also need to change the insertion index.  Code turned		 * off for 6.2, should be revisited later.		 */		if (entry_s->flags & XFS_ATTR_INCOMPLETE) { /* skip partials? */			memset(XFS_ATTR_LEAF_NAME(leaf_s, start_s + i), 0, tmp);			be16_add(&hdr_s->usedbytes, -tmp);			be16_add(&hdr_s->count, -1);			entry_d--;	/* to compensate for ++ in loop hdr */			desti--;			if ((start_s + i) < offset)				result++;	/* insertion index adjustment */		} else {#endif /* GROT */			be16_add(&hdr_d->firstused, -tmp);			/* both on-disk, don't endian flip twice */			entry_d->hashval = entry_s->hashval;			/* both on-disk, don't endian flip twice */			entry_d->nameidx = hdr_d->firstused;			entry_d->flags = entry_s->flags;			ASSERT(be16_to_cpu(entry_d->nameidx) + tmp							<= XFS_LBSIZE(mp));			memmove(XFS_ATTR_LEAF_NAME(leaf_d, desti),				XFS_ATTR_LEAF_NAME(leaf_s, start_s + i), tmp);			ASSERT(be16_to_cpu(entry_s->nameidx) + tmp							<= XFS_LBSIZE(mp));			memset(XFS_ATTR_LEAF_NAME(leaf_s, start_s + i), 0, tmp);			be16_add(&hdr_s->usedbytes, -tmp);			be16_add(&hdr_d->usedbytes, tmp);			be16_add(&hdr_s->count, -1);			be16_add(&hdr_d->count, 1);			tmp = be16_to_cpu(hdr_d->count)						* sizeof(xfs_attr_leaf_entry_t)					

⌨️ 快捷键说明

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