xfs_attr.c

来自「Linux Kernel 2.6.9 for OMAP1710」· C语言 代码 · 共 2,474 行 · 第 1/5 页

C
2,474
字号
	int blkcnt, valuelen, nmap, error, tmp, committed;	dp = args->dp;	mp = dp->i_mount;	src = args->value;	/*	 * Find a "hole" in the attribute address space large enough for	 * us to drop the new attribute's value into.	 */	blkcnt = XFS_B_TO_FSB(mp, args->valuelen);	lfileoff = 0;	error = xfs_bmap_first_unused(args->trans, args->dp, blkcnt, &lfileoff,						   XFS_ATTR_FORK);	if (error) {		return(error);	}	args->rmtblkno = lblkno = (xfs_dablk_t)lfileoff;	args->rmtblkcnt = blkcnt;	/*	 * Roll through the "value", allocating blocks on disk as required.	 */	while (blkcnt > 0) {		/*		 * Allocate a single extent, up to the size of the value.		 */		XFS_BMAP_INIT(args->flist, args->firstblock);		nmap = 1;		error = xfs_bmapi(args->trans, dp, (xfs_fileoff_t)lblkno,				  blkcnt,				  XFS_BMAPI_ATTRFORK | XFS_BMAPI_METADATA |							XFS_BMAPI_WRITE,				  args->firstblock, args->total, &map, &nmap,				  args->flist);		if (!error) {			error = xfs_bmap_finish(&args->trans, args->flist,						*args->firstblock, &committed);		}		if (error) {			ASSERT(committed);			args->trans = NULL;			xfs_bmap_cancel(args->flist);			return(error);		}		/*		 * bmap_finish() may have committed the last trans and started		 * a new one.  We need the inode to be in all transactions.		 */		if (committed) {			xfs_trans_ijoin(args->trans, dp, XFS_ILOCK_EXCL);			xfs_trans_ihold(args->trans, dp);		}		ASSERT(nmap == 1);		ASSERT((map.br_startblock != DELAYSTARTBLOCK) &&		       (map.br_startblock != HOLESTARTBLOCK));		lblkno += map.br_blockcount;		blkcnt -= map.br_blockcount;		/*		 * Start the next trans in the chain.		 */		if ((error = xfs_attr_rolltrans(&args->trans, dp)))			return (error);	}	/*	 * Roll through the "value", copying the attribute value to the	 * already-allocated blocks.  Blocks are written synchronously	 * so that we can know they are all on disk before we turn off	 * the INCOMPLETE flag.	 */	lblkno = args->rmtblkno;	valuelen = args->valuelen;	while (valuelen > 0) {		/*		 * Try to remember where we decided to put the value.		 */		XFS_BMAP_INIT(args->flist, args->firstblock);		nmap = 1;		error = xfs_bmapi(NULL, dp, (xfs_fileoff_t)lblkno,				  args->rmtblkcnt,				  XFS_BMAPI_ATTRFORK | XFS_BMAPI_METADATA,				  args->firstblock, 0, &map, &nmap, NULL);		if (error) {			return(error);		}		ASSERT(nmap == 1);		ASSERT((map.br_startblock != DELAYSTARTBLOCK) &&		       (map.br_startblock != HOLESTARTBLOCK));		dblkno = XFS_FSB_TO_DADDR(mp, map.br_startblock),		blkcnt = XFS_FSB_TO_BB(mp, map.br_blockcount);		bp = xfs_buf_get_flags(mp->m_ddev_targp, dblkno,							blkcnt, XFS_BUF_LOCK);		ASSERT(bp);		ASSERT(!XFS_BUF_GETERROR(bp));		tmp = (valuelen < XFS_BUF_SIZE(bp)) ? valuelen :							XFS_BUF_SIZE(bp);		xfs_biomove(bp, 0, tmp, src, XFS_B_WRITE);		if (tmp < XFS_BUF_SIZE(bp))			xfs_biozero(bp, tmp, XFS_BUF_SIZE(bp) - tmp);		if ((error = xfs_bwrite(mp, bp))) {/* GROT: NOTE: synchronous write */			return (error);		}		src += tmp;		valuelen -= tmp;		lblkno += map.br_blockcount;	}	ASSERT(valuelen == 0);	return(0);}/* * Remove the value associated with an attribute by deleting the * out-of-line buffer that it is stored on. */STATIC intxfs_attr_rmtval_remove(xfs_da_args_t *args){	xfs_mount_t *mp;	xfs_bmbt_irec_t map;	xfs_buf_t *bp;	xfs_daddr_t dblkno;	xfs_dablk_t lblkno;	int valuelen, blkcnt, nmap, error, done, committed;	mp = args->dp->i_mount;	/*	 * Roll through the "value", invalidating the attribute value's	 * blocks.	 */	lblkno = args->rmtblkno;	valuelen = args->rmtblkcnt;	while (valuelen > 0) {		/*		 * Try to remember where we decided to put the value.		 */		XFS_BMAP_INIT(args->flist, args->firstblock);		nmap = 1;		error = xfs_bmapi(NULL, args->dp, (xfs_fileoff_t)lblkno,					args->rmtblkcnt,					XFS_BMAPI_ATTRFORK | XFS_BMAPI_METADATA,					args->firstblock, 0, &map, &nmap,					args->flist);		if (error) {			return(error);		}		ASSERT(nmap == 1);		ASSERT((map.br_startblock != DELAYSTARTBLOCK) &&		       (map.br_startblock != HOLESTARTBLOCK));		dblkno = XFS_FSB_TO_DADDR(mp, map.br_startblock),		blkcnt = XFS_FSB_TO_BB(mp, map.br_blockcount);		/*		 * If the "remote" value is in the cache, remove it.		 */		bp = xfs_incore(mp->m_ddev_targp, dblkno, blkcnt,				XFS_INCORE_TRYLOCK);		if (bp) {			XFS_BUF_STALE(bp);			XFS_BUF_UNDELAYWRITE(bp);			xfs_buf_relse(bp);			bp = NULL;		}		valuelen -= map.br_blockcount;		lblkno += map.br_blockcount;	}	/*	 * Keep de-allocating extents until the remote-value region is gone.	 */	lblkno = args->rmtblkno;	blkcnt = args->rmtblkcnt;	done = 0;	while (!done) {		XFS_BMAP_INIT(args->flist, args->firstblock);		error = xfs_bunmapi(args->trans, args->dp, lblkno, blkcnt,				    XFS_BMAPI_ATTRFORK | XFS_BMAPI_METADATA,				    1, args->firstblock, args->flist, &done);		if (!error) {			error = xfs_bmap_finish(&args->trans, args->flist,						*args->firstblock, &committed);		}		if (error) {			ASSERT(committed);			args->trans = NULL;			xfs_bmap_cancel(args->flist);			return(error);		}		/*		 * bmap_finish() may have committed the last trans and started		 * a new one.  We need the inode to be in all transactions.		 */		if (committed) {			xfs_trans_ijoin(args->trans, args->dp, XFS_ILOCK_EXCL);			xfs_trans_ihold(args->trans, args->dp);		}		/*		 * Close out trans and start the next one in the chain.		 */		if ((error = xfs_attr_rolltrans(&args->trans, args->dp)))			return (error);	}	return(0);}#if defined(XFS_ATTR_TRACE)/* * Add a trace buffer entry for an attr_list context structure. */voidxfs_attr_trace_l_c(char *where, struct xfs_attr_list_context *context){	xfs_attr_trace_enter(XFS_ATTR_KTRACE_L_C, where,		(__psunsigned_t)context->dp,		(__psunsigned_t)context->cursor->hashval,		(__psunsigned_t)context->cursor->blkno,		(__psunsigned_t)context->cursor->offset,		(__psunsigned_t)context->alist,		(__psunsigned_t)context->bufsize,		(__psunsigned_t)context->count,		(__psunsigned_t)context->firstu,		(__psunsigned_t)			((context->count > 0) &&			!(context->flags & (ATTR_KERNAMELS|ATTR_KERNOVAL)))				? (ATTR_ENTRY(context->alist,					      context->count-1)->a_valuelen)				: 0,		(__psunsigned_t)context->dupcnt,		(__psunsigned_t)context->flags,		(__psunsigned_t)NULL,		(__psunsigned_t)NULL,		(__psunsigned_t)NULL);}/* * Add a trace buffer entry for a context structure and a Btree node. */voidxfs_attr_trace_l_cn(char *where, struct xfs_attr_list_context *context,			 struct xfs_da_intnode *node){	xfs_attr_trace_enter(XFS_ATTR_KTRACE_L_CN, where,		(__psunsigned_t)context->dp,		(__psunsigned_t)context->cursor->hashval,		(__psunsigned_t)context->cursor->blkno,		(__psunsigned_t)context->cursor->offset,		(__psunsigned_t)context->alist,		(__psunsigned_t)context->bufsize,		(__psunsigned_t)context->count,		(__psunsigned_t)context->firstu,		(__psunsigned_t)			((context->count > 0) &&			!(context->flags & (ATTR_KERNAMELS|ATTR_KERNOVAL)))				? (ATTR_ENTRY(context->alist,					      context->count-1)->a_valuelen)				: 0,		(__psunsigned_t)context->dupcnt,		(__psunsigned_t)context->flags,		(__psunsigned_t)INT_GET(node->hdr.count, ARCH_CONVERT),		(__psunsigned_t)INT_GET(node->btree[0].hashval, ARCH_CONVERT),		(__psunsigned_t)INT_GET(node->btree[INT_GET(node->hdr.count, ARCH_CONVERT)-1].hashval, ARCH_CONVERT));}/* * Add a trace buffer entry for a context structure and a Btree element. */voidxfs_attr_trace_l_cb(char *where, struct xfs_attr_list_context *context,			  struct xfs_da_node_entry *btree){	xfs_attr_trace_enter(XFS_ATTR_KTRACE_L_CB, where,		(__psunsigned_t)context->dp,		(__psunsigned_t)context->cursor->hashval,		(__psunsigned_t)context->cursor->blkno,		(__psunsigned_t)context->cursor->offset,		(__psunsigned_t)context->alist,		(__psunsigned_t)context->bufsize,		(__psunsigned_t)context->count,		(__psunsigned_t)context->firstu,		(__psunsigned_t)			((context->count > 0) &&			!(context->flags & (ATTR_KERNAMELS|ATTR_KERNOVAL)))				? (ATTR_ENTRY(context->alist,					      context->count-1)->a_valuelen)				: 0,		(__psunsigned_t)context->dupcnt,		(__psunsigned_t)context->flags,		(__psunsigned_t)INT_GET(btree->hashval, ARCH_CONVERT),		(__psunsigned_t)INT_GET(btree->before, ARCH_CONVERT),		(__psunsigned_t)NULL);}/* * Add a trace buffer entry for a context structure and a leaf block. */voidxfs_attr_trace_l_cl(char *where, struct xfs_attr_list_context *context,			      struct xfs_attr_leafblock *leaf){	xfs_attr_trace_enter(XFS_ATTR_KTRACE_L_CL, where,		(__psunsigned_t)context->dp,		(__psunsigned_t)context->cursor->hashval,		(__psunsigned_t)context->cursor->blkno,		(__psunsigned_t)context->cursor->offset,		(__psunsigned_t)context->alist,		(__psunsigned_t)context->bufsize,		(__psunsigned_t)context->count,		(__psunsigned_t)context->firstu,		(__psunsigned_t)			((context->count > 0) &&			!(context->flags & (ATTR_KERNAMELS|ATTR_KERNOVAL)))				? (ATTR_ENTRY(context->alist,					      context->count-1)->a_valuelen)				: 0,		(__psunsigned_t)context->dupcnt,		(__psunsigned_t)context->flags,		(__psunsigned_t)INT_GET(leaf->hdr.count, ARCH_CONVERT),		(__psunsigned_t)INT_GET(leaf->entries[0].hashval, ARCH_CONVERT),		(__psunsigned_t)INT_GET(leaf->entries[INT_GET(leaf->hdr.count, ARCH_CONVERT)-1].hashval, ARCH_CONVERT));}/* * Add a trace buffer entry for the arguments given to the routine, * generic form. */voidxfs_attr_trace_enter(int type, char *where,			 __psunsigned_t a2, __psunsigned_t a3,			 __psunsigned_t a4, __psunsigned_t a5,			 __psunsigned_t a6, __psunsigned_t a7,			 __psunsigned_t a8, __psunsigned_t a9,			 __psunsigned_t a10, __psunsigned_t a11,			 __psunsigned_t a12, __psunsigned_t a13,			 __psunsigned_t a14, __psunsigned_t a15){	ASSERT(xfs_attr_trace_buf);	ktrace_enter(xfs_attr_trace_buf, (void *)((__psunsigned_t)type),					 (void *)where,					 (void *)a2,  (void *)a3,  (void *)a4,					 (void *)a5,  (void *)a6,  (void *)a7,					 (void *)a8,  (void *)a9,  (void *)a10,					 (void *)a11, (void *)a12, (void *)a13,					 (void *)a14, (void *)a15);}#endif	/* XFS_ATTR_TRACE *//*======================================================================== * System (pseudo) namespace attribute interface routines. *========================================================================*/STATIC intposix_acl_access_set(	vnode_t	*vp, char *name, void *data, size_t size, int xflags){	return xfs_acl_vset(vp, data, size, _ACL_TYPE_ACCESS);}STATIC intposix_acl_access_remove(	struct vnode *vp, char *name, int xflags){	return xfs_acl_vremove(vp, _ACL_TYPE_ACCESS);}STATIC intposix_acl_access_get(	vnode_t *vp, char *name, void *data, size_t size, int xflags){	return xfs_acl_vget(vp, data, size, _ACL_TYPE_ACCESS);}STATIC intposix_acl_access_exists(	vnode_t *vp){	return xfs_acl_vhasacl_access(vp);}STATIC intposix_acl_default_set(	vnode_t	*vp, char *name, void *data, size_t size, int xflags){	return xfs_acl_vset(vp, data, size, _ACL_TYPE_DEFAULT);}STATIC intposix_acl_default_get(	vnode_t *vp, char *name, void *data, size_t size, int xflags){	return xfs_acl_vget(vp, data, size, _ACL_TYPE_DEFAULT);}STATIC intposix_acl_default_remove(	struct vnode *vp, char *name, int xflags){	return xfs_acl_vremove(vp, _ACL_TYPE_DEFAULT);}STATIC intposix_acl_default_exists(	vnode_t *vp){	return xfs_acl_vhasacl_default(vp);}struct attrnames posix_acl_access = {	.attr_name	= "posix_acl_access",	.attr_namelen	= sizeof("posix_acl_access") - 1,	.attr_get	= posix_acl_access_get,	.attr_set	= posix_acl_access_set,	.attr_remove	= posix_acl_access_remove,	.attr_exists	= posix_acl_access_exists,};struct attrnames posix_acl_default = {	.attr_name	= "posix_acl_default",	.attr_namelen	= sizeof("posix_acl_default") - 1,	.attr_get	= posix_acl_default_get,	.attr_set	= posix_acl_default_set,	.attr_remove	= posix_acl_default_remove,	.attr_exists	= posix_acl_default_exists,};struct attrnames *attr_system_names[] =	{ &posix_acl_access, &posix_acl_default };/*======================================================================== * Namespace-prefix-style attribute name interface routines. *========================================================================*/STATIC intattr_generic_set(	struct vnode *vp, char *name, void *data, size_t size, int xflags){	int 	error;	VOP_ATTR_SET(vp, name, data, size, xflags, NULL, error);	return -error;}STATIC intattr_generic_get(	struct vnode *vp, char *name, void *data, size_t size, int xflags){	int	error, asize = size;	VOP_ATTR_GET(vp, name, data, &asize, xflags, NULL, error);	if (!error)		return asize;	return -error;}STATIC intattr_generic_remove(	struct vnode *vp, char *name, int xflags){	int	error;	VOP_ATTR_REMOVE(vp, name, xflags, NULL, error);	return -error;}STATIC intattr_generic_listadd(	attrnames_t		*prefix,	attrnames_t		*namesp,	void			*data,	size_t			size,	ssize_t			*result){	char			*p = data + *result;	*result += prefix->attr_namelen;	*result += namesp->attr_namelen + 1;	if (!size)		return 0;	if (*result > size)		return

⌨️ 快捷键说明

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