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