Back to home page

OSCL-LXR

 
 

    


0001 /* SPDX-License-Identifier: GPL-2.0 */
0002 /*
0003  * Copyright (c) 2000,2002-2003,2005 Silicon Graphics, Inc.
0004  * All Rights Reserved.
0005  */
0006 #ifndef __XFS_ATTR_H__
0007 #define __XFS_ATTR_H__
0008 
0009 struct xfs_inode;
0010 struct xfs_da_args;
0011 struct xfs_attr_list_context;
0012 
0013 /*
0014  * Large attribute lists are structured around Btrees where all the data
0015  * elements are in the leaf nodes.  Attribute names are hashed into an int,
0016  * then that int is used as the index into the Btree.  Since the hashval
0017  * of an attribute name may not be unique, we may have duplicate keys.
0018  * The internal links in the Btree are logical block offsets into the file.
0019  *
0020  * Small attribute lists use a different format and are packed as tightly
0021  * as possible so as to fit into the literal area of the inode.
0022  */
0023 
0024 /*
0025  * The maximum size (into the kernel or returned from the kernel) of an
0026  * attribute value or the buffer used for an attr_list() call.  Larger
0027  * sizes will result in an ERANGE return code.
0028  */
0029 #define ATTR_MAX_VALUELEN   (64*1024)   /* max length of a value */
0030 
0031 /*
0032  * Kernel-internal version of the attrlist cursor.
0033  */
0034 struct xfs_attrlist_cursor_kern {
0035     __u32   hashval;    /* hash value of next entry to add */
0036     __u32   blkno;      /* block containing entry (suggestion) */
0037     __u32   offset;     /* offset in list of equal-hashvals */
0038     __u16   pad1;       /* padding to match user-level */
0039     __u8    pad2;       /* padding to match user-level */
0040     __u8    initted;    /* T/F: cursor has been initialized */
0041 };
0042 
0043 
0044 /*========================================================================
0045  * Structure used to pass context around among the routines.
0046  *========================================================================*/
0047 
0048 
0049 /* void; state communicated via *context */
0050 typedef void (*put_listent_func_t)(struct xfs_attr_list_context *, int,
0051                   unsigned char *, int, int);
0052 
0053 struct xfs_attr_list_context {
0054     struct xfs_trans    *tp;
0055     struct xfs_inode    *dp;        /* inode */
0056     struct xfs_attrlist_cursor_kern cursor; /* position in list */
0057     void            *buffer;    /* output buffer */
0058 
0059     /*
0060      * Abort attribute list iteration if non-zero.  Can be used to pass
0061      * error values to the xfs_attr_list caller.
0062      */
0063     int         seen_enough;
0064     bool            allow_incomplete;
0065 
0066     ssize_t         count;      /* num used entries */
0067     int         dupcnt;     /* count dup hashvals seen */
0068     int         bufsize;    /* total buffer size */
0069     int         firstu;     /* first used byte in buffer */
0070     unsigned int        attr_filter;    /* XFS_ATTR_{ROOT,SECURE} */
0071     int         resynch;    /* T/F: resynch with cursor */
0072     put_listent_func_t  put_listent;    /* list output fmt function */
0073     int         index;      /* index into output buffer */
0074 };
0075 
0076 
0077 /*
0078  * ========================================================================
0079  * Structure used to pass context around among the delayed routines.
0080  * ========================================================================
0081  */
0082 
0083 /*
0084  * Below is a state machine diagram for attr remove operations. The  XFS_DAS_*
0085  * states indicate places where the function would return -EAGAIN, and then
0086  * immediately resume from after being called by the calling function. States
0087  * marked as a "subroutine state" indicate that they belong to a subroutine, and
0088  * so the calling function needs to pass them back to that subroutine to allow
0089  * it to finish where it left off. But they otherwise do not have a role in the
0090  * calling function other than just passing through.
0091  *
0092  * xfs_attr_remove_iter()
0093  *              │
0094  *              v
0095  *        have attr to remove? ──n──> done
0096  *              │
0097  *              y
0098  *              │
0099  *              v
0100  *        are we short form? ──y──> xfs_attr_shortform_remove ──> done
0101  *              │
0102  *              n
0103  *              │
0104  *              V
0105  *        are we leaf form? ──y──> xfs_attr_leaf_removename ──> done
0106  *              │
0107  *              n
0108  *              │
0109  *              V
0110  *   ┌── need to setup state?
0111  *   │          │
0112  *   n          y
0113  *   │          │
0114  *   │          v
0115  *   │ find attr and get state
0116  *   │ attr has remote blks? ──n─┐
0117  *   │          │                v
0118  *   │          │         find and invalidate
0119  *   │          y         the remote blocks.
0120  *   │          │         mark attr incomplete
0121  *   │          ├────────────────┘
0122  *   └──────────┤
0123  *              │
0124  *              v
0125  *   Have remote blks to remove? ───y─────┐
0126  *              │        ^          remove the blks
0127  *              │        │                │
0128  *              │        │                v
0129  *              │  XFS_DAS_RMTBLK <─n── done?
0130  *              │  re-enter with          │
0131  *              │  one less blk to        y
0132  *              │      remove             │
0133  *              │                         V
0134  *              │                  refill the state
0135  *              n                         │
0136  *              │                         v
0137  *              │                   XFS_DAS_RM_NAME
0138  *              │                         │
0139  *              ├─────────────────────────┘
0140  *              │
0141  *              v
0142  *       remove leaf and
0143  *       update hash with
0144  *   xfs_attr_node_remove_cleanup
0145  *              │
0146  *              v
0147  *           need to
0148  *        shrink tree? ─n─┐
0149  *              │         │
0150  *              y         │
0151  *              │         │
0152  *              v         │
0153  *          join leaf     │
0154  *              │         │
0155  *              v         │
0156  *      XFS_DAS_RM_SHRINK │
0157  *              │         │
0158  *              v         │
0159  *       do the shrink    │
0160  *              │         │
0161  *              v         │
0162  *          free state <──┘
0163  *              │
0164  *              v
0165  *            done
0166  *
0167  *
0168  * Below is a state machine diagram for attr set operations.
0169  *
0170  * It seems the challenge with understanding this system comes from trying to
0171  * absorb the state machine all at once, when really one should only be looking
0172  * at it with in the context of a single function. Once a state sensitive
0173  * function is called, the idea is that it "takes ownership" of the
0174  * state machine. It isn't concerned with the states that may have belonged to
0175  * it's calling parent. Only the states relevant to itself or any other
0176  * subroutines there in. Once a calling function hands off the state machine to
0177  * a subroutine, it needs to respect the simple rule that it doesn't "own" the
0178  * state machine anymore, and it's the responsibility of that calling function
0179  * to propagate the -EAGAIN back up the call stack. Upon reentry, it is
0180  * committed to re-calling that subroutine until it returns something other than
0181  * -EAGAIN. Once that subroutine signals completion (by returning anything other
0182  * than -EAGAIN), the calling function can resume using the state machine.
0183  *
0184  *  xfs_attr_set_iter()
0185  *              │
0186  *              v
0187  *   ┌─y─ has an attr fork?
0188  *   │          |
0189  *   │          n
0190  *   │          |
0191  *   │          V
0192  *   │       add a fork
0193  *   │          │
0194  *   └──────────┤
0195  *              │
0196  *              V
0197  *   ┌─── is shortform?
0198  *   │          │
0199  *   │          y
0200  *   │          │
0201  *   │          V
0202  *   │   xfs_attr_set_fmt
0203  *   │          |
0204  *   │          V
0205  *   │ xfs_attr_try_sf_addname
0206  *   │          │
0207  *   │          V
0208  *   │      had enough ──y──> done
0209  *   │        space?
0210  *   n          │
0211  *   │          n
0212  *   │          │
0213  *   │          V
0214  *   │   transform to leaf
0215  *   │          │
0216  *   │          V
0217  *   │   hold the leaf buffer
0218  *   │          │
0219  *   │          V
0220  *   │     return -EAGAIN
0221  *   │      Re-enter in
0222  *   │       leaf form
0223  *   │
0224  *   └─> release leaf buffer
0225  *          if needed
0226  *              │
0227  *              V
0228  *   ┌───n── fork has
0229  *   │      only 1 blk?
0230  *   │          │
0231  *   │          y
0232  *   │          │
0233  *   │          v
0234  *   │ xfs_attr_leaf_try_add()
0235  *   │          │
0236  *   │          v
0237  *   │      had enough ──────────────y─────────────┐
0238  *   │        space?                               │
0239  *   │          │                                  │
0240  *   │          n                                  │
0241  *   │          │                                  │
0242  *   │          v                                  │
0243  *   │    return -EAGAIN                           │
0244  *   │      re-enter in                            │
0245  *   │        node form                            │
0246  *   │          │                                  │
0247  *   └──────────┤                                  │
0248  *              │                                  │
0249  *              V                                  │
0250  * xfs_attr_node_addname_find_attr                 │
0251  *        determines if this                       │
0252  *       is create or rename                       │
0253  *     find space to store attr                    │
0254  *              │                                  │
0255  *              v                                  │
0256  *     xfs_attr_node_addname                       │
0257  *              │                                  │
0258  *              v                                  │
0259  *   fits in a node leaf? ────n─────┐              │
0260  *              │     ^             v              │
0261  *              │     │       single leaf node?    │
0262  *              │     │         │            │     │
0263  *              y     │         y            n     │
0264  *              │     │         │            │     │
0265  *              v     │         v            v     │
0266  *            update  │    grow the leaf  split if │
0267  *           hashvals └── return -EAGAIN   needed  │
0268  *              │         retry leaf add     │     │
0269  *              │           on reentry       │     │
0270  *              ├────────────────────────────┘     │
0271  *              │                                  │
0272  *              v                                  │
0273  *         need to alloc                           │
0274  *   ┌─y── or flip flag?                           │
0275  *   │          │                                  │
0276  *   │          n                                  │
0277  *   │          │                                  │
0278  *   │          v                                  │
0279  *   │         done                                │
0280  *   │                                             │
0281  *   │                                             │
0282  *   │         XFS_DAS_FOUND_LBLK <────────────────┘
0283  *   │                  │
0284  *   │                  V
0285  *   │        xfs_attr_leaf_addname()
0286  *   │                  │
0287  *   │                  v
0288  *   │      ┌──first time through?
0289  *   │      │          │
0290  *   │      │          y
0291  *   │      │          │
0292  *   │      n          v
0293  *   │      │    if we have rmt blks
0294  *   │      │    find space for them
0295  *   │      │          │
0296  *   │      └──────────┤
0297  *   │                 │
0298  *   │                 v
0299  *   │            still have
0300  *   │      ┌─n─ blks to alloc? <──┐
0301  *   │      │          │           │
0302  *   │      │          y           │
0303  *   │      │          │           │
0304  *   │      │          v           │
0305  *   │      │     alloc one blk    │
0306  *   │      │     return -EAGAIN ──┘
0307  *   │      │    re-enter with one
0308  *   │      │    less blk to alloc
0309  *   │      │
0310  *   │      │
0311  *   │      └───> set the rmt
0312  *   │               value
0313  *   │                 │
0314  *   │                 v
0315  *   │               was this
0316  *   │              a rename? ──n─┐
0317  *   │                 │          │
0318  *   │                 y          │
0319  *   │                 │          │
0320  *   │                 v          │
0321  *   │           flip incomplete  │
0322  *   │               flag         │
0323  *   │                 │          │
0324  *   │                 v          │
0325  *   │         XFS_DAS_FLIP_LFLAG │
0326  *   │                 │          │
0327  *   │                 v          │
0328  *   │          need to remove    │
0329  *   │              old bks? ──n──┤
0330  *   │                 │          │
0331  *   │                 y          │
0332  *   │                 │          │
0333  *   │                 V          │
0334  *   │               remove       │
0335  *   │        ┌───> old blks      │
0336  *   │        │        │          │
0337  *   │ XFS_DAS_RM_LBLK │          │
0338  *   │        ^        │          │
0339  *   │        │        v          │
0340  *   │        └──y── more to      │
0341  *   │              remove?       │
0342  *   │                 │          │
0343  *   │                 n          │
0344  *   │                 │          │
0345  *   │                 v          │
0346  *   │          XFS_DAS_RD_LEAF   │
0347  *   │                 │          │
0348  *   │                 v          │
0349  *   │            remove leaf     │
0350  *   │                 │          │
0351  *   │                 v          │
0352  *   │            shrink to sf    │
0353  *   │             if needed      │
0354  *   │                 │          │
0355  *   │                 v          │
0356  *   │                done <──────┘
0357  *   │
0358  *   └──────> XFS_DAS_FOUND_NBLK
0359  *                     │
0360  *                     v
0361  *       ┌─────n──  need to
0362  *       │        alloc blks?
0363  *       │             │
0364  *       │             y
0365  *       │             │
0366  *       │             v
0367  *       │        find space
0368  *       │             │
0369  *       │             v
0370  *       │  ┌─>XFS_DAS_ALLOC_NODE
0371  *       │  │          │
0372  *       │  │          v
0373  *       │  │      alloc blk
0374  *       │  │          │
0375  *       │  │          v
0376  *       │  └──y── need to alloc
0377  *       │         more blocks?
0378  *       │             │
0379  *       │             n
0380  *       │             │
0381  *       │             v
0382  *       │      set the rmt value
0383  *       │             │
0384  *       │             v
0385  *       │          was this
0386  *       └────────> a rename? ──n─┐
0387  *                     │          │
0388  *                     y          │
0389  *                     │          │
0390  *                     v          │
0391  *               flip incomplete  │
0392  *                   flag         │
0393  *                     │          │
0394  *                     v          │
0395  *             XFS_DAS_FLIP_NFLAG │
0396  *                     │          │
0397  *                     v          │
0398  *                 need to        │
0399  *               remove blks? ─n──┤
0400  *                     │          │
0401  *                     y          │
0402  *                     │          │
0403  *                     v          │
0404  *                   remove       │
0405  *        ┌────────> old blks     │
0406  *        │            │          │
0407  *  XFS_DAS_RM_NBLK    │          │
0408  *        ^            │          │
0409  *        │            v          │
0410  *        └──────y── more to      │
0411  *                   remove       │
0412  *                     │          │
0413  *                     n          │
0414  *                     │          │
0415  *                     v          │
0416  *              XFS_DAS_CLR_FLAG  │
0417  *                     │          │
0418  *                     v          │
0419  *                clear flags     │
0420  *                     │          │
0421  *                     ├──────────┘
0422  *                     │
0423  *                     v
0424  *                   done
0425  */
0426 
0427 /*
0428  * Enum values for xfs_attr_intent.xattri_da_state
0429  *
0430  * These values are used by delayed attribute operations to keep track  of where
0431  * they were before they returned -EAGAIN.  A return code of -EAGAIN signals the
0432  * calling function to roll the transaction, and then call the subroutine to
0433  * finish the operation.  The enum is then used by the subroutine to jump back
0434  * to where it was and resume executing where it left off.
0435  */
0436 enum xfs_delattr_state {
0437     XFS_DAS_UNINIT      = 0,    /* No state has been set yet */
0438 
0439     /*
0440      * Initial sequence states. The replace setup code relies on the
0441      * ADD and REMOVE states for a specific format to be sequential so
0442      * that we can transform the initial operation to be performed
0443      * according to the xfs_has_larp() state easily.
0444      */
0445     XFS_DAS_SF_ADD,         /* Initial sf add state */
0446     XFS_DAS_SF_REMOVE,      /* Initial sf replace/remove state */
0447 
0448     XFS_DAS_LEAF_ADD,       /* Initial leaf add state */
0449     XFS_DAS_LEAF_REMOVE,        /* Initial leaf replace/remove state */
0450 
0451     XFS_DAS_NODE_ADD,       /* Initial node add state */
0452     XFS_DAS_NODE_REMOVE,        /* Initial node replace/remove state */
0453 
0454     /* Leaf state set/replace/remove sequence */
0455     XFS_DAS_LEAF_SET_RMT,       /* set a remote xattr from a leaf */
0456     XFS_DAS_LEAF_ALLOC_RMT,     /* We are allocating remote blocks */
0457     XFS_DAS_LEAF_REPLACE,       /* Perform replace ops on a leaf */
0458     XFS_DAS_LEAF_REMOVE_OLD,    /* Start removing old attr from leaf */
0459     XFS_DAS_LEAF_REMOVE_RMT,    /* A rename is removing remote blocks */
0460     XFS_DAS_LEAF_REMOVE_ATTR,   /* Remove the old attr from a leaf */
0461 
0462     /* Node state sequence, must match leaf state above */
0463     XFS_DAS_NODE_SET_RMT,       /* set a remote xattr from a node */
0464     XFS_DAS_NODE_ALLOC_RMT,     /* We are allocating remote blocks */
0465     XFS_DAS_NODE_REPLACE,       /* Perform replace ops on a node */
0466     XFS_DAS_NODE_REMOVE_OLD,    /* Start removing old attr from node */
0467     XFS_DAS_NODE_REMOVE_RMT,    /* A rename is removing remote blocks */
0468     XFS_DAS_NODE_REMOVE_ATTR,   /* Remove the old attr from a node */
0469 
0470     XFS_DAS_DONE,           /* finished operation */
0471 };
0472 
0473 #define XFS_DAS_STRINGS \
0474     { XFS_DAS_UNINIT,       "XFS_DAS_UNINIT" }, \
0475     { XFS_DAS_SF_ADD,       "XFS_DAS_SF_ADD" }, \
0476     { XFS_DAS_SF_REMOVE,        "XFS_DAS_SF_REMOVE" }, \
0477     { XFS_DAS_LEAF_ADD,     "XFS_DAS_LEAF_ADD" }, \
0478     { XFS_DAS_LEAF_REMOVE,      "XFS_DAS_LEAF_REMOVE" }, \
0479     { XFS_DAS_NODE_ADD,     "XFS_DAS_NODE_ADD" }, \
0480     { XFS_DAS_NODE_REMOVE,      "XFS_DAS_NODE_REMOVE" }, \
0481     { XFS_DAS_LEAF_SET_RMT,     "XFS_DAS_LEAF_SET_RMT" }, \
0482     { XFS_DAS_LEAF_ALLOC_RMT,   "XFS_DAS_LEAF_ALLOC_RMT" }, \
0483     { XFS_DAS_LEAF_REPLACE,     "XFS_DAS_LEAF_REPLACE" }, \
0484     { XFS_DAS_LEAF_REMOVE_OLD,  "XFS_DAS_LEAF_REMOVE_OLD" }, \
0485     { XFS_DAS_LEAF_REMOVE_RMT,  "XFS_DAS_LEAF_REMOVE_RMT" }, \
0486     { XFS_DAS_LEAF_REMOVE_ATTR, "XFS_DAS_LEAF_REMOVE_ATTR" }, \
0487     { XFS_DAS_NODE_SET_RMT,     "XFS_DAS_NODE_SET_RMT" }, \
0488     { XFS_DAS_NODE_ALLOC_RMT,   "XFS_DAS_NODE_ALLOC_RMT" },  \
0489     { XFS_DAS_NODE_REPLACE,     "XFS_DAS_NODE_REPLACE" },  \
0490     { XFS_DAS_NODE_REMOVE_OLD,  "XFS_DAS_NODE_REMOVE_OLD" }, \
0491     { XFS_DAS_NODE_REMOVE_RMT,  "XFS_DAS_NODE_REMOVE_RMT" }, \
0492     { XFS_DAS_NODE_REMOVE_ATTR, "XFS_DAS_NODE_REMOVE_ATTR" }, \
0493     { XFS_DAS_DONE,         "XFS_DAS_DONE" }
0494 
0495 struct xfs_attri_log_nameval;
0496 
0497 /*
0498  * Context used for keeping track of delayed attribute operations
0499  */
0500 struct xfs_attr_intent {
0501     /*
0502      * used to log this item to an intent containing a list of attrs to
0503      * commit later
0504      */
0505     struct list_head        xattri_list;
0506 
0507     /* Used in xfs_attr_node_removename to roll through removing blocks */
0508     struct xfs_da_state     *xattri_da_state;
0509 
0510     struct xfs_da_args      *xattri_da_args;
0511 
0512     /*
0513      * Shared buffer containing the attr name and value so that the logging
0514      * code can share large memory buffers between log items.
0515      */
0516     struct xfs_attri_log_nameval    *xattri_nameval;
0517 
0518     /* Used to keep track of current state of delayed operation */
0519     enum xfs_delattr_state      xattri_dela_state;
0520 
0521     /*
0522      * Attr operation being performed - XFS_ATTRI_OP_FLAGS_*
0523      */
0524     unsigned int            xattri_op_flags;
0525 
0526     /* Used in xfs_attr_rmtval_set_blk to roll through allocating blocks */
0527     xfs_dablk_t         xattri_lblkno;
0528     int             xattri_blkcnt;
0529     struct xfs_bmbt_irec        xattri_map;
0530 };
0531 
0532 
0533 /*========================================================================
0534  * Function prototypes for the kernel.
0535  *========================================================================*/
0536 
0537 /*
0538  * Overall external interface routines.
0539  */
0540 int xfs_attr_inactive(struct xfs_inode *dp);
0541 int xfs_attr_list_ilocked(struct xfs_attr_list_context *);
0542 int xfs_attr_list(struct xfs_attr_list_context *);
0543 int xfs_inode_hasattr(struct xfs_inode *ip);
0544 bool xfs_attr_is_leaf(struct xfs_inode *ip);
0545 int xfs_attr_get_ilocked(struct xfs_da_args *args);
0546 int xfs_attr_get(struct xfs_da_args *args);
0547 int xfs_attr_set(struct xfs_da_args *args);
0548 int xfs_attr_set_iter(struct xfs_attr_intent *attr);
0549 int xfs_attr_remove_iter(struct xfs_attr_intent *attr);
0550 bool xfs_attr_namecheck(const void *name, size_t length);
0551 int xfs_attr_calc_size(struct xfs_da_args *args, int *local);
0552 void xfs_init_attr_trans(struct xfs_da_args *args, struct xfs_trans_res *tres,
0553              unsigned int *total);
0554 
0555 /*
0556  * Check to see if the attr should be upgraded from non-existent or shortform to
0557  * single-leaf-block attribute list.
0558  */
0559 static inline bool
0560 xfs_attr_is_shortform(
0561     struct xfs_inode    *ip)
0562 {
0563     return ip->i_af.if_format == XFS_DINODE_FMT_LOCAL ||
0564            (ip->i_af.if_format == XFS_DINODE_FMT_EXTENTS &&
0565         ip->i_af.if_nextents == 0);
0566 }
0567 
0568 static inline enum xfs_delattr_state
0569 xfs_attr_init_add_state(struct xfs_da_args *args)
0570 {
0571     /*
0572      * When called from the completion of a attr remove to determine the
0573      * next state, the attribute fork may be null. This can occur only occur
0574      * on a pure remove, but we grab the next state before we check if a
0575      * replace operation is being performed. If we are called from any other
0576      * context, i_af is guaranteed to exist. Hence if the attr fork is
0577      * null, we were called from a pure remove operation and so we are done.
0578      */
0579     if (!xfs_inode_has_attr_fork(args->dp))
0580         return XFS_DAS_DONE;
0581 
0582     args->op_flags |= XFS_DA_OP_ADDNAME;
0583     if (xfs_attr_is_shortform(args->dp))
0584         return XFS_DAS_SF_ADD;
0585     if (xfs_attr_is_leaf(args->dp))
0586         return XFS_DAS_LEAF_ADD;
0587     return XFS_DAS_NODE_ADD;
0588 }
0589 
0590 static inline enum xfs_delattr_state
0591 xfs_attr_init_remove_state(struct xfs_da_args *args)
0592 {
0593     args->op_flags |= XFS_DA_OP_REMOVE;
0594     if (xfs_attr_is_shortform(args->dp))
0595         return XFS_DAS_SF_REMOVE;
0596     if (xfs_attr_is_leaf(args->dp))
0597         return XFS_DAS_LEAF_REMOVE;
0598     return XFS_DAS_NODE_REMOVE;
0599 }
0600 
0601 /*
0602  * If we are logging the attributes, then we have to start with removal of the
0603  * old attribute so that there is always consistent state that we can recover
0604  * from if the system goes down part way through. We always log the new attr
0605  * value, so even when we remove the attr first we still have the information in
0606  * the log to finish the replace operation atomically.
0607  */
0608 static inline enum xfs_delattr_state
0609 xfs_attr_init_replace_state(struct xfs_da_args *args)
0610 {
0611     args->op_flags |= XFS_DA_OP_ADDNAME | XFS_DA_OP_REPLACE;
0612     if (args->op_flags & XFS_DA_OP_LOGGED)
0613         return xfs_attr_init_remove_state(args);
0614     return xfs_attr_init_add_state(args);
0615 }
0616 
0617 extern struct kmem_cache *xfs_attr_intent_cache;
0618 int __init xfs_attr_intent_init_cache(void);
0619 void xfs_attr_intent_destroy_cache(void);
0620 
0621 #endif  /* __XFS_ATTR_H__ */