1  /* SPDX-License-Identifier: GPL-2.0 */
2  /*
3   * Copyright (c) 2000,2002-2003,2005 Silicon Graphics, Inc.
4   * All Rights Reserved.
5   */
6  #ifndef __XFS_ATTR_H__
7  #define	__XFS_ATTR_H__
8  
9  struct xfs_inode;
10  struct xfs_da_args;
11  struct xfs_attr_list_context;
12  
13  /*
14   * Large attribute lists are structured around Btrees where all the data
15   * elements are in the leaf nodes.  Attribute names are hashed into an int,
16   * then that int is used as the index into the Btree.  Since the hashval
17   * of an attribute name may not be unique, we may have duplicate keys.
18   * The internal links in the Btree are logical block offsets into the file.
19   *
20   * Small attribute lists use a different format and are packed as tightly
21   * as possible so as to fit into the literal area of the inode.
22   */
23  
24  /*
25   * The maximum size (into the kernel or returned from the kernel) of an
26   * attribute value or the buffer used for an attr_list() call.  Larger
27   * sizes will result in an ERANGE return code.
28   */
29  #define	ATTR_MAX_VALUELEN	(64*1024)	/* max length of a value */
30  
31  /*
32   * Kernel-internal version of the attrlist cursor.
33   */
34  struct xfs_attrlist_cursor_kern {
35  	__u32	hashval;	/* hash value of next entry to add */
36  	__u32	blkno;		/* block containing entry (suggestion) */
37  	__u32	offset;		/* offset in list of equal-hashvals */
38  	__u16	pad1;		/* padding to match user-level */
39  	__u8	pad2;		/* padding to match user-level */
40  	__u8	initted;	/* T/F: cursor has been initialized */
41  };
42  
43  
44  /*========================================================================
45   * Structure used to pass context around among the routines.
46   *========================================================================*/
47  
48  
49  /* void; state communicated via *context */
50  typedef void (*put_listent_func_t)(struct xfs_attr_list_context *context,
51  		int flags, unsigned char *name, int namelen, void *value,
52  		int valuelen);
53  
54  struct xfs_attr_list_context {
55  	struct xfs_trans	*tp;
56  	struct xfs_inode	*dp;		/* inode */
57  	struct xfs_attrlist_cursor_kern cursor;	/* position in list */
58  	void			*buffer;	/* output buffer */
59  
60  	/*
61  	 * Abort attribute list iteration if non-zero.  Can be used to pass
62  	 * error values to the xfs_attr_list caller.
63  	 */
64  	int			seen_enough;
65  	bool			allow_incomplete;
66  
67  	ssize_t			count;		/* num used entries */
68  	int			dupcnt;		/* count dup hashvals seen */
69  	int			bufsize;	/* total buffer size */
70  	int			firstu;		/* first used byte in buffer */
71  	unsigned int		attr_filter;	/* XFS_ATTR_{ROOT,SECURE} */
72  	int			resynch;	/* T/F: resynch with cursor */
73  	put_listent_func_t	put_listent;	/* list output fmt function */
74  	int			index;		/* index into output buffer */
75  };
76  
77  
78  /*
79   * ========================================================================
80   * Structure used to pass context around among the delayed routines.
81   * ========================================================================
82   */
83  
84  /*
85   * Below is a state machine diagram for attr remove operations. The  XFS_DAS_*
86   * states indicate places where the function would return -EAGAIN, and then
87   * immediately resume from after being called by the calling function. States
88   * marked as a "subroutine state" indicate that they belong to a subroutine, and
89   * so the calling function needs to pass them back to that subroutine to allow
90   * it to finish where it left off. But they otherwise do not have a role in the
91   * calling function other than just passing through.
92   *
93   * xfs_attr_remove_iter()
94   *              │
95   *              v
96   *        have attr to remove? ──n──> done
97   *              │
98   *              y
99   *              │
100   *              v
101   *        are we short form? ──y──> xfs_attr_shortform_remove ──> done
102   *              │
103   *              n
104   *              │
105   *              V
106   *        are we leaf form? ──y──> xfs_attr_leaf_removename ──> done
107   *              │
108   *              n
109   *              │
110   *              V
111   *   ┌── need to setup state?
112   *   │          │
113   *   n          y
114   *   │          │
115   *   │          v
116   *   │ find attr and get state
117   *   │ attr has remote blks? ──n─┐
118   *   │          │                v
119   *   │          │         find and invalidate
120   *   │          y         the remote blocks.
121   *   │          │         mark attr incomplete
122   *   │          ├────────────────┘
123   *   └──────────┤
124   *              │
125   *              v
126   *   Have remote blks to remove? ───y─────┐
127   *              │        ^          remove the blks
128   *              │        │                │
129   *              │        │                v
130   *              │  XFS_DAS_RMTBLK <─n── done?
131   *              │  re-enter with          │
132   *              │  one less blk to        y
133   *              │      remove             │
134   *              │                         V
135   *              │                  refill the state
136   *              n                         │
137   *              │                         v
138   *              │                   XFS_DAS_RM_NAME
139   *              │                         │
140   *              ├─────────────────────────┘
141   *              │
142   *              v
143   *       remove leaf and
144   *       update hash with
145   *   xfs_attr_node_remove_cleanup
146   *              │
147   *              v
148   *           need to
149   *        shrink tree? ─n─┐
150   *              │         │
151   *              y         │
152   *              │         │
153   *              v         │
154   *          join leaf     │
155   *              │         │
156   *              v         │
157   *      XFS_DAS_RM_SHRINK │
158   *              │         │
159   *              v         │
160   *       do the shrink    │
161   *              │         │
162   *              v         │
163   *          free state <──┘
164   *              │
165   *              v
166   *            done
167   *
168   *
169   * Below is a state machine diagram for attr set operations.
170   *
171   * It seems the challenge with understanding this system comes from trying to
172   * absorb the state machine all at once, when really one should only be looking
173   * at it with in the context of a single function. Once a state sensitive
174   * function is called, the idea is that it "takes ownership" of the
175   * state machine. It isn't concerned with the states that may have belonged to
176   * it's calling parent. Only the states relevant to itself or any other
177   * subroutines there in. Once a calling function hands off the state machine to
178   * a subroutine, it needs to respect the simple rule that it doesn't "own" the
179   * state machine anymore, and it's the responsibility of that calling function
180   * to propagate the -EAGAIN back up the call stack. Upon reentry, it is
181   * committed to re-calling that subroutine until it returns something other than
182   * -EAGAIN. Once that subroutine signals completion (by returning anything other
183   * than -EAGAIN), the calling function can resume using the state machine.
184   *
185   *  xfs_attr_set_iter()
186   *              │
187   *              v
188   *   ┌─y─ has an attr fork?
189   *   │          |
190   *   │          n
191   *   │          |
192   *   │          V
193   *   │       add a fork
194   *   │          │
195   *   └──────────┤
196   *              │
197   *              V
198   *   ┌─── is shortform?
199   *   │          │
200   *   │          y
201   *   │          │
202   *   │          V
203   *   │   xfs_attr_set_fmt
204   *   │          |
205   *   │          V
206   *   │ xfs_attr_try_sf_addname
207   *   │          │
208   *   │          V
209   *   │      had enough ──y──> done
210   *   │        space?
211   *   n          │
212   *   │          n
213   *   │          │
214   *   │          V
215   *   │   transform to leaf
216   *   │          │
217   *   │          V
218   *   │   hold the leaf buffer
219   *   │          │
220   *   │          V
221   *   │     return -EAGAIN
222   *   │      Re-enter in
223   *   │       leaf form
224   *   │
225   *   └─> release leaf buffer
226   *          if needed
227   *              │
228   *              V
229   *   ┌───n── fork has
230   *   │      only 1 blk?
231   *   │          │
232   *   │          y
233   *   │          │
234   *   │          v
235   *   │ xfs_attr_leaf_try_add()
236   *   │          │
237   *   │          v
238   *   │      had enough ──────────────y─────────────┐
239   *   │        space?                               │
240   *   │          │                                  │
241   *   │          n                                  │
242   *   │          │                                  │
243   *   │          v                                  │
244   *   │    return -EAGAIN                           │
245   *   │      re-enter in                            │
246   *   │        node form                            │
247   *   │          │                                  │
248   *   └──────────┤                                  │
249   *              │                                  │
250   *              V                                  │
251   * xfs_attr_node_addname_find_attr                 │
252   *        determines if this                       │
253   *       is create or rename                       │
254   *     find space to store attr                    │
255   *              │                                  │
256   *              v                                  │
257   *     xfs_attr_node_addname                       │
258   *              │                                  │
259   *              v                                  │
260   *   fits in a node leaf? ────n─────┐              │
261   *              │     ^             v              │
262   *              │     │       single leaf node?    │
263   *              │     │         │            │     │
264   *              y     │         y            n     │
265   *              │     │         │            │     │
266   *              v     │         v            v     │
267   *            update  │    grow the leaf  split if │
268   *           hashvals └── return -EAGAIN   needed  │
269   *              │         retry leaf add     │     │
270   *              │           on reentry       │     │
271   *              ├────────────────────────────┘     │
272   *              │                                  │
273   *              v                                  │
274   *         need to alloc                           │
275   *   ┌─y── or flip flag?                           │
276   *   │          │                                  │
277   *   │          n                                  │
278   *   │          │                                  │
279   *   │          v                                  │
280   *   │         done                                │
281   *   │                                             │
282   *   │                                             │
283   *   │         XFS_DAS_FOUND_LBLK <────────────────┘
284   *   │                  │
285   *   │                  V
286   *   │        xfs_attr_leaf_addname()
287   *   │                  │
288   *   │                  v
289   *   │      ┌──first time through?
290   *   │      │          │
291   *   │      │          y
292   *   │      │          │
293   *   │      n          v
294   *   │      │    if we have rmt blks
295   *   │      │    find space for them
296   *   │      │          │
297   *   │      └──────────┤
298   *   │                 │
299   *   │                 v
300   *   │            still have
301   *   │      ┌─n─ blks to alloc? <──┐
302   *   │      │          │           │
303   *   │      │          y           │
304   *   │      │          │           │
305   *   │      │          v           │
306   *   │      │     alloc one blk    │
307   *   │      │     return -EAGAIN ──┘
308   *   │      │    re-enter with one
309   *   │      │    less blk to alloc
310   *   │      │
311   *   │      │
312   *   │      └───> set the rmt
313   *   │               value
314   *   │                 │
315   *   │                 v
316   *   │               was this
317   *   │              a rename? ──n─┐
318   *   │                 │          │
319   *   │                 y          │
320   *   │                 │          │
321   *   │                 v          │
322   *   │           flip incomplete  │
323   *   │               flag         │
324   *   │                 │          │
325   *   │                 v          │
326   *   │         XFS_DAS_FLIP_LFLAG │
327   *   │                 │          │
328   *   │                 v          │
329   *   │          need to remove    │
330   *   │              old bks? ──n──┤
331   *   │                 │          │
332   *   │                 y          │
333   *   │                 │          │
334   *   │                 V          │
335   *   │               remove       │
336   *   │        ┌───> old blks      │
337   *   │        │        │          │
338   *   │ XFS_DAS_RM_LBLK │          │
339   *   │        ^        │          │
340   *   │        │        v          │
341   *   │        └──y── more to      │
342   *   │              remove?       │
343   *   │                 │          │
344   *   │                 n          │
345   *   │                 │          │
346   *   │                 v          │
347   *   │          XFS_DAS_RD_LEAF   │
348   *   │                 │          │
349   *   │                 v          │
350   *   │            remove leaf     │
351   *   │                 │          │
352   *   │                 v          │
353   *   │            shrink to sf    │
354   *   │             if needed      │
355   *   │                 │          │
356   *   │                 v          │
357   *   │                done <──────┘
358   *   │
359   *   └──────> XFS_DAS_FOUND_NBLK
360   *                     │
361   *                     v
362   *       ┌─────n──  need to
363   *       │        alloc blks?
364   *       │             │
365   *       │             y
366   *       │             │
367   *       │             v
368   *       │        find space
369   *       │             │
370   *       │             v
371   *       │  ┌─>XFS_DAS_ALLOC_NODE
372   *       │  │          │
373   *       │  │          v
374   *       │  │      alloc blk
375   *       │  │          │
376   *       │  │          v
377   *       │  └──y── need to alloc
378   *       │         more blocks?
379   *       │             │
380   *       │             n
381   *       │             │
382   *       │             v
383   *       │      set the rmt value
384   *       │             │
385   *       │             v
386   *       │          was this
387   *       └────────> a rename? ──n─┐
388   *                     │          │
389   *                     y          │
390   *                     │          │
391   *                     v          │
392   *               flip incomplete  │
393   *                   flag         │
394   *                     │          │
395   *                     v          │
396   *             XFS_DAS_FLIP_NFLAG │
397   *                     │          │
398   *                     v          │
399   *                 need to        │
400   *               remove blks? ─n──┤
401   *                     │          │
402   *                     y          │
403   *                     │          │
404   *                     v          │
405   *                   remove       │
406   *        ┌────────> old blks     │
407   *        │            │          │
408   *  XFS_DAS_RM_NBLK    │          │
409   *        ^            │          │
410   *        │            v          │
411   *        └──────y── more to      │
412   *                   remove       │
413   *                     │          │
414   *                     n          │
415   *                     │          │
416   *                     v          │
417   *              XFS_DAS_CLR_FLAG  │
418   *                     │          │
419   *                     v          │
420   *                clear flags     │
421   *                     │          │
422   *                     ├──────────┘
423   *                     │
424   *                     v
425   *                   done
426   */
427  
428  /*
429   * Enum values for xfs_attr_intent.xattri_da_state
430   *
431   * These values are used by delayed attribute operations to keep track  of where
432   * they were before they returned -EAGAIN.  A return code of -EAGAIN signals the
433   * calling function to roll the transaction, and then call the subroutine to
434   * finish the operation.  The enum is then used by the subroutine to jump back
435   * to where it was and resume executing where it left off.
436   */
437  enum xfs_delattr_state {
438  	XFS_DAS_UNINIT		= 0,	/* No state has been set yet */
439  
440  	/*
441  	 * Initial sequence states. The replace setup code relies on the
442  	 * ADD and REMOVE states for a specific format to be sequential so
443  	 * that we can transform the initial operation to be performed
444  	 * according to the xfs_has_larp() state easily.
445  	 */
446  	XFS_DAS_SF_ADD,			/* Initial sf add state */
447  	XFS_DAS_SF_REMOVE,		/* Initial sf replace/remove state */
448  
449  	XFS_DAS_LEAF_ADD,		/* Initial leaf add state */
450  	XFS_DAS_LEAF_REMOVE,		/* Initial leaf replace/remove state */
451  
452  	XFS_DAS_NODE_ADD,		/* Initial node add state */
453  	XFS_DAS_NODE_REMOVE,		/* Initial node replace/remove state */
454  
455  	/* Leaf state set/replace/remove sequence */
456  	XFS_DAS_LEAF_SET_RMT,		/* set a remote xattr from a leaf */
457  	XFS_DAS_LEAF_ALLOC_RMT,		/* We are allocating remote blocks */
458  	XFS_DAS_LEAF_REPLACE,		/* Perform replace ops on a leaf */
459  	XFS_DAS_LEAF_REMOVE_OLD,	/* Start removing old attr from leaf */
460  	XFS_DAS_LEAF_REMOVE_RMT,	/* A rename is removing remote blocks */
461  	XFS_DAS_LEAF_REMOVE_ATTR,	/* Remove the old attr from a leaf */
462  
463  	/* Node state sequence, must match leaf state above */
464  	XFS_DAS_NODE_SET_RMT,		/* set a remote xattr from a node */
465  	XFS_DAS_NODE_ALLOC_RMT,		/* We are allocating remote blocks */
466  	XFS_DAS_NODE_REPLACE,		/* Perform replace ops on a node */
467  	XFS_DAS_NODE_REMOVE_OLD,	/* Start removing old attr from node */
468  	XFS_DAS_NODE_REMOVE_RMT,	/* A rename is removing remote blocks */
469  	XFS_DAS_NODE_REMOVE_ATTR,	/* Remove the old attr from a node */
470  
471  	XFS_DAS_DONE,			/* finished operation */
472  };
473  
474  #define XFS_DAS_STRINGS	\
475  	{ XFS_DAS_UNINIT,		"XFS_DAS_UNINIT" }, \
476  	{ XFS_DAS_SF_ADD,		"XFS_DAS_SF_ADD" }, \
477  	{ XFS_DAS_SF_REMOVE,		"XFS_DAS_SF_REMOVE" }, \
478  	{ XFS_DAS_LEAF_ADD,		"XFS_DAS_LEAF_ADD" }, \
479  	{ XFS_DAS_LEAF_REMOVE,		"XFS_DAS_LEAF_REMOVE" }, \
480  	{ XFS_DAS_NODE_ADD,		"XFS_DAS_NODE_ADD" }, \
481  	{ XFS_DAS_NODE_REMOVE,		"XFS_DAS_NODE_REMOVE" }, \
482  	{ XFS_DAS_LEAF_SET_RMT,		"XFS_DAS_LEAF_SET_RMT" }, \
483  	{ XFS_DAS_LEAF_ALLOC_RMT,	"XFS_DAS_LEAF_ALLOC_RMT" }, \
484  	{ XFS_DAS_LEAF_REPLACE,		"XFS_DAS_LEAF_REPLACE" }, \
485  	{ XFS_DAS_LEAF_REMOVE_OLD,	"XFS_DAS_LEAF_REMOVE_OLD" }, \
486  	{ XFS_DAS_LEAF_REMOVE_RMT,	"XFS_DAS_LEAF_REMOVE_RMT" }, \
487  	{ XFS_DAS_LEAF_REMOVE_ATTR,	"XFS_DAS_LEAF_REMOVE_ATTR" }, \
488  	{ XFS_DAS_NODE_SET_RMT,		"XFS_DAS_NODE_SET_RMT" }, \
489  	{ XFS_DAS_NODE_ALLOC_RMT,	"XFS_DAS_NODE_ALLOC_RMT" },  \
490  	{ XFS_DAS_NODE_REPLACE,		"XFS_DAS_NODE_REPLACE" },  \
491  	{ XFS_DAS_NODE_REMOVE_OLD,	"XFS_DAS_NODE_REMOVE_OLD" }, \
492  	{ XFS_DAS_NODE_REMOVE_RMT,	"XFS_DAS_NODE_REMOVE_RMT" }, \
493  	{ XFS_DAS_NODE_REMOVE_ATTR,	"XFS_DAS_NODE_REMOVE_ATTR" }, \
494  	{ XFS_DAS_DONE,			"XFS_DAS_DONE" }
495  
496  struct xfs_attri_log_nameval;
497  
498  /*
499   * Context used for keeping track of delayed attribute operations
500   */
501  struct xfs_attr_intent {
502  	/*
503  	 * used to log this item to an intent containing a list of attrs to
504  	 * commit later
505  	 */
506  	struct list_head		xattri_list;
507  
508  	/* Used in xfs_attr_node_removename to roll through removing blocks */
509  	struct xfs_da_state		*xattri_da_state;
510  
511  	struct xfs_da_args		*xattri_da_args;
512  
513  	/*
514  	 * Shared buffer containing the attr name, new name, and value so that
515  	 * the logging code can share large memory buffers between log items.
516  	 */
517  	struct xfs_attri_log_nameval	*xattri_nameval;
518  
519  	/* Used to keep track of current state of delayed operation */
520  	enum xfs_delattr_state		xattri_dela_state;
521  
522  	/*
523  	 * Attr operation being performed - XFS_ATTRI_OP_FLAGS_*
524  	 */
525  	unsigned int			xattri_op_flags;
526  
527  	/* Used in xfs_attr_rmtval_set_blk to roll through allocating blocks */
528  	xfs_dablk_t			xattri_lblkno;
529  	int				xattri_blkcnt;
530  	struct xfs_bmbt_irec		xattri_map;
531  };
532  
533  static inline unsigned int
xfs_attr_intent_op(const struct xfs_attr_intent * attr)534  xfs_attr_intent_op(const struct xfs_attr_intent *attr)
535  {
536  	return attr->xattri_op_flags & XFS_ATTRI_OP_FLAGS_TYPE_MASK;
537  }
538  
539  /*========================================================================
540   * Function prototypes for the kernel.
541   *========================================================================*/
542  
543  /*
544   * Overall external interface routines.
545   */
546  int xfs_attr_inactive(struct xfs_inode *dp);
547  int xfs_attr_list_ilocked(struct xfs_attr_list_context *);
548  int xfs_attr_list(struct xfs_attr_list_context *);
549  int xfs_inode_hasattr(struct xfs_inode *ip);
550  bool xfs_attr_is_leaf(struct xfs_inode *ip);
551  int xfs_attr_get_ilocked(struct xfs_da_args *args);
552  int xfs_attr_get(struct xfs_da_args *args);
553  
554  enum xfs_attr_update {
555  	XFS_ATTRUPDATE_REMOVE,	/* remove attr */
556  	XFS_ATTRUPDATE_UPSERT,	/* set value, replace any existing attr */
557  	XFS_ATTRUPDATE_CREATE,	/* set value, fail if attr already exists */
558  	XFS_ATTRUPDATE_REPLACE,	/* set value, fail if attr does not exist */
559  };
560  
561  int xfs_attr_set(struct xfs_da_args *args, enum xfs_attr_update op, bool rsvd);
562  int xfs_attr_set_iter(struct xfs_attr_intent *attr);
563  int xfs_attr_remove_iter(struct xfs_attr_intent *attr);
564  bool xfs_attr_check_namespace(unsigned int attr_flags);
565  bool xfs_attr_namecheck(unsigned int attr_flags, const void *name,
566  		size_t length);
567  int xfs_attr_calc_size(struct xfs_da_args *args, int *local);
568  struct xfs_trans_res xfs_attr_set_resv(const struct xfs_da_args *args);
569  
570  /*
571   * Check to see if the attr should be upgraded from non-existent or shortform to
572   * single-leaf-block attribute list.
573   */
574  static inline bool
xfs_attr_is_shortform(struct xfs_inode * ip)575  xfs_attr_is_shortform(
576  	struct xfs_inode    *ip)
577  {
578  	return ip->i_af.if_format == XFS_DINODE_FMT_LOCAL ||
579  	       (ip->i_af.if_format == XFS_DINODE_FMT_EXTENTS &&
580  		ip->i_af.if_nextents == 0);
581  }
582  
583  static inline enum xfs_delattr_state
xfs_attr_init_add_state(struct xfs_da_args * args)584  xfs_attr_init_add_state(struct xfs_da_args *args)
585  {
586  	/*
587  	 * When called from the completion of a attr remove to determine the
588  	 * next state, the attribute fork may be null. This can occur only occur
589  	 * on a pure remove, but we grab the next state before we check if a
590  	 * replace operation is being performed. If we are called from any other
591  	 * context, i_af is guaranteed to exist. Hence if the attr fork is
592  	 * null, we were called from a pure remove operation and so we are done.
593  	 */
594  	if (!xfs_inode_has_attr_fork(args->dp))
595  		return XFS_DAS_DONE;
596  
597  	args->op_flags |= XFS_DA_OP_ADDNAME;
598  	if (xfs_attr_is_shortform(args->dp))
599  		return XFS_DAS_SF_ADD;
600  	if (xfs_attr_is_leaf(args->dp))
601  		return XFS_DAS_LEAF_ADD;
602  	return XFS_DAS_NODE_ADD;
603  }
604  
605  static inline enum xfs_delattr_state
xfs_attr_init_remove_state(struct xfs_da_args * args)606  xfs_attr_init_remove_state(struct xfs_da_args *args)
607  {
608  	if (xfs_attr_is_shortform(args->dp))
609  		return XFS_DAS_SF_REMOVE;
610  	if (xfs_attr_is_leaf(args->dp))
611  		return XFS_DAS_LEAF_REMOVE;
612  	return XFS_DAS_NODE_REMOVE;
613  }
614  
615  /*
616   * If we are logging the attributes, then we have to start with removal of the
617   * old attribute so that there is always consistent state that we can recover
618   * from if the system goes down part way through. We always log the new attr
619   * value, so even when we remove the attr first we still have the information in
620   * the log to finish the replace operation atomically.
621   */
622  static inline enum xfs_delattr_state
xfs_attr_init_replace_state(struct xfs_da_args * args)623  xfs_attr_init_replace_state(struct xfs_da_args *args)
624  {
625  	args->op_flags |= XFS_DA_OP_ADDNAME | XFS_DA_OP_REPLACE;
626  	if (args->op_flags & XFS_DA_OP_LOGGED)
627  		return xfs_attr_init_remove_state(args);
628  	return xfs_attr_init_add_state(args);
629  }
630  
631  xfs_dahash_t xfs_attr_hashname(const uint8_t *name, int namelen);
632  
633  xfs_dahash_t xfs_attr_hashval(struct xfs_mount *mp, unsigned int attr_flags,
634  		const uint8_t *name, int namelen, const void *value,
635  		int valuelen);
636  
637  /* Set the hash value for any extended attribute from any namespace. */
xfs_attr_sethash(struct xfs_da_args * args)638  static inline void xfs_attr_sethash(struct xfs_da_args *args)
639  {
640  	args->hashval = xfs_attr_hashval(args->dp->i_mount, args->attr_filter,
641  					 args->name, args->namelen,
642  					 args->value, args->valuelen);
643  }
644  
645  extern struct kmem_cache *xfs_attr_intent_cache;
646  int __init xfs_attr_intent_init_cache(void);
647  void xfs_attr_intent_destroy_cache(void);
648  
649  int xfs_attr_sf_totsize(struct xfs_inode *dp);
650  int xfs_attr_add_fork(struct xfs_inode *ip, int size, int rsvd);
651  
652  #endif	/* __XFS_ATTR_H__ */
653