File Index
Files and directories
Sign in
FILE

xfs_attr.h

File preview with syntax highlighting.

linux-6.19.14/fs/xfs/libxfs/xfs_attr.h C
  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
  9struct xfs_inode;
 10struct xfs_da_args;
 11struct 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 */
 34struct 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 */
 50typedef 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
 54struct 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 */
437enum 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
496struct xfs_attri_log_nameval;
497
498/*
499 * Context used for keeping track of delayed attribute operations
500 */
501struct 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
533static inline unsigned int
534xfs_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 */
546int xfs_attr_inactive(struct xfs_inode *dp);
547int xfs_attr_list_ilocked(struct xfs_attr_list_context *);
548int xfs_attr_list(struct xfs_attr_list_context *);
549int xfs_inode_hasattr(struct xfs_inode *ip);
550bool xfs_attr_is_leaf(struct xfs_inode *ip);
551int xfs_attr_get_ilocked(struct xfs_da_args *args);
552int xfs_attr_get(struct xfs_da_args *args);
553
554enum 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
561int xfs_attr_set(struct xfs_da_args *args, enum xfs_attr_update op, bool rsvd);
562int xfs_attr_set_iter(struct xfs_attr_intent *attr);
563int xfs_attr_remove_iter(struct xfs_attr_intent *attr);
564bool xfs_attr_check_namespace(unsigned int attr_flags);
565bool xfs_attr_namecheck(unsigned int attr_flags, const void *name,
566		size_t length);
567int xfs_attr_calc_size(struct xfs_da_args *args, int *local);
568struct 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 */
574static inline bool
575xfs_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
583static inline enum xfs_delattr_state
584xfs_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
605static inline enum xfs_delattr_state
606xfs_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 */
622static inline enum xfs_delattr_state
623xfs_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
631xfs_dahash_t xfs_attr_hashname(const uint8_t *name, int namelen);
632
633xfs_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. */
638static 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
645extern struct kmem_cache *xfs_attr_intent_cache;
646int __init xfs_attr_intent_init_cache(void);
647void xfs_attr_intent_destroy_cache(void);
648
649int xfs_attr_sf_totsize(struct xfs_inode *dp);
650int xfs_attr_add_fork(struct xfs_inode *ip, int size, int rsvd);
651
652#endif	/* __XFS_ATTR_H__ */
~/ Read-only file preview.