2 * Copyright (c) 2005 Silicon Graphics, Inc. All Rights Reserved.
4 * This program is free software; you can redistribute it and/or modify it
5 * under the terms of version 2 of the GNU General Public License as
6 * published by the Free Software Foundation.
8 * This program is distributed in the hope that it would be useful, but
9 * WITHOUT ANY WARRANTY; without even the implied warranty of
10 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
12 * Further, this software is distributed without any warranty that it is
13 * free of the rightful claim of any third person regarding infringement
14 * or the like. Any license provided herein, whether implied or
15 * otherwise, applies only to this software file. Patent licenses, if
16 * any, provided herein do not apply to combinations of this program with
17 * other software, or any other product whatsoever.
19 * You should have received a copy of the GNU General Public License along
20 * with this program; if not, write the Free Software Foundation, Inc., 59
21 * Temple Place - Suite 330, Boston MA 02111-1307, USA.
23 * Contact information: Silicon Graphics, Inc., 1600 Amphitheatre Pkwy,
24 * Mountain View, CA 94043, or:
28 * For further information regarding this notice, see:
30 * http://oss.sgi.com/projects/GenInfo/SGIGPLNoticeExplan/
38 * Provide the external interfaces to manage attribute lists.
41 /*========================================================================
42 * Function prototypes for the kernel.
43 *========================================================================*/
46 * Internal routines when attribute list fits inside the inode.
48 STATIC
int xfs_attr_shortform_addname(xfs_da_args_t
*args
);
51 * Internal routines when attribute list is one block.
53 STATIC
int xfs_attr_leaf_get(xfs_da_args_t
*args
);
54 STATIC
int xfs_attr_leaf_addname(xfs_da_args_t
*args
);
55 STATIC
int xfs_attr_leaf_removename(xfs_da_args_t
*args
);
56 STATIC
int xfs_attr_leaf_list(xfs_attr_list_context_t
*context
);
59 * Internal routines when attribute list is more than one block.
61 STATIC
int xfs_attr_node_get(xfs_da_args_t
*args
);
62 STATIC
int xfs_attr_node_addname(xfs_da_args_t
*args
);
63 STATIC
int xfs_attr_node_removename(xfs_da_args_t
*args
);
64 STATIC
int xfs_attr_node_list(xfs_attr_list_context_t
*context
);
65 STATIC
int xfs_attr_fillstate(xfs_da_state_t
*state
);
66 STATIC
int xfs_attr_refillstate(xfs_da_state_t
*state
);
69 * Routines to manipulate out-of-line attribute values.
71 STATIC
int xfs_attr_rmtval_get(xfs_da_args_t
*args
);
72 STATIC
int xfs_attr_rmtval_set(xfs_da_args_t
*args
);
73 STATIC
int xfs_attr_rmtval_remove(xfs_da_args_t
*args
);
75 #define ATTR_RMTVALUE_MAPSIZE 1 /* # of map entries at once */
77 /*========================================================================
78 * Overall external interface routines.
79 *========================================================================*/
82 xfs_attr_set_int(xfs_inode_t
*dp
, char *name
, int namelen
,
83 char *value
, int valuelen
, int flags
)
86 xfs_fsblock_t firstblock
;
87 xfs_bmap_free_t flist
;
88 int error
, err2
, committed
;
91 xfs_mount_t
*mp
= dp
->i_mount
;
92 int rsvd
= (flags
& ATTR_ROOT
) != 0;
95 * Attach the dquots to the inode.
97 if ((error
= XFS_QM_DQATTACH(mp
, dp
, 0)))
101 * Determine space new attribute will use, and if it would be
102 * "local" or "remote" (note: local != inline).
104 size
= xfs_attr_leaf_newentsize(namelen
, valuelen
,
105 mp
->m_sb
.sb_blocksize
, &local
);
108 * If the inode doesn't have an attribute fork, add one.
109 * (inode must not be locked when we call this routine)
111 if (XFS_IFORK_Q(dp
) == 0) {
112 if ((error
= xfs_bmap_add_attrfork(dp
, size
, rsvd
)))
117 * Fill in the arg structure for this request.
119 memset((char *)&args
, 0, sizeof(args
));
121 args
.namelen
= namelen
;
123 args
.valuelen
= valuelen
;
125 args
.hashval
= xfs_da_hashname(args
.name
, args
.namelen
);
127 args
.firstblock
= &firstblock
;
129 args
.whichfork
= XFS_ATTR_FORK
;
133 nblks
= XFS_DAENTER_SPACE_RES(mp
, XFS_ATTR_FORK
);
135 if (size
> (mp
->m_sb
.sb_blocksize
>> 1)) {
136 /* Double split possible */
140 uint dblocks
= XFS_B_TO_FSB(mp
, valuelen
);
141 /* Out of line attribute, cannot double split, but make
142 * room for the attribute value itself.
145 nblks
+= XFS_NEXTENTADD_SPACE_RES(mp
, dblocks
, XFS_ATTR_FORK
);
148 /* Size is now blocks for attribute data */
152 * Start our first transaction of the day.
154 * All future transactions during this code must be "chained" off
155 * this one via the trans_dup() call. All transactions will contain
156 * the inode, and the inode will always be marked with trans_ihold().
157 * Since the inode will be locked in all transactions, we must log
158 * the inode in every transaction to let it float upward through
161 args
.trans
= xfs_trans_alloc(mp
, XFS_TRANS_ATTR_SET
);
164 * Root fork attributes can use reserved data blocks for this
165 * operation if necessary
169 args
.trans
->t_flags
|= XFS_TRANS_RESERVE
;
171 if ((error
= xfs_trans_reserve(args
.trans
, (uint
) nblks
,
172 XFS_ATTRSET_LOG_RES(mp
, nblks
),
173 0, XFS_TRANS_PERM_LOG_RES
,
174 XFS_ATTRSET_LOG_COUNT
))) {
175 xfs_trans_cancel(args
.trans
, 0);
178 xfs_ilock(dp
, XFS_ILOCK_EXCL
);
180 error
= XFS_TRANS_RESERVE_QUOTA_NBLKS(mp
, args
.trans
, dp
, nblks
, 0,
181 rsvd
? XFS_QMOPT_RES_REGBLKS
| XFS_QMOPT_FORCE_RES
:
182 XFS_QMOPT_RES_REGBLKS
);
184 xfs_iunlock(dp
, XFS_ILOCK_EXCL
);
185 xfs_trans_cancel(args
.trans
, XFS_TRANS_RELEASE_LOG_RES
);
189 xfs_trans_ijoin(args
.trans
, dp
, XFS_ILOCK_EXCL
);
190 xfs_trans_ihold(args
.trans
, dp
);
193 * If the attribute list is non-existant or a shortform list,
194 * upgrade it to a single-leaf-block attribute list.
196 if ((dp
->i_d
.di_aformat
== XFS_DINODE_FMT_LOCAL
) ||
197 ((dp
->i_d
.di_aformat
== XFS_DINODE_FMT_EXTENTS
) &&
198 (dp
->i_d
.di_anextents
== 0))) {
201 * Build initial attribute list (if required).
203 if (dp
->i_d
.di_aformat
== XFS_DINODE_FMT_EXTENTS
)
204 xfs_attr_shortform_create(&args
);
207 * Try to add the attr to the attribute list in
210 error
= xfs_attr_shortform_addname(&args
);
211 if (error
!= ENOSPC
) {
213 * Commit the shortform mods, and we're done.
214 * NOTE: this is also the error path (EEXIST, etc).
216 ASSERT(args
.trans
!= NULL
);
219 * If this is a synchronous mount, make sure that
220 * the transaction goes to disk before returning
223 if (mp
->m_flags
& XFS_MOUNT_WSYNC
) {
224 xfs_trans_set_sync(args
.trans
);
226 err2
= xfs_trans_commit(args
.trans
,
227 XFS_TRANS_RELEASE_LOG_RES
,
229 xfs_iunlock(dp
, XFS_ILOCK_EXCL
);
232 * Hit the inode change time.
234 if (!error
&& (flags
& ATTR_KERNOTIME
) == 0) {
235 xfs_ichgtime(dp
, XFS_ICHGTIME_CHG
);
237 return(error
== 0 ? err2
: error
);
241 * It won't fit in the shortform, transform to a leaf block.
242 * GROT: another possible req'mt for a double-split btree op.
244 XFS_BMAP_INIT(args
.flist
, args
.firstblock
);
245 error
= xfs_attr_shortform_to_leaf(&args
);
247 error
= xfs_bmap_finish(&args
.trans
, args
.flist
,
248 *args
.firstblock
, &committed
);
253 xfs_bmap_cancel(&flist
);
258 * bmap_finish() may have committed the last trans and started
259 * a new one. We need the inode to be in all transactions.
262 xfs_trans_ijoin(args
.trans
, dp
, XFS_ILOCK_EXCL
);
263 xfs_trans_ihold(args
.trans
, dp
);
267 * Commit the leaf transformation. We'll need another (linked)
268 * transaction to add the new attribute to the leaf.
270 if ((error
= xfs_attr_rolltrans(&args
.trans
, dp
)))
275 if (xfs_bmap_one_block(dp
, XFS_ATTR_FORK
)) {
276 error
= xfs_attr_leaf_addname(&args
);
278 error
= xfs_attr_node_addname(&args
);
285 * If this is a synchronous mount, make sure that the
286 * transaction goes to disk before returning to the user.
288 if (mp
->m_flags
& XFS_MOUNT_WSYNC
) {
289 xfs_trans_set_sync(args
.trans
);
293 * Commit the last in the sequence of transactions.
295 xfs_trans_log_inode(args
.trans
, dp
, XFS_ILOG_CORE
);
296 error
= xfs_trans_commit(args
.trans
, XFS_TRANS_RELEASE_LOG_RES
,
298 xfs_iunlock(dp
, XFS_ILOCK_EXCL
);
301 * Hit the inode change time.
303 if (!error
&& (flags
& ATTR_KERNOTIME
) == 0) {
304 xfs_ichgtime(dp
, XFS_ICHGTIME_CHG
);
311 xfs_trans_cancel(args
.trans
,
312 XFS_TRANS_RELEASE_LOG_RES
|XFS_TRANS_ABORT
);
313 xfs_iunlock(dp
, XFS_ILOCK_EXCL
);
318 xfs_attr_remove_int(xfs_inode_t
*dp
, char *name
, int namelen
, int flags
)
321 xfs_fsblock_t firstblock
;
322 xfs_bmap_free_t flist
;
324 xfs_mount_t
*mp
= dp
->i_mount
;
327 * Fill in the arg structure for this request.
329 memset((char *)&args
, 0, sizeof(args
));
331 args
.namelen
= namelen
;
333 args
.hashval
= xfs_da_hashname(args
.name
, args
.namelen
);
335 args
.firstblock
= &firstblock
;
338 args
.whichfork
= XFS_ATTR_FORK
;
341 * Attach the dquots to the inode.
343 if ((error
= XFS_QM_DQATTACH(mp
, dp
, 0)))
347 * Start our first transaction of the day.
349 * All future transactions during this code must be "chained" off
350 * this one via the trans_dup() call. All transactions will contain
351 * the inode, and the inode will always be marked with trans_ihold().
352 * Since the inode will be locked in all transactions, we must log
353 * the inode in every transaction to let it float upward through
356 args
.trans
= xfs_trans_alloc(mp
, XFS_TRANS_ATTR_RM
);
359 * Root fork attributes can use reserved data blocks for this
360 * operation if necessary
363 if (flags
& ATTR_ROOT
)
364 args
.trans
->t_flags
|= XFS_TRANS_RESERVE
;
366 if ((error
= xfs_trans_reserve(args
.trans
,
367 XFS_ATTRRM_SPACE_RES(mp
),
368 XFS_ATTRRM_LOG_RES(mp
),
369 0, XFS_TRANS_PERM_LOG_RES
,
370 XFS_ATTRRM_LOG_COUNT
))) {
371 xfs_trans_cancel(args
.trans
, 0);
375 xfs_ilock(dp
, XFS_ILOCK_EXCL
);
377 * No need to make quota reservations here. We expect to release some
378 * blocks not allocate in the common case.
380 xfs_trans_ijoin(args
.trans
, dp
, XFS_ILOCK_EXCL
);
381 xfs_trans_ihold(args
.trans
, dp
);
384 * Decide on what work routines to call based on the inode size.
386 if (XFS_IFORK_Q(dp
) == 0 ||
387 (dp
->i_d
.di_aformat
== XFS_DINODE_FMT_EXTENTS
&&
388 dp
->i_d
.di_anextents
== 0)) {
389 error
= XFS_ERROR(ENOATTR
);
392 if (dp
->i_d
.di_aformat
== XFS_DINODE_FMT_LOCAL
) {
393 ASSERT(dp
->i_afp
->if_flags
& XFS_IFINLINE
);
394 error
= xfs_attr_shortform_remove(&args
);
398 } else if (xfs_bmap_one_block(dp
, XFS_ATTR_FORK
)) {
399 error
= xfs_attr_leaf_removename(&args
);
401 error
= xfs_attr_node_removename(&args
);
408 * If this is a synchronous mount, make sure that the
409 * transaction goes to disk before returning to the user.
411 if (mp
->m_flags
& XFS_MOUNT_WSYNC
) {
412 xfs_trans_set_sync(args
.trans
);
416 * Commit the last in the sequence of transactions.
418 xfs_trans_log_inode(args
.trans
, dp
, XFS_ILOG_CORE
);
419 error
= xfs_trans_commit(args
.trans
, XFS_TRANS_RELEASE_LOG_RES
,
421 xfs_iunlock(dp
, XFS_ILOCK_EXCL
);
424 * Hit the inode change time.
426 if (!error
&& (flags
& ATTR_KERNOTIME
) == 0) {
427 xfs_ichgtime(dp
, XFS_ICHGTIME_CHG
);
434 xfs_trans_cancel(args
.trans
,
435 XFS_TRANS_RELEASE_LOG_RES
|XFS_TRANS_ABORT
);
436 xfs_iunlock(dp
, XFS_ILOCK_EXCL
);
441 /*========================================================================
442 * External routines when attribute list is inside the inode
443 *========================================================================*/
446 * Add a name to the shortform attribute list structure
447 * This is the external routine.
450 xfs_attr_shortform_addname(xfs_da_args_t
*args
)
452 int newsize
, forkoff
, retval
;
454 retval
= xfs_attr_shortform_lookup(args
);
455 if ((args
->flags
& ATTR_REPLACE
) && (retval
== ENOATTR
)) {
457 } else if (retval
== EEXIST
) {
458 if (args
->flags
& ATTR_CREATE
)
460 retval
= xfs_attr_shortform_remove(args
);
464 if (args
->namelen
>= XFS_ATTR_SF_ENTSIZE_MAX
||
465 args
->valuelen
>= XFS_ATTR_SF_ENTSIZE_MAX
)
466 return(XFS_ERROR(ENOSPC
));
468 newsize
= XFS_ATTR_SF_TOTSIZE(args
->dp
);
469 newsize
+= XFS_ATTR_SF_ENTSIZE_BYNAME(args
->namelen
, args
->valuelen
);
471 forkoff
= xfs_attr_shortform_bytesfit(args
->dp
, newsize
);
473 return(XFS_ERROR(ENOSPC
));
475 xfs_attr_shortform_add(args
, forkoff
);
480 /*========================================================================
481 * External routines when attribute list is one block
482 *========================================================================*/
485 * Add a name to the leaf attribute list structure
487 * This leaf block cannot have a "remote" value, we only call this routine
488 * if bmap_one_block() says there is only one block (ie: no remote blks).
491 xfs_attr_leaf_addname(xfs_da_args_t
*args
)
495 int retval
, error
, committed
, forkoff
;
498 * Read the (only) block in the attribute list in.
502 error
= xfs_da_read_buf(args
->trans
, args
->dp
, args
->blkno
, -1, &bp
,
509 * Look up the given attribute in the leaf block. Figure out if
510 * the given flags produce an error or call for an atomic rename.
512 retval
= xfs_attr_leaf_lookup_int(bp
, args
);
513 if ((args
->flags
& ATTR_REPLACE
) && (retval
== ENOATTR
)) {
514 xfs_da_brelse(args
->trans
, bp
);
516 } else if (retval
== EEXIST
) {
517 if (args
->flags
& ATTR_CREATE
) { /* pure create op */
518 xfs_da_brelse(args
->trans
, bp
);
521 args
->rename
= 1; /* an atomic rename */
522 args
->blkno2
= args
->blkno
; /* set 2nd entry info*/
523 args
->index2
= args
->index
;
524 args
->rmtblkno2
= args
->rmtblkno
;
525 args
->rmtblkcnt2
= args
->rmtblkcnt
;
529 * Add the attribute to the leaf block, transitioning to a Btree
532 retval
= xfs_attr_leaf_add(bp
, args
);
534 if (retval
== ENOSPC
) {
536 * Promote the attribute list to the Btree format, then
537 * Commit that transaction so that the node_addname() call
538 * can manage its own transactions.
540 XFS_BMAP_INIT(args
->flist
, args
->firstblock
);
541 error
= xfs_attr_leaf_to_node(args
);
543 error
= xfs_bmap_finish(&args
->trans
, args
->flist
,
544 *args
->firstblock
, &committed
);
549 xfs_bmap_cancel(args
->flist
);
554 * bmap_finish() may have committed the last trans and started
555 * a new one. We need the inode to be in all transactions.
558 xfs_trans_ijoin(args
->trans
, dp
, XFS_ILOCK_EXCL
);
559 xfs_trans_ihold(args
->trans
, dp
);
563 * Commit the current trans (including the inode) and start
566 if ((error
= xfs_attr_rolltrans(&args
->trans
, dp
)))
570 * Fob the whole rest of the problem off on the Btree code.
572 error
= xfs_attr_node_addname(args
);
577 * Commit the transaction that added the attr name so that
578 * later routines can manage their own transactions.
580 if ((error
= xfs_attr_rolltrans(&args
->trans
, dp
)))
584 * If there was an out-of-line value, allocate the blocks we
585 * identified for its storage and copy the value. This is done
586 * after we create the attribute so that we don't overflow the
587 * maximum size of a transaction and/or hit a deadlock.
589 if (args
->rmtblkno
> 0) {
590 error
= xfs_attr_rmtval_set(args
);
596 * If this is an atomic rename operation, we must "flip" the
597 * incomplete flags on the "new" and "old" attribute/value pairs
598 * so that one disappears and one appears atomically. Then we
599 * must remove the "old" attribute/value pair.
603 * In a separate transaction, set the incomplete flag on the
604 * "old" attr and clear the incomplete flag on the "new" attr.
606 error
= xfs_attr_leaf_flipflags(args
);
611 * Dismantle the "old" attribute/value pair by removing
612 * a "remote" value (if it exists).
614 args
->index
= args
->index2
;
615 args
->blkno
= args
->blkno2
;
616 args
->rmtblkno
= args
->rmtblkno2
;
617 args
->rmtblkcnt
= args
->rmtblkcnt2
;
618 if (args
->rmtblkno
) {
619 error
= xfs_attr_rmtval_remove(args
);
625 * Read in the block containing the "old" attr, then
626 * remove the "old" attr from that block (neat, huh!)
628 error
= xfs_da_read_buf(args
->trans
, args
->dp
, args
->blkno
, -1,
633 (void)xfs_attr_leaf_remove(bp
, args
);
636 * If the result is small enough, shrink it all into the inode.
638 if ((forkoff
= xfs_attr_shortform_allfit(bp
, dp
))) {
639 XFS_BMAP_INIT(args
->flist
, args
->firstblock
);
640 error
= xfs_attr_leaf_to_shortform(bp
, args
, forkoff
);
641 /* bp is gone due to xfs_da_shrink_inode */
643 error
= xfs_bmap_finish(&args
->trans
,
651 xfs_bmap_cancel(args
->flist
);
656 * bmap_finish() may have committed the last trans
657 * and started a new one. We need the inode to be
658 * in all transactions.
661 xfs_trans_ijoin(args
->trans
, dp
, XFS_ILOCK_EXCL
);
662 xfs_trans_ihold(args
->trans
, dp
);
668 * Commit the remove and start the next trans in series.
670 error
= xfs_attr_rolltrans(&args
->trans
, dp
);
672 } else if (args
->rmtblkno
> 0) {
674 * Added a "remote" value, just clear the incomplete flag.
676 error
= xfs_attr_leaf_clearflag(args
);
682 * Remove a name from the leaf attribute list structure
684 * This leaf block cannot have a "remote" value, we only call this routine
685 * if bmap_one_block() says there is only one block (ie: no remote blks).
688 xfs_attr_leaf_removename(xfs_da_args_t
*args
)
692 int error
, committed
, forkoff
;
695 * Remove the attribute.
699 error
= xfs_da_read_buf(args
->trans
, args
->dp
, args
->blkno
, -1, &bp
,
706 error
= xfs_attr_leaf_lookup_int(bp
, args
);
707 if (error
== ENOATTR
) {
708 xfs_da_brelse(args
->trans
, bp
);
712 (void)xfs_attr_leaf_remove(bp
, args
);
715 * If the result is small enough, shrink it all into the inode.
717 if ((forkoff
= xfs_attr_shortform_allfit(bp
, dp
))) {
718 XFS_BMAP_INIT(args
->flist
, args
->firstblock
);
719 error
= xfs_attr_leaf_to_shortform(bp
, args
, forkoff
);
720 /* bp is gone due to xfs_da_shrink_inode */
722 error
= xfs_bmap_finish(&args
->trans
, args
->flist
,
723 *args
->firstblock
, &committed
);
728 xfs_bmap_cancel(args
->flist
);
733 * bmap_finish() may have committed the last trans and started
734 * a new one. We need the inode to be in all transactions.
737 xfs_trans_ijoin(args
->trans
, dp
, XFS_ILOCK_EXCL
);
738 xfs_trans_ihold(args
->trans
, dp
);
745 /*========================================================================
746 * External routines when attribute list size > XFS_LBSIZE(mp).
747 *========================================================================*/
750 * Add a name to a Btree-format attribute list.
752 * This will involve walking down the Btree, and may involve splitting
753 * leaf nodes and even splitting intermediate nodes up to and including
754 * the root node (a special case of an intermediate node).
756 * "Remote" attribute values confuse the issue and atomic rename operations
757 * add a whole extra layer of confusion on top of that.
760 xfs_attr_node_addname(xfs_da_args_t
*args
)
762 xfs_da_state_t
*state
;
763 xfs_da_state_blk_t
*blk
;
766 int committed
, retval
, error
;
769 * Fill in bucket of arguments/results/context to carry around.
774 state
= xfs_da_state_alloc();
777 state
->blocksize
= state
->mp
->m_sb
.sb_blocksize
;
778 state
->node_ents
= state
->mp
->m_attr_node_ents
;
781 * Search to see if name already exists, and get back a pointer
782 * to where it should go.
784 error
= xfs_da_node_lookup_int(state
, &retval
);
787 blk
= &state
->path
.blk
[ state
->path
.active
-1 ];
788 ASSERT(blk
->magic
== XFS_ATTR_LEAF_MAGIC
);
789 if ((args
->flags
& ATTR_REPLACE
) && (retval
== ENOATTR
)) {
791 } else if (retval
== EEXIST
) {
792 if (args
->flags
& ATTR_CREATE
)
794 args
->rename
= 1; /* atomic rename op */
795 args
->blkno2
= args
->blkno
; /* set 2nd entry info*/
796 args
->index2
= args
->index
;
797 args
->rmtblkno2
= args
->rmtblkno
;
798 args
->rmtblkcnt2
= args
->rmtblkcnt
;
803 retval
= xfs_attr_leaf_add(blk
->bp
, state
->args
);
804 if (retval
== ENOSPC
) {
805 if (state
->path
.active
== 1) {
807 * Its really a single leaf node, but it had
808 * out-of-line values so it looked like it *might*
809 * have been a b-tree.
811 xfs_da_state_free(state
);
812 XFS_BMAP_INIT(args
->flist
, args
->firstblock
);
813 error
= xfs_attr_leaf_to_node(args
);
815 error
= xfs_bmap_finish(&args
->trans
,
823 xfs_bmap_cancel(args
->flist
);
828 * bmap_finish() may have committed the last trans
829 * and started a new one. We need the inode to be
830 * in all transactions.
833 xfs_trans_ijoin(args
->trans
, dp
, XFS_ILOCK_EXCL
);
834 xfs_trans_ihold(args
->trans
, dp
);
838 * Commit the node conversion and start the next
839 * trans in the chain.
841 if ((error
= xfs_attr_rolltrans(&args
->trans
, dp
)))
848 * Split as many Btree elements as required.
849 * This code tracks the new and old attr's location
850 * in the index/blkno/rmtblkno/rmtblkcnt fields and
851 * in the index2/blkno2/rmtblkno2/rmtblkcnt2 fields.
853 XFS_BMAP_INIT(args
->flist
, args
->firstblock
);
854 error
= xfs_da_split(state
);
856 error
= xfs_bmap_finish(&args
->trans
, args
->flist
,
857 *args
->firstblock
, &committed
);
862 xfs_bmap_cancel(args
->flist
);
867 * bmap_finish() may have committed the last trans and started
868 * a new one. We need the inode to be in all transactions.
871 xfs_trans_ijoin(args
->trans
, dp
, XFS_ILOCK_EXCL
);
872 xfs_trans_ihold(args
->trans
, dp
);
876 * Addition succeeded, update Btree hashvals.
878 xfs_da_fixhashpath(state
, &state
->path
);
882 * Kill the state structure, we're done with it and need to
883 * allow the buffers to come back later.
885 xfs_da_state_free(state
);
889 * Commit the leaf addition or btree split and start the next
890 * trans in the chain.
892 if ((error
= xfs_attr_rolltrans(&args
->trans
, dp
)))
896 * If there was an out-of-line value, allocate the blocks we
897 * identified for its storage and copy the value. This is done
898 * after we create the attribute so that we don't overflow the
899 * maximum size of a transaction and/or hit a deadlock.
901 if (args
->rmtblkno
> 0) {
902 error
= xfs_attr_rmtval_set(args
);
908 * If this is an atomic rename operation, we must "flip" the
909 * incomplete flags on the "new" and "old" attribute/value pairs
910 * so that one disappears and one appears atomically. Then we
911 * must remove the "old" attribute/value pair.
915 * In a separate transaction, set the incomplete flag on the
916 * "old" attr and clear the incomplete flag on the "new" attr.
918 error
= xfs_attr_leaf_flipflags(args
);
923 * Dismantle the "old" attribute/value pair by removing
924 * a "remote" value (if it exists).
926 args
->index
= args
->index2
;
927 args
->blkno
= args
->blkno2
;
928 args
->rmtblkno
= args
->rmtblkno2
;
929 args
->rmtblkcnt
= args
->rmtblkcnt2
;
930 if (args
->rmtblkno
) {
931 error
= xfs_attr_rmtval_remove(args
);
937 * Re-find the "old" attribute entry after any split ops.
938 * The INCOMPLETE flag means that we will find the "old"
939 * attr, not the "new" one.
941 args
->flags
|= XFS_ATTR_INCOMPLETE
;
942 state
= xfs_da_state_alloc();
945 state
->blocksize
= state
->mp
->m_sb
.sb_blocksize
;
946 state
->node_ents
= state
->mp
->m_attr_node_ents
;
948 error
= xfs_da_node_lookup_int(state
, &retval
);
953 * Remove the name and update the hashvals in the tree.
955 blk
= &state
->path
.blk
[ state
->path
.active
-1 ];
956 ASSERT(blk
->magic
== XFS_ATTR_LEAF_MAGIC
);
957 error
= xfs_attr_leaf_remove(blk
->bp
, args
);
958 xfs_da_fixhashpath(state
, &state
->path
);
961 * Check to see if the tree needs to be collapsed.
963 if (retval
&& (state
->path
.active
> 1)) {
964 XFS_BMAP_INIT(args
->flist
, args
->firstblock
);
965 error
= xfs_da_join(state
);
967 error
= xfs_bmap_finish(&args
->trans
,
975 xfs_bmap_cancel(args
->flist
);
980 * bmap_finish() may have committed the last trans
981 * and started a new one. We need the inode to be
982 * in all transactions.
985 xfs_trans_ijoin(args
->trans
, dp
, XFS_ILOCK_EXCL
);
986 xfs_trans_ihold(args
->trans
, dp
);
991 * Commit and start the next trans in the chain.
993 if ((error
= xfs_attr_rolltrans(&args
->trans
, dp
)))
996 } else if (args
->rmtblkno
> 0) {
998 * Added a "remote" value, just clear the incomplete flag.
1000 error
= xfs_attr_leaf_clearflag(args
);
1008 xfs_da_state_free(state
);
1015 * Remove a name from a B-tree attribute list.
1017 * This will involve walking down the Btree, and may involve joining
1018 * leaf nodes and even joining intermediate nodes up to and including
1019 * the root node (a special case of an intermediate node).
1022 xfs_attr_node_removename(xfs_da_args_t
*args
)
1024 xfs_da_state_t
*state
;
1025 xfs_da_state_blk_t
*blk
;
1028 int retval
, error
, committed
, forkoff
;
1031 * Tie a string around our finger to remind us where we are.
1034 state
= xfs_da_state_alloc();
1036 state
->mp
= dp
->i_mount
;
1037 state
->blocksize
= state
->mp
->m_sb
.sb_blocksize
;
1038 state
->node_ents
= state
->mp
->m_attr_node_ents
;
1041 * Search to see if name exists, and get back a pointer to it.
1043 error
= xfs_da_node_lookup_int(state
, &retval
);
1044 if (error
|| (retval
!= EEXIST
)) {
1051 * If there is an out-of-line value, de-allocate the blocks.
1052 * This is done before we remove the attribute so that we don't
1053 * overflow the maximum size of a transaction and/or hit a deadlock.
1055 blk
= &state
->path
.blk
[ state
->path
.active
-1 ];
1056 ASSERT(blk
->bp
!= NULL
);
1057 ASSERT(blk
->magic
== XFS_ATTR_LEAF_MAGIC
);
1058 if (args
->rmtblkno
> 0) {
1060 * Fill in disk block numbers in the state structure
1061 * so that we can get the buffers back after we commit
1062 * several transactions in the following calls.
1064 error
= xfs_attr_fillstate(state
);
1069 * Mark the attribute as INCOMPLETE, then bunmapi() the
1072 error
= xfs_attr_leaf_setflag(args
);
1075 error
= xfs_attr_rmtval_remove(args
);
1080 * Refill the state structure with buffers, the prior calls
1081 * released our buffers.
1083 error
= xfs_attr_refillstate(state
);
1089 * Remove the name and update the hashvals in the tree.
1091 blk
= &state
->path
.blk
[ state
->path
.active
-1 ];
1092 ASSERT(blk
->magic
== XFS_ATTR_LEAF_MAGIC
);
1093 retval
= xfs_attr_leaf_remove(blk
->bp
, args
);
1094 xfs_da_fixhashpath(state
, &state
->path
);
1097 * Check to see if the tree needs to be collapsed.
1099 if (retval
&& (state
->path
.active
> 1)) {
1100 XFS_BMAP_INIT(args
->flist
, args
->firstblock
);
1101 error
= xfs_da_join(state
);
1103 error
= xfs_bmap_finish(&args
->trans
, args
->flist
,
1104 *args
->firstblock
, &committed
);
1109 xfs_bmap_cancel(args
->flist
);
1114 * bmap_finish() may have committed the last trans and started
1115 * a new one. We need the inode to be in all transactions.
1118 xfs_trans_ijoin(args
->trans
, dp
, XFS_ILOCK_EXCL
);
1119 xfs_trans_ihold(args
->trans
, dp
);
1123 * Commit the Btree join operation and start a new trans.
1125 if ((error
= xfs_attr_rolltrans(&args
->trans
, dp
)))
1130 * If the result is small enough, push it all into the inode.
1132 if (xfs_bmap_one_block(dp
, XFS_ATTR_FORK
)) {
1134 * Have to get rid of the copy of this dabuf in the state.
1136 ASSERT(state
->path
.active
== 1);
1137 ASSERT(state
->path
.blk
[0].bp
);
1138 xfs_da_buf_done(state
->path
.blk
[0].bp
);
1139 state
->path
.blk
[0].bp
= NULL
;
1141 error
= xfs_da_read_buf(args
->trans
, args
->dp
, 0, -1, &bp
,
1145 ASSERT(INT_GET(((xfs_attr_leafblock_t
*)
1146 bp
->data
)->hdr
.info
.magic
, ARCH_CONVERT
)
1147 == XFS_ATTR_LEAF_MAGIC
);
1149 if ((forkoff
= xfs_attr_shortform_allfit(bp
, dp
))) {
1150 XFS_BMAP_INIT(args
->flist
, args
->firstblock
);
1151 error
= xfs_attr_leaf_to_shortform(bp
, args
, forkoff
);
1152 /* bp is gone due to xfs_da_shrink_inode */
1154 error
= xfs_bmap_finish(&args
->trans
,
1162 xfs_bmap_cancel(args
->flist
);
1167 * bmap_finish() may have committed the last trans
1168 * and started a new one. We need the inode to be
1169 * in all transactions.
1172 xfs_trans_ijoin(args
->trans
, dp
, XFS_ILOCK_EXCL
);
1173 xfs_trans_ihold(args
->trans
, dp
);
1176 xfs_da_brelse(args
->trans
, bp
);
1181 xfs_da_state_free(state
);
1186 * Fill in the disk block numbers in the state structure for the buffers
1187 * that are attached to the state structure.
1188 * This is done so that we can quickly reattach ourselves to those buffers
1189 * after some set of transaction commit's has released these buffers.
1192 xfs_attr_fillstate(xfs_da_state_t
*state
)
1194 xfs_da_state_path_t
*path
;
1195 xfs_da_state_blk_t
*blk
;
1199 * Roll down the "path" in the state structure, storing the on-disk
1200 * block number for those buffers in the "path".
1202 path
= &state
->path
;
1203 ASSERT((path
->active
>= 0) && (path
->active
< XFS_DA_NODE_MAXDEPTH
));
1204 for (blk
= path
->blk
, level
= 0; level
< path
->active
; blk
++, level
++) {
1206 blk
->disk_blkno
= xfs_da_blkno(blk
->bp
);
1207 xfs_da_buf_done(blk
->bp
);
1210 blk
->disk_blkno
= 0;
1215 * Roll down the "altpath" in the state structure, storing the on-disk
1216 * block number for those buffers in the "altpath".
1218 path
= &state
->altpath
;
1219 ASSERT((path
->active
>= 0) && (path
->active
< XFS_DA_NODE_MAXDEPTH
));
1220 for (blk
= path
->blk
, level
= 0; level
< path
->active
; blk
++, level
++) {
1222 blk
->disk_blkno
= xfs_da_blkno(blk
->bp
);
1223 xfs_da_buf_done(blk
->bp
);
1226 blk
->disk_blkno
= 0;
1234 * Reattach the buffers to the state structure based on the disk block
1235 * numbers stored in the state structure.
1236 * This is done after some set of transaction commit's has released those
1237 * buffers from our grip.
1240 xfs_attr_refillstate(xfs_da_state_t
*state
)
1242 xfs_da_state_path_t
*path
;
1243 xfs_da_state_blk_t
*blk
;
1247 * Roll down the "path" in the state structure, storing the on-disk
1248 * block number for those buffers in the "path".
1250 path
= &state
->path
;
1251 ASSERT((path
->active
>= 0) && (path
->active
< XFS_DA_NODE_MAXDEPTH
));
1252 for (blk
= path
->blk
, level
= 0; level
< path
->active
; blk
++, level
++) {
1253 if (blk
->disk_blkno
) {
1254 error
= xfs_da_read_buf(state
->args
->trans
,
1256 blk
->blkno
, blk
->disk_blkno
,
1257 &blk
->bp
, XFS_ATTR_FORK
);
1266 * Roll down the "altpath" in the state structure, storing the on-disk
1267 * block number for those buffers in the "altpath".
1269 path
= &state
->altpath
;
1270 ASSERT((path
->active
>= 0) && (path
->active
< XFS_DA_NODE_MAXDEPTH
));
1271 for (blk
= path
->blk
, level
= 0; level
< path
->active
; blk
++, level
++) {
1272 if (blk
->disk_blkno
) {
1273 error
= xfs_da_read_buf(state
->args
->trans
,
1275 blk
->blkno
, blk
->disk_blkno
,
1276 &blk
->bp
, XFS_ATTR_FORK
);
1288 * Write the value associated with an attribute into the out-of-line buffer
1289 * that we have defined for it.
1292 xfs_attr_rmtval_set(xfs_da_args_t
*args
)
1295 xfs_fileoff_t lfileoff
;
1297 xfs_bmbt_irec_t map
;
1302 int blkcnt
, valuelen
, nmap
, error
, tmp
, committed
;
1309 * Find a "hole" in the attribute address space large enough for
1310 * us to drop the new attribute's value into.
1312 blkcnt
= XFS_B_TO_FSB(mp
, args
->valuelen
);
1314 error
= xfs_bmap_first_unused(args
->trans
, args
->dp
, blkcnt
, &lfileoff
,
1319 args
->rmtblkno
= lblkno
= (xfs_dablk_t
)lfileoff
;
1320 args
->rmtblkcnt
= blkcnt
;
1323 * Roll through the "value", allocating blocks on disk as required.
1325 while (blkcnt
> 0) {
1327 * Allocate a single extent, up to the size of the value.
1329 XFS_BMAP_INIT(args
->flist
, args
->firstblock
);
1331 error
= xfs_bmapi(args
->trans
, dp
, (xfs_fileoff_t
)lblkno
,
1333 XFS_BMAPI_ATTRFORK
| XFS_BMAPI_METADATA
|
1335 args
->firstblock
, args
->total
, &map
, &nmap
,
1338 error
= xfs_bmap_finish(&args
->trans
, args
->flist
,
1339 *args
->firstblock
, &committed
);
1344 xfs_bmap_cancel(args
->flist
);
1349 * bmap_finish() may have committed the last trans and started
1350 * a new one. We need the inode to be in all transactions.
1353 xfs_trans_ijoin(args
->trans
, dp
, XFS_ILOCK_EXCL
);
1354 xfs_trans_ihold(args
->trans
, dp
);
1358 ASSERT((map
.br_startblock
!= DELAYSTARTBLOCK
) &&
1359 (map
.br_startblock
!= HOLESTARTBLOCK
));
1360 lblkno
+= map
.br_blockcount
;
1361 blkcnt
-= map
.br_blockcount
;
1364 * Start the next trans in the chain.
1366 if ((error
= xfs_attr_rolltrans(&args
->trans
, dp
)))
1371 * Roll through the "value", copying the attribute value to the
1372 * already-allocated blocks. Blocks are written synchronously
1373 * so that we can know they are all on disk before we turn off
1374 * the INCOMPLETE flag.
1376 lblkno
= args
->rmtblkno
;
1377 valuelen
= args
->valuelen
;
1378 while (valuelen
> 0) {
1380 * Try to remember where we decided to put the value.
1382 XFS_BMAP_INIT(args
->flist
, args
->firstblock
);
1384 error
= xfs_bmapi(NULL
, dp
, (xfs_fileoff_t
)lblkno
,
1386 XFS_BMAPI_ATTRFORK
| XFS_BMAPI_METADATA
,
1387 args
->firstblock
, 0, &map
, &nmap
, NULL
);
1392 ASSERT((map
.br_startblock
!= DELAYSTARTBLOCK
) &&
1393 (map
.br_startblock
!= HOLESTARTBLOCK
));
1395 dblkno
= XFS_FSB_TO_DADDR(mp
, map
.br_startblock
),
1396 blkcnt
= XFS_FSB_TO_BB(mp
, map
.br_blockcount
);
1398 bp
= xfs_buf_get_flags(mp
->m_ddev_targp
, dblkno
,
1399 blkcnt
, XFS_BUF_LOCK
);
1401 ASSERT(!XFS_BUF_GETERROR(bp
));
1403 tmp
= (valuelen
< XFS_BUF_SIZE(bp
)) ? valuelen
:
1405 xfs_biomove(bp
, 0, tmp
, src
, XFS_B_WRITE
);
1406 if (tmp
< XFS_BUF_SIZE(bp
))
1407 xfs_biozero(bp
, tmp
, XFS_BUF_SIZE(bp
) - tmp
);
1408 if ((error
= xfs_bwrite(mp
, bp
))) {/* GROT: NOTE: synchronous write */
1414 lblkno
+= map
.br_blockcount
;
1416 ASSERT(valuelen
== 0);
1421 * Remove the value associated with an attribute by deleting the
1422 * out-of-line buffer that it is stored on.
1425 xfs_attr_rmtval_remove(xfs_da_args_t
*args
)
1428 xfs_bmbt_irec_t map
;
1432 int valuelen
, blkcnt
, nmap
, error
, done
, committed
;
1434 mp
= args
->dp
->i_mount
;
1437 * Roll through the "value", invalidating the attribute value's
1440 lblkno
= args
->rmtblkno
;
1441 valuelen
= args
->rmtblkcnt
;
1442 while (valuelen
> 0) {
1444 * Try to remember where we decided to put the value.
1446 XFS_BMAP_INIT(args
->flist
, args
->firstblock
);
1448 error
= xfs_bmapi(NULL
, args
->dp
, (xfs_fileoff_t
)lblkno
,
1450 XFS_BMAPI_ATTRFORK
| XFS_BMAPI_METADATA
,
1451 args
->firstblock
, 0, &map
, &nmap
,
1457 ASSERT((map
.br_startblock
!= DELAYSTARTBLOCK
) &&
1458 (map
.br_startblock
!= HOLESTARTBLOCK
));
1460 dblkno
= XFS_FSB_TO_DADDR(mp
, map
.br_startblock
),
1461 blkcnt
= XFS_FSB_TO_BB(mp
, map
.br_blockcount
);
1464 * If the "remote" value is in the cache, remove it.
1466 bp
= xfs_incore(mp
->m_ddev_targp
, dblkno
, blkcnt
,
1467 XFS_INCORE_TRYLOCK
);
1470 XFS_BUF_UNDELAYWRITE(bp
);
1475 valuelen
-= map
.br_blockcount
;
1477 lblkno
+= map
.br_blockcount
;
1481 * Keep de-allocating extents until the remote-value region is gone.
1483 lblkno
= args
->rmtblkno
;
1484 blkcnt
= args
->rmtblkcnt
;
1487 XFS_BMAP_INIT(args
->flist
, args
->firstblock
);
1488 error
= xfs_bunmapi(args
->trans
, args
->dp
, lblkno
, blkcnt
,
1489 XFS_BMAPI_ATTRFORK
| XFS_BMAPI_METADATA
,
1490 1, args
->firstblock
, args
->flist
, &done
);
1492 error
= xfs_bmap_finish(&args
->trans
, args
->flist
,
1493 *args
->firstblock
, &committed
);
1498 xfs_bmap_cancel(args
->flist
);
1503 * bmap_finish() may have committed the last trans and started
1504 * a new one. We need the inode to be in all transactions.
1507 xfs_trans_ijoin(args
->trans
, args
->dp
, XFS_ILOCK_EXCL
);
1508 xfs_trans_ihold(args
->trans
, args
->dp
);
1512 * Close out trans and start the next one in the chain.
1514 if ((error
= xfs_attr_rolltrans(&args
->trans
, args
->dp
)))