0001
0002
0003
0004
0005
0006 #include "xfs.h"
0007 #include "xfs_fs.h"
0008 #include "xfs_shared.h"
0009 #include "xfs_format.h"
0010 #include "xfs_log_format.h"
0011 #include "xfs_trans_resv.h"
0012 #include "xfs_mount.h"
0013 #include "xfs_defer.h"
0014 #include "xfs_da_format.h"
0015 #include "xfs_da_btree.h"
0016 #include "xfs_attr_sf.h"
0017 #include "xfs_inode.h"
0018 #include "xfs_trans.h"
0019 #include "xfs_bmap.h"
0020 #include "xfs_bmap_btree.h"
0021 #include "xfs_attr.h"
0022 #include "xfs_attr_leaf.h"
0023 #include "xfs_attr_remote.h"
0024 #include "xfs_quota.h"
0025 #include "xfs_trans_space.h"
0026 #include "xfs_trace.h"
0027 #include "xfs_attr_item.h"
0028 #include "xfs_xattr.h"
0029
0030 struct kmem_cache *xfs_attr_intent_cache;
0031
0032
0033
0034
0035
0036
0037
0038
0039
0040
0041
0042
0043
0044
0045 STATIC int xfs_attr_shortform_addname(xfs_da_args_t *args);
0046
0047
0048
0049
0050 STATIC int xfs_attr_leaf_get(xfs_da_args_t *args);
0051 STATIC int xfs_attr_leaf_removename(xfs_da_args_t *args);
0052 STATIC int xfs_attr_leaf_hasname(struct xfs_da_args *args, struct xfs_buf **bp);
0053 STATIC int xfs_attr_leaf_try_add(struct xfs_da_args *args);
0054
0055
0056
0057
0058 STATIC int xfs_attr_node_get(xfs_da_args_t *args);
0059 STATIC void xfs_attr_restore_rmt_blk(struct xfs_da_args *args);
0060 static int xfs_attr_node_try_addname(struct xfs_attr_intent *attr);
0061 STATIC int xfs_attr_node_addname_find_attr(struct xfs_attr_intent *attr);
0062 STATIC int xfs_attr_node_remove_attr(struct xfs_attr_intent *attr);
0063 STATIC int xfs_attr_node_lookup(struct xfs_da_args *args,
0064 struct xfs_da_state *state);
0065
0066 int
0067 xfs_inode_hasattr(
0068 struct xfs_inode *ip)
0069 {
0070 if (!xfs_inode_has_attr_fork(ip))
0071 return 0;
0072 if (ip->i_af.if_format == XFS_DINODE_FMT_EXTENTS &&
0073 ip->i_af.if_nextents == 0)
0074 return 0;
0075 return 1;
0076 }
0077
0078
0079
0080
0081
0082 bool
0083 xfs_attr_is_leaf(
0084 struct xfs_inode *ip)
0085 {
0086 struct xfs_ifork *ifp = &ip->i_af;
0087 struct xfs_iext_cursor icur;
0088 struct xfs_bmbt_irec imap;
0089
0090 if (ifp->if_nextents != 1 || ifp->if_format != XFS_DINODE_FMT_EXTENTS)
0091 return false;
0092
0093 xfs_iext_first(ifp, &icur);
0094 xfs_iext_get_extent(ifp, &icur, &imap);
0095 return imap.br_startoff == 0 && imap.br_blockcount == 1;
0096 }
0097
0098
0099
0100
0101
0102
0103
0104
0105
0106
0107
0108
0109 #if 0
0110
0111
0112
0113
0114
0115
0116 static int
0117 xfs_attr_fillstate(xfs_da_state_t *state)
0118 {
0119 xfs_da_state_path_t *path;
0120 xfs_da_state_blk_t *blk;
0121 int level;
0122
0123 trace_xfs_attr_fillstate(state->args);
0124
0125
0126
0127
0128
0129 path = &state->path;
0130 ASSERT((path->active >= 0) && (path->active < XFS_DA_NODE_MAXDEPTH));
0131 for (blk = path->blk, level = 0; level < path->active; blk++, level++) {
0132 if (blk->bp) {
0133 blk->disk_blkno = xfs_buf_daddr(blk->bp);
0134 blk->bp = NULL;
0135 } else {
0136 blk->disk_blkno = 0;
0137 }
0138 }
0139
0140
0141
0142
0143
0144 path = &state->altpath;
0145 ASSERT((path->active >= 0) && (path->active < XFS_DA_NODE_MAXDEPTH));
0146 for (blk = path->blk, level = 0; level < path->active; blk++, level++) {
0147 if (blk->bp) {
0148 blk->disk_blkno = xfs_buf_daddr(blk->bp);
0149 blk->bp = NULL;
0150 } else {
0151 blk->disk_blkno = 0;
0152 }
0153 }
0154
0155 return 0;
0156 }
0157
0158
0159
0160
0161
0162
0163
0164 static int
0165 xfs_attr_refillstate(xfs_da_state_t *state)
0166 {
0167 xfs_da_state_path_t *path;
0168 xfs_da_state_blk_t *blk;
0169 int level, error;
0170
0171 trace_xfs_attr_refillstate(state->args);
0172
0173
0174
0175
0176
0177 path = &state->path;
0178 ASSERT((path->active >= 0) && (path->active < XFS_DA_NODE_MAXDEPTH));
0179 for (blk = path->blk, level = 0; level < path->active; blk++, level++) {
0180 if (blk->disk_blkno) {
0181 error = xfs_da3_node_read_mapped(state->args->trans,
0182 state->args->dp, blk->disk_blkno,
0183 &blk->bp, XFS_ATTR_FORK);
0184 if (error)
0185 return error;
0186 } else {
0187 blk->bp = NULL;
0188 }
0189 }
0190
0191
0192
0193
0194
0195 path = &state->altpath;
0196 ASSERT((path->active >= 0) && (path->active < XFS_DA_NODE_MAXDEPTH));
0197 for (blk = path->blk, level = 0; level < path->active; blk++, level++) {
0198 if (blk->disk_blkno) {
0199 error = xfs_da3_node_read_mapped(state->args->trans,
0200 state->args->dp, blk->disk_blkno,
0201 &blk->bp, XFS_ATTR_FORK);
0202 if (error)
0203 return error;
0204 } else {
0205 blk->bp = NULL;
0206 }
0207 }
0208
0209 return 0;
0210 }
0211 #else
0212 static int xfs_attr_fillstate(xfs_da_state_t *state) { return 0; }
0213 #endif
0214
0215
0216
0217
0218
0219
0220
0221
0222
0223 int
0224 xfs_attr_get_ilocked(
0225 struct xfs_da_args *args)
0226 {
0227 ASSERT(xfs_isilocked(args->dp, XFS_ILOCK_SHARED | XFS_ILOCK_EXCL));
0228
0229 if (!xfs_inode_hasattr(args->dp))
0230 return -ENOATTR;
0231
0232 if (args->dp->i_af.if_format == XFS_DINODE_FMT_LOCAL)
0233 return xfs_attr_shortform_getvalue(args);
0234 if (xfs_attr_is_leaf(args->dp))
0235 return xfs_attr_leaf_get(args);
0236 return xfs_attr_node_get(args);
0237 }
0238
0239
0240
0241
0242
0243
0244
0245
0246
0247
0248
0249
0250
0251
0252
0253
0254
0255 int
0256 xfs_attr_get(
0257 struct xfs_da_args *args)
0258 {
0259 uint lock_mode;
0260 int error;
0261
0262 XFS_STATS_INC(args->dp->i_mount, xs_attr_get);
0263
0264 if (xfs_is_shutdown(args->dp->i_mount))
0265 return -EIO;
0266
0267 args->geo = args->dp->i_mount->m_attr_geo;
0268 args->whichfork = XFS_ATTR_FORK;
0269 args->hashval = xfs_da_hashname(args->name, args->namelen);
0270
0271
0272 args->op_flags = XFS_DA_OP_OKNOENT;
0273
0274 lock_mode = xfs_ilock_attr_map_shared(args->dp);
0275 error = xfs_attr_get_ilocked(args);
0276 xfs_iunlock(args->dp, lock_mode);
0277
0278 return error;
0279 }
0280
0281
0282
0283
0284 int
0285 xfs_attr_calc_size(
0286 struct xfs_da_args *args,
0287 int *local)
0288 {
0289 struct xfs_mount *mp = args->dp->i_mount;
0290 int size;
0291 int nblks;
0292
0293
0294
0295
0296
0297 size = xfs_attr_leaf_newentsize(args, local);
0298 nblks = XFS_DAENTER_SPACE_RES(mp, XFS_ATTR_FORK);
0299 if (*local) {
0300 if (size > (args->geo->blksize / 2)) {
0301
0302 nblks *= 2;
0303 }
0304 } else {
0305
0306
0307
0308
0309 uint dblocks = xfs_attr3_rmt_blocks(mp, args->valuelen);
0310 nblks += dblocks;
0311 nblks += XFS_NEXTENTADD_SPACE_RES(mp, dblocks, XFS_ATTR_FORK);
0312 }
0313
0314 return nblks;
0315 }
0316
0317
0318 void
0319 xfs_init_attr_trans(
0320 struct xfs_da_args *args,
0321 struct xfs_trans_res *tres,
0322 unsigned int *total)
0323 {
0324 struct xfs_mount *mp = args->dp->i_mount;
0325
0326 if (args->value) {
0327 tres->tr_logres = M_RES(mp)->tr_attrsetm.tr_logres +
0328 M_RES(mp)->tr_attrsetrt.tr_logres *
0329 args->total;
0330 tres->tr_logcount = XFS_ATTRSET_LOG_COUNT;
0331 tres->tr_logflags = XFS_TRANS_PERM_LOG_RES;
0332 *total = args->total;
0333 } else {
0334 *tres = M_RES(mp)->tr_attrrm;
0335 *total = XFS_ATTRRM_SPACE_RES(mp);
0336 }
0337 }
0338
0339
0340
0341
0342
0343
0344 STATIC int
0345 xfs_attr_try_sf_addname(
0346 struct xfs_inode *dp,
0347 struct xfs_da_args *args)
0348 {
0349
0350 int error;
0351
0352
0353
0354
0355 if (dp->i_af.if_format == XFS_DINODE_FMT_EXTENTS)
0356 xfs_attr_shortform_create(args);
0357
0358 error = xfs_attr_shortform_addname(args);
0359 if (error == -ENOSPC)
0360 return error;
0361
0362
0363
0364
0365
0366 if (!error && !(args->op_flags & XFS_DA_OP_NOTIME))
0367 xfs_trans_ichgtime(args->trans, dp, XFS_ICHGTIME_CHG);
0368
0369 if (xfs_has_wsync(dp->i_mount))
0370 xfs_trans_set_sync(args->trans);
0371
0372 return error;
0373 }
0374
0375 static int
0376 xfs_attr_sf_addname(
0377 struct xfs_attr_intent *attr)
0378 {
0379 struct xfs_da_args *args = attr->xattri_da_args;
0380 struct xfs_inode *dp = args->dp;
0381 int error = 0;
0382
0383 error = xfs_attr_try_sf_addname(dp, args);
0384 if (error != -ENOSPC) {
0385 ASSERT(!error || error == -EEXIST);
0386 attr->xattri_dela_state = XFS_DAS_DONE;
0387 goto out;
0388 }
0389
0390
0391
0392
0393
0394 error = xfs_attr_shortform_to_leaf(args);
0395 if (error)
0396 return error;
0397
0398 attr->xattri_dela_state = XFS_DAS_LEAF_ADD;
0399 out:
0400 trace_xfs_attr_sf_addname_return(attr->xattri_dela_state, args->dp);
0401 return error;
0402 }
0403
0404
0405
0406
0407
0408
0409
0410
0411
0412
0413
0414
0415 static enum xfs_delattr_state
0416 xfs_attr_complete_op(
0417 struct xfs_attr_intent *attr,
0418 enum xfs_delattr_state replace_state)
0419 {
0420 struct xfs_da_args *args = attr->xattri_da_args;
0421 bool do_replace = args->op_flags & XFS_DA_OP_REPLACE;
0422
0423 args->op_flags &= ~XFS_DA_OP_REPLACE;
0424 if (do_replace) {
0425 args->attr_filter &= ~XFS_ATTR_INCOMPLETE;
0426 return replace_state;
0427 }
0428 return XFS_DAS_DONE;
0429 }
0430
0431 static int
0432 xfs_attr_leaf_addname(
0433 struct xfs_attr_intent *attr)
0434 {
0435 struct xfs_da_args *args = attr->xattri_da_args;
0436 int error;
0437
0438 ASSERT(xfs_attr_is_leaf(args->dp));
0439
0440
0441
0442
0443
0444 error = xfs_attr_leaf_try_add(args);
0445
0446 if (error == -ENOSPC) {
0447 error = xfs_attr3_leaf_to_node(args);
0448 if (error)
0449 return error;
0450
0451
0452
0453
0454
0455 attr->xattri_dela_state = XFS_DAS_NODE_ADD;
0456 goto out;
0457 }
0458 if (error)
0459 return error;
0460
0461
0462
0463
0464
0465
0466 if (args->rmtblkno)
0467 attr->xattri_dela_state = XFS_DAS_LEAF_SET_RMT;
0468 else
0469 attr->xattri_dela_state = xfs_attr_complete_op(attr,
0470 XFS_DAS_LEAF_REPLACE);
0471 out:
0472 trace_xfs_attr_leaf_addname_return(attr->xattri_dela_state, args->dp);
0473 return error;
0474 }
0475
0476
0477
0478
0479
0480
0481
0482
0483 static int
0484 xfs_attr_node_addname(
0485 struct xfs_attr_intent *attr)
0486 {
0487 struct xfs_da_args *args = attr->xattri_da_args;
0488 int error;
0489
0490 error = xfs_attr_node_addname_find_attr(attr);
0491 if (error)
0492 return error;
0493
0494 error = xfs_attr_node_try_addname(attr);
0495 if (error == -ENOSPC) {
0496 error = xfs_attr3_leaf_to_node(args);
0497 if (error)
0498 return error;
0499
0500
0501
0502
0503 goto out;
0504 }
0505 if (error)
0506 return error;
0507
0508 if (args->rmtblkno)
0509 attr->xattri_dela_state = XFS_DAS_NODE_SET_RMT;
0510 else
0511 attr->xattri_dela_state = xfs_attr_complete_op(attr,
0512 XFS_DAS_NODE_REPLACE);
0513 out:
0514 trace_xfs_attr_node_addname_return(attr->xattri_dela_state, args->dp);
0515 return error;
0516 }
0517
0518 static int
0519 xfs_attr_rmtval_alloc(
0520 struct xfs_attr_intent *attr)
0521 {
0522 struct xfs_da_args *args = attr->xattri_da_args;
0523 int error = 0;
0524
0525
0526
0527
0528
0529
0530
0531 if (attr->xattri_blkcnt > 0) {
0532 error = xfs_attr_rmtval_set_blk(attr);
0533 if (error)
0534 return error;
0535
0536 if (attr->xattri_blkcnt > 0)
0537 goto out;
0538 }
0539
0540 error = xfs_attr_rmtval_set_value(args);
0541 if (error)
0542 return error;
0543
0544 attr->xattri_dela_state = xfs_attr_complete_op(attr,
0545 ++attr->xattri_dela_state);
0546
0547
0548
0549
0550
0551 if (attr->xattri_dela_state == XFS_DAS_DONE)
0552 error = xfs_attr3_leaf_clearflag(args);
0553 out:
0554 trace_xfs_attr_rmtval_alloc(attr->xattri_dela_state, args->dp);
0555 return error;
0556 }
0557
0558
0559
0560
0561
0562 static int
0563 xfs_attr_leaf_mark_incomplete(
0564 struct xfs_da_args *args,
0565 struct xfs_da_state *state)
0566 {
0567 int error;
0568
0569
0570
0571
0572
0573
0574 error = xfs_attr_fillstate(state);
0575 if (error)
0576 return error;
0577
0578
0579
0580
0581 return xfs_attr3_leaf_setflag(args);
0582 }
0583
0584
0585 static inline void
0586 xfs_attr_item_init_da_state(
0587 struct xfs_attr_intent *attr)
0588 {
0589 struct xfs_da_args *args = attr->xattri_da_args;
0590
0591 if (!attr->xattri_da_state)
0592 attr->xattri_da_state = xfs_da_state_alloc(args);
0593 else
0594 xfs_da_state_reset(attr->xattri_da_state, args);
0595 }
0596
0597
0598
0599
0600
0601
0602 static
0603 int xfs_attr_node_removename_setup(
0604 struct xfs_attr_intent *attr)
0605 {
0606 struct xfs_da_args *args = attr->xattri_da_args;
0607 struct xfs_da_state *state;
0608 int error;
0609
0610 xfs_attr_item_init_da_state(attr);
0611 error = xfs_attr_node_lookup(args, attr->xattri_da_state);
0612 if (error != -EEXIST)
0613 goto out;
0614 error = 0;
0615
0616 state = attr->xattri_da_state;
0617 ASSERT(state->path.blk[state->path.active - 1].bp != NULL);
0618 ASSERT(state->path.blk[state->path.active - 1].magic ==
0619 XFS_ATTR_LEAF_MAGIC);
0620
0621 error = xfs_attr_leaf_mark_incomplete(args, state);
0622 if (error)
0623 goto out;
0624 if (args->rmtblkno > 0)
0625 error = xfs_attr_rmtval_invalidate(args);
0626 out:
0627 if (error) {
0628 xfs_da_state_free(attr->xattri_da_state);
0629 attr->xattri_da_state = NULL;
0630 }
0631
0632 return error;
0633 }
0634
0635
0636
0637
0638
0639
0640 static int
0641 xfs_attr_leaf_remove_attr(
0642 struct xfs_attr_intent *attr)
0643 {
0644 struct xfs_da_args *args = attr->xattri_da_args;
0645 struct xfs_inode *dp = args->dp;
0646 struct xfs_buf *bp = NULL;
0647 int forkoff;
0648 int error;
0649
0650 error = xfs_attr3_leaf_read(args->trans, args->dp, args->blkno,
0651 &bp);
0652 if (error)
0653 return error;
0654
0655 xfs_attr3_leaf_remove(bp, args);
0656
0657 forkoff = xfs_attr_shortform_allfit(bp, dp);
0658 if (forkoff)
0659 error = xfs_attr3_leaf_to_shortform(bp, args, forkoff);
0660
0661
0662 return error;
0663 }
0664
0665
0666
0667
0668
0669
0670 static int
0671 xfs_attr_leaf_shrink(
0672 struct xfs_da_args *args)
0673 {
0674 struct xfs_inode *dp = args->dp;
0675 struct xfs_buf *bp;
0676 int forkoff;
0677 int error;
0678
0679 if (!xfs_attr_is_leaf(dp))
0680 return 0;
0681
0682 error = xfs_attr3_leaf_read(args->trans, args->dp, 0, &bp);
0683 if (error)
0684 return error;
0685
0686 forkoff = xfs_attr_shortform_allfit(bp, dp);
0687 if (forkoff) {
0688 error = xfs_attr3_leaf_to_shortform(bp, args, forkoff);
0689
0690 } else {
0691 xfs_trans_brelse(args->trans, bp);
0692 }
0693
0694 return error;
0695 }
0696
0697
0698
0699
0700
0701
0702
0703
0704
0705 int
0706 xfs_attr_set_iter(
0707 struct xfs_attr_intent *attr)
0708 {
0709 struct xfs_da_args *args = attr->xattri_da_args;
0710 int error = 0;
0711
0712
0713 next_state:
0714 switch (attr->xattri_dela_state) {
0715 case XFS_DAS_UNINIT:
0716 ASSERT(0);
0717 return -EFSCORRUPTED;
0718 case XFS_DAS_SF_ADD:
0719 return xfs_attr_sf_addname(attr);
0720 case XFS_DAS_LEAF_ADD:
0721 return xfs_attr_leaf_addname(attr);
0722 case XFS_DAS_NODE_ADD:
0723 return xfs_attr_node_addname(attr);
0724
0725 case XFS_DAS_SF_REMOVE:
0726 error = xfs_attr_sf_removename(args);
0727 attr->xattri_dela_state = xfs_attr_complete_op(attr,
0728 xfs_attr_init_add_state(args));
0729 break;
0730 case XFS_DAS_LEAF_REMOVE:
0731 error = xfs_attr_leaf_removename(args);
0732 attr->xattri_dela_state = xfs_attr_complete_op(attr,
0733 xfs_attr_init_add_state(args));
0734 break;
0735 case XFS_DAS_NODE_REMOVE:
0736 error = xfs_attr_node_removename_setup(attr);
0737 if (error == -ENOATTR &&
0738 (args->op_flags & XFS_DA_OP_RECOVERY)) {
0739 attr->xattri_dela_state = xfs_attr_complete_op(attr,
0740 xfs_attr_init_add_state(args));
0741 error = 0;
0742 break;
0743 }
0744 if (error)
0745 return error;
0746 attr->xattri_dela_state = XFS_DAS_NODE_REMOVE_RMT;
0747 if (args->rmtblkno == 0)
0748 attr->xattri_dela_state++;
0749 break;
0750
0751 case XFS_DAS_LEAF_SET_RMT:
0752 case XFS_DAS_NODE_SET_RMT:
0753 error = xfs_attr_rmtval_find_space(attr);
0754 if (error)
0755 return error;
0756 attr->xattri_dela_state++;
0757 fallthrough;
0758
0759 case XFS_DAS_LEAF_ALLOC_RMT:
0760 case XFS_DAS_NODE_ALLOC_RMT:
0761 error = xfs_attr_rmtval_alloc(attr);
0762 if (error)
0763 return error;
0764 if (attr->xattri_dela_state == XFS_DAS_DONE)
0765 break;
0766 goto next_state;
0767
0768 case XFS_DAS_LEAF_REPLACE:
0769 case XFS_DAS_NODE_REPLACE:
0770
0771
0772
0773
0774
0775 error = xfs_attr3_leaf_flipflags(args);
0776 if (error)
0777 return error;
0778
0779
0780
0781
0782 attr->xattri_dela_state++;
0783 break;
0784
0785 case XFS_DAS_LEAF_REMOVE_OLD:
0786 case XFS_DAS_NODE_REMOVE_OLD:
0787
0788
0789
0790
0791
0792
0793
0794 xfs_attr_restore_rmt_blk(args);
0795 if (args->rmtblkno) {
0796 error = xfs_attr_rmtval_invalidate(args);
0797 if (error)
0798 return error;
0799 } else {
0800 attr->xattri_dela_state++;
0801 }
0802
0803 attr->xattri_dela_state++;
0804 goto next_state;
0805
0806 case XFS_DAS_LEAF_REMOVE_RMT:
0807 case XFS_DAS_NODE_REMOVE_RMT:
0808 error = xfs_attr_rmtval_remove(attr);
0809 if (error == -EAGAIN) {
0810 error = 0;
0811 break;
0812 }
0813 if (error)
0814 return error;
0815
0816
0817
0818
0819
0820
0821
0822
0823
0824 attr->xattri_dela_state++;
0825 break;
0826
0827 case XFS_DAS_LEAF_REMOVE_ATTR:
0828 error = xfs_attr_leaf_remove_attr(attr);
0829 attr->xattri_dela_state = xfs_attr_complete_op(attr,
0830 xfs_attr_init_add_state(args));
0831 break;
0832
0833 case XFS_DAS_NODE_REMOVE_ATTR:
0834 error = xfs_attr_node_remove_attr(attr);
0835 if (!error)
0836 error = xfs_attr_leaf_shrink(args);
0837 attr->xattri_dela_state = xfs_attr_complete_op(attr,
0838 xfs_attr_init_add_state(args));
0839 break;
0840 default:
0841 ASSERT(0);
0842 break;
0843 }
0844
0845 trace_xfs_attr_set_iter_return(attr->xattri_dela_state, args->dp);
0846 return error;
0847 }
0848
0849
0850
0851
0852
0853 static int
0854 xfs_attr_lookup(
0855 struct xfs_da_args *args)
0856 {
0857 struct xfs_inode *dp = args->dp;
0858 struct xfs_buf *bp = NULL;
0859 struct xfs_da_state *state;
0860 int error;
0861
0862 if (!xfs_inode_hasattr(dp))
0863 return -ENOATTR;
0864
0865 if (dp->i_af.if_format == XFS_DINODE_FMT_LOCAL)
0866 return xfs_attr_sf_findname(args, NULL, NULL);
0867
0868 if (xfs_attr_is_leaf(dp)) {
0869 error = xfs_attr_leaf_hasname(args, &bp);
0870
0871 if (bp)
0872 xfs_trans_brelse(args->trans, bp);
0873
0874 return error;
0875 }
0876
0877 state = xfs_da_state_alloc(args);
0878 error = xfs_attr_node_lookup(args, state);
0879 xfs_da_state_free(state);
0880 return error;
0881 }
0882
0883 static int
0884 xfs_attr_intent_init(
0885 struct xfs_da_args *args,
0886 unsigned int op_flags,
0887 struct xfs_attr_intent **attr)
0888 {
0889
0890 struct xfs_attr_intent *new;
0891
0892 new = kmem_cache_zalloc(xfs_attr_intent_cache, GFP_NOFS | __GFP_NOFAIL);
0893 new->xattri_op_flags = op_flags;
0894 new->xattri_da_args = args;
0895
0896 *attr = new;
0897 return 0;
0898 }
0899
0900
0901 static int
0902 xfs_attr_defer_add(
0903 struct xfs_da_args *args)
0904 {
0905 struct xfs_attr_intent *new;
0906 int error = 0;
0907
0908 error = xfs_attr_intent_init(args, XFS_ATTRI_OP_FLAGS_SET, &new);
0909 if (error)
0910 return error;
0911
0912 new->xattri_dela_state = xfs_attr_init_add_state(args);
0913 xfs_defer_add(args->trans, XFS_DEFER_OPS_TYPE_ATTR, &new->xattri_list);
0914 trace_xfs_attr_defer_add(new->xattri_dela_state, args->dp);
0915
0916 return 0;
0917 }
0918
0919
0920 static int
0921 xfs_attr_defer_replace(
0922 struct xfs_da_args *args)
0923 {
0924 struct xfs_attr_intent *new;
0925 int error = 0;
0926
0927 error = xfs_attr_intent_init(args, XFS_ATTRI_OP_FLAGS_REPLACE, &new);
0928 if (error)
0929 return error;
0930
0931 new->xattri_dela_state = xfs_attr_init_replace_state(args);
0932 xfs_defer_add(args->trans, XFS_DEFER_OPS_TYPE_ATTR, &new->xattri_list);
0933 trace_xfs_attr_defer_replace(new->xattri_dela_state, args->dp);
0934
0935 return 0;
0936 }
0937
0938
0939 static int
0940 xfs_attr_defer_remove(
0941 struct xfs_da_args *args)
0942 {
0943
0944 struct xfs_attr_intent *new;
0945 int error;
0946
0947 error = xfs_attr_intent_init(args, XFS_ATTRI_OP_FLAGS_REMOVE, &new);
0948 if (error)
0949 return error;
0950
0951 new->xattri_dela_state = xfs_attr_init_remove_state(args);
0952 xfs_defer_add(args->trans, XFS_DEFER_OPS_TYPE_ATTR, &new->xattri_list);
0953 trace_xfs_attr_defer_remove(new->xattri_dela_state, args->dp);
0954
0955 return 0;
0956 }
0957
0958
0959
0960
0961
0962 int
0963 xfs_attr_set(
0964 struct xfs_da_args *args)
0965 {
0966 struct xfs_inode *dp = args->dp;
0967 struct xfs_mount *mp = dp->i_mount;
0968 struct xfs_trans_res tres;
0969 bool rsvd = (args->attr_filter & XFS_ATTR_ROOT);
0970 int error, local;
0971 int rmt_blks = 0;
0972 unsigned int total;
0973
0974 if (xfs_is_shutdown(dp->i_mount))
0975 return -EIO;
0976
0977 error = xfs_qm_dqattach(dp);
0978 if (error)
0979 return error;
0980
0981 args->geo = mp->m_attr_geo;
0982 args->whichfork = XFS_ATTR_FORK;
0983 args->hashval = xfs_da_hashname(args->name, args->namelen);
0984
0985
0986
0987
0988
0989
0990
0991 args->op_flags = XFS_DA_OP_OKNOENT |
0992 (args->op_flags & XFS_DA_OP_LOGGED);
0993
0994 if (args->value) {
0995 XFS_STATS_INC(mp, xs_attr_set);
0996 args->total = xfs_attr_calc_size(args, &local);
0997
0998
0999
1000
1001
1002 if (xfs_inode_has_attr_fork(dp) == 0) {
1003 int sf_size = sizeof(struct xfs_attr_sf_hdr) +
1004 xfs_attr_sf_entsize_byname(args->namelen,
1005 args->valuelen);
1006
1007 error = xfs_bmap_add_attrfork(dp, sf_size, rsvd);
1008 if (error)
1009 return error;
1010 }
1011
1012 if (!local)
1013 rmt_blks = xfs_attr3_rmt_blocks(mp, args->valuelen);
1014 } else {
1015 XFS_STATS_INC(mp, xs_attr_remove);
1016 rmt_blks = xfs_attr3_rmt_blocks(mp, XFS_XATTR_SIZE_MAX);
1017 }
1018
1019
1020
1021
1022
1023 xfs_init_attr_trans(args, &tres, &total);
1024 error = xfs_trans_alloc_inode(dp, &tres, total, 0, rsvd, &args->trans);
1025 if (error)
1026 return error;
1027
1028 if (args->value || xfs_inode_hasattr(dp)) {
1029 error = xfs_iext_count_may_overflow(dp, XFS_ATTR_FORK,
1030 XFS_IEXT_ATTR_MANIP_CNT(rmt_blks));
1031 if (error == -EFBIG)
1032 error = xfs_iext_count_upgrade(args->trans, dp,
1033 XFS_IEXT_ATTR_MANIP_CNT(rmt_blks));
1034 if (error)
1035 goto out_trans_cancel;
1036 }
1037
1038 error = xfs_attr_lookup(args);
1039 switch (error) {
1040 case -EEXIST:
1041
1042 if (!args->value) {
1043 error = xfs_attr_defer_remove(args);
1044 break;
1045 }
1046
1047 if (args->attr_flags & XATTR_CREATE)
1048 goto out_trans_cancel;
1049
1050 error = xfs_attr_defer_replace(args);
1051 break;
1052 case -ENOATTR:
1053
1054 if (!args->value)
1055 goto out_trans_cancel;
1056
1057
1058 if (args->attr_flags & XATTR_REPLACE)
1059 goto out_trans_cancel;
1060
1061 error = xfs_attr_defer_add(args);
1062 break;
1063 default:
1064 goto out_trans_cancel;
1065 }
1066 if (error)
1067 goto out_trans_cancel;
1068
1069
1070
1071
1072
1073 if (xfs_has_wsync(mp))
1074 xfs_trans_set_sync(args->trans);
1075
1076 if (!(args->op_flags & XFS_DA_OP_NOTIME))
1077 xfs_trans_ichgtime(args->trans, dp, XFS_ICHGTIME_CHG);
1078
1079
1080
1081
1082 xfs_trans_log_inode(args->trans, dp, XFS_ILOG_CORE);
1083 error = xfs_trans_commit(args->trans);
1084 out_unlock:
1085 xfs_iunlock(dp, XFS_ILOCK_EXCL);
1086 return error;
1087
1088 out_trans_cancel:
1089 if (args->trans)
1090 xfs_trans_cancel(args->trans);
1091 goto out_unlock;
1092 }
1093
1094
1095
1096
1097
1098 static inline int xfs_attr_sf_totsize(struct xfs_inode *dp)
1099 {
1100 struct xfs_attr_shortform *sf;
1101
1102 sf = (struct xfs_attr_shortform *)dp->i_af.if_u1.if_data;
1103 return be16_to_cpu(sf->hdr.totsize);
1104 }
1105
1106
1107
1108
1109
1110 static int
1111 xfs_attr_shortform_addname(
1112 struct xfs_da_args *args)
1113 {
1114 int newsize, forkoff;
1115 int error;
1116
1117 trace_xfs_attr_sf_addname(args);
1118
1119 error = xfs_attr_shortform_lookup(args);
1120 switch (error) {
1121 case -ENOATTR:
1122 if (args->op_flags & XFS_DA_OP_REPLACE)
1123 return error;
1124 break;
1125 case -EEXIST:
1126 if (!(args->op_flags & XFS_DA_OP_REPLACE))
1127 return error;
1128
1129 error = xfs_attr_sf_removename(args);
1130 if (error)
1131 return error;
1132
1133
1134
1135
1136
1137
1138
1139 args->op_flags &= ~XFS_DA_OP_REPLACE;
1140 break;
1141 case 0:
1142 break;
1143 default:
1144 return error;
1145 }
1146
1147 if (args->namelen >= XFS_ATTR_SF_ENTSIZE_MAX ||
1148 args->valuelen >= XFS_ATTR_SF_ENTSIZE_MAX)
1149 return -ENOSPC;
1150
1151 newsize = xfs_attr_sf_totsize(args->dp);
1152 newsize += xfs_attr_sf_entsize_byname(args->namelen, args->valuelen);
1153
1154 forkoff = xfs_attr_shortform_bytesfit(args->dp, newsize);
1155 if (!forkoff)
1156 return -ENOSPC;
1157
1158 xfs_attr_shortform_add(args, forkoff);
1159 return 0;
1160 }
1161
1162
1163
1164
1165
1166
1167
1168 static void
1169 xfs_attr_save_rmt_blk(
1170 struct xfs_da_args *args)
1171 {
1172 args->blkno2 = args->blkno;
1173 args->index2 = args->index;
1174 args->rmtblkno2 = args->rmtblkno;
1175 args->rmtblkcnt2 = args->rmtblkcnt;
1176 args->rmtvaluelen2 = args->rmtvaluelen;
1177 args->rmtblkno = 0;
1178 args->rmtblkcnt = 0;
1179 args->rmtvaluelen = 0;
1180 }
1181
1182
1183 static void
1184 xfs_attr_restore_rmt_blk(
1185 struct xfs_da_args *args)
1186 {
1187 args->blkno = args->blkno2;
1188 args->index = args->index2;
1189 args->rmtblkno = args->rmtblkno2;
1190 args->rmtblkcnt = args->rmtblkcnt2;
1191 args->rmtvaluelen = args->rmtvaluelen2;
1192 }
1193
1194
1195
1196
1197
1198
1199
1200
1201
1202
1203
1204 STATIC int
1205 xfs_attr_leaf_try_add(
1206 struct xfs_da_args *args)
1207 {
1208 struct xfs_buf *bp;
1209 int error;
1210
1211 error = xfs_attr3_leaf_read(args->trans, args->dp, 0, &bp);
1212 if (error)
1213 return error;
1214
1215
1216
1217
1218 error = xfs_attr3_leaf_lookup_int(bp, args);
1219 switch (error) {
1220 case -ENOATTR:
1221 if (args->op_flags & XFS_DA_OP_REPLACE)
1222 goto out_brelse;
1223 break;
1224 case -EEXIST:
1225 if (!(args->op_flags & XFS_DA_OP_REPLACE))
1226 goto out_brelse;
1227
1228 trace_xfs_attr_leaf_replace(args);
1229
1230
1231
1232
1233
1234 xfs_attr_save_rmt_blk(args);
1235 break;
1236 case 0:
1237 break;
1238 default:
1239 goto out_brelse;
1240 }
1241
1242 return xfs_attr3_leaf_add(bp, args);
1243
1244 out_brelse:
1245 xfs_trans_brelse(args->trans, bp);
1246 return error;
1247 }
1248
1249
1250
1251
1252 STATIC int
1253 xfs_attr_leaf_hasname(
1254 struct xfs_da_args *args,
1255 struct xfs_buf **bp)
1256 {
1257 int error = 0;
1258
1259 error = xfs_attr3_leaf_read(args->trans, args->dp, 0, bp);
1260 if (error)
1261 return error;
1262
1263 error = xfs_attr3_leaf_lookup_int(*bp, args);
1264 if (error != -ENOATTR && error != -EEXIST)
1265 xfs_trans_brelse(args->trans, *bp);
1266
1267 return error;
1268 }
1269
1270
1271
1272
1273
1274
1275
1276 STATIC int
1277 xfs_attr_leaf_removename(
1278 struct xfs_da_args *args)
1279 {
1280 struct xfs_inode *dp;
1281 struct xfs_buf *bp;
1282 int error, forkoff;
1283
1284 trace_xfs_attr_leaf_removename(args);
1285
1286
1287
1288
1289 dp = args->dp;
1290
1291 error = xfs_attr_leaf_hasname(args, &bp);
1292 if (error == -ENOATTR) {
1293 xfs_trans_brelse(args->trans, bp);
1294 if (args->op_flags & XFS_DA_OP_RECOVERY)
1295 return 0;
1296 return error;
1297 } else if (error != -EEXIST)
1298 return error;
1299
1300 xfs_attr3_leaf_remove(bp, args);
1301
1302
1303
1304
1305 forkoff = xfs_attr_shortform_allfit(bp, dp);
1306 if (forkoff)
1307 return xfs_attr3_leaf_to_shortform(bp, args, forkoff);
1308
1309
1310 return 0;
1311 }
1312
1313
1314
1315
1316
1317
1318
1319
1320
1321 STATIC int
1322 xfs_attr_leaf_get(xfs_da_args_t *args)
1323 {
1324 struct xfs_buf *bp;
1325 int error;
1326
1327 trace_xfs_attr_leaf_get(args);
1328
1329 error = xfs_attr_leaf_hasname(args, &bp);
1330
1331 if (error == -ENOATTR) {
1332 xfs_trans_brelse(args->trans, bp);
1333 return error;
1334 } else if (error != -EEXIST)
1335 return error;
1336
1337
1338 error = xfs_attr3_leaf_getvalue(bp, args);
1339 xfs_trans_brelse(args->trans, bp);
1340 return error;
1341 }
1342
1343
1344 STATIC int
1345 xfs_attr_node_lookup(
1346 struct xfs_da_args *args,
1347 struct xfs_da_state *state)
1348 {
1349 int retval, error;
1350
1351
1352
1353
1354 error = xfs_da3_node_lookup_int(state, &retval);
1355 if (error)
1356 return error;
1357
1358 return retval;
1359 }
1360
1361
1362
1363
1364
1365 STATIC int
1366 xfs_attr_node_addname_find_attr(
1367 struct xfs_attr_intent *attr)
1368 {
1369 struct xfs_da_args *args = attr->xattri_da_args;
1370 int error;
1371
1372
1373
1374
1375
1376 xfs_attr_item_init_da_state(attr);
1377 error = xfs_attr_node_lookup(args, attr->xattri_da_state);
1378 switch (error) {
1379 case -ENOATTR:
1380 if (args->op_flags & XFS_DA_OP_REPLACE)
1381 goto error;
1382 break;
1383 case -EEXIST:
1384 if (!(args->op_flags & XFS_DA_OP_REPLACE))
1385 goto error;
1386
1387
1388 trace_xfs_attr_node_replace(args);
1389
1390
1391
1392
1393
1394 xfs_attr_save_rmt_blk(args);
1395 break;
1396 case 0:
1397 break;
1398 default:
1399 goto error;
1400 }
1401
1402 return 0;
1403 error:
1404 if (attr->xattri_da_state) {
1405 xfs_da_state_free(attr->xattri_da_state);
1406 attr->xattri_da_state = NULL;
1407 }
1408 return error;
1409 }
1410
1411
1412
1413
1414
1415
1416
1417
1418 static int
1419 xfs_attr_node_try_addname(
1420 struct xfs_attr_intent *attr)
1421 {
1422 struct xfs_da_state *state = attr->xattri_da_state;
1423 struct xfs_da_state_blk *blk;
1424 int error;
1425
1426 trace_xfs_attr_node_addname(state->args);
1427
1428 blk = &state->path.blk[state->path.active-1];
1429 ASSERT(blk->magic == XFS_ATTR_LEAF_MAGIC);
1430
1431 error = xfs_attr3_leaf_add(blk->bp, state->args);
1432 if (error == -ENOSPC) {
1433 if (state->path.active == 1) {
1434
1435
1436
1437
1438
1439 goto out;
1440 }
1441
1442
1443
1444
1445
1446
1447
1448 error = xfs_da3_split(state);
1449 if (error)
1450 goto out;
1451 } else {
1452
1453
1454
1455 xfs_da3_fixhashpath(state, &state->path);
1456 }
1457
1458 out:
1459 xfs_da_state_free(state);
1460 attr->xattri_da_state = NULL;
1461 return error;
1462 }
1463
1464 static int
1465 xfs_attr_node_removename(
1466 struct xfs_da_args *args,
1467 struct xfs_da_state *state)
1468 {
1469 struct xfs_da_state_blk *blk;
1470 int retval;
1471
1472
1473
1474
1475 blk = &state->path.blk[state->path.active-1];
1476 ASSERT(blk->magic == XFS_ATTR_LEAF_MAGIC);
1477 retval = xfs_attr3_leaf_remove(blk->bp, args);
1478 xfs_da3_fixhashpath(state, &state->path);
1479
1480 return retval;
1481 }
1482
1483 static int
1484 xfs_attr_node_remove_attr(
1485 struct xfs_attr_intent *attr)
1486 {
1487 struct xfs_da_args *args = attr->xattri_da_args;
1488 struct xfs_da_state *state = xfs_da_state_alloc(args);
1489 int retval = 0;
1490 int error = 0;
1491
1492
1493
1494
1495
1496
1497 args->attr_filter |= XFS_ATTR_INCOMPLETE;
1498 error = xfs_da3_node_lookup_int(state, &retval);
1499 if (error)
1500 goto out;
1501
1502 error = xfs_attr_node_removename(args, state);
1503
1504
1505
1506
1507 if (retval && (state->path.active > 1)) {
1508 error = xfs_da3_join(state);
1509 if (error)
1510 goto out;
1511 }
1512 retval = error = 0;
1513
1514 out:
1515 xfs_da_state_free(state);
1516 if (error)
1517 return error;
1518 return retval;
1519 }
1520
1521
1522
1523
1524
1525
1526
1527
1528
1529
1530 STATIC int
1531 xfs_attr_node_get(
1532 struct xfs_da_args *args)
1533 {
1534 struct xfs_da_state *state;
1535 struct xfs_da_state_blk *blk;
1536 int i;
1537 int error;
1538
1539 trace_xfs_attr_node_get(args);
1540
1541
1542
1543
1544 state = xfs_da_state_alloc(args);
1545 error = xfs_attr_node_lookup(args, state);
1546 if (error != -EEXIST)
1547 goto out_release;
1548
1549
1550
1551
1552 blk = &state->path.blk[state->path.active - 1];
1553 error = xfs_attr3_leaf_getvalue(blk->bp, args);
1554
1555
1556
1557
1558 out_release:
1559 for (i = 0; i < state->path.active; i++) {
1560 xfs_trans_brelse(args->trans, state->path.blk[i].bp);
1561 state->path.blk[i].bp = NULL;
1562 }
1563
1564 xfs_da_state_free(state);
1565 return error;
1566 }
1567
1568
1569 bool
1570 xfs_attr_namecheck(
1571 const void *name,
1572 size_t length)
1573 {
1574
1575
1576
1577
1578 if (length >= MAXNAMELEN)
1579 return false;
1580
1581
1582 return !memchr(name, 0, length);
1583 }
1584
1585 int __init
1586 xfs_attr_intent_init_cache(void)
1587 {
1588 xfs_attr_intent_cache = kmem_cache_create("xfs_attr_intent",
1589 sizeof(struct xfs_attr_intent),
1590 0, 0, NULL);
1591
1592 return xfs_attr_intent_cache != NULL ? 0 : -ENOMEM;
1593 }
1594
1595 void
1596 xfs_attr_intent_destroy_cache(void)
1597 {
1598 kmem_cache_destroy(xfs_attr_intent_cache);
1599 xfs_attr_intent_cache = NULL;
1600 }