]> git.ipfire.org Git - thirdparty/xfsprogs-dev.git/blob - libxfs/xfs_attr.c
xfsprogs: remove unused functions
[thirdparty/xfsprogs-dev.git] / libxfs / xfs_attr.c
1 // SPDX-License-Identifier: GPL-2.0
2 /*
3 * Copyright (c) 2000-2005 Silicon Graphics, Inc.
4 * All Rights Reserved.
5 */
6 #include "libxfs_priv.h"
7 #include "xfs_fs.h"
8 #include "xfs_shared.h"
9 #include "xfs_format.h"
10 #include "xfs_log_format.h"
11 #include "xfs_trans_resv.h"
12 #include "xfs_bit.h"
13 #include "xfs_mount.h"
14 #include "xfs_defer.h"
15 #include "xfs_da_format.h"
16 #include "xfs_da_btree.h"
17 #include "xfs_attr_sf.h"
18 #include "xfs_inode.h"
19 #include "xfs_alloc.h"
20 #include "xfs_trans.h"
21 #include "xfs_bmap.h"
22 #include "xfs_bmap_btree.h"
23 #include "xfs_attr_leaf.h"
24 #include "xfs_attr_remote.h"
25 #include "xfs_trans_space.h"
26 #include "xfs_trace.h"
27
28 /*
29 * xfs_attr.c
30 *
31 * Provide the external interfaces to manage attribute lists.
32 */
33
34 /*========================================================================
35 * Function prototypes for the kernel.
36 *========================================================================*/
37
38 /*
39 * Internal routines when attribute list fits inside the inode.
40 */
41 STATIC int xfs_attr_shortform_addname(xfs_da_args_t *args);
42
43 /*
44 * Internal routines when attribute list is one block.
45 */
46 STATIC int xfs_attr_leaf_get(xfs_da_args_t *args);
47 STATIC int xfs_attr_leaf_addname(xfs_da_args_t *args);
48 STATIC int xfs_attr_leaf_removename(xfs_da_args_t *args);
49
50 /*
51 * Internal routines when attribute list is more than one block.
52 */
53 STATIC int xfs_attr_node_get(xfs_da_args_t *args);
54 STATIC int xfs_attr_node_addname(xfs_da_args_t *args);
55 STATIC int xfs_attr_node_removename(xfs_da_args_t *args);
56 STATIC int xfs_attr_fillstate(xfs_da_state_t *state);
57 STATIC int xfs_attr_refillstate(xfs_da_state_t *state);
58
59
60 STATIC int
61 xfs_attr_args_init(
62 struct xfs_da_args *args,
63 struct xfs_inode *dp,
64 const unsigned char *name,
65 int flags)
66 {
67
68 if (!name)
69 return -EINVAL;
70
71 memset(args, 0, sizeof(*args));
72 args->geo = dp->i_mount->m_attr_geo;
73 args->whichfork = XFS_ATTR_FORK;
74 args->dp = dp;
75 args->flags = flags;
76 args->name = name;
77 args->namelen = strlen((const char *)name);
78 if (args->namelen >= MAXNAMELEN)
79 return -EFAULT; /* match IRIX behaviour */
80
81 args->hashval = xfs_da_hashname(args->name, args->namelen);
82 return 0;
83 }
84
85 int
86 xfs_inode_hasattr(
87 struct xfs_inode *ip)
88 {
89 if (!XFS_IFORK_Q(ip) ||
90 (ip->i_d.di_aformat == XFS_DINODE_FMT_EXTENTS &&
91 ip->i_d.di_anextents == 0))
92 return 0;
93 return 1;
94 }
95
96 /*========================================================================
97 * Overall external interface routines.
98 *========================================================================*/
99
100 /* Retrieve an extended attribute and its value. Must have ilock. */
101 int
102 xfs_attr_get_ilocked(
103 struct xfs_inode *ip,
104 struct xfs_da_args *args)
105 {
106 ASSERT(xfs_isilocked(ip, XFS_ILOCK_SHARED | XFS_ILOCK_EXCL));
107
108 if (!xfs_inode_hasattr(ip))
109 return -ENOATTR;
110 else if (ip->i_d.di_aformat == XFS_DINODE_FMT_LOCAL)
111 return xfs_attr_shortform_getvalue(args);
112 else if (xfs_bmap_one_block(ip, XFS_ATTR_FORK))
113 return xfs_attr_leaf_get(args);
114 else
115 return xfs_attr_node_get(args);
116 }
117
118 /* Retrieve an extended attribute by name, and its value. */
119 int
120 xfs_attr_get(
121 struct xfs_inode *ip,
122 const unsigned char *name,
123 unsigned char *value,
124 int *valuelenp,
125 int flags)
126 {
127 struct xfs_da_args args;
128 uint lock_mode;
129 int error;
130
131 XFS_STATS_INC(ip->i_mount, xs_attr_get);
132
133 if (XFS_FORCED_SHUTDOWN(ip->i_mount))
134 return -EIO;
135
136 error = xfs_attr_args_init(&args, ip, name, flags);
137 if (error)
138 return error;
139
140 args.value = value;
141 args.valuelen = *valuelenp;
142 /* Entirely possible to look up a name which doesn't exist */
143 args.op_flags = XFS_DA_OP_OKNOENT;
144
145 lock_mode = xfs_ilock_attr_map_shared(ip);
146 error = xfs_attr_get_ilocked(ip, &args);
147 xfs_iunlock(ip, lock_mode);
148
149 *valuelenp = args.valuelen;
150 return error == -EEXIST ? 0 : error;
151 }
152
153 /*
154 * Calculate how many blocks we need for the new attribute,
155 */
156 STATIC int
157 xfs_attr_calc_size(
158 struct xfs_da_args *args,
159 int *local)
160 {
161 struct xfs_mount *mp = args->dp->i_mount;
162 int size;
163 int nblks;
164
165 /*
166 * Determine space new attribute will use, and if it would be
167 * "local" or "remote" (note: local != inline).
168 */
169 size = xfs_attr_leaf_newentsize(args, local);
170 nblks = XFS_DAENTER_SPACE_RES(mp, XFS_ATTR_FORK);
171 if (*local) {
172 if (size > (args->geo->blksize / 2)) {
173 /* Double split possible */
174 nblks *= 2;
175 }
176 } else {
177 /*
178 * Out of line attribute, cannot double split, but
179 * make room for the attribute value itself.
180 */
181 uint dblocks = xfs_attr3_rmt_blocks(mp, args->valuelen);
182 nblks += dblocks;
183 nblks += XFS_NEXTENTADD_SPACE_RES(mp, dblocks, XFS_ATTR_FORK);
184 }
185
186 return nblks;
187 }
188
189 int
190 xfs_attr_set(
191 struct xfs_inode *dp,
192 const unsigned char *name,
193 unsigned char *value,
194 int valuelen,
195 int flags)
196 {
197 struct xfs_mount *mp = dp->i_mount;
198 struct xfs_buf *leaf_bp = NULL;
199 struct xfs_da_args args;
200 struct xfs_trans_res tres;
201 int rsvd = (flags & ATTR_ROOT) != 0;
202 int error, err2, local;
203
204 XFS_STATS_INC(mp, xs_attr_set);
205
206 if (XFS_FORCED_SHUTDOWN(dp->i_mount))
207 return -EIO;
208
209 error = xfs_attr_args_init(&args, dp, name, flags);
210 if (error)
211 return error;
212
213 args.value = value;
214 args.valuelen = valuelen;
215 args.op_flags = XFS_DA_OP_ADDNAME | XFS_DA_OP_OKNOENT;
216 args.total = xfs_attr_calc_size(&args, &local);
217
218 error = xfs_qm_dqattach(dp);
219 if (error)
220 return error;
221
222 /*
223 * If the inode doesn't have an attribute fork, add one.
224 * (inode must not be locked when we call this routine)
225 */
226 if (XFS_IFORK_Q(dp) == 0) {
227 int sf_size = sizeof(xfs_attr_sf_hdr_t) +
228 XFS_ATTR_SF_ENTSIZE_BYNAME(args.namelen, valuelen);
229
230 error = xfs_bmap_add_attrfork(dp, sf_size, rsvd);
231 if (error)
232 return error;
233 }
234
235 tres.tr_logres = M_RES(mp)->tr_attrsetm.tr_logres +
236 M_RES(mp)->tr_attrsetrt.tr_logres * args.total;
237 tres.tr_logcount = XFS_ATTRSET_LOG_COUNT;
238 tres.tr_logflags = XFS_TRANS_PERM_LOG_RES;
239
240 /*
241 * Root fork attributes can use reserved data blocks for this
242 * operation if necessary
243 */
244 error = xfs_trans_alloc(mp, &tres, args.total, 0,
245 rsvd ? XFS_TRANS_RESERVE : 0, &args.trans);
246 if (error)
247 return error;
248
249 xfs_ilock(dp, XFS_ILOCK_EXCL);
250 error = xfs_trans_reserve_quota_nblks(args.trans, dp, args.total, 0,
251 rsvd ? XFS_QMOPT_RES_REGBLKS | XFS_QMOPT_FORCE_RES :
252 XFS_QMOPT_RES_REGBLKS);
253 if (error) {
254 xfs_iunlock(dp, XFS_ILOCK_EXCL);
255 xfs_trans_cancel(args.trans);
256 return error;
257 }
258
259 xfs_trans_ijoin(args.trans, dp, 0);
260
261 /*
262 * If the attribute list is non-existent or a shortform list,
263 * upgrade it to a single-leaf-block attribute list.
264 */
265 if (dp->i_d.di_aformat == XFS_DINODE_FMT_LOCAL ||
266 (dp->i_d.di_aformat == XFS_DINODE_FMT_EXTENTS &&
267 dp->i_d.di_anextents == 0)) {
268
269 /*
270 * Build initial attribute list (if required).
271 */
272 if (dp->i_d.di_aformat == XFS_DINODE_FMT_EXTENTS)
273 xfs_attr_shortform_create(&args);
274
275 /*
276 * Try to add the attr to the attribute list in
277 * the inode.
278 */
279 error = xfs_attr_shortform_addname(&args);
280 if (error != -ENOSPC) {
281 /*
282 * Commit the shortform mods, and we're done.
283 * NOTE: this is also the error path (EEXIST, etc).
284 */
285 ASSERT(args.trans != NULL);
286
287 /*
288 * If this is a synchronous mount, make sure that
289 * the transaction goes to disk before returning
290 * to the user.
291 */
292 if (mp->m_flags & XFS_MOUNT_WSYNC)
293 xfs_trans_set_sync(args.trans);
294
295 if (!error && (flags & ATTR_KERNOTIME) == 0) {
296 xfs_trans_ichgtime(args.trans, dp,
297 XFS_ICHGTIME_CHG);
298 }
299 err2 = xfs_trans_commit(args.trans);
300 xfs_iunlock(dp, XFS_ILOCK_EXCL);
301
302 return error ? error : err2;
303 }
304
305 /*
306 * It won't fit in the shortform, transform to a leaf block.
307 * GROT: another possible req'mt for a double-split btree op.
308 */
309 error = xfs_attr_shortform_to_leaf(&args, &leaf_bp);
310 if (error)
311 goto out;
312 /*
313 * Prevent the leaf buffer from being unlocked so that a
314 * concurrent AIL push cannot grab the half-baked leaf
315 * buffer and run into problems with the write verifier.
316 */
317 xfs_trans_bhold(args.trans, leaf_bp);
318 error = xfs_defer_finish(&args.trans);
319 if (error)
320 goto out;
321
322 /*
323 * Commit the leaf transformation. We'll need another (linked)
324 * transaction to add the new attribute to the leaf, which
325 * means that we have to hold & join the leaf buffer here too.
326 */
327 error = xfs_trans_roll_inode(&args.trans, dp);
328 if (error)
329 goto out;
330 xfs_trans_bjoin(args.trans, leaf_bp);
331 leaf_bp = NULL;
332 }
333
334 if (xfs_bmap_one_block(dp, XFS_ATTR_FORK))
335 error = xfs_attr_leaf_addname(&args);
336 else
337 error = xfs_attr_node_addname(&args);
338 if (error)
339 goto out;
340
341 /*
342 * If this is a synchronous mount, make sure that the
343 * transaction goes to disk before returning to the user.
344 */
345 if (mp->m_flags & XFS_MOUNT_WSYNC)
346 xfs_trans_set_sync(args.trans);
347
348 if ((flags & ATTR_KERNOTIME) == 0)
349 xfs_trans_ichgtime(args.trans, dp, XFS_ICHGTIME_CHG);
350
351 /*
352 * Commit the last in the sequence of transactions.
353 */
354 xfs_trans_log_inode(args.trans, dp, XFS_ILOG_CORE);
355 error = xfs_trans_commit(args.trans);
356 xfs_iunlock(dp, XFS_ILOCK_EXCL);
357
358 return error;
359
360 out:
361 if (leaf_bp)
362 xfs_trans_brelse(args.trans, leaf_bp);
363 if (args.trans)
364 xfs_trans_cancel(args.trans);
365 xfs_iunlock(dp, XFS_ILOCK_EXCL);
366 return error;
367 }
368
369 /*
370 * Generic handler routine to remove a name from an attribute list.
371 * Transitions attribute list from Btree to shortform as necessary.
372 */
373 int
374 xfs_attr_remove(
375 struct xfs_inode *dp,
376 const unsigned char *name,
377 int flags)
378 {
379 struct xfs_mount *mp = dp->i_mount;
380 struct xfs_da_args args;
381 int error;
382
383 XFS_STATS_INC(mp, xs_attr_remove);
384
385 if (XFS_FORCED_SHUTDOWN(dp->i_mount))
386 return -EIO;
387
388 error = xfs_attr_args_init(&args, dp, name, flags);
389 if (error)
390 return error;
391
392 /*
393 * we have no control over the attribute names that userspace passes us
394 * to remove, so we have to allow the name lookup prior to attribute
395 * removal to fail.
396 */
397 args.op_flags = XFS_DA_OP_OKNOENT;
398
399 error = xfs_qm_dqattach(dp);
400 if (error)
401 return error;
402
403 /*
404 * Root fork attributes can use reserved data blocks for this
405 * operation if necessary
406 */
407 error = xfs_trans_alloc(mp, &M_RES(mp)->tr_attrrm,
408 XFS_ATTRRM_SPACE_RES(mp), 0,
409 (flags & ATTR_ROOT) ? XFS_TRANS_RESERVE : 0,
410 &args.trans);
411 if (error)
412 return error;
413
414 xfs_ilock(dp, XFS_ILOCK_EXCL);
415 /*
416 * No need to make quota reservations here. We expect to release some
417 * blocks not allocate in the common case.
418 */
419 xfs_trans_ijoin(args.trans, dp, 0);
420
421 if (!xfs_inode_hasattr(dp)) {
422 error = -ENOATTR;
423 } else if (dp->i_d.di_aformat == XFS_DINODE_FMT_LOCAL) {
424 ASSERT(dp->i_afp->if_flags & XFS_IFINLINE);
425 error = xfs_attr_shortform_remove(&args);
426 } else if (xfs_bmap_one_block(dp, XFS_ATTR_FORK)) {
427 error = xfs_attr_leaf_removename(&args);
428 } else {
429 error = xfs_attr_node_removename(&args);
430 }
431
432 if (error)
433 goto out;
434
435 /*
436 * If this is a synchronous mount, make sure that the
437 * transaction goes to disk before returning to the user.
438 */
439 if (mp->m_flags & XFS_MOUNT_WSYNC)
440 xfs_trans_set_sync(args.trans);
441
442 if ((flags & ATTR_KERNOTIME) == 0)
443 xfs_trans_ichgtime(args.trans, dp, XFS_ICHGTIME_CHG);
444
445 /*
446 * Commit the last in the sequence of transactions.
447 */
448 xfs_trans_log_inode(args.trans, dp, XFS_ILOG_CORE);
449 error = xfs_trans_commit(args.trans);
450 xfs_iunlock(dp, XFS_ILOCK_EXCL);
451
452 return error;
453
454 out:
455 if (args.trans)
456 xfs_trans_cancel(args.trans);
457 xfs_iunlock(dp, XFS_ILOCK_EXCL);
458 return error;
459 }
460
461 /*========================================================================
462 * External routines when attribute list is inside the inode
463 *========================================================================*/
464
465 /*
466 * Add a name to the shortform attribute list structure
467 * This is the external routine.
468 */
469 STATIC int
470 xfs_attr_shortform_addname(xfs_da_args_t *args)
471 {
472 int newsize, forkoff, retval;
473
474 trace_xfs_attr_sf_addname(args);
475
476 retval = xfs_attr_shortform_lookup(args);
477 if ((args->flags & ATTR_REPLACE) && (retval == -ENOATTR)) {
478 return retval;
479 } else if (retval == -EEXIST) {
480 if (args->flags & ATTR_CREATE)
481 return retval;
482 retval = xfs_attr_shortform_remove(args);
483 if (retval)
484 return retval;
485 /*
486 * Since we have removed the old attr, clear ATTR_REPLACE so
487 * that the leaf format add routine won't trip over the attr
488 * not being around.
489 */
490 args->flags &= ~ATTR_REPLACE;
491 }
492
493 if (args->namelen >= XFS_ATTR_SF_ENTSIZE_MAX ||
494 args->valuelen >= XFS_ATTR_SF_ENTSIZE_MAX)
495 return -ENOSPC;
496
497 newsize = XFS_ATTR_SF_TOTSIZE(args->dp);
498 newsize += XFS_ATTR_SF_ENTSIZE_BYNAME(args->namelen, args->valuelen);
499
500 forkoff = xfs_attr_shortform_bytesfit(args->dp, newsize);
501 if (!forkoff)
502 return -ENOSPC;
503
504 xfs_attr_shortform_add(args, forkoff);
505 return 0;
506 }
507
508
509 /*========================================================================
510 * External routines when attribute list is one block
511 *========================================================================*/
512
513 /*
514 * Add a name to the leaf attribute list structure
515 *
516 * This leaf block cannot have a "remote" value, we only call this routine
517 * if bmap_one_block() says there is only one block (ie: no remote blks).
518 */
519 STATIC int
520 xfs_attr_leaf_addname(
521 struct xfs_da_args *args)
522 {
523 struct xfs_inode *dp;
524 struct xfs_buf *bp;
525 int retval, error, forkoff;
526
527 trace_xfs_attr_leaf_addname(args);
528
529 /*
530 * Read the (only) block in the attribute list in.
531 */
532 dp = args->dp;
533 args->blkno = 0;
534 error = xfs_attr3_leaf_read(args->trans, args->dp, args->blkno, -1, &bp);
535 if (error)
536 return error;
537
538 /*
539 * Look up the given attribute in the leaf block. Figure out if
540 * the given flags produce an error or call for an atomic rename.
541 */
542 retval = xfs_attr3_leaf_lookup_int(bp, args);
543 if ((args->flags & ATTR_REPLACE) && (retval == -ENOATTR)) {
544 xfs_trans_brelse(args->trans, bp);
545 return retval;
546 } else if (retval == -EEXIST) {
547 if (args->flags & ATTR_CREATE) { /* pure create op */
548 xfs_trans_brelse(args->trans, bp);
549 return retval;
550 }
551
552 trace_xfs_attr_leaf_replace(args);
553
554 /* save the attribute state for later removal*/
555 args->op_flags |= XFS_DA_OP_RENAME; /* an atomic rename */
556 args->blkno2 = args->blkno; /* set 2nd entry info*/
557 args->index2 = args->index;
558 args->rmtblkno2 = args->rmtblkno;
559 args->rmtblkcnt2 = args->rmtblkcnt;
560 args->rmtvaluelen2 = args->rmtvaluelen;
561
562 /*
563 * clear the remote attr state now that it is saved so that the
564 * values reflect the state of the attribute we are about to
565 * add, not the attribute we just found and will remove later.
566 */
567 args->rmtblkno = 0;
568 args->rmtblkcnt = 0;
569 args->rmtvaluelen = 0;
570 }
571
572 /*
573 * Add the attribute to the leaf block, transitioning to a Btree
574 * if required.
575 */
576 retval = xfs_attr3_leaf_add(bp, args);
577 if (retval == -ENOSPC) {
578 /*
579 * Promote the attribute list to the Btree format, then
580 * Commit that transaction so that the node_addname() call
581 * can manage its own transactions.
582 */
583 error = xfs_attr3_leaf_to_node(args);
584 if (error)
585 return error;
586 error = xfs_defer_finish(&args->trans);
587 if (error)
588 return error;
589
590 /*
591 * Commit the current trans (including the inode) and start
592 * a new one.
593 */
594 error = xfs_trans_roll_inode(&args->trans, dp);
595 if (error)
596 return error;
597
598 /*
599 * Fob the whole rest of the problem off on the Btree code.
600 */
601 error = xfs_attr_node_addname(args);
602 return error;
603 }
604
605 /*
606 * Commit the transaction that added the attr name so that
607 * later routines can manage their own transactions.
608 */
609 error = xfs_trans_roll_inode(&args->trans, dp);
610 if (error)
611 return error;
612
613 /*
614 * If there was an out-of-line value, allocate the blocks we
615 * identified for its storage and copy the value. This is done
616 * after we create the attribute so that we don't overflow the
617 * maximum size of a transaction and/or hit a deadlock.
618 */
619 if (args->rmtblkno > 0) {
620 error = xfs_attr_rmtval_set(args);
621 if (error)
622 return error;
623 }
624
625 /*
626 * If this is an atomic rename operation, we must "flip" the
627 * incomplete flags on the "new" and "old" attribute/value pairs
628 * so that one disappears and one appears atomically. Then we
629 * must remove the "old" attribute/value pair.
630 */
631 if (args->op_flags & XFS_DA_OP_RENAME) {
632 /*
633 * In a separate transaction, set the incomplete flag on the
634 * "old" attr and clear the incomplete flag on the "new" attr.
635 */
636 error = xfs_attr3_leaf_flipflags(args);
637 if (error)
638 return error;
639
640 /*
641 * Dismantle the "old" attribute/value pair by removing
642 * a "remote" value (if it exists).
643 */
644 args->index = args->index2;
645 args->blkno = args->blkno2;
646 args->rmtblkno = args->rmtblkno2;
647 args->rmtblkcnt = args->rmtblkcnt2;
648 args->rmtvaluelen = args->rmtvaluelen2;
649 if (args->rmtblkno) {
650 error = xfs_attr_rmtval_remove(args);
651 if (error)
652 return error;
653 }
654
655 /*
656 * Read in the block containing the "old" attr, then
657 * remove the "old" attr from that block (neat, huh!)
658 */
659 error = xfs_attr3_leaf_read(args->trans, args->dp, args->blkno,
660 -1, &bp);
661 if (error)
662 return error;
663
664 xfs_attr3_leaf_remove(bp, args);
665
666 /*
667 * If the result is small enough, shrink it all into the inode.
668 */
669 if ((forkoff = xfs_attr_shortform_allfit(bp, dp))) {
670 error = xfs_attr3_leaf_to_shortform(bp, args, forkoff);
671 /* bp is gone due to xfs_da_shrink_inode */
672 if (error)
673 return error;
674 error = xfs_defer_finish(&args->trans);
675 if (error)
676 return error;
677 }
678
679 /*
680 * Commit the remove and start the next trans in series.
681 */
682 error = xfs_trans_roll_inode(&args->trans, dp);
683
684 } else if (args->rmtblkno > 0) {
685 /*
686 * Added a "remote" value, just clear the incomplete flag.
687 */
688 error = xfs_attr3_leaf_clearflag(args);
689 }
690 return error;
691 }
692
693 /*
694 * Remove a name from the leaf attribute list structure
695 *
696 * This leaf block cannot have a "remote" value, we only call this routine
697 * if bmap_one_block() says there is only one block (ie: no remote blks).
698 */
699 STATIC int
700 xfs_attr_leaf_removename(
701 struct xfs_da_args *args)
702 {
703 struct xfs_inode *dp;
704 struct xfs_buf *bp;
705 int error, forkoff;
706
707 trace_xfs_attr_leaf_removename(args);
708
709 /*
710 * Remove the attribute.
711 */
712 dp = args->dp;
713 args->blkno = 0;
714 error = xfs_attr3_leaf_read(args->trans, args->dp, args->blkno, -1, &bp);
715 if (error)
716 return error;
717
718 error = xfs_attr3_leaf_lookup_int(bp, args);
719 if (error == -ENOATTR) {
720 xfs_trans_brelse(args->trans, bp);
721 return error;
722 }
723
724 xfs_attr3_leaf_remove(bp, args);
725
726 /*
727 * If the result is small enough, shrink it all into the inode.
728 */
729 if ((forkoff = xfs_attr_shortform_allfit(bp, dp))) {
730 error = xfs_attr3_leaf_to_shortform(bp, args, forkoff);
731 /* bp is gone due to xfs_da_shrink_inode */
732 if (error)
733 return error;
734 error = xfs_defer_finish(&args->trans);
735 if (error)
736 return error;
737 }
738 return 0;
739 }
740
741 /*
742 * Look up a name in a leaf attribute list structure.
743 *
744 * This leaf block cannot have a "remote" value, we only call this routine
745 * if bmap_one_block() says there is only one block (ie: no remote blks).
746 */
747 STATIC int
748 xfs_attr_leaf_get(xfs_da_args_t *args)
749 {
750 struct xfs_buf *bp;
751 int error;
752
753 trace_xfs_attr_leaf_get(args);
754
755 args->blkno = 0;
756 error = xfs_attr3_leaf_read(args->trans, args->dp, args->blkno, -1, &bp);
757 if (error)
758 return error;
759
760 error = xfs_attr3_leaf_lookup_int(bp, args);
761 if (error != -EEXIST) {
762 xfs_trans_brelse(args->trans, bp);
763 return error;
764 }
765 error = xfs_attr3_leaf_getvalue(bp, args);
766 xfs_trans_brelse(args->trans, bp);
767 if (!error && (args->rmtblkno > 0) && !(args->flags & ATTR_KERNOVAL)) {
768 error = xfs_attr_rmtval_get(args);
769 }
770 return error;
771 }
772
773 /*========================================================================
774 * External routines when attribute list size > geo->blksize
775 *========================================================================*/
776
777 /*
778 * Add a name to a Btree-format attribute list.
779 *
780 * This will involve walking down the Btree, and may involve splitting
781 * leaf nodes and even splitting intermediate nodes up to and including
782 * the root node (a special case of an intermediate node).
783 *
784 * "Remote" attribute values confuse the issue and atomic rename operations
785 * add a whole extra layer of confusion on top of that.
786 */
787 STATIC int
788 xfs_attr_node_addname(
789 struct xfs_da_args *args)
790 {
791 struct xfs_da_state *state;
792 struct xfs_da_state_blk *blk;
793 struct xfs_inode *dp;
794 struct xfs_mount *mp;
795 int retval, error;
796
797 trace_xfs_attr_node_addname(args);
798
799 /*
800 * Fill in bucket of arguments/results/context to carry around.
801 */
802 dp = args->dp;
803 mp = dp->i_mount;
804 restart:
805 state = xfs_da_state_alloc();
806 state->args = args;
807 state->mp = mp;
808
809 /*
810 * Search to see if name already exists, and get back a pointer
811 * to where it should go.
812 */
813 error = xfs_da3_node_lookup_int(state, &retval);
814 if (error)
815 goto out;
816 blk = &state->path.blk[ state->path.active-1 ];
817 ASSERT(blk->magic == XFS_ATTR_LEAF_MAGIC);
818 if ((args->flags & ATTR_REPLACE) && (retval == -ENOATTR)) {
819 goto out;
820 } else if (retval == -EEXIST) {
821 if (args->flags & ATTR_CREATE)
822 goto out;
823
824 trace_xfs_attr_node_replace(args);
825
826 /* save the attribute state for later removal*/
827 args->op_flags |= XFS_DA_OP_RENAME; /* atomic rename op */
828 args->blkno2 = args->blkno; /* set 2nd entry info*/
829 args->index2 = args->index;
830 args->rmtblkno2 = args->rmtblkno;
831 args->rmtblkcnt2 = args->rmtblkcnt;
832 args->rmtvaluelen2 = args->rmtvaluelen;
833
834 /*
835 * clear the remote attr state now that it is saved so that the
836 * values reflect the state of the attribute we are about to
837 * add, not the attribute we just found and will remove later.
838 */
839 args->rmtblkno = 0;
840 args->rmtblkcnt = 0;
841 args->rmtvaluelen = 0;
842 }
843
844 retval = xfs_attr3_leaf_add(blk->bp, state->args);
845 if (retval == -ENOSPC) {
846 if (state->path.active == 1) {
847 /*
848 * Its really a single leaf node, but it had
849 * out-of-line values so it looked like it *might*
850 * have been a b-tree.
851 */
852 xfs_da_state_free(state);
853 state = NULL;
854 error = xfs_attr3_leaf_to_node(args);
855 if (error)
856 goto out;
857 error = xfs_defer_finish(&args->trans);
858 if (error)
859 goto out;
860
861 /*
862 * Commit the node conversion and start the next
863 * trans in the chain.
864 */
865 error = xfs_trans_roll_inode(&args->trans, dp);
866 if (error)
867 goto out;
868
869 goto restart;
870 }
871
872 /*
873 * Split as many Btree elements as required.
874 * This code tracks the new and old attr's location
875 * in the index/blkno/rmtblkno/rmtblkcnt fields and
876 * in the index2/blkno2/rmtblkno2/rmtblkcnt2 fields.
877 */
878 error = xfs_da3_split(state);
879 if (error)
880 goto out;
881 error = xfs_defer_finish(&args->trans);
882 if (error)
883 goto out;
884 } else {
885 /*
886 * Addition succeeded, update Btree hashvals.
887 */
888 xfs_da3_fixhashpath(state, &state->path);
889 }
890
891 /*
892 * Kill the state structure, we're done with it and need to
893 * allow the buffers to come back later.
894 */
895 xfs_da_state_free(state);
896 state = NULL;
897
898 /*
899 * Commit the leaf addition or btree split and start the next
900 * trans in the chain.
901 */
902 error = xfs_trans_roll_inode(&args->trans, dp);
903 if (error)
904 goto out;
905
906 /*
907 * If there was an out-of-line value, allocate the blocks we
908 * identified for its storage and copy the value. This is done
909 * after we create the attribute so that we don't overflow the
910 * maximum size of a transaction and/or hit a deadlock.
911 */
912 if (args->rmtblkno > 0) {
913 error = xfs_attr_rmtval_set(args);
914 if (error)
915 return error;
916 }
917
918 /*
919 * If this is an atomic rename operation, we must "flip" the
920 * incomplete flags on the "new" and "old" attribute/value pairs
921 * so that one disappears and one appears atomically. Then we
922 * must remove the "old" attribute/value pair.
923 */
924 if (args->op_flags & XFS_DA_OP_RENAME) {
925 /*
926 * In a separate transaction, set the incomplete flag on the
927 * "old" attr and clear the incomplete flag on the "new" attr.
928 */
929 error = xfs_attr3_leaf_flipflags(args);
930 if (error)
931 goto out;
932
933 /*
934 * Dismantle the "old" attribute/value pair by removing
935 * a "remote" value (if it exists).
936 */
937 args->index = args->index2;
938 args->blkno = args->blkno2;
939 args->rmtblkno = args->rmtblkno2;
940 args->rmtblkcnt = args->rmtblkcnt2;
941 args->rmtvaluelen = args->rmtvaluelen2;
942 if (args->rmtblkno) {
943 error = xfs_attr_rmtval_remove(args);
944 if (error)
945 return error;
946 }
947
948 /*
949 * Re-find the "old" attribute entry after any split ops.
950 * The INCOMPLETE flag means that we will find the "old"
951 * attr, not the "new" one.
952 */
953 args->flags |= XFS_ATTR_INCOMPLETE;
954 state = xfs_da_state_alloc();
955 state->args = args;
956 state->mp = mp;
957 state->inleaf = 0;
958 error = xfs_da3_node_lookup_int(state, &retval);
959 if (error)
960 goto out;
961
962 /*
963 * Remove the name and update the hashvals in the tree.
964 */
965 blk = &state->path.blk[ state->path.active-1 ];
966 ASSERT(blk->magic == XFS_ATTR_LEAF_MAGIC);
967 error = xfs_attr3_leaf_remove(blk->bp, args);
968 xfs_da3_fixhashpath(state, &state->path);
969
970 /*
971 * Check to see if the tree needs to be collapsed.
972 */
973 if (retval && (state->path.active > 1)) {
974 error = xfs_da3_join(state);
975 if (error)
976 goto out;
977 error = xfs_defer_finish(&args->trans);
978 if (error)
979 goto out;
980 }
981
982 /*
983 * Commit and start the next trans in the chain.
984 */
985 error = xfs_trans_roll_inode(&args->trans, dp);
986 if (error)
987 goto out;
988
989 } else if (args->rmtblkno > 0) {
990 /*
991 * Added a "remote" value, just clear the incomplete flag.
992 */
993 error = xfs_attr3_leaf_clearflag(args);
994 if (error)
995 goto out;
996 }
997 retval = error = 0;
998
999 out:
1000 if (state)
1001 xfs_da_state_free(state);
1002 if (error)
1003 return error;
1004 return retval;
1005 }
1006
1007 /*
1008 * Remove a name from a B-tree attribute list.
1009 *
1010 * This will involve walking down the Btree, and may involve joining
1011 * leaf nodes and even joining intermediate nodes up to and including
1012 * the root node (a special case of an intermediate node).
1013 */
1014 STATIC int
1015 xfs_attr_node_removename(
1016 struct xfs_da_args *args)
1017 {
1018 struct xfs_da_state *state;
1019 struct xfs_da_state_blk *blk;
1020 struct xfs_inode *dp;
1021 struct xfs_buf *bp;
1022 int retval, error, forkoff;
1023
1024 trace_xfs_attr_node_removename(args);
1025
1026 /*
1027 * Tie a string around our finger to remind us where we are.
1028 */
1029 dp = args->dp;
1030 state = xfs_da_state_alloc();
1031 state->args = args;
1032 state->mp = dp->i_mount;
1033
1034 /*
1035 * Search to see if name exists, and get back a pointer to it.
1036 */
1037 error = xfs_da3_node_lookup_int(state, &retval);
1038 if (error || (retval != -EEXIST)) {
1039 if (error == 0)
1040 error = retval;
1041 goto out;
1042 }
1043
1044 /*
1045 * If there is an out-of-line value, de-allocate the blocks.
1046 * This is done before we remove the attribute so that we don't
1047 * overflow the maximum size of a transaction and/or hit a deadlock.
1048 */
1049 blk = &state->path.blk[ state->path.active-1 ];
1050 ASSERT(blk->bp != NULL);
1051 ASSERT(blk->magic == XFS_ATTR_LEAF_MAGIC);
1052 if (args->rmtblkno > 0) {
1053 /*
1054 * Fill in disk block numbers in the state structure
1055 * so that we can get the buffers back after we commit
1056 * several transactions in the following calls.
1057 */
1058 error = xfs_attr_fillstate(state);
1059 if (error)
1060 goto out;
1061
1062 /*
1063 * Mark the attribute as INCOMPLETE, then bunmapi() the
1064 * remote value.
1065 */
1066 error = xfs_attr3_leaf_setflag(args);
1067 if (error)
1068 goto out;
1069 error = xfs_attr_rmtval_remove(args);
1070 if (error)
1071 goto out;
1072
1073 /*
1074 * Refill the state structure with buffers, the prior calls
1075 * released our buffers.
1076 */
1077 error = xfs_attr_refillstate(state);
1078 if (error)
1079 goto out;
1080 }
1081
1082 /*
1083 * Remove the name and update the hashvals in the tree.
1084 */
1085 blk = &state->path.blk[ state->path.active-1 ];
1086 ASSERT(blk->magic == XFS_ATTR_LEAF_MAGIC);
1087 retval = xfs_attr3_leaf_remove(blk->bp, args);
1088 xfs_da3_fixhashpath(state, &state->path);
1089
1090 /*
1091 * Check to see if the tree needs to be collapsed.
1092 */
1093 if (retval && (state->path.active > 1)) {
1094 error = xfs_da3_join(state);
1095 if (error)
1096 goto out;
1097 error = xfs_defer_finish(&args->trans);
1098 if (error)
1099 goto out;
1100 /*
1101 * Commit the Btree join operation and start a new trans.
1102 */
1103 error = xfs_trans_roll_inode(&args->trans, dp);
1104 if (error)
1105 goto out;
1106 }
1107
1108 /*
1109 * If the result is small enough, push it all into the inode.
1110 */
1111 if (xfs_bmap_one_block(dp, XFS_ATTR_FORK)) {
1112 /*
1113 * Have to get rid of the copy of this dabuf in the state.
1114 */
1115 ASSERT(state->path.active == 1);
1116 ASSERT(state->path.blk[0].bp);
1117 state->path.blk[0].bp = NULL;
1118
1119 error = xfs_attr3_leaf_read(args->trans, args->dp, 0, -1, &bp);
1120 if (error)
1121 goto out;
1122
1123 if ((forkoff = xfs_attr_shortform_allfit(bp, dp))) {
1124 error = xfs_attr3_leaf_to_shortform(bp, args, forkoff);
1125 /* bp is gone due to xfs_da_shrink_inode */
1126 if (error)
1127 goto out;
1128 error = xfs_defer_finish(&args->trans);
1129 if (error)
1130 goto out;
1131 } else
1132 xfs_trans_brelse(args->trans, bp);
1133 }
1134 error = 0;
1135
1136 out:
1137 xfs_da_state_free(state);
1138 return error;
1139 }
1140
1141 /*
1142 * Fill in the disk block numbers in the state structure for the buffers
1143 * that are attached to the state structure.
1144 * This is done so that we can quickly reattach ourselves to those buffers
1145 * after some set of transaction commits have released these buffers.
1146 */
1147 STATIC int
1148 xfs_attr_fillstate(xfs_da_state_t *state)
1149 {
1150 xfs_da_state_path_t *path;
1151 xfs_da_state_blk_t *blk;
1152 int level;
1153
1154 trace_xfs_attr_fillstate(state->args);
1155
1156 /*
1157 * Roll down the "path" in the state structure, storing the on-disk
1158 * block number for those buffers in the "path".
1159 */
1160 path = &state->path;
1161 ASSERT((path->active >= 0) && (path->active < XFS_DA_NODE_MAXDEPTH));
1162 for (blk = path->blk, level = 0; level < path->active; blk++, level++) {
1163 if (blk->bp) {
1164 blk->disk_blkno = XFS_BUF_ADDR(blk->bp);
1165 blk->bp = NULL;
1166 } else {
1167 blk->disk_blkno = 0;
1168 }
1169 }
1170
1171 /*
1172 * Roll down the "altpath" in the state structure, storing the on-disk
1173 * block number for those buffers in the "altpath".
1174 */
1175 path = &state->altpath;
1176 ASSERT((path->active >= 0) && (path->active < XFS_DA_NODE_MAXDEPTH));
1177 for (blk = path->blk, level = 0; level < path->active; blk++, level++) {
1178 if (blk->bp) {
1179 blk->disk_blkno = XFS_BUF_ADDR(blk->bp);
1180 blk->bp = NULL;
1181 } else {
1182 blk->disk_blkno = 0;
1183 }
1184 }
1185
1186 return 0;
1187 }
1188
1189 /*
1190 * Reattach the buffers to the state structure based on the disk block
1191 * numbers stored in the state structure.
1192 * This is done after some set of transaction commits have released those
1193 * buffers from our grip.
1194 */
1195 STATIC int
1196 xfs_attr_refillstate(xfs_da_state_t *state)
1197 {
1198 xfs_da_state_path_t *path;
1199 xfs_da_state_blk_t *blk;
1200 int level, error;
1201
1202 trace_xfs_attr_refillstate(state->args);
1203
1204 /*
1205 * Roll down the "path" in the state structure, storing the on-disk
1206 * block number for those buffers in the "path".
1207 */
1208 path = &state->path;
1209 ASSERT((path->active >= 0) && (path->active < XFS_DA_NODE_MAXDEPTH));
1210 for (blk = path->blk, level = 0; level < path->active; blk++, level++) {
1211 if (blk->disk_blkno) {
1212 error = xfs_da3_node_read(state->args->trans,
1213 state->args->dp,
1214 blk->blkno, blk->disk_blkno,
1215 &blk->bp, XFS_ATTR_FORK);
1216 if (error)
1217 return error;
1218 } else {
1219 blk->bp = NULL;
1220 }
1221 }
1222
1223 /*
1224 * Roll down the "altpath" in the state structure, storing the on-disk
1225 * block number for those buffers in the "altpath".
1226 */
1227 path = &state->altpath;
1228 ASSERT((path->active >= 0) && (path->active < XFS_DA_NODE_MAXDEPTH));
1229 for (blk = path->blk, level = 0; level < path->active; blk++, level++) {
1230 if (blk->disk_blkno) {
1231 error = xfs_da3_node_read(state->args->trans,
1232 state->args->dp,
1233 blk->blkno, blk->disk_blkno,
1234 &blk->bp, XFS_ATTR_FORK);
1235 if (error)
1236 return error;
1237 } else {
1238 blk->bp = NULL;
1239 }
1240 }
1241
1242 return 0;
1243 }
1244
1245 /*
1246 * Look up a filename in a node attribute list.
1247 *
1248 * This routine gets called for any attribute fork that has more than one
1249 * block, ie: both true Btree attr lists and for single-leaf-blocks with
1250 * "remote" values taking up more blocks.
1251 */
1252 STATIC int
1253 xfs_attr_node_get(xfs_da_args_t *args)
1254 {
1255 xfs_da_state_t *state;
1256 xfs_da_state_blk_t *blk;
1257 int error, retval;
1258 int i;
1259
1260 trace_xfs_attr_node_get(args);
1261
1262 state = xfs_da_state_alloc();
1263 state->args = args;
1264 state->mp = args->dp->i_mount;
1265
1266 /*
1267 * Search to see if name exists, and get back a pointer to it.
1268 */
1269 error = xfs_da3_node_lookup_int(state, &retval);
1270 if (error) {
1271 retval = error;
1272 } else if (retval == -EEXIST) {
1273 blk = &state->path.blk[ state->path.active-1 ];
1274 ASSERT(blk->bp != NULL);
1275 ASSERT(blk->magic == XFS_ATTR_LEAF_MAGIC);
1276
1277 /*
1278 * Get the value, local or "remote"
1279 */
1280 retval = xfs_attr3_leaf_getvalue(blk->bp, args);
1281 if (!retval && (args->rmtblkno > 0)
1282 && !(args->flags & ATTR_KERNOVAL)) {
1283 retval = xfs_attr_rmtval_get(args);
1284 }
1285 }
1286
1287 /*
1288 * If not in a transaction, we have to release all the buffers.
1289 */
1290 for (i = 0; i < state->path.active; i++) {
1291 xfs_trans_brelse(args->trans, state->path.blk[i].bp);
1292 state->path.blk[i].bp = NULL;
1293 }
1294
1295 xfs_da_state_free(state);
1296 return retval;
1297 }