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