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