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 + -
显示快捷键?