📄 xfs_attr.c
字号:
* Read the value associated with an attribute from the out-of-line buffer * that we stored it in. */intxfs_attr_rmtval_get(xfs_da_args_t *args){ xfs_bmbt_irec_t map[ATTR_RMTVALUE_MAPSIZE]; xfs_mount_t *mp; xfs_daddr_t dblkno; xfs_caddr_t dst; xfs_buf_t *bp; int nmap, error, tmp, valuelen, blkcnt, i; xfs_dablk_t lblkno; ASSERT(!(args->flags & ATTR_KERNOVAL)); mp = args->dp->i_mount; dst = args->value; valuelen = args->valuelen; lblkno = args->rmtblkno; while (valuelen > 0) { nmap = ATTR_RMTVALUE_MAPSIZE; error = xfs_bmapi(args->trans, args->dp, (xfs_fileoff_t)lblkno, args->rmtblkcnt, XFS_BMAPI_ATTRFORK | XFS_BMAPI_METADATA, NULL, 0, map, &nmap, NULL, NULL); if (error) return(error); ASSERT(nmap >= 1); for (i = 0; (i < nmap) && (valuelen > 0); i++) { ASSERT((map[i].br_startblock != DELAYSTARTBLOCK) && (map[i].br_startblock != HOLESTARTBLOCK)); dblkno = XFS_FSB_TO_DADDR(mp, map[i].br_startblock); blkcnt = XFS_FSB_TO_BB(mp, map[i].br_blockcount); error = xfs_read_buf(mp, mp->m_ddev_targp, dblkno, blkcnt, XFS_BUF_LOCK, &bp); if (error) return(error); tmp = (valuelen < XFS_BUF_SIZE(bp)) ? valuelen : XFS_BUF_SIZE(bp); xfs_biomove(bp, 0, tmp, dst, XFS_B_READ); xfs_buf_relse(bp); dst += tmp; valuelen -= tmp; lblkno += map[i].br_blockcount; } } ASSERT(valuelen == 0); return(0);}/* * Write the value associated with an attribute into the out-of-line buffer * that we have defined for it. */STATIC intxfs_attr_rmtval_set(xfs_da_args_t *args){ xfs_mount_t *mp; xfs_fileoff_t lfileoff; xfs_inode_t *dp; xfs_bmbt_irec_t map; xfs_daddr_t dblkno; xfs_caddr_t src; xfs_buf_t *bp; xfs_dablk_t lblkno; 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, NULL); if (!error) { error = xfs_bmap_finish(&args->trans, args->flist, &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, 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, 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); /* * 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, NULL, &done); if (!error) { error = xfs_bmap_finish(&args->trans, args->flist, &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)be16_to_cpu(node->hdr.count), (__psunsigned_t)be32_to_cpu(node->btree[0].hashval), (__psunsigned_t)be32_to_cpu(node->btree[ be16_to_cpu(node->hdr.count)-1].hashval));}/* * 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)be32_to_cpu(btree->hashval), (__psunsigned_t)be32_to_cpu(btree->before), (__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)be16_to_cpu(leaf->hdr.count), (__psunsigned_t)be32_to_cpu(leaf->entries[0].hashval), (__psunsigned_t)be32_to_cpu(leaf->entries[ be16_to_cpu(leaf->hdr.count)-1].hashval));}/* * 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( bhv_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( bhv_vnode_t *vp, char *name, int xflags){ return xfs_acl_vremove(vp, _ACL_TYPE_ACCESS);}STATIC intposix_acl_access_get( bhv_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( bhv_vnode_t *vp){ return xfs_acl_vhasacl_access(vp);}STATIC intposix_acl_default_set( bhv_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( bhv_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( bhv_vnode_t *vp, char *name, int xflags){ return xfs_acl_vremove(vp, _ACL_TYPE_DEFAULT);}STATIC intposix_acl_default_exists( bhv_vnode_t *vp){ return xfs_acl_vhasacl_default(vp);}static 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_
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -