brintos

brintos / linux-shallow public Read only

0
0
Text · 39.2 KiB · c63da14 Raw
1594 lines · c
1// SPDX-License-Identifier: GPL-2.02/*3 * Copyright (c) 2000-2005 Silicon Graphics, Inc.4 * All Rights Reserved.5 */6#include "xfs.h"7#include "xfs_fs.h"8#include "xfs_shared.h"9#include "xfs_format.h"10#include "xfs_log_format.h"11#include "xfs_trans_resv.h"12#include "xfs_mount.h"13#include "xfs_defer.h"14#include "xfs_da_format.h"15#include "xfs_da_btree.h"16#include "xfs_attr_sf.h"17#include "xfs_inode.h"18#include "xfs_trans.h"19#include "xfs_bmap.h"20#include "xfs_bmap_btree.h"21#include "xfs_attr.h"22#include "xfs_attr_leaf.h"23#include "xfs_attr_remote.h"24#include "xfs_quota.h"25#include "xfs_trans_space.h"26#include "xfs_trace.h"27#include "xfs_attr_item.h"28#include "xfs_xattr.h"29#include "xfs_parent.h"30 31struct kmem_cache		*xfs_attr_intent_cache;32 33/*34 * xfs_attr.c35 *36 * Provide the external interfaces to manage attribute lists.37 */38 39/*========================================================================40 * Function prototypes for the kernel.41 *========================================================================*/42 43/*44 * Internal routines when attribute list fits inside the inode.45 */46STATIC int xfs_attr_shortform_addname(xfs_da_args_t *args);47 48/*49 * Internal routines when attribute list is one block.50 */51STATIC int xfs_attr_leaf_get(xfs_da_args_t *args);52STATIC int xfs_attr_leaf_removename(xfs_da_args_t *args);53STATIC int xfs_attr_leaf_hasname(struct xfs_da_args *args, struct xfs_buf **bp);54 55/*56 * Internal routines when attribute list is more than one block.57 */58STATIC int xfs_attr_node_get(xfs_da_args_t *args);59STATIC void xfs_attr_restore_rmt_blk(struct xfs_da_args *args);60static int xfs_attr_node_try_addname(struct xfs_attr_intent *attr);61STATIC int xfs_attr_node_addname_find_attr(struct xfs_attr_intent *attr);62STATIC int xfs_attr_node_remove_attr(struct xfs_attr_intent *attr);63STATIC int xfs_attr_node_lookup(struct xfs_da_args *args,64		struct xfs_da_state *state);65 66int67xfs_inode_hasattr(68	struct xfs_inode	*ip)69{70	if (!xfs_inode_has_attr_fork(ip))71		return 0;72	if (ip->i_af.if_format == XFS_DINODE_FMT_EXTENTS &&73	    ip->i_af.if_nextents == 0)74		return 0;75	return 1;76}77 78/*79 * Returns true if the there is exactly only block in the attr fork, in which80 * case the attribute fork consists of a single leaf block entry.81 */82bool83xfs_attr_is_leaf(84	struct xfs_inode	*ip)85{86	struct xfs_ifork	*ifp = &ip->i_af;87	struct xfs_iext_cursor	icur;88	struct xfs_bmbt_irec	imap;89 90	ASSERT(!xfs_need_iread_extents(ifp));91 92	if (ifp->if_nextents != 1 || ifp->if_format != XFS_DINODE_FMT_EXTENTS)93		return false;94 95	xfs_iext_first(ifp, &icur);96	xfs_iext_get_extent(ifp, &icur, &imap);97	return imap.br_startoff == 0 && imap.br_blockcount == 1;98}99 100/*101 * XXX (dchinner): name path state saving and refilling is an optimisation to102 * avoid needing to look up name entries after rolling transactions removing103 * remote xattr blocks between the name entry lookup and name entry removal.104 * This optimisation got sidelined when combining the set and remove state105 * machines, but the code has been left in place because it is worthwhile to106 * restore the optimisation once the combined state machine paths have settled.107 *108 * This comment is a public service announcement to remind Future Dave that he109 * still needs to restore this code to working order.110 */111#if 0112/*113 * Fill in the disk block numbers in the state structure for the buffers114 * that are attached to the state structure.115 * This is done so that we can quickly reattach ourselves to those buffers116 * after some set of transaction commits have released these buffers.117 */118static int119xfs_attr_fillstate(xfs_da_state_t *state)120{121	xfs_da_state_path_t *path;122	xfs_da_state_blk_t *blk;123	int level;124 125	trace_xfs_attr_fillstate(state->args);126 127	/*128	 * Roll down the "path" in the state structure, storing the on-disk129	 * block number for those buffers in the "path".130	 */131	path = &state->path;132	ASSERT((path->active >= 0) && (path->active < XFS_DA_NODE_MAXDEPTH));133	for (blk = path->blk, level = 0; level < path->active; blk++, level++) {134		if (blk->bp) {135			blk->disk_blkno = xfs_buf_daddr(blk->bp);136			blk->bp = NULL;137		} else {138			blk->disk_blkno = 0;139		}140	}141 142	/*143	 * Roll down the "altpath" in the state structure, storing the on-disk144	 * block number for those buffers in the "altpath".145	 */146	path = &state->altpath;147	ASSERT((path->active >= 0) && (path->active < XFS_DA_NODE_MAXDEPTH));148	for (blk = path->blk, level = 0; level < path->active; blk++, level++) {149		if (blk->bp) {150			blk->disk_blkno = xfs_buf_daddr(blk->bp);151			blk->bp = NULL;152		} else {153			blk->disk_blkno = 0;154		}155	}156 157	return 0;158}159 160/*161 * Reattach the buffers to the state structure based on the disk block162 * numbers stored in the state structure.163 * This is done after some set of transaction commits have released those164 * buffers from our grip.165 */166static int167xfs_attr_refillstate(xfs_da_state_t *state)168{169	xfs_da_state_path_t *path;170	xfs_da_state_blk_t *blk;171	int level, error;172 173	trace_xfs_attr_refillstate(state->args);174 175	/*176	 * Roll down the "path" in the state structure, storing the on-disk177	 * block number for those buffers in the "path".178	 */179	path = &state->path;180	ASSERT((path->active >= 0) && (path->active < XFS_DA_NODE_MAXDEPTH));181	for (blk = path->blk, level = 0; level < path->active; blk++, level++) {182		if (blk->disk_blkno) {183			error = xfs_da3_node_read_mapped(state->args->trans,184					state->args->dp, blk->disk_blkno,185					&blk->bp, XFS_ATTR_FORK);186			if (error)187				return error;188		} else {189			blk->bp = NULL;190		}191	}192 193	/*194	 * Roll down the "altpath" in the state structure, storing the on-disk195	 * block number for those buffers in the "altpath".196	 */197	path = &state->altpath;198	ASSERT((path->active >= 0) && (path->active < XFS_DA_NODE_MAXDEPTH));199	for (blk = path->blk, level = 0; level < path->active; blk++, level++) {200		if (blk->disk_blkno) {201			error = xfs_da3_node_read_mapped(state->args->trans,202					state->args->dp, blk->disk_blkno,203					&blk->bp, XFS_ATTR_FORK);204			if (error)205				return error;206		} else {207			blk->bp = NULL;208		}209	}210 211	return 0;212}213#else214static int xfs_attr_fillstate(xfs_da_state_t *state) { return 0; }215#endif216 217/*========================================================================218 * Overall external interface routines.219 *========================================================================*/220 221/*222 * Retrieve an extended attribute and its value.  Must have ilock.223 * Returns 0 on successful retrieval, otherwise an error.224 */225int226xfs_attr_get_ilocked(227	struct xfs_da_args	*args)228{229	int			error;230 231	xfs_assert_ilocked(args->dp, XFS_ILOCK_SHARED | XFS_ILOCK_EXCL);232 233	if (!xfs_inode_hasattr(args->dp))234		return -ENOATTR;235 236	/*237	 * The incore attr fork iext tree must be loaded for xfs_attr_is_leaf238	 * to work correctly.239	 */240	error = xfs_iread_extents(args->trans, args->dp, XFS_ATTR_FORK);241	if (error)242		return error;243 244	if (args->dp->i_af.if_format == XFS_DINODE_FMT_LOCAL)245		return xfs_attr_shortform_getvalue(args);246	if (xfs_attr_is_leaf(args->dp))247		return xfs_attr_leaf_get(args);248	return xfs_attr_node_get(args);249}250 251/*252 * Retrieve an extended attribute by name, and its value if requested.253 *254 * If args->valuelen is zero, then the caller does not want the value, just an255 * indication whether the attribute exists and the size of the value if it256 * exists. The size is returned in args.valuelen.257 *258 * If args->value is NULL but args->valuelen is non-zero, allocate the buffer259 * for the value after existence of the attribute has been determined. The260 * caller always has to free args->value if it is set, no matter if this261 * function was successful or not.262 *263 * If the attribute is found, but exceeds the size limit set by the caller in264 * args->valuelen, return -ERANGE with the size of the attribute that was found265 * in args->valuelen.266 */267int268xfs_attr_get(269	struct xfs_da_args	*args)270{271	uint			lock_mode;272	int			error;273 274	XFS_STATS_INC(args->dp->i_mount, xs_attr_get);275 276	if (xfs_is_shutdown(args->dp->i_mount))277		return -EIO;278 279	if (!args->owner)280		args->owner = args->dp->i_ino;281	args->geo = args->dp->i_mount->m_attr_geo;282	args->whichfork = XFS_ATTR_FORK;283	xfs_attr_sethash(args);284 285	/* Entirely possible to look up a name which doesn't exist */286	args->op_flags = XFS_DA_OP_OKNOENT;287 288	lock_mode = xfs_ilock_attr_map_shared(args->dp);289	error = xfs_attr_get_ilocked(args);290	xfs_iunlock(args->dp, lock_mode);291 292	return error;293}294 295/*296 * Calculate how many blocks we need for the new attribute,297 */298int299xfs_attr_calc_size(300	struct xfs_da_args	*args,301	int			*local)302{303	struct xfs_mount	*mp = args->dp->i_mount;304	int			size;305	int			nblks;306 307	/*308	 * Determine space new attribute will use, and if it would be309	 * "local" or "remote" (note: local != inline).310	 */311	size = xfs_attr_leaf_newentsize(args, local);312	nblks = XFS_DAENTER_SPACE_RES(mp, XFS_ATTR_FORK);313	if (*local) {314		if (size > (args->geo->blksize / 2)) {315			/* Double split possible */316			nblks *= 2;317		}318	} else {319		/*320		 * Out of line attribute, cannot double split, but321		 * make room for the attribute value itself.322		 */323		uint	dblocks = xfs_attr3_rmt_blocks(mp, args->valuelen);324		nblks += dblocks;325		nblks += XFS_NEXTENTADD_SPACE_RES(mp, dblocks, XFS_ATTR_FORK);326	}327 328	return nblks;329}330 331/* Initialize transaction reservation for an xattr set/replace/upsert */332inline struct xfs_trans_res333xfs_attr_set_resv(334	const struct xfs_da_args	*args)335{336	struct xfs_mount		*mp = args->dp->i_mount;337	struct xfs_trans_res		ret = {338		.tr_logres = M_RES(mp)->tr_attrsetm.tr_logres +339			    M_RES(mp)->tr_attrsetrt.tr_logres * args->total,340		.tr_logcount		= XFS_ATTRSET_LOG_COUNT,341		.tr_logflags		= XFS_TRANS_PERM_LOG_RES,342	};343 344	return ret;345}346 347/*348 * Add an attr to a shortform fork. If there is no space,349 * xfs_attr_shortform_addname() will convert to leaf format and return -ENOSPC.350 * to use.351 */352STATIC int353xfs_attr_try_sf_addname(354	struct xfs_inode	*dp,355	struct xfs_da_args	*args)356{357 358	int			error;359 360	/*361	 * Build initial attribute list (if required).362	 */363	if (dp->i_af.if_format == XFS_DINODE_FMT_EXTENTS)364		xfs_attr_shortform_create(args);365 366	error = xfs_attr_shortform_addname(args);367	if (error == -ENOSPC)368		return error;369 370	/*371	 * Commit the shortform mods, and we're done.372	 * NOTE: this is also the error path (EEXIST, etc).373	 */374	if (!error)375		xfs_trans_ichgtime(args->trans, dp, XFS_ICHGTIME_CHG);376 377	if (xfs_has_wsync(dp->i_mount))378		xfs_trans_set_sync(args->trans);379 380	return error;381}382 383static int384xfs_attr_sf_addname(385	struct xfs_attr_intent		*attr)386{387	struct xfs_da_args		*args = attr->xattri_da_args;388	struct xfs_inode		*dp = args->dp;389	int				error = 0;390 391	error = xfs_attr_try_sf_addname(dp, args);392	if (error != -ENOSPC) {393		ASSERT(!error || error == -EEXIST);394		attr->xattri_dela_state = XFS_DAS_DONE;395		goto out;396	}397 398	/*399	 * It won't fit in the shortform, transform to a leaf block.  GROT:400	 * another possible req'mt for a double-split btree op.401	 */402	error = xfs_attr_shortform_to_leaf(args);403	if (error)404		return error;405 406	attr->xattri_dela_state = XFS_DAS_LEAF_ADD;407out:408	trace_xfs_attr_sf_addname_return(attr->xattri_dela_state, args->dp);409	return error;410}411 412/* Compute the hash value for a user/root/secure extended attribute */413xfs_dahash_t414xfs_attr_hashname(415	const uint8_t		*name,416	int			namelen)417{418	return xfs_da_hashname(name, namelen);419}420 421/* Compute the hash value for any extended attribute from any namespace. */422xfs_dahash_t423xfs_attr_hashval(424	struct xfs_mount	*mp,425	unsigned int		attr_flags,426	const uint8_t		*name,427	int			namelen,428	const void		*value,429	int			valuelen)430{431	ASSERT(xfs_attr_check_namespace(attr_flags));432 433	if (attr_flags & XFS_ATTR_PARENT)434		return xfs_parent_hashattr(mp, name, namelen, value, valuelen);435 436	return xfs_attr_hashname(name, namelen);437}438 439/* Save the current remote block info and clear the current pointers. */440static void441xfs_attr_save_rmt_blk(442	struct xfs_da_args	*args)443{444	args->blkno2 = args->blkno;445	args->index2 = args->index;446	args->rmtblkno2 = args->rmtblkno;447	args->rmtblkcnt2 = args->rmtblkcnt;448	args->rmtvaluelen2 = args->rmtvaluelen;449	args->rmtblkno = 0;450	args->rmtblkcnt = 0;451	args->rmtvaluelen = 0;452}453 454/* Set stored info about a remote block */455static void456xfs_attr_restore_rmt_blk(457	struct xfs_da_args	*args)458{459	args->blkno = args->blkno2;460	args->index = args->index2;461	args->rmtblkno = args->rmtblkno2;462	args->rmtblkcnt = args->rmtblkcnt2;463	args->rmtvaluelen = args->rmtvaluelen2;464}465 466/*467 * PPTR_REPLACE operations require the caller to set the old and new names and468 * values explicitly.  Update the canonical fields to the new name and value469 * here now that the removal phase has finished.470 */471static void472xfs_attr_update_pptr_replace_args(473	struct xfs_da_args	*args)474{475	ASSERT(args->new_namelen > 0);476	args->name = args->new_name;477	args->namelen = args->new_namelen;478	args->value = args->new_value;479	args->valuelen = args->new_valuelen;480	xfs_attr_sethash(args);481}482 483/*484 * Handle the state change on completion of a multi-state attr operation.485 *486 * If the XFS_DA_OP_REPLACE flag is set, this means the operation was the first487 * modification in a attr replace operation and we still have to do the second488 * state, indicated by @replace_state.489 *490 * We consume the XFS_DA_OP_REPLACE flag so that when we are called again on491 * completion of the second half of the attr replace operation we correctly492 * signal that it is done.493 */494static enum xfs_delattr_state495xfs_attr_complete_op(496	struct xfs_attr_intent	*attr,497	enum xfs_delattr_state	replace_state)498{499	struct xfs_da_args	*args = attr->xattri_da_args;500 501	if (!(args->op_flags & XFS_DA_OP_REPLACE))502		replace_state = XFS_DAS_DONE;503	else if (xfs_attr_intent_op(attr) == XFS_ATTRI_OP_FLAGS_PPTR_REPLACE)504		xfs_attr_update_pptr_replace_args(args);505 506	args->op_flags &= ~XFS_DA_OP_REPLACE;507	args->attr_filter &= ~XFS_ATTR_INCOMPLETE;508	return replace_state;509}510 511/*512 * Try to add an attribute to an inode in leaf form.513 */514static int515xfs_attr_leaf_addname(516	struct xfs_attr_intent	*attr)517{518	struct xfs_da_args	*args = attr->xattri_da_args;519	struct xfs_buf		*bp;520	int			error;521 522	ASSERT(xfs_attr_is_leaf(args->dp));523 524	error = xfs_attr3_leaf_read(args->trans, args->dp, args->owner, 0, &bp);525	if (error)526		return error;527 528	/*529	 * Look up the xattr name to set the insertion point for the new xattr.530	 */531	error = xfs_attr3_leaf_lookup_int(bp, args);532	switch (error) {533	case -ENOATTR:534		if (args->op_flags & XFS_DA_OP_REPLACE)535			goto out_brelse;536		break;537	case -EEXIST:538		if (!(args->op_flags & XFS_DA_OP_REPLACE))539			goto out_brelse;540 541		trace_xfs_attr_leaf_replace(args);542		/*543		 * Save the existing remote attr state so that the current544		 * values reflect the state of the new attribute we are about to545		 * add, not the attribute we just found and will remove later.546		 */547		xfs_attr_save_rmt_blk(args);548		break;549	case 0:550		break;551	default:552		goto out_brelse;553	}554 555	/*556	 * We need to commit and roll if we need to allocate remote xattr blocks557	 * or perform more xattr manipulations. Otherwise there is nothing more558	 * to do and we can return success.559	 */560	if (!xfs_attr3_leaf_add(bp, args)) {561		error = xfs_attr3_leaf_to_node(args);562		if (error)563			return error;564 565		attr->xattri_dela_state = XFS_DAS_NODE_ADD;566	} else if (args->rmtblkno) {567		attr->xattri_dela_state = XFS_DAS_LEAF_SET_RMT;568	} else {569		attr->xattri_dela_state =570			xfs_attr_complete_op(attr, XFS_DAS_LEAF_REPLACE);571	}572 573	trace_xfs_attr_leaf_addname_return(attr->xattri_dela_state, args->dp);574	return 0;575 576out_brelse:577	xfs_trans_brelse(args->trans, bp);578	return error;579}580 581/*582 * Add an entry to a node format attr tree.583 *584 * Note that we might still have a leaf here - xfs_attr_is_leaf() cannot tell585 * the difference between leaf + remote attr blocks and a node format tree,586 * so we may still end up having to convert from leaf to node format here.587 */588static int589xfs_attr_node_addname(590	struct xfs_attr_intent	*attr)591{592	struct xfs_da_args	*args = attr->xattri_da_args;593	int			error;594 595	error = xfs_attr_node_addname_find_attr(attr);596	if (error)597		return error;598 599	error = xfs_attr_node_try_addname(attr);600	if (error == 1) {601		error = xfs_attr3_leaf_to_node(args);602		if (error)603			return error;604		/*605		 * No state change, we really are in node form now606		 * but we need the transaction rolled to continue.607		 */608		goto out;609	}610	if (error)611		return error;612 613	if (args->rmtblkno)614		attr->xattri_dela_state = XFS_DAS_NODE_SET_RMT;615	else616		attr->xattri_dela_state = xfs_attr_complete_op(attr,617							XFS_DAS_NODE_REPLACE);618out:619	trace_xfs_attr_node_addname_return(attr->xattri_dela_state, args->dp);620	return error;621}622 623static int624xfs_attr_rmtval_alloc(625	struct xfs_attr_intent		*attr)626{627	struct xfs_da_args              *args = attr->xattri_da_args;628	int				error = 0;629 630	/*631	 * If there was an out-of-line value, allocate the blocks we632	 * identified for its storage and copy the value.  This is done633	 * after we create the attribute so that we don't overflow the634	 * maximum size of a transaction and/or hit a deadlock.635	 */636	if (attr->xattri_blkcnt > 0) {637		error = xfs_attr_rmtval_set_blk(attr);638		if (error)639			return error;640		/* Roll the transaction only if there is more to allocate. */641		if (attr->xattri_blkcnt > 0)642			goto out;643	}644 645	error = xfs_attr_rmtval_set_value(args);646	if (error)647		return error;648 649	attr->xattri_dela_state = xfs_attr_complete_op(attr,650						++attr->xattri_dela_state);651	/*652	 * If we are not doing a rename, we've finished the operation but still653	 * have to clear the incomplete flag protecting the new attr from654	 * exposing partially initialised state if we crash during creation.655	 */656	if (attr->xattri_dela_state == XFS_DAS_DONE)657		error = xfs_attr3_leaf_clearflag(args);658out:659	trace_xfs_attr_rmtval_alloc(attr->xattri_dela_state, args->dp);660	return error;661}662 663/*664 * Mark an attribute entry INCOMPLETE and save pointers to the relevant buffers665 * for later deletion of the entry.666 */667static int668xfs_attr_leaf_mark_incomplete(669	struct xfs_da_args	*args,670	struct xfs_da_state	*state)671{672	int			error;673 674	/*675	 * Fill in disk block numbers in the state structure676	 * so that we can get the buffers back after we commit677	 * several transactions in the following calls.678	 */679	error = xfs_attr_fillstate(state);680	if (error)681		return error;682 683	/*684	 * Mark the attribute as INCOMPLETE685	 */686	return xfs_attr3_leaf_setflag(args);687}688 689/* Ensure the da state of an xattr deferred work item is ready to go. */690static inline void691xfs_attr_item_init_da_state(692	struct xfs_attr_intent	*attr)693{694	struct xfs_da_args	*args = attr->xattri_da_args;695 696	if (!attr->xattri_da_state)697		attr->xattri_da_state = xfs_da_state_alloc(args);698	else699		xfs_da_state_reset(attr->xattri_da_state, args);700}701 702/*703 * Initial setup for xfs_attr_node_removename.  Make sure the attr is there and704 * the blocks are valid.  Attr keys with remote blocks will be marked705 * incomplete.706 */707static708int xfs_attr_node_removename_setup(709	struct xfs_attr_intent		*attr)710{711	struct xfs_da_args		*args = attr->xattri_da_args;712	struct xfs_da_state		*state;713	int				error;714 715	xfs_attr_item_init_da_state(attr);716	error = xfs_attr_node_lookup(args, attr->xattri_da_state);717	if (error != -EEXIST)718		goto out;719	error = 0;720 721	state = attr->xattri_da_state;722	ASSERT(state->path.blk[state->path.active - 1].bp != NULL);723	ASSERT(state->path.blk[state->path.active - 1].magic ==724		XFS_ATTR_LEAF_MAGIC);725 726	error = xfs_attr_leaf_mark_incomplete(args, state);727	if (error)728		goto out;729	if (args->rmtblkno > 0)730		error = xfs_attr_rmtval_invalidate(args);731out:732	if (error) {733		xfs_da_state_free(attr->xattri_da_state);734		attr->xattri_da_state = NULL;735	}736 737	return error;738}739 740/*741 * Remove the original attr we have just replaced. This is dependent on the742 * original lookup and insert placing the old attr in args->blkno/args->index743 * and the new attr in args->blkno2/args->index2.744 */745static int746xfs_attr_leaf_remove_attr(747	struct xfs_attr_intent		*attr)748{749	struct xfs_da_args              *args = attr->xattri_da_args;750	struct xfs_inode		*dp = args->dp;751	struct xfs_buf			*bp = NULL;752	int				forkoff;753	int				error;754 755	error = xfs_attr3_leaf_read(args->trans, args->dp, args->owner,756			args->blkno, &bp);757	if (error)758		return error;759 760	xfs_attr3_leaf_remove(bp, args);761 762	forkoff = xfs_attr_shortform_allfit(bp, dp);763	if (forkoff)764		error = xfs_attr3_leaf_to_shortform(bp, args, forkoff);765		/* bp is gone due to xfs_da_shrink_inode */766 767	return error;768}769 770/*771 * Shrink an attribute from leaf to shortform. Used by the node format remove772 * path when the node format collapses to a single block and so we have to check773 * if it can be collapsed further.774 */775static int776xfs_attr_leaf_shrink(777	struct xfs_da_args	*args)778{779	struct xfs_inode	*dp = args->dp;780	struct xfs_buf		*bp;781	int			forkoff;782	int			error;783 784	if (!xfs_attr_is_leaf(dp))785		return 0;786 787	error = xfs_attr3_leaf_read(args->trans, args->dp, args->owner, 0, &bp);788	if (error)789		return error;790 791	forkoff = xfs_attr_shortform_allfit(bp, dp);792	if (forkoff) {793		error = xfs_attr3_leaf_to_shortform(bp, args, forkoff);794		/* bp is gone due to xfs_da_shrink_inode */795	} else {796		xfs_trans_brelse(args->trans, bp);797	}798 799	return error;800}801 802/*803 * Run the attribute operation specified in @attr.804 *805 * This routine is meant to function as a delayed operation and will set the806 * state to XFS_DAS_DONE when the operation is complete.  Calling functions will807 * need to handle this, and recall the function until either an error or808 * XFS_DAS_DONE is detected.809 */810int811xfs_attr_set_iter(812	struct xfs_attr_intent		*attr)813{814	struct xfs_da_args              *args = attr->xattri_da_args;815	int				error = 0;816 817	/* State machine switch */818next_state:819	switch (attr->xattri_dela_state) {820	case XFS_DAS_UNINIT:821		ASSERT(0);822		return -EFSCORRUPTED;823	case XFS_DAS_SF_ADD:824		return xfs_attr_sf_addname(attr);825	case XFS_DAS_LEAF_ADD:826		return xfs_attr_leaf_addname(attr);827	case XFS_DAS_NODE_ADD:828		return xfs_attr_node_addname(attr);829 830	case XFS_DAS_SF_REMOVE:831		error = xfs_attr_sf_removename(args);832		attr->xattri_dela_state = xfs_attr_complete_op(attr,833						xfs_attr_init_add_state(args));834		break;835	case XFS_DAS_LEAF_REMOVE:836		error = xfs_attr_leaf_removename(args);837		attr->xattri_dela_state = xfs_attr_complete_op(attr,838						xfs_attr_init_add_state(args));839		break;840	case XFS_DAS_NODE_REMOVE:841		error = xfs_attr_node_removename_setup(attr);842		if (error == -ENOATTR &&843		    (args->op_flags & XFS_DA_OP_RECOVERY)) {844			attr->xattri_dela_state = xfs_attr_complete_op(attr,845						xfs_attr_init_add_state(args));846			error = 0;847			break;848		}849		if (error)850			return error;851		attr->xattri_dela_state = XFS_DAS_NODE_REMOVE_RMT;852		if (args->rmtblkno == 0)853			attr->xattri_dela_state++;854		break;855 856	case XFS_DAS_LEAF_SET_RMT:857	case XFS_DAS_NODE_SET_RMT:858		error = xfs_attr_rmtval_find_space(attr);859		if (error)860			return error;861		attr->xattri_dela_state++;862		fallthrough;863 864	case XFS_DAS_LEAF_ALLOC_RMT:865	case XFS_DAS_NODE_ALLOC_RMT:866		error = xfs_attr_rmtval_alloc(attr);867		if (error)868			return error;869		if (attr->xattri_dela_state == XFS_DAS_DONE)870			break;871		goto next_state;872 873	case XFS_DAS_LEAF_REPLACE:874	case XFS_DAS_NODE_REPLACE:875		/*876		 * We must "flip" the incomplete flags on the "new" and "old"877		 * attribute/value pairs so that one disappears and one appears878		 * atomically.879		 */880		error = xfs_attr3_leaf_flipflags(args);881		if (error)882			return error;883		/*884		 * We must commit the flag value change now to make it atomic885		 * and then we can start the next trans in series at REMOVE_OLD.886		 */887		attr->xattri_dela_state++;888		break;889 890	case XFS_DAS_LEAF_REMOVE_OLD:891	case XFS_DAS_NODE_REMOVE_OLD:892		/*893		 * If we have a remote attr, start the process of removing it894		 * by invalidating any cached buffers.895		 *896		 * If we don't have a remote attr, we skip the remote block897		 * removal state altogether with a second state increment.898		 */899		xfs_attr_restore_rmt_blk(args);900		if (args->rmtblkno) {901			error = xfs_attr_rmtval_invalidate(args);902			if (error)903				return error;904		} else {905			attr->xattri_dela_state++;906		}907 908		attr->xattri_dela_state++;909		goto next_state;910 911	case XFS_DAS_LEAF_REMOVE_RMT:912	case XFS_DAS_NODE_REMOVE_RMT:913		error = xfs_attr_rmtval_remove(attr);914		if (error == -EAGAIN) {915			error = 0;916			break;917		}918		if (error)919			return error;920 921		/*922		 * We've finished removing the remote attr blocks, so commit the923		 * transaction and move on to removing the attr name from the924		 * leaf/node block. Removing the attr might require a full925		 * transaction reservation for btree block freeing, so we926		 * can't do that in the same transaction where we removed the927		 * remote attr blocks.928		 */929		attr->xattri_dela_state++;930		break;931 932	case XFS_DAS_LEAF_REMOVE_ATTR:933		error = xfs_attr_leaf_remove_attr(attr);934		attr->xattri_dela_state = xfs_attr_complete_op(attr,935						xfs_attr_init_add_state(args));936		break;937 938	case XFS_DAS_NODE_REMOVE_ATTR:939		error = xfs_attr_node_remove_attr(attr);940		if (!error)941			error = xfs_attr_leaf_shrink(args);942		attr->xattri_dela_state = xfs_attr_complete_op(attr,943						xfs_attr_init_add_state(args));944		break;945	default:946		ASSERT(0);947		break;948	}949 950	trace_xfs_attr_set_iter_return(attr->xattri_dela_state, args->dp);951	return error;952}953 954 955/*956 * Return EEXIST if attr is found, or ENOATTR if not957 */958static int959xfs_attr_lookup(960	struct xfs_da_args	*args)961{962	struct xfs_inode	*dp = args->dp;963	struct xfs_buf		*bp = NULL;964	struct xfs_da_state	*state;965	int			error;966 967	if (!xfs_inode_hasattr(dp))968		return -ENOATTR;969 970	if (dp->i_af.if_format == XFS_DINODE_FMT_LOCAL) {971		if (xfs_attr_sf_findname(args))972			return -EEXIST;973		return -ENOATTR;974	}975 976	/* Prerequisite for xfs_attr_is_leaf */977	error = xfs_iread_extents(args->trans, args->dp, XFS_ATTR_FORK);978	if (error)979		return error;980 981	if (xfs_attr_is_leaf(dp)) {982		error = xfs_attr_leaf_hasname(args, &bp);983 984		if (bp)985			xfs_trans_brelse(args->trans, bp);986 987		return error;988	}989 990	state = xfs_da_state_alloc(args);991	error = xfs_attr_node_lookup(args, state);992	xfs_da_state_free(state);993	return error;994}995 996int997xfs_attr_add_fork(998	struct xfs_inode	*ip,		/* incore inode pointer */999	int			size,		/* space new attribute needs */1000	int			rsvd)		/* xact may use reserved blks */1001{1002	struct xfs_mount	*mp = ip->i_mount;1003	struct xfs_trans	*tp;		/* transaction pointer */1004	unsigned int		blks;		/* space reservation */1005	int			error;		/* error return value */1006 1007	ASSERT(!XFS_NOT_DQATTACHED(mp, ip));1008 1009	blks = XFS_ADDAFORK_SPACE_RES(mp);1010 1011	error = xfs_trans_alloc_inode(ip, &M_RES(mp)->tr_addafork, blks, 0,1012			rsvd, &tp);1013	if (error)1014		return error;1015 1016	if (xfs_inode_has_attr_fork(ip))1017		goto trans_cancel;1018 1019	error = xfs_bmap_add_attrfork(tp, ip, size, rsvd);1020	if (error)1021		goto trans_cancel;1022 1023	error = xfs_trans_commit(tp);1024	xfs_iunlock(ip, XFS_ILOCK_EXCL);1025	return error;1026 1027trans_cancel:1028	xfs_trans_cancel(tp);1029	xfs_iunlock(ip, XFS_ILOCK_EXCL);1030	return error;1031}1032 1033/*1034 * Make a change to the xattr structure.1035 *1036 * The caller must have initialized @args, attached dquots, and must not hold1037 * any ILOCKs.  Reserved data blocks may be used if @rsvd is set.1038 *1039 * Returns -EEXIST for XFS_ATTRUPDATE_CREATE if the name already exists.1040 * Returns -ENOATTR for XFS_ATTRUPDATE_REMOVE if the name does not exist.1041 * Returns 0 on success, or a negative errno if something else went wrong.1042 */1043int1044xfs_attr_set(1045	struct xfs_da_args	*args,1046	enum xfs_attr_update	op,1047	bool			rsvd)1048{1049	struct xfs_inode	*dp = args->dp;1050	struct xfs_mount	*mp = dp->i_mount;1051	struct xfs_trans_res	tres;1052	int			error, local;1053	int			rmt_blks = 0;1054	unsigned int		total = 0;1055 1056	ASSERT(!args->trans);1057 1058	switch (op) {1059	case XFS_ATTRUPDATE_UPSERT:1060	case XFS_ATTRUPDATE_CREATE:1061	case XFS_ATTRUPDATE_REPLACE:1062		XFS_STATS_INC(mp, xs_attr_set);1063		args->total = xfs_attr_calc_size(args, &local);1064 1065		/*1066		 * If the inode doesn't have an attribute fork, add one.1067		 * (inode must not be locked when we call this routine)1068		 */1069		if (xfs_inode_has_attr_fork(dp) == 0) {1070			int sf_size = sizeof(struct xfs_attr_sf_hdr) +1071				xfs_attr_sf_entsize_byname(args->namelen,1072						args->valuelen);1073 1074			error = xfs_attr_add_fork(dp, sf_size, rsvd);1075			if (error)1076				return error;1077		}1078 1079		if (!local)1080			rmt_blks = xfs_attr3_rmt_blocks(mp, args->valuelen);1081 1082		tres = xfs_attr_set_resv(args);1083		total = args->total;1084		break;1085	case XFS_ATTRUPDATE_REMOVE:1086		XFS_STATS_INC(mp, xs_attr_remove);1087		rmt_blks = xfs_attr3_max_rmt_blocks(mp);1088		tres = M_RES(mp)->tr_attrrm;1089		total = XFS_ATTRRM_SPACE_RES(mp);1090		break;1091	}1092 1093	/*1094	 * Root fork attributes can use reserved data blocks for this1095	 * operation if necessary1096	 */1097	error = xfs_trans_alloc_inode(dp, &tres, total, 0, rsvd, &args->trans);1098	if (error)1099		return error;1100 1101	if (op != XFS_ATTRUPDATE_REMOVE || xfs_inode_hasattr(dp)) {1102		error = xfs_iext_count_extend(args->trans, dp, XFS_ATTR_FORK,1103				XFS_IEXT_ATTR_MANIP_CNT(rmt_blks));1104		if (error)1105			goto out_trans_cancel;1106	}1107 1108	error = xfs_attr_lookup(args);1109	switch (error) {1110	case -EEXIST:1111		if (op == XFS_ATTRUPDATE_REMOVE) {1112			/* if no value, we are performing a remove operation */1113			xfs_attr_defer_add(args, XFS_ATTR_DEFER_REMOVE);1114			break;1115		}1116 1117		/* Pure create fails if the attr already exists */1118		if (op == XFS_ATTRUPDATE_CREATE)1119			goto out_trans_cancel;1120		xfs_attr_defer_add(args, XFS_ATTR_DEFER_REPLACE);1121		break;1122	case -ENOATTR:1123		/* Can't remove what isn't there. */1124		if (op == XFS_ATTRUPDATE_REMOVE)1125			goto out_trans_cancel;1126 1127		/* Pure replace fails if no existing attr to replace. */1128		if (op == XFS_ATTRUPDATE_REPLACE)1129			goto out_trans_cancel;1130		xfs_attr_defer_add(args, XFS_ATTR_DEFER_SET);1131		break;1132	default:1133		goto out_trans_cancel;1134	}1135 1136	/*1137	 * If this is a synchronous mount, make sure that the1138	 * transaction goes to disk before returning to the user.1139	 */1140	if (xfs_has_wsync(mp))1141		xfs_trans_set_sync(args->trans);1142 1143	xfs_trans_ichgtime(args->trans, dp, XFS_ICHGTIME_CHG);1144 1145	/*1146	 * Commit the last in the sequence of transactions.1147	 */1148	xfs_trans_log_inode(args->trans, dp, XFS_ILOG_CORE);1149	error = xfs_trans_commit(args->trans);1150out_unlock:1151	xfs_iunlock(dp, XFS_ILOCK_EXCL);1152	args->trans = NULL;1153	return error;1154 1155out_trans_cancel:1156	if (args->trans)1157		xfs_trans_cancel(args->trans);1158	goto out_unlock;1159}1160 1161/*========================================================================1162 * External routines when attribute list is inside the inode1163 *========================================================================*/1164 1165int xfs_attr_sf_totsize(struct xfs_inode *dp)1166{1167	struct xfs_attr_sf_hdr *sf = dp->i_af.if_data;1168 1169	return be16_to_cpu(sf->totsize);1170}1171 1172/*1173 * Add a name to the shortform attribute list structure1174 * This is the external routine.1175 */1176static int1177xfs_attr_shortform_addname(1178	struct xfs_da_args	*args)1179{1180	int			newsize, forkoff;1181 1182	trace_xfs_attr_sf_addname(args);1183 1184	if (xfs_attr_sf_findname(args)) {1185		int		error;1186 1187		ASSERT(args->op_flags & XFS_DA_OP_REPLACE);1188 1189		error = xfs_attr_sf_removename(args);1190		if (error)1191			return error;1192 1193		/*1194		 * Since we have removed the old attr, clear XFS_DA_OP_REPLACE1195		 * so that the new attr doesn't fit in shortform format, the1196		 * leaf format add routine won't trip over the attr not being1197		 * around.1198		 */1199		args->op_flags &= ~XFS_DA_OP_REPLACE;1200	} else {1201		ASSERT(!(args->op_flags & XFS_DA_OP_REPLACE));1202	}1203 1204	if (args->namelen >= XFS_ATTR_SF_ENTSIZE_MAX ||1205	    args->valuelen >= XFS_ATTR_SF_ENTSIZE_MAX)1206		return -ENOSPC;1207 1208	newsize = xfs_attr_sf_totsize(args->dp);1209	newsize += xfs_attr_sf_entsize_byname(args->namelen, args->valuelen);1210 1211	forkoff = xfs_attr_shortform_bytesfit(args->dp, newsize);1212	if (!forkoff)1213		return -ENOSPC;1214 1215	xfs_attr_shortform_add(args, forkoff);1216	return 0;1217}1218 1219 1220/*========================================================================1221 * External routines when attribute list is one block1222 *========================================================================*/1223 1224/*1225 * Return EEXIST if attr is found, or ENOATTR if not1226 */1227STATIC int1228xfs_attr_leaf_hasname(1229	struct xfs_da_args	*args,1230	struct xfs_buf		**bp)1231{1232	int                     error = 0;1233 1234	error = xfs_attr3_leaf_read(args->trans, args->dp, args->owner, 0, bp);1235	if (error)1236		return error;1237 1238	error = xfs_attr3_leaf_lookup_int(*bp, args);1239	if (error != -ENOATTR && error != -EEXIST)1240		xfs_trans_brelse(args->trans, *bp);1241 1242	return error;1243}1244 1245/*1246 * Remove a name from the leaf attribute list structure1247 *1248 * This leaf block cannot have a "remote" value, we only call this routine1249 * if bmap_one_block() says there is only one block (ie: no remote blks).1250 */1251STATIC int1252xfs_attr_leaf_removename(1253	struct xfs_da_args	*args)1254{1255	struct xfs_inode	*dp;1256	struct xfs_buf		*bp;1257	int			error, forkoff;1258 1259	trace_xfs_attr_leaf_removename(args);1260 1261	/*1262	 * Remove the attribute.1263	 */1264	dp = args->dp;1265 1266	error = xfs_attr_leaf_hasname(args, &bp);1267	if (error == -ENOATTR) {1268		xfs_trans_brelse(args->trans, bp);1269		if (args->op_flags & XFS_DA_OP_RECOVERY)1270			return 0;1271		return error;1272	} else if (error != -EEXIST)1273		return error;1274 1275	xfs_attr3_leaf_remove(bp, args);1276 1277	/*1278	 * If the result is small enough, shrink it all into the inode.1279	 */1280	forkoff = xfs_attr_shortform_allfit(bp, dp);1281	if (forkoff)1282		return xfs_attr3_leaf_to_shortform(bp, args, forkoff);1283		/* bp is gone due to xfs_da_shrink_inode */1284 1285	return 0;1286}1287 1288/*1289 * Look up a name in a leaf attribute list structure.1290 *1291 * This leaf block cannot have a "remote" value, we only call this routine1292 * if bmap_one_block() says there is only one block (ie: no remote blks).1293 *1294 * Returns 0 on successful retrieval, otherwise an error.1295 */1296STATIC int1297xfs_attr_leaf_get(xfs_da_args_t *args)1298{1299	struct xfs_buf *bp;1300	int error;1301 1302	trace_xfs_attr_leaf_get(args);1303 1304	error = xfs_attr_leaf_hasname(args, &bp);1305 1306	if (error == -ENOATTR)  {1307		xfs_trans_brelse(args->trans, bp);1308		return error;1309	} else if (error != -EEXIST)1310		return error;1311 1312 1313	error = xfs_attr3_leaf_getvalue(bp, args);1314	xfs_trans_brelse(args->trans, bp);1315	return error;1316}1317 1318/* Return EEXIST if attr is found, or ENOATTR if not. */1319STATIC int1320xfs_attr_node_lookup(1321	struct xfs_da_args	*args,1322	struct xfs_da_state	*state)1323{1324	int			retval, error;1325 1326	/*1327	 * Search to see if name exists, and get back a pointer to it.1328	 */1329	error = xfs_da3_node_lookup_int(state, &retval);1330	if (error)1331		return error;1332 1333	return retval;1334}1335 1336/*========================================================================1337 * External routines when attribute list size > geo->blksize1338 *========================================================================*/1339 1340STATIC int1341xfs_attr_node_addname_find_attr(1342	 struct xfs_attr_intent	*attr)1343{1344	struct xfs_da_args	*args = attr->xattri_da_args;1345	int			error;1346 1347	/*1348	 * Search to see if name already exists, and get back a pointer1349	 * to where it should go.1350	 */1351	xfs_attr_item_init_da_state(attr);1352	error = xfs_attr_node_lookup(args, attr->xattri_da_state);1353	switch (error) {1354	case -ENOATTR:1355		if (args->op_flags & XFS_DA_OP_REPLACE)1356			goto error;1357		break;1358	case -EEXIST:1359		if (!(args->op_flags & XFS_DA_OP_REPLACE))1360			goto error;1361 1362 1363		trace_xfs_attr_node_replace(args);1364		/*1365		 * Save the existing remote attr state so that the current1366		 * values reflect the state of the new attribute we are about to1367		 * add, not the attribute we just found and will remove later.1368		 */1369		xfs_attr_save_rmt_blk(args);1370		break;1371	case 0:1372		break;1373	default:1374		goto error;1375	}1376 1377	return 0;1378error:1379	if (attr->xattri_da_state) {1380		xfs_da_state_free(attr->xattri_da_state);1381		attr->xattri_da_state = NULL;1382	}1383	return error;1384}1385 1386/*1387 * Add a name to a Btree-format attribute list.1388 *1389 * This will involve walking down the Btree, and may involve splitting leaf1390 * nodes and even splitting intermediate nodes up to and including the root1391 * node (a special case of an intermediate node).1392 *1393 * If the tree was still in single leaf format and needs to converted to1394 * real node format return 1 and let the caller handle that.1395 */1396static int1397xfs_attr_node_try_addname(1398	struct xfs_attr_intent		*attr)1399{1400	struct xfs_da_state		*state = attr->xattri_da_state;1401	struct xfs_da_state_blk		*blk;1402	int				error = 0;1403 1404	trace_xfs_attr_node_addname(state->args);1405 1406	blk = &state->path.blk[state->path.active-1];1407	ASSERT(blk->magic == XFS_ATTR_LEAF_MAGIC);1408 1409	if (!xfs_attr3_leaf_add(blk->bp, state->args)) {1410		if (state->path.active == 1) {1411			/*1412			 * Its really a single leaf node, but it had1413			 * out-of-line values so it looked like it *might*1414			 * have been a b-tree. Let the caller deal with this.1415			 */1416			error = 1;1417			goto out;1418		}1419 1420		/*1421		 * Split as many Btree elements as required.1422		 * This code tracks the new and old attr's location1423		 * in the index/blkno/rmtblkno/rmtblkcnt fields and1424		 * in the index2/blkno2/rmtblkno2/rmtblkcnt2 fields.1425		 */1426		error = xfs_da3_split(state);1427		if (error)1428			goto out;1429	} else {1430		/*1431		 * Addition succeeded, update Btree hashvals.1432		 */1433		xfs_da3_fixhashpath(state, &state->path);1434	}1435 1436out:1437	xfs_da_state_free(state);1438	attr->xattri_da_state = NULL;1439	return error;1440}1441 1442static int1443xfs_attr_node_removename(1444	struct xfs_da_args	*args,1445	struct xfs_da_state	*state)1446{1447	struct xfs_da_state_blk	*blk;1448	int			retval;1449 1450	/*1451	 * Remove the name and update the hashvals in the tree.1452	 */1453	blk = &state->path.blk[state->path.active-1];1454	ASSERT(blk->magic == XFS_ATTR_LEAF_MAGIC);1455	retval = xfs_attr3_leaf_remove(blk->bp, args);1456	xfs_da3_fixhashpath(state, &state->path);1457 1458	return retval;1459}1460 1461static int1462xfs_attr_node_remove_attr(1463	struct xfs_attr_intent		*attr)1464{1465	struct xfs_da_args		*args = attr->xattri_da_args;1466	struct xfs_da_state		*state = xfs_da_state_alloc(args);1467	int				retval = 0;1468	int				error = 0;1469 1470	/*1471	 * The attr we are removing has already been marked incomplete, so1472	 * we need to set the filter appropriately to re-find the "old"1473	 * attribute entry after any split ops.1474	 */1475	args->attr_filter |= XFS_ATTR_INCOMPLETE;1476	error = xfs_da3_node_lookup_int(state, &retval);1477	if (error)1478		goto out;1479 1480	error = xfs_attr_node_removename(args, state);1481 1482	/*1483	 * Check to see if the tree needs to be collapsed.1484	 */1485	if (retval && (state->path.active > 1)) {1486		error = xfs_da3_join(state);1487		if (error)1488			goto out;1489	}1490	retval = error = 0;1491 1492out:1493	xfs_da_state_free(state);1494	if (error)1495		return error;1496	return retval;1497}1498 1499/*1500 * Retrieve the attribute data from a node attribute list.1501 *1502 * This routine gets called for any attribute fork that has more than one1503 * block, ie: both true Btree attr lists and for single-leaf-blocks with1504 * "remote" values taking up more blocks.1505 *1506 * Returns 0 on successful retrieval, otherwise an error.1507 */1508STATIC int1509xfs_attr_node_get(1510	struct xfs_da_args	*args)1511{1512	struct xfs_da_state	*state;1513	struct xfs_da_state_blk	*blk;1514	int			i;1515	int			error;1516 1517	trace_xfs_attr_node_get(args);1518 1519	/*1520	 * Search to see if name exists, and get back a pointer to it.1521	 */1522	state = xfs_da_state_alloc(args);1523	error = xfs_attr_node_lookup(args, state);1524	if (error != -EEXIST)1525		goto out_release;1526 1527	/*1528	 * Get the value, local or "remote"1529	 */1530	blk = &state->path.blk[state->path.active - 1];1531	error = xfs_attr3_leaf_getvalue(blk->bp, args);1532 1533	/*1534	 * If not in a transaction, we have to release all the buffers.1535	 */1536out_release:1537	for (i = 0; i < state->path.active; i++) {1538		xfs_trans_brelse(args->trans, state->path.blk[i].bp);1539		state->path.blk[i].bp = NULL;1540	}1541 1542	xfs_da_state_free(state);1543	return error;1544}1545 1546/* Enforce that there is at most one namespace bit per attr. */1547inline bool xfs_attr_check_namespace(unsigned int attr_flags)1548{1549	return hweight32(attr_flags & XFS_ATTR_NSP_ONDISK_MASK) < 2;1550}1551 1552/* Returns true if the attribute entry name is valid. */1553bool1554xfs_attr_namecheck(1555	unsigned int	attr_flags,1556	const void	*name,1557	size_t		length)1558{1559	/* Only one namespace bit allowed. */1560	if (!xfs_attr_check_namespace(attr_flags))1561		return false;1562 1563	/*1564	 * MAXNAMELEN includes the trailing null, but (name/length) leave it1565	 * out, so use >= for the length check.1566	 */1567	if (length >= MAXNAMELEN)1568		return false;1569 1570	/* Parent pointers have their own validation. */1571	if (attr_flags & XFS_ATTR_PARENT)1572		return xfs_parent_namecheck(attr_flags, name, length);1573 1574	/* There shouldn't be any nulls here */1575	return !memchr(name, 0, length);1576}1577 1578int __init1579xfs_attr_intent_init_cache(void)1580{1581	xfs_attr_intent_cache = kmem_cache_create("xfs_attr_intent",1582			sizeof(struct xfs_attr_intent),1583			0, 0, NULL);1584 1585	return xfs_attr_intent_cache != NULL ? 0 : -ENOMEM;1586}1587 1588void1589xfs_attr_intent_destroy_cache(void)1590{1591	kmem_cache_destroy(xfs_attr_intent_cache);1592	xfs_attr_intent_cache = NULL;1593}1594