2 * Copyright (c) 2000-2005 Silicon Graphics, Inc.
5 * This program is free software; you can redistribute it and/or
6 * modify it under the terms of the GNU General Public License as
7 * published by the Free Software Foundation.
9 * This program is distributed in the hope that it would be useful,
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 * GNU General Public License for more details.
14 * You should have received a copy of the GNU General Public License
15 * along with this program; if not, write the Free Software Foundation,
16 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
20 #include "xfs_types.h"
23 #include "xfs_trans.h"
26 #include "xfs_mount.h"
27 #include "xfs_da_btree.h"
28 #include "xfs_bmap_btree.h"
29 #include "xfs_attr_sf.h"
30 #include "xfs_dinode.h"
31 #include "xfs_inode.h"
32 #include "xfs_alloc.h"
33 #include "xfs_inode_item.h"
36 #include "xfs_attr_leaf.h"
37 #include "xfs_attr_remote.h"
38 #include "xfs_error.h"
39 #include "xfs_quota.h"
40 #include "xfs_trans_space.h"
41 #include "xfs_vnodeops.h"
42 #include "xfs_trace.h"
47 * Provide the external interfaces to manage attribute lists.
50 /*========================================================================
51 * Function prototypes for the kernel.
52 *========================================================================*/
55 * Internal routines when attribute list fits inside the inode.
57 STATIC
int xfs_attr_shortform_addname(xfs_da_args_t
*args
);
60 * Internal routines when attribute list is one block.
62 STATIC
int xfs_attr_leaf_get(xfs_da_args_t
*args
);
63 STATIC
int xfs_attr_leaf_addname(xfs_da_args_t
*args
);
64 STATIC
int xfs_attr_leaf_removename(xfs_da_args_t
*args
);
65 STATIC
int xfs_attr_leaf_list(xfs_attr_list_context_t
*context
);
68 * Internal routines when attribute list is more than one block.
70 STATIC
int xfs_attr_node_get(xfs_da_args_t
*args
);
71 STATIC
int xfs_attr_node_addname(xfs_da_args_t
*args
);
72 STATIC
int xfs_attr_node_removename(xfs_da_args_t
*args
);
73 STATIC
int xfs_attr_node_list(xfs_attr_list_context_t
*context
);
74 STATIC
int xfs_attr_fillstate(xfs_da_state_t
*state
);
75 STATIC
int xfs_attr_refillstate(xfs_da_state_t
*state
);
79 xfs_attr_name_to_xname(
80 struct xfs_name
*xname
,
81 const unsigned char *aname
)
86 xname
->len
= strlen((char *)aname
);
87 if (xname
->len
>= MAXNAMELEN
)
88 return EFAULT
; /* match IRIX behaviour */
97 if (!XFS_IFORK_Q(ip
) ||
98 (ip
->i_d
.di_aformat
== XFS_DINODE_FMT_EXTENTS
&&
99 ip
->i_d
.di_anextents
== 0))
104 /*========================================================================
105 * Overall external interface routines.
106 *========================================================================*/
110 struct xfs_inode
*ip
,
111 struct xfs_name
*name
,
112 unsigned char *value
,
119 if (!xfs_inode_hasattr(ip
))
123 * Fill in the arg structure for this request.
125 memset((char *)&args
, 0, sizeof(args
));
126 args
.name
= name
->name
;
127 args
.namelen
= name
->len
;
129 args
.valuelen
= *valuelenp
;
131 args
.hashval
= xfs_da_hashname(args
.name
, args
.namelen
);
133 args
.whichfork
= XFS_ATTR_FORK
;
136 * Decide on what work routines to call based on the inode size.
138 if (ip
->i_d
.di_aformat
== XFS_DINODE_FMT_LOCAL
) {
139 error
= xfs_attr_shortform_getvalue(&args
);
140 } else if (xfs_bmap_one_block(ip
, XFS_ATTR_FORK
)) {
141 error
= xfs_attr_leaf_get(&args
);
143 error
= xfs_attr_node_get(&args
);
147 * Return the number of bytes in the value to the caller.
149 *valuelenp
= args
.valuelen
;
159 const unsigned char *name
,
160 unsigned char *value
,
165 struct xfs_name xname
;
167 XFS_STATS_INC(xs_attr_get
);
169 if (XFS_FORCED_SHUTDOWN(ip
->i_mount
))
172 error
= xfs_attr_name_to_xname(&xname
, name
);
176 xfs_ilock(ip
, XFS_ILOCK_SHARED
);
177 error
= xfs_attr_get_int(ip
, &xname
, value
, valuelenp
, flags
);
178 xfs_iunlock(ip
, XFS_ILOCK_SHARED
);
183 * Calculate how many blocks we need for the new attribute,
187 struct xfs_inode
*ip
,
192 struct xfs_mount
*mp
= ip
->i_mount
;
197 * Determine space new attribute will use, and if it would be
198 * "local" or "remote" (note: local != inline).
200 size
= xfs_attr_leaf_newentsize(namelen
, valuelen
,
201 mp
->m_sb
.sb_blocksize
, local
);
203 nblks
= XFS_DAENTER_SPACE_RES(mp
, XFS_ATTR_FORK
);
205 if (size
> (mp
->m_sb
.sb_blocksize
>> 1)) {
206 /* Double split possible */
211 * Out of line attribute, cannot double split, but
212 * make room for the attribute value itself.
214 uint dblocks
= XFS_B_TO_FSB(mp
, valuelen
);
216 nblks
+= XFS_NEXTENTADD_SPACE_RES(mp
, dblocks
, XFS_ATTR_FORK
);
224 struct xfs_inode
*dp
,
225 struct xfs_name
*name
,
226 unsigned char *value
,
231 xfs_fsblock_t firstblock
;
232 xfs_bmap_free_t flist
;
233 int error
, err2
, committed
;
234 xfs_mount_t
*mp
= dp
->i_mount
;
235 int rsvd
= (flags
& ATTR_ROOT
) != 0;
239 * Attach the dquots to the inode.
241 error
= xfs_qm_dqattach(dp
, 0);
246 * If the inode doesn't have an attribute fork, add one.
247 * (inode must not be locked when we call this routine)
249 if (XFS_IFORK_Q(dp
) == 0) {
250 int sf_size
= sizeof(xfs_attr_sf_hdr_t
) +
251 XFS_ATTR_SF_ENTSIZE_BYNAME(name
->len
, valuelen
);
253 if ((error
= xfs_bmap_add_attrfork(dp
, sf_size
, rsvd
)))
258 * Fill in the arg structure for this request.
260 memset((char *)&args
, 0, sizeof(args
));
261 args
.name
= name
->name
;
262 args
.namelen
= name
->len
;
264 args
.valuelen
= valuelen
;
266 args
.hashval
= xfs_da_hashname(args
.name
, args
.namelen
);
268 args
.firstblock
= &firstblock
;
270 args
.whichfork
= XFS_ATTR_FORK
;
271 args
.op_flags
= XFS_DA_OP_ADDNAME
| XFS_DA_OP_OKNOENT
;
273 /* Size is now blocks for attribute data */
274 args
.total
= xfs_attr_calc_size(dp
, name
->len
, valuelen
, &local
);
277 * Start our first transaction of the day.
279 * All future transactions during this code must be "chained" off
280 * this one via the trans_dup() call. All transactions will contain
281 * the inode, and the inode will always be marked with trans_ihold().
282 * Since the inode will be locked in all transactions, we must log
283 * the inode in every transaction to let it float upward through
286 args
.trans
= xfs_trans_alloc(mp
, XFS_TRANS_ATTR_SET
);
289 * Root fork attributes can use reserved data blocks for this
290 * operation if necessary
294 args
.trans
->t_flags
|= XFS_TRANS_RESERVE
;
296 error
= xfs_trans_reserve(args
.trans
, args
.total
,
297 XFS_ATTRSETM_LOG_RES(mp
) +
298 XFS_ATTRSETRT_LOG_RES(mp
) * args
.total
,
299 0, XFS_TRANS_PERM_LOG_RES
,
300 XFS_ATTRSET_LOG_COUNT
);
302 xfs_trans_cancel(args
.trans
, 0);
305 xfs_ilock(dp
, XFS_ILOCK_EXCL
);
307 error
= xfs_trans_reserve_quota_nblks(args
.trans
, dp
, args
.total
, 0,
308 rsvd
? XFS_QMOPT_RES_REGBLKS
| XFS_QMOPT_FORCE_RES
:
309 XFS_QMOPT_RES_REGBLKS
);
311 xfs_iunlock(dp
, XFS_ILOCK_EXCL
);
312 xfs_trans_cancel(args
.trans
, XFS_TRANS_RELEASE_LOG_RES
);
316 xfs_trans_ijoin(args
.trans
, dp
, 0);
319 * If the attribute list is non-existent or a shortform list,
320 * upgrade it to a single-leaf-block attribute list.
322 if ((dp
->i_d
.di_aformat
== XFS_DINODE_FMT_LOCAL
) ||
323 ((dp
->i_d
.di_aformat
== XFS_DINODE_FMT_EXTENTS
) &&
324 (dp
->i_d
.di_anextents
== 0))) {
327 * Build initial attribute list (if required).
329 if (dp
->i_d
.di_aformat
== XFS_DINODE_FMT_EXTENTS
)
330 xfs_attr_shortform_create(&args
);
333 * Try to add the attr to the attribute list in
336 error
= xfs_attr_shortform_addname(&args
);
337 if (error
!= ENOSPC
) {
339 * Commit the shortform mods, and we're done.
340 * NOTE: this is also the error path (EEXIST, etc).
342 ASSERT(args
.trans
!= NULL
);
345 * If this is a synchronous mount, make sure that
346 * the transaction goes to disk before returning
349 if (mp
->m_flags
& XFS_MOUNT_WSYNC
) {
350 xfs_trans_set_sync(args
.trans
);
353 if (!error
&& (flags
& ATTR_KERNOTIME
) == 0) {
354 xfs_trans_ichgtime(args
.trans
, dp
,
357 err2
= xfs_trans_commit(args
.trans
,
358 XFS_TRANS_RELEASE_LOG_RES
);
359 xfs_iunlock(dp
, XFS_ILOCK_EXCL
);
361 return(error
== 0 ? err2
: error
);
365 * It won't fit in the shortform, transform to a leaf block.
366 * GROT: another possible req'mt for a double-split btree op.
368 xfs_bmap_init(args
.flist
, args
.firstblock
);
369 error
= xfs_attr_shortform_to_leaf(&args
);
371 error
= xfs_bmap_finish(&args
.trans
, args
.flist
,
377 xfs_bmap_cancel(&flist
);
382 * bmap_finish() may have committed the last trans and started
383 * a new one. We need the inode to be in all transactions.
386 xfs_trans_ijoin(args
.trans
, dp
, 0);
389 * Commit the leaf transformation. We'll need another (linked)
390 * transaction to add the new attribute to the leaf.
393 error
= xfs_trans_roll(&args
.trans
, dp
);
399 if (xfs_bmap_one_block(dp
, XFS_ATTR_FORK
)) {
400 error
= xfs_attr_leaf_addname(&args
);
402 error
= xfs_attr_node_addname(&args
);
409 * If this is a synchronous mount, make sure that the
410 * transaction goes to disk before returning to the user.
412 if (mp
->m_flags
& XFS_MOUNT_WSYNC
) {
413 xfs_trans_set_sync(args
.trans
);
416 if ((flags
& ATTR_KERNOTIME
) == 0)
417 xfs_trans_ichgtime(args
.trans
, dp
, XFS_ICHGTIME_CHG
);
420 * Commit the last in the sequence of transactions.
422 xfs_trans_log_inode(args
.trans
, dp
, XFS_ILOG_CORE
);
423 error
= xfs_trans_commit(args
.trans
, XFS_TRANS_RELEASE_LOG_RES
);
424 xfs_iunlock(dp
, XFS_ILOCK_EXCL
);
430 xfs_trans_cancel(args
.trans
,
431 XFS_TRANS_RELEASE_LOG_RES
|XFS_TRANS_ABORT
);
432 xfs_iunlock(dp
, XFS_ILOCK_EXCL
);
439 const unsigned char *name
,
440 unsigned char *value
,
445 struct xfs_name xname
;
447 XFS_STATS_INC(xs_attr_set
);
449 if (XFS_FORCED_SHUTDOWN(dp
->i_mount
))
452 error
= xfs_attr_name_to_xname(&xname
, name
);
456 return xfs_attr_set_int(dp
, &xname
, value
, valuelen
, flags
);
460 * Generic handler routine to remove a name from an attribute list.
461 * Transitions attribute list from Btree to shortform as necessary.
464 xfs_attr_remove_int(xfs_inode_t
*dp
, struct xfs_name
*name
, int flags
)
467 xfs_fsblock_t firstblock
;
468 xfs_bmap_free_t flist
;
470 xfs_mount_t
*mp
= dp
->i_mount
;
473 * Fill in the arg structure for this request.
475 memset((char *)&args
, 0, sizeof(args
));
476 args
.name
= name
->name
;
477 args
.namelen
= name
->len
;
479 args
.hashval
= xfs_da_hashname(args
.name
, args
.namelen
);
481 args
.firstblock
= &firstblock
;
484 args
.whichfork
= XFS_ATTR_FORK
;
487 * we have no control over the attribute names that userspace passes us
488 * to remove, so we have to allow the name lookup prior to attribute
491 args
.op_flags
= XFS_DA_OP_OKNOENT
;
494 * Attach the dquots to the inode.
496 error
= xfs_qm_dqattach(dp
, 0);
501 * Start our first transaction of the day.
503 * All future transactions during this code must be "chained" off
504 * this one via the trans_dup() call. All transactions will contain
505 * the inode, and the inode will always be marked with trans_ihold().
506 * Since the inode will be locked in all transactions, we must log
507 * the inode in every transaction to let it float upward through
510 args
.trans
= xfs_trans_alloc(mp
, XFS_TRANS_ATTR_RM
);
513 * Root fork attributes can use reserved data blocks for this
514 * operation if necessary
517 if (flags
& ATTR_ROOT
)
518 args
.trans
->t_flags
|= XFS_TRANS_RESERVE
;
520 if ((error
= xfs_trans_reserve(args
.trans
,
521 XFS_ATTRRM_SPACE_RES(mp
),
522 XFS_ATTRRM_LOG_RES(mp
),
523 0, XFS_TRANS_PERM_LOG_RES
,
524 XFS_ATTRRM_LOG_COUNT
))) {
525 xfs_trans_cancel(args
.trans
, 0);
529 xfs_ilock(dp
, XFS_ILOCK_EXCL
);
531 * No need to make quota reservations here. We expect to release some
532 * blocks not allocate in the common case.
534 xfs_trans_ijoin(args
.trans
, dp
, 0);
537 * Decide on what work routines to call based on the inode size.
539 if (!xfs_inode_hasattr(dp
)) {
540 error
= XFS_ERROR(ENOATTR
);
543 if (dp
->i_d
.di_aformat
== XFS_DINODE_FMT_LOCAL
) {
544 ASSERT(dp
->i_afp
->if_flags
& XFS_IFINLINE
);
545 error
= xfs_attr_shortform_remove(&args
);
549 } else if (xfs_bmap_one_block(dp
, XFS_ATTR_FORK
)) {
550 error
= xfs_attr_leaf_removename(&args
);
552 error
= xfs_attr_node_removename(&args
);
559 * If this is a synchronous mount, make sure that the
560 * transaction goes to disk before returning to the user.
562 if (mp
->m_flags
& XFS_MOUNT_WSYNC
) {
563 xfs_trans_set_sync(args
.trans
);
566 if ((flags
& ATTR_KERNOTIME
) == 0)
567 xfs_trans_ichgtime(args
.trans
, dp
, XFS_ICHGTIME_CHG
);
570 * Commit the last in the sequence of transactions.
572 xfs_trans_log_inode(args
.trans
, dp
, XFS_ILOG_CORE
);
573 error
= xfs_trans_commit(args
.trans
, XFS_TRANS_RELEASE_LOG_RES
);
574 xfs_iunlock(dp
, XFS_ILOCK_EXCL
);
580 xfs_trans_cancel(args
.trans
,
581 XFS_TRANS_RELEASE_LOG_RES
|XFS_TRANS_ABORT
);
582 xfs_iunlock(dp
, XFS_ILOCK_EXCL
);
589 const unsigned char *name
,
593 struct xfs_name xname
;
595 XFS_STATS_INC(xs_attr_remove
);
597 if (XFS_FORCED_SHUTDOWN(dp
->i_mount
))
600 error
= xfs_attr_name_to_xname(&xname
, name
);
604 xfs_ilock(dp
, XFS_ILOCK_SHARED
);
605 if (!xfs_inode_hasattr(dp
)) {
606 xfs_iunlock(dp
, XFS_ILOCK_SHARED
);
607 return XFS_ERROR(ENOATTR
);
609 xfs_iunlock(dp
, XFS_ILOCK_SHARED
);
611 return xfs_attr_remove_int(dp
, &xname
, flags
);
615 xfs_attr_list_int(xfs_attr_list_context_t
*context
)
618 xfs_inode_t
*dp
= context
->dp
;
620 XFS_STATS_INC(xs_attr_list
);
622 if (XFS_FORCED_SHUTDOWN(dp
->i_mount
))
625 xfs_ilock(dp
, XFS_ILOCK_SHARED
);
628 * Decide on what work routines to call based on the inode size.
630 if (!xfs_inode_hasattr(dp
)) {
632 } else if (dp
->i_d
.di_aformat
== XFS_DINODE_FMT_LOCAL
) {
633 error
= xfs_attr_shortform_list(context
);
634 } else if (xfs_bmap_one_block(dp
, XFS_ATTR_FORK
)) {
635 error
= xfs_attr_leaf_list(context
);
637 error
= xfs_attr_node_list(context
);
640 xfs_iunlock(dp
, XFS_ILOCK_SHARED
);
645 #define ATTR_ENTBASESIZE /* minimum bytes used by an attr */ \
646 (((struct attrlist_ent *) 0)->a_name - (char *) 0)
647 #define ATTR_ENTSIZE(namelen) /* actual bytes used by an attr */ \
648 ((ATTR_ENTBASESIZE + (namelen) + 1 + sizeof(u_int32_t)-1) \
649 & ~(sizeof(u_int32_t)-1))
652 * Format an attribute and copy it out to the user's buffer.
653 * Take care to check values and protect against them changing later,
654 * we may be reading them directly out of a user buffer.
658 xfs_attr_put_listent(
659 xfs_attr_list_context_t
*context
,
664 unsigned char *value
)
666 struct attrlist
*alist
= (struct attrlist
*)context
->alist
;
670 ASSERT(!(context
->flags
& ATTR_KERNOVAL
));
671 ASSERT(context
->count
>= 0);
672 ASSERT(context
->count
< (ATTR_MAX_VALUELEN
/8));
673 ASSERT(context
->firstu
>= sizeof(*alist
));
674 ASSERT(context
->firstu
<= context
->bufsize
);
677 * Only list entries in the right namespace.
679 if (((context
->flags
& ATTR_SECURE
) == 0) !=
680 ((flags
& XFS_ATTR_SECURE
) == 0))
682 if (((context
->flags
& ATTR_ROOT
) == 0) !=
683 ((flags
& XFS_ATTR_ROOT
) == 0))
686 arraytop
= sizeof(*alist
) +
687 context
->count
* sizeof(alist
->al_offset
[0]);
688 context
->firstu
-= ATTR_ENTSIZE(namelen
);
689 if (context
->firstu
< arraytop
) {
690 trace_xfs_attr_list_full(context
);
692 context
->seen_enough
= 1;
696 aep
= (attrlist_ent_t
*)&context
->alist
[context
->firstu
];
697 aep
->a_valuelen
= valuelen
;
698 memcpy(aep
->a_name
, name
, namelen
);
699 aep
->a_name
[namelen
] = 0;
700 alist
->al_offset
[context
->count
++] = context
->firstu
;
701 alist
->al_count
= context
->count
;
702 trace_xfs_attr_list_add(context
);
707 * Generate a list of extended attribute names and optionally
708 * also value lengths. Positive return value follows the XFS
709 * convention of being an error, zero or negative return code
710 * is the length of the buffer returned (negated), indicating
719 attrlist_cursor_kern_t
*cursor
)
721 xfs_attr_list_context_t context
;
722 struct attrlist
*alist
;
726 * Validate the cursor.
728 if (cursor
->pad1
|| cursor
->pad2
)
729 return(XFS_ERROR(EINVAL
));
730 if ((cursor
->initted
== 0) &&
731 (cursor
->hashval
|| cursor
->blkno
|| cursor
->offset
))
732 return XFS_ERROR(EINVAL
);
735 * Check for a properly aligned buffer.
737 if (((long)buffer
) & (sizeof(int)-1))
738 return XFS_ERROR(EFAULT
);
739 if (flags
& ATTR_KERNOVAL
)
743 * Initialize the output buffer.
745 memset(&context
, 0, sizeof(context
));
747 context
.cursor
= cursor
;
749 context
.flags
= flags
;
750 context
.alist
= buffer
;
751 context
.bufsize
= (bufsize
& ~(sizeof(int)-1)); /* align */
752 context
.firstu
= context
.bufsize
;
753 context
.put_listent
= xfs_attr_put_listent
;
755 alist
= (struct attrlist
*)context
.alist
;
758 alist
->al_offset
[0] = context
.bufsize
;
760 error
= xfs_attr_list_int(&context
);
766 xfs_attr_inactive(xfs_inode_t
*dp
)
773 ASSERT(! XFS_NOT_DQATTACHED(mp
, dp
));
775 xfs_ilock(dp
, XFS_ILOCK_SHARED
);
776 if (!xfs_inode_hasattr(dp
) ||
777 dp
->i_d
.di_aformat
== XFS_DINODE_FMT_LOCAL
) {
778 xfs_iunlock(dp
, XFS_ILOCK_SHARED
);
781 xfs_iunlock(dp
, XFS_ILOCK_SHARED
);
784 * Start our first transaction of the day.
786 * All future transactions during this code must be "chained" off
787 * this one via the trans_dup() call. All transactions will contain
788 * the inode, and the inode will always be marked with trans_ihold().
789 * Since the inode will be locked in all transactions, we must log
790 * the inode in every transaction to let it float upward through
793 trans
= xfs_trans_alloc(mp
, XFS_TRANS_ATTRINVAL
);
794 if ((error
= xfs_trans_reserve(trans
, 0, XFS_ATTRINVAL_LOG_RES(mp
), 0,
795 XFS_TRANS_PERM_LOG_RES
,
796 XFS_ATTRINVAL_LOG_COUNT
))) {
797 xfs_trans_cancel(trans
, 0);
800 xfs_ilock(dp
, XFS_ILOCK_EXCL
);
803 * No need to make quota reservations here. We expect to release some
804 * blocks, not allocate, in the common case.
806 xfs_trans_ijoin(trans
, dp
, 0);
809 * Decide on what work routines to call based on the inode size.
811 if (!xfs_inode_hasattr(dp
) ||
812 dp
->i_d
.di_aformat
== XFS_DINODE_FMT_LOCAL
) {
816 error
= xfs_attr3_root_inactive(&trans
, dp
);
820 error
= xfs_itruncate_extents(&trans
, dp
, XFS_ATTR_FORK
, 0);
824 error
= xfs_trans_commit(trans
, XFS_TRANS_RELEASE_LOG_RES
);
825 xfs_iunlock(dp
, XFS_ILOCK_EXCL
);
830 xfs_trans_cancel(trans
, XFS_TRANS_RELEASE_LOG_RES
|XFS_TRANS_ABORT
);
831 xfs_iunlock(dp
, XFS_ILOCK_EXCL
);
837 /*========================================================================
838 * External routines when attribute list is inside the inode
839 *========================================================================*/
842 * Add a name to the shortform attribute list structure
843 * This is the external routine.
846 xfs_attr_shortform_addname(xfs_da_args_t
*args
)
848 int newsize
, forkoff
, retval
;
850 trace_xfs_attr_sf_addname(args
);
852 retval
= xfs_attr_shortform_lookup(args
);
853 if ((args
->flags
& ATTR_REPLACE
) && (retval
== ENOATTR
)) {
855 } else if (retval
== EEXIST
) {
856 if (args
->flags
& ATTR_CREATE
)
858 retval
= xfs_attr_shortform_remove(args
);
862 if (args
->namelen
>= XFS_ATTR_SF_ENTSIZE_MAX
||
863 args
->valuelen
>= XFS_ATTR_SF_ENTSIZE_MAX
)
864 return(XFS_ERROR(ENOSPC
));
866 newsize
= XFS_ATTR_SF_TOTSIZE(args
->dp
);
867 newsize
+= XFS_ATTR_SF_ENTSIZE_BYNAME(args
->namelen
, args
->valuelen
);
869 forkoff
= xfs_attr_shortform_bytesfit(args
->dp
, newsize
);
871 return(XFS_ERROR(ENOSPC
));
873 xfs_attr_shortform_add(args
, forkoff
);
878 /*========================================================================
879 * External routines when attribute list is one block
880 *========================================================================*/
883 * Add a name to the leaf attribute list structure
885 * This leaf block cannot have a "remote" value, we only call this routine
886 * if bmap_one_block() says there is only one block (ie: no remote blks).
889 xfs_attr_leaf_addname(xfs_da_args_t
*args
)
893 int retval
, error
, committed
, forkoff
;
895 trace_xfs_attr_leaf_addname(args
);
898 * Read the (only) block in the attribute list in.
902 error
= xfs_attr3_leaf_read(args
->trans
, args
->dp
, args
->blkno
, -1, &bp
);
907 * Look up the given attribute in the leaf block. Figure out if
908 * the given flags produce an error or call for an atomic rename.
910 retval
= xfs_attr3_leaf_lookup_int(bp
, args
);
911 if ((args
->flags
& ATTR_REPLACE
) && (retval
== ENOATTR
)) {
912 xfs_trans_brelse(args
->trans
, bp
);
914 } else if (retval
== EEXIST
) {
915 if (args
->flags
& ATTR_CREATE
) { /* pure create op */
916 xfs_trans_brelse(args
->trans
, bp
);
920 trace_xfs_attr_leaf_replace(args
);
922 args
->op_flags
|= XFS_DA_OP_RENAME
; /* an atomic rename */
923 args
->blkno2
= args
->blkno
; /* set 2nd entry info*/
924 args
->index2
= args
->index
;
925 args
->rmtblkno2
= args
->rmtblkno
;
926 args
->rmtblkcnt2
= args
->rmtblkcnt
;
930 * Add the attribute to the leaf block, transitioning to a Btree
933 retval
= xfs_attr3_leaf_add(bp
, args
);
934 if (retval
== ENOSPC
) {
936 * Promote the attribute list to the Btree format, then
937 * Commit that transaction so that the node_addname() call
938 * can manage its own transactions.
940 xfs_bmap_init(args
->flist
, args
->firstblock
);
941 error
= xfs_attr3_leaf_to_node(args
);
943 error
= xfs_bmap_finish(&args
->trans
, args
->flist
,
949 xfs_bmap_cancel(args
->flist
);
954 * bmap_finish() may have committed the last trans and started
955 * a new one. We need the inode to be in all transactions.
958 xfs_trans_ijoin(args
->trans
, dp
, 0);
961 * Commit the current trans (including the inode) and start
964 error
= xfs_trans_roll(&args
->trans
, dp
);
969 * Fob the whole rest of the problem off on the Btree code.
971 error
= xfs_attr_node_addname(args
);
976 * Commit the transaction that added the attr name so that
977 * later routines can manage their own transactions.
979 error
= xfs_trans_roll(&args
->trans
, dp
);
984 * If there was an out-of-line value, allocate the blocks we
985 * identified for its storage and copy the value. This is done
986 * after we create the attribute so that we don't overflow the
987 * maximum size of a transaction and/or hit a deadlock.
989 if (args
->rmtblkno
> 0) {
990 error
= xfs_attr_rmtval_set(args
);
996 * If this is an atomic rename operation, we must "flip" the
997 * incomplete flags on the "new" and "old" attribute/value pairs
998 * so that one disappears and one appears atomically. Then we
999 * must remove the "old" attribute/value pair.
1001 if (args
->op_flags
& XFS_DA_OP_RENAME
) {
1003 * In a separate transaction, set the incomplete flag on the
1004 * "old" attr and clear the incomplete flag on the "new" attr.
1006 error
= xfs_attr3_leaf_flipflags(args
);
1011 * Dismantle the "old" attribute/value pair by removing
1012 * a "remote" value (if it exists).
1014 args
->index
= args
->index2
;
1015 args
->blkno
= args
->blkno2
;
1016 args
->rmtblkno
= args
->rmtblkno2
;
1017 args
->rmtblkcnt
= args
->rmtblkcnt2
;
1018 if (args
->rmtblkno
) {
1019 error
= xfs_attr_rmtval_remove(args
);
1025 * Read in the block containing the "old" attr, then
1026 * remove the "old" attr from that block (neat, huh!)
1028 error
= xfs_attr3_leaf_read(args
->trans
, args
->dp
, args
->blkno
,
1033 xfs_attr3_leaf_remove(bp
, args
);
1036 * If the result is small enough, shrink it all into the inode.
1038 if ((forkoff
= xfs_attr_shortform_allfit(bp
, dp
))) {
1039 xfs_bmap_init(args
->flist
, args
->firstblock
);
1040 error
= xfs_attr3_leaf_to_shortform(bp
, args
, forkoff
);
1041 /* bp is gone due to xfs_da_shrink_inode */
1043 error
= xfs_bmap_finish(&args
->trans
,
1050 xfs_bmap_cancel(args
->flist
);
1055 * bmap_finish() may have committed the last trans
1056 * and started a new one. We need the inode to be
1057 * in all transactions.
1060 xfs_trans_ijoin(args
->trans
, dp
, 0);
1064 * Commit the remove and start the next trans in series.
1066 error
= xfs_trans_roll(&args
->trans
, dp
);
1068 } else if (args
->rmtblkno
> 0) {
1070 * Added a "remote" value, just clear the incomplete flag.
1072 error
= xfs_attr3_leaf_clearflag(args
);
1078 * Remove a name from the leaf attribute list structure
1080 * This leaf block cannot have a "remote" value, we only call this routine
1081 * if bmap_one_block() says there is only one block (ie: no remote blks).
1084 xfs_attr_leaf_removename(xfs_da_args_t
*args
)
1088 int error
, committed
, forkoff
;
1090 trace_xfs_attr_leaf_removename(args
);
1093 * Remove the attribute.
1097 error
= xfs_attr3_leaf_read(args
->trans
, args
->dp
, args
->blkno
, -1, &bp
);
1101 error
= xfs_attr3_leaf_lookup_int(bp
, args
);
1102 if (error
== ENOATTR
) {
1103 xfs_trans_brelse(args
->trans
, bp
);
1107 xfs_attr3_leaf_remove(bp
, args
);
1110 * If the result is small enough, shrink it all into the inode.
1112 if ((forkoff
= xfs_attr_shortform_allfit(bp
, dp
))) {
1113 xfs_bmap_init(args
->flist
, args
->firstblock
);
1114 error
= xfs_attr3_leaf_to_shortform(bp
, args
, forkoff
);
1115 /* bp is gone due to xfs_da_shrink_inode */
1117 error
= xfs_bmap_finish(&args
->trans
, args
->flist
,
1123 xfs_bmap_cancel(args
->flist
);
1128 * bmap_finish() may have committed the last trans and started
1129 * a new one. We need the inode to be in all transactions.
1132 xfs_trans_ijoin(args
->trans
, dp
, 0);
1138 * Look up a name in a leaf attribute list structure.
1140 * This leaf block cannot have a "remote" value, we only call this routine
1141 * if bmap_one_block() says there is only one block (ie: no remote blks).
1144 xfs_attr_leaf_get(xfs_da_args_t
*args
)
1149 trace_xfs_attr_leaf_get(args
);
1152 error
= xfs_attr3_leaf_read(args
->trans
, args
->dp
, args
->blkno
, -1, &bp
);
1156 error
= xfs_attr3_leaf_lookup_int(bp
, args
);
1157 if (error
!= EEXIST
) {
1158 xfs_trans_brelse(args
->trans
, bp
);
1161 error
= xfs_attr3_leaf_getvalue(bp
, args
);
1162 xfs_trans_brelse(args
->trans
, bp
);
1163 if (!error
&& (args
->rmtblkno
> 0) && !(args
->flags
& ATTR_KERNOVAL
)) {
1164 error
= xfs_attr_rmtval_get(args
);
1170 * Copy out attribute entries for attr_list(), for leaf attribute lists.
1173 xfs_attr_leaf_list(xfs_attr_list_context_t
*context
)
1178 trace_xfs_attr_leaf_list(context
);
1180 context
->cursor
->blkno
= 0;
1181 error
= xfs_attr3_leaf_read(NULL
, context
->dp
, 0, -1, &bp
);
1183 return XFS_ERROR(error
);
1185 error
= xfs_attr3_leaf_list_int(bp
, context
);
1186 xfs_trans_brelse(NULL
, bp
);
1187 return XFS_ERROR(error
);
1191 /*========================================================================
1192 * External routines when attribute list size > XFS_LBSIZE(mp).
1193 *========================================================================*/
1196 * Add a name to a Btree-format attribute list.
1198 * This will involve walking down the Btree, and may involve splitting
1199 * leaf nodes and even splitting intermediate nodes up to and including
1200 * the root node (a special case of an intermediate node).
1202 * "Remote" attribute values confuse the issue and atomic rename operations
1203 * add a whole extra layer of confusion on top of that.
1206 xfs_attr_node_addname(xfs_da_args_t
*args
)
1208 xfs_da_state_t
*state
;
1209 xfs_da_state_blk_t
*blk
;
1212 int committed
, retval
, error
;
1214 trace_xfs_attr_node_addname(args
);
1217 * Fill in bucket of arguments/results/context to carry around.
1222 state
= xfs_da_state_alloc();
1225 state
->blocksize
= state
->mp
->m_sb
.sb_blocksize
;
1226 state
->node_ents
= state
->mp
->m_attr_node_ents
;
1229 * Search to see if name already exists, and get back a pointer
1230 * to where it should go.
1232 error
= xfs_da3_node_lookup_int(state
, &retval
);
1235 blk
= &state
->path
.blk
[ state
->path
.active
-1 ];
1236 ASSERT(blk
->magic
== XFS_ATTR_LEAF_MAGIC
);
1237 if ((args
->flags
& ATTR_REPLACE
) && (retval
== ENOATTR
)) {
1239 } else if (retval
== EEXIST
) {
1240 if (args
->flags
& ATTR_CREATE
)
1243 trace_xfs_attr_node_replace(args
);
1245 args
->op_flags
|= XFS_DA_OP_RENAME
; /* atomic rename op */
1246 args
->blkno2
= args
->blkno
; /* set 2nd entry info*/
1247 args
->index2
= args
->index
;
1248 args
->rmtblkno2
= args
->rmtblkno
;
1249 args
->rmtblkcnt2
= args
->rmtblkcnt
;
1251 args
->rmtblkcnt
= 0;
1254 retval
= xfs_attr3_leaf_add(blk
->bp
, state
->args
);
1255 if (retval
== ENOSPC
) {
1256 if (state
->path
.active
== 1) {
1258 * Its really a single leaf node, but it had
1259 * out-of-line values so it looked like it *might*
1260 * have been a b-tree.
1262 xfs_da_state_free(state
);
1263 xfs_bmap_init(args
->flist
, args
->firstblock
);
1264 error
= xfs_attr3_leaf_to_node(args
);
1266 error
= xfs_bmap_finish(&args
->trans
,
1273 xfs_bmap_cancel(args
->flist
);
1278 * bmap_finish() may have committed the last trans
1279 * and started a new one. We need the inode to be
1280 * in all transactions.
1283 xfs_trans_ijoin(args
->trans
, dp
, 0);
1286 * Commit the node conversion and start the next
1287 * trans in the chain.
1289 error
= xfs_trans_roll(&args
->trans
, dp
);
1297 * Split as many Btree elements as required.
1298 * This code tracks the new and old attr's location
1299 * in the index/blkno/rmtblkno/rmtblkcnt fields and
1300 * in the index2/blkno2/rmtblkno2/rmtblkcnt2 fields.
1302 xfs_bmap_init(args
->flist
, args
->firstblock
);
1303 error
= xfs_da3_split(state
);
1305 error
= xfs_bmap_finish(&args
->trans
, args
->flist
,
1311 xfs_bmap_cancel(args
->flist
);
1316 * bmap_finish() may have committed the last trans and started
1317 * a new one. We need the inode to be in all transactions.
1320 xfs_trans_ijoin(args
->trans
, dp
, 0);
1323 * Addition succeeded, update Btree hashvals.
1325 xfs_da3_fixhashpath(state
, &state
->path
);
1329 * Kill the state structure, we're done with it and need to
1330 * allow the buffers to come back later.
1332 xfs_da_state_free(state
);
1336 * Commit the leaf addition or btree split and start the next
1337 * trans in the chain.
1339 error
= xfs_trans_roll(&args
->trans
, dp
);
1344 * If there was an out-of-line value, allocate the blocks we
1345 * identified for its storage and copy the value. This is done
1346 * after we create the attribute so that we don't overflow the
1347 * maximum size of a transaction and/or hit a deadlock.
1349 if (args
->rmtblkno
> 0) {
1350 error
= xfs_attr_rmtval_set(args
);
1356 * If this is an atomic rename operation, we must "flip" the
1357 * incomplete flags on the "new" and "old" attribute/value pairs
1358 * so that one disappears and one appears atomically. Then we
1359 * must remove the "old" attribute/value pair.
1361 if (args
->op_flags
& XFS_DA_OP_RENAME
) {
1363 * In a separate transaction, set the incomplete flag on the
1364 * "old" attr and clear the incomplete flag on the "new" attr.
1366 error
= xfs_attr3_leaf_flipflags(args
);
1371 * Dismantle the "old" attribute/value pair by removing
1372 * a "remote" value (if it exists).
1374 args
->index
= args
->index2
;
1375 args
->blkno
= args
->blkno2
;
1376 args
->rmtblkno
= args
->rmtblkno2
;
1377 args
->rmtblkcnt
= args
->rmtblkcnt2
;
1378 if (args
->rmtblkno
) {
1379 error
= xfs_attr_rmtval_remove(args
);
1385 * Re-find the "old" attribute entry after any split ops.
1386 * The INCOMPLETE flag means that we will find the "old"
1387 * attr, not the "new" one.
1389 args
->flags
|= XFS_ATTR_INCOMPLETE
;
1390 state
= xfs_da_state_alloc();
1393 state
->blocksize
= state
->mp
->m_sb
.sb_blocksize
;
1394 state
->node_ents
= state
->mp
->m_attr_node_ents
;
1396 error
= xfs_da3_node_lookup_int(state
, &retval
);
1401 * Remove the name and update the hashvals in the tree.
1403 blk
= &state
->path
.blk
[ state
->path
.active
-1 ];
1404 ASSERT(blk
->magic
== XFS_ATTR_LEAF_MAGIC
);
1405 error
= xfs_attr3_leaf_remove(blk
->bp
, args
);
1406 xfs_da3_fixhashpath(state
, &state
->path
);
1409 * Check to see if the tree needs to be collapsed.
1411 if (retval
&& (state
->path
.active
> 1)) {
1412 xfs_bmap_init(args
->flist
, args
->firstblock
);
1413 error
= xfs_da3_join(state
);
1415 error
= xfs_bmap_finish(&args
->trans
,
1422 xfs_bmap_cancel(args
->flist
);
1427 * bmap_finish() may have committed the last trans
1428 * and started a new one. We need the inode to be
1429 * in all transactions.
1432 xfs_trans_ijoin(args
->trans
, dp
, 0);
1436 * Commit and start the next trans in the chain.
1438 error
= xfs_trans_roll(&args
->trans
, dp
);
1442 } else if (args
->rmtblkno
> 0) {
1444 * Added a "remote" value, just clear the incomplete flag.
1446 error
= xfs_attr3_leaf_clearflag(args
);
1454 xfs_da_state_free(state
);
1461 * Remove a name from a B-tree attribute list.
1463 * This will involve walking down the Btree, and may involve joining
1464 * leaf nodes and even joining intermediate nodes up to and including
1465 * the root node (a special case of an intermediate node).
1468 xfs_attr_node_removename(xfs_da_args_t
*args
)
1470 xfs_da_state_t
*state
;
1471 xfs_da_state_blk_t
*blk
;
1474 int retval
, error
, committed
, forkoff
;
1476 trace_xfs_attr_node_removename(args
);
1479 * Tie a string around our finger to remind us where we are.
1482 state
= xfs_da_state_alloc();
1484 state
->mp
= dp
->i_mount
;
1485 state
->blocksize
= state
->mp
->m_sb
.sb_blocksize
;
1486 state
->node_ents
= state
->mp
->m_attr_node_ents
;
1489 * Search to see if name exists, and get back a pointer to it.
1491 error
= xfs_da3_node_lookup_int(state
, &retval
);
1492 if (error
|| (retval
!= EEXIST
)) {
1499 * If there is an out-of-line value, de-allocate the blocks.
1500 * This is done before we remove the attribute so that we don't
1501 * overflow the maximum size of a transaction and/or hit a deadlock.
1503 blk
= &state
->path
.blk
[ state
->path
.active
-1 ];
1504 ASSERT(blk
->bp
!= NULL
);
1505 ASSERT(blk
->magic
== XFS_ATTR_LEAF_MAGIC
);
1506 if (args
->rmtblkno
> 0) {
1508 * Fill in disk block numbers in the state structure
1509 * so that we can get the buffers back after we commit
1510 * several transactions in the following calls.
1512 error
= xfs_attr_fillstate(state
);
1517 * Mark the attribute as INCOMPLETE, then bunmapi() the
1520 error
= xfs_attr3_leaf_setflag(args
);
1523 error
= xfs_attr_rmtval_remove(args
);
1528 * Refill the state structure with buffers, the prior calls
1529 * released our buffers.
1531 error
= xfs_attr_refillstate(state
);
1537 * Remove the name and update the hashvals in the tree.
1539 blk
= &state
->path
.blk
[ state
->path
.active
-1 ];
1540 ASSERT(blk
->magic
== XFS_ATTR_LEAF_MAGIC
);
1541 retval
= xfs_attr3_leaf_remove(blk
->bp
, args
);
1542 xfs_da3_fixhashpath(state
, &state
->path
);
1545 * Check to see if the tree needs to be collapsed.
1547 if (retval
&& (state
->path
.active
> 1)) {
1548 xfs_bmap_init(args
->flist
, args
->firstblock
);
1549 error
= xfs_da3_join(state
);
1551 error
= xfs_bmap_finish(&args
->trans
, args
->flist
,
1557 xfs_bmap_cancel(args
->flist
);
1562 * bmap_finish() may have committed the last trans and started
1563 * a new one. We need the inode to be in all transactions.
1566 xfs_trans_ijoin(args
->trans
, dp
, 0);
1569 * Commit the Btree join operation and start a new trans.
1571 error
= xfs_trans_roll(&args
->trans
, dp
);
1577 * If the result is small enough, push it all into the inode.
1579 if (xfs_bmap_one_block(dp
, XFS_ATTR_FORK
)) {
1581 * Have to get rid of the copy of this dabuf in the state.
1583 ASSERT(state
->path
.active
== 1);
1584 ASSERT(state
->path
.blk
[0].bp
);
1585 state
->path
.blk
[0].bp
= NULL
;
1587 error
= xfs_attr3_leaf_read(args
->trans
, args
->dp
, 0, -1, &bp
);
1591 if ((forkoff
= xfs_attr_shortform_allfit(bp
, dp
))) {
1592 xfs_bmap_init(args
->flist
, args
->firstblock
);
1593 error
= xfs_attr3_leaf_to_shortform(bp
, args
, forkoff
);
1594 /* bp is gone due to xfs_da_shrink_inode */
1596 error
= xfs_bmap_finish(&args
->trans
,
1603 xfs_bmap_cancel(args
->flist
);
1608 * bmap_finish() may have committed the last trans
1609 * and started a new one. We need the inode to be
1610 * in all transactions.
1613 xfs_trans_ijoin(args
->trans
, dp
, 0);
1615 xfs_trans_brelse(args
->trans
, bp
);
1620 xfs_da_state_free(state
);
1625 * Fill in the disk block numbers in the state structure for the buffers
1626 * that are attached to the state structure.
1627 * This is done so that we can quickly reattach ourselves to those buffers
1628 * after some set of transaction commits have released these buffers.
1631 xfs_attr_fillstate(xfs_da_state_t
*state
)
1633 xfs_da_state_path_t
*path
;
1634 xfs_da_state_blk_t
*blk
;
1637 trace_xfs_attr_fillstate(state
->args
);
1640 * Roll down the "path" in the state structure, storing the on-disk
1641 * block number for those buffers in the "path".
1643 path
= &state
->path
;
1644 ASSERT((path
->active
>= 0) && (path
->active
< XFS_DA_NODE_MAXDEPTH
));
1645 for (blk
= path
->blk
, level
= 0; level
< path
->active
; blk
++, level
++) {
1647 blk
->disk_blkno
= XFS_BUF_ADDR(blk
->bp
);
1650 blk
->disk_blkno
= 0;
1655 * Roll down the "altpath" in the state structure, storing the on-disk
1656 * block number for those buffers in the "altpath".
1658 path
= &state
->altpath
;
1659 ASSERT((path
->active
>= 0) && (path
->active
< XFS_DA_NODE_MAXDEPTH
));
1660 for (blk
= path
->blk
, level
= 0; level
< path
->active
; blk
++, level
++) {
1662 blk
->disk_blkno
= XFS_BUF_ADDR(blk
->bp
);
1665 blk
->disk_blkno
= 0;
1673 * Reattach the buffers to the state structure based on the disk block
1674 * numbers stored in the state structure.
1675 * This is done after some set of transaction commits have released those
1676 * buffers from our grip.
1679 xfs_attr_refillstate(xfs_da_state_t
*state
)
1681 xfs_da_state_path_t
*path
;
1682 xfs_da_state_blk_t
*blk
;
1685 trace_xfs_attr_refillstate(state
->args
);
1688 * Roll down the "path" in the state structure, storing the on-disk
1689 * block number for those buffers in the "path".
1691 path
= &state
->path
;
1692 ASSERT((path
->active
>= 0) && (path
->active
< XFS_DA_NODE_MAXDEPTH
));
1693 for (blk
= path
->blk
, level
= 0; level
< path
->active
; blk
++, level
++) {
1694 if (blk
->disk_blkno
) {
1695 error
= xfs_da3_node_read(state
->args
->trans
,
1697 blk
->blkno
, blk
->disk_blkno
,
1698 &blk
->bp
, XFS_ATTR_FORK
);
1707 * Roll down the "altpath" in the state structure, storing the on-disk
1708 * block number for those buffers in the "altpath".
1710 path
= &state
->altpath
;
1711 ASSERT((path
->active
>= 0) && (path
->active
< XFS_DA_NODE_MAXDEPTH
));
1712 for (blk
= path
->blk
, level
= 0; level
< path
->active
; blk
++, level
++) {
1713 if (blk
->disk_blkno
) {
1714 error
= xfs_da3_node_read(state
->args
->trans
,
1716 blk
->blkno
, blk
->disk_blkno
,
1717 &blk
->bp
, XFS_ATTR_FORK
);
1729 * Look up a filename in a node attribute list.
1731 * This routine gets called for any attribute fork that has more than one
1732 * block, ie: both true Btree attr lists and for single-leaf-blocks with
1733 * "remote" values taking up more blocks.
1736 xfs_attr_node_get(xfs_da_args_t
*args
)
1738 xfs_da_state_t
*state
;
1739 xfs_da_state_blk_t
*blk
;
1743 trace_xfs_attr_node_get(args
);
1745 state
= xfs_da_state_alloc();
1747 state
->mp
= args
->dp
->i_mount
;
1748 state
->blocksize
= state
->mp
->m_sb
.sb_blocksize
;
1749 state
->node_ents
= state
->mp
->m_attr_node_ents
;
1752 * Search to see if name exists, and get back a pointer to it.
1754 error
= xfs_da3_node_lookup_int(state
, &retval
);
1757 } else if (retval
== EEXIST
) {
1758 blk
= &state
->path
.blk
[ state
->path
.active
-1 ];
1759 ASSERT(blk
->bp
!= NULL
);
1760 ASSERT(blk
->magic
== XFS_ATTR_LEAF_MAGIC
);
1763 * Get the value, local or "remote"
1765 retval
= xfs_attr3_leaf_getvalue(blk
->bp
, args
);
1766 if (!retval
&& (args
->rmtblkno
> 0)
1767 && !(args
->flags
& ATTR_KERNOVAL
)) {
1768 retval
= xfs_attr_rmtval_get(args
);
1773 * If not in a transaction, we have to release all the buffers.
1775 for (i
= 0; i
< state
->path
.active
; i
++) {
1776 xfs_trans_brelse(args
->trans
, state
->path
.blk
[i
].bp
);
1777 state
->path
.blk
[i
].bp
= NULL
;
1780 xfs_da_state_free(state
);
1784 STATIC
int /* error */
1785 xfs_attr_node_list(xfs_attr_list_context_t
*context
)
1787 attrlist_cursor_kern_t
*cursor
;
1788 xfs_attr_leafblock_t
*leaf
;
1789 xfs_da_intnode_t
*node
;
1790 struct xfs_attr3_icleaf_hdr leafhdr
;
1791 struct xfs_da3_icnode_hdr nodehdr
;
1792 struct xfs_da_node_entry
*btree
;
1796 trace_xfs_attr_node_list(context
);
1798 cursor
= context
->cursor
;
1799 cursor
->initted
= 1;
1802 * Do all sorts of validation on the passed-in cursor structure.
1803 * If anything is amiss, ignore the cursor and look up the hashval
1804 * starting from the btree root.
1807 if (cursor
->blkno
> 0) {
1808 error
= xfs_da3_node_read(NULL
, context
->dp
, cursor
->blkno
, -1,
1809 &bp
, XFS_ATTR_FORK
);
1810 if ((error
!= 0) && (error
!= EFSCORRUPTED
))
1813 struct xfs_attr_leaf_entry
*entries
;
1816 switch (be16_to_cpu(node
->hdr
.info
.magic
)) {
1817 case XFS_DA_NODE_MAGIC
:
1818 case XFS_DA3_NODE_MAGIC
:
1819 trace_xfs_attr_list_wrong_blk(context
);
1820 xfs_trans_brelse(NULL
, bp
);
1823 case XFS_ATTR_LEAF_MAGIC
:
1824 case XFS_ATTR3_LEAF_MAGIC
:
1826 xfs_attr3_leaf_hdr_from_disk(&leafhdr
, leaf
);
1827 entries
= xfs_attr3_leaf_entryp(leaf
);
1828 if (cursor
->hashval
> be32_to_cpu(
1829 entries
[leafhdr
.count
- 1].hashval
)) {
1830 trace_xfs_attr_list_wrong_blk(context
);
1831 xfs_trans_brelse(NULL
, bp
);
1833 } else if (cursor
->hashval
<= be32_to_cpu(
1834 entries
[0].hashval
)) {
1835 trace_xfs_attr_list_wrong_blk(context
);
1836 xfs_trans_brelse(NULL
, bp
);
1841 trace_xfs_attr_list_wrong_blk(context
);
1842 xfs_trans_brelse(NULL
, bp
);
1849 * We did not find what we expected given the cursor's contents,
1850 * so we start from the top and work down based on the hash value.
1851 * Note that start of node block is same as start of leaf block.
1858 error
= xfs_da3_node_read(NULL
, context
->dp
,
1859 cursor
->blkno
, -1, &bp
,
1864 magic
= be16_to_cpu(node
->hdr
.info
.magic
);
1865 if (magic
== XFS_ATTR_LEAF_MAGIC
||
1866 magic
== XFS_ATTR3_LEAF_MAGIC
)
1868 if (magic
!= XFS_DA_NODE_MAGIC
&&
1869 magic
!= XFS_DA3_NODE_MAGIC
) {
1870 XFS_CORRUPTION_ERROR("xfs_attr_node_list(3)",
1872 context
->dp
->i_mount
,
1874 xfs_trans_brelse(NULL
, bp
);
1875 return XFS_ERROR(EFSCORRUPTED
);
1878 xfs_da3_node_hdr_from_disk(&nodehdr
, node
);
1879 btree
= xfs_da3_node_tree_p(node
);
1880 for (i
= 0; i
< nodehdr
.count
; btree
++, i
++) {
1882 <= be32_to_cpu(btree
->hashval
)) {
1883 cursor
->blkno
= be32_to_cpu(btree
->before
);
1884 trace_xfs_attr_list_node_descend(context
,
1889 if (i
== nodehdr
.count
) {
1890 xfs_trans_brelse(NULL
, bp
);
1893 xfs_trans_brelse(NULL
, bp
);
1899 * Roll upward through the blocks, processing each leaf block in
1900 * order. As long as there is space in the result buffer, keep
1901 * adding the information.
1905 error
= xfs_attr3_leaf_list_int(bp
, context
);
1907 xfs_trans_brelse(NULL
, bp
);
1910 xfs_attr3_leaf_hdr_from_disk(&leafhdr
, leaf
);
1911 if (context
->seen_enough
|| leafhdr
.forw
== 0)
1913 cursor
->blkno
= leafhdr
.forw
;
1914 xfs_trans_brelse(NULL
, bp
);
1915 error
= xfs_attr3_leaf_read(NULL
, context
->dp
, cursor
->blkno
, -1,
1920 xfs_trans_brelse(NULL
, bp
);