0001
0002
0003
0004
0005
0006
0007 #include "xfs.h"
0008 #include "xfs_fs.h"
0009 #include "xfs_format.h"
0010 #include "xfs_trans_resv.h"
0011 #include "xfs_shared.h"
0012 #include "xfs_mount.h"
0013 #include "xfs_defer.h"
0014 #include "xfs_log_format.h"
0015 #include "xfs_trans.h"
0016 #include "xfs_bmap_btree.h"
0017 #include "xfs_trans_priv.h"
0018 #include "xfs_log.h"
0019 #include "xfs_inode.h"
0020 #include "xfs_da_format.h"
0021 #include "xfs_da_btree.h"
0022 #include "xfs_attr.h"
0023 #include "xfs_attr_item.h"
0024 #include "xfs_trace.h"
0025 #include "xfs_trans_space.h"
0026 #include "xfs_errortag.h"
0027 #include "xfs_error.h"
0028 #include "xfs_log_priv.h"
0029 #include "xfs_log_recover.h"
0030
0031 struct kmem_cache *xfs_attri_cache;
0032 struct kmem_cache *xfs_attrd_cache;
0033
0034 static const struct xfs_item_ops xfs_attri_item_ops;
0035 static const struct xfs_item_ops xfs_attrd_item_ops;
0036 static struct xfs_attrd_log_item *xfs_trans_get_attrd(struct xfs_trans *tp,
0037 struct xfs_attri_log_item *attrip);
0038
0039 static inline struct xfs_attri_log_item *ATTRI_ITEM(struct xfs_log_item *lip)
0040 {
0041 return container_of(lip, struct xfs_attri_log_item, attri_item);
0042 }
0043
0044
0045
0046
0047
0048
0049
0050
0051
0052
0053
0054
0055 static inline struct xfs_attri_log_nameval *
0056 xfs_attri_log_nameval_get(
0057 struct xfs_attri_log_nameval *nv)
0058 {
0059 if (!refcount_inc_not_zero(&nv->refcount))
0060 return NULL;
0061 return nv;
0062 }
0063
0064 static inline void
0065 xfs_attri_log_nameval_put(
0066 struct xfs_attri_log_nameval *nv)
0067 {
0068 if (!nv)
0069 return;
0070 if (refcount_dec_and_test(&nv->refcount))
0071 kvfree(nv);
0072 }
0073
0074 static inline struct xfs_attri_log_nameval *
0075 xfs_attri_log_nameval_alloc(
0076 const void *name,
0077 unsigned int name_len,
0078 const void *value,
0079 unsigned int value_len)
0080 {
0081 struct xfs_attri_log_nameval *nv;
0082
0083
0084
0085
0086
0087 nv = xlog_kvmalloc(sizeof(struct xfs_attri_log_nameval) +
0088 name_len + value_len);
0089 if (!nv)
0090 return nv;
0091
0092 nv->name.i_addr = nv + 1;
0093 nv->name.i_len = name_len;
0094 nv->name.i_type = XLOG_REG_TYPE_ATTR_NAME;
0095 memcpy(nv->name.i_addr, name, name_len);
0096
0097 if (value_len) {
0098 nv->value.i_addr = nv->name.i_addr + name_len;
0099 nv->value.i_len = value_len;
0100 memcpy(nv->value.i_addr, value, value_len);
0101 } else {
0102 nv->value.i_addr = NULL;
0103 nv->value.i_len = 0;
0104 }
0105 nv->value.i_type = XLOG_REG_TYPE_ATTR_VALUE;
0106
0107 refcount_set(&nv->refcount, 1);
0108 return nv;
0109 }
0110
0111 STATIC void
0112 xfs_attri_item_free(
0113 struct xfs_attri_log_item *attrip)
0114 {
0115 kmem_free(attrip->attri_item.li_lv_shadow);
0116 xfs_attri_log_nameval_put(attrip->attri_nameval);
0117 kmem_cache_free(xfs_attri_cache, attrip);
0118 }
0119
0120
0121
0122
0123
0124
0125
0126
0127 STATIC void
0128 xfs_attri_release(
0129 struct xfs_attri_log_item *attrip)
0130 {
0131 ASSERT(atomic_read(&attrip->attri_refcount) > 0);
0132 if (!atomic_dec_and_test(&attrip->attri_refcount))
0133 return;
0134
0135 xfs_trans_ail_delete(&attrip->attri_item, 0);
0136 xfs_attri_item_free(attrip);
0137 }
0138
0139 STATIC void
0140 xfs_attri_item_size(
0141 struct xfs_log_item *lip,
0142 int *nvecs,
0143 int *nbytes)
0144 {
0145 struct xfs_attri_log_item *attrip = ATTRI_ITEM(lip);
0146 struct xfs_attri_log_nameval *nv = attrip->attri_nameval;
0147
0148 *nvecs += 2;
0149 *nbytes += sizeof(struct xfs_attri_log_format) +
0150 xlog_calc_iovec_len(nv->name.i_len);
0151
0152 if (!nv->value.i_len)
0153 return;
0154
0155 *nvecs += 1;
0156 *nbytes += xlog_calc_iovec_len(nv->value.i_len);
0157 }
0158
0159
0160
0161
0162
0163
0164 STATIC void
0165 xfs_attri_item_format(
0166 struct xfs_log_item *lip,
0167 struct xfs_log_vec *lv)
0168 {
0169 struct xfs_attri_log_item *attrip = ATTRI_ITEM(lip);
0170 struct xfs_log_iovec *vecp = NULL;
0171 struct xfs_attri_log_nameval *nv = attrip->attri_nameval;
0172
0173 attrip->attri_format.alfi_type = XFS_LI_ATTRI;
0174 attrip->attri_format.alfi_size = 1;
0175
0176
0177
0178
0179
0180
0181
0182
0183 ASSERT(nv->name.i_len > 0);
0184 attrip->attri_format.alfi_size++;
0185
0186 if (nv->value.i_len > 0)
0187 attrip->attri_format.alfi_size++;
0188
0189 xlog_copy_iovec(lv, &vecp, XLOG_REG_TYPE_ATTRI_FORMAT,
0190 &attrip->attri_format,
0191 sizeof(struct xfs_attri_log_format));
0192 xlog_copy_from_iovec(lv, &vecp, &nv->name);
0193 if (nv->value.i_len > 0)
0194 xlog_copy_from_iovec(lv, &vecp, &nv->value);
0195 }
0196
0197
0198
0199
0200
0201
0202
0203
0204
0205
0206 STATIC void
0207 xfs_attri_item_unpin(
0208 struct xfs_log_item *lip,
0209 int remove)
0210 {
0211 xfs_attri_release(ATTRI_ITEM(lip));
0212 }
0213
0214
0215 STATIC void
0216 xfs_attri_item_release(
0217 struct xfs_log_item *lip)
0218 {
0219 xfs_attri_release(ATTRI_ITEM(lip));
0220 }
0221
0222
0223
0224
0225
0226 STATIC struct xfs_attri_log_item *
0227 xfs_attri_init(
0228 struct xfs_mount *mp,
0229 struct xfs_attri_log_nameval *nv)
0230 {
0231 struct xfs_attri_log_item *attrip;
0232
0233 attrip = kmem_cache_zalloc(xfs_attri_cache, GFP_NOFS | __GFP_NOFAIL);
0234
0235
0236
0237
0238
0239 attrip->attri_nameval = xfs_attri_log_nameval_get(nv);
0240 ASSERT(attrip->attri_nameval);
0241
0242 xfs_log_item_init(mp, &attrip->attri_item, XFS_LI_ATTRI,
0243 &xfs_attri_item_ops);
0244 attrip->attri_format.alfi_id = (uintptr_t)(void *)attrip;
0245 atomic_set(&attrip->attri_refcount, 2);
0246
0247 return attrip;
0248 }
0249
0250
0251
0252
0253
0254 STATIC int
0255 xfs_attri_copy_format(
0256 struct xfs_log_iovec *buf,
0257 struct xfs_attri_log_format *dst_attr_fmt)
0258 {
0259 struct xfs_attri_log_format *src_attr_fmt = buf->i_addr;
0260 size_t len;
0261
0262 len = sizeof(struct xfs_attri_log_format);
0263 if (buf->i_len != len) {
0264 XFS_ERROR_REPORT(__func__, XFS_ERRLEVEL_LOW, NULL);
0265 return -EFSCORRUPTED;
0266 }
0267
0268 memcpy((char *)dst_attr_fmt, (char *)src_attr_fmt, len);
0269 return 0;
0270 }
0271
0272 static inline struct xfs_attrd_log_item *ATTRD_ITEM(struct xfs_log_item *lip)
0273 {
0274 return container_of(lip, struct xfs_attrd_log_item, attrd_item);
0275 }
0276
0277 STATIC void
0278 xfs_attrd_item_free(struct xfs_attrd_log_item *attrdp)
0279 {
0280 kmem_free(attrdp->attrd_item.li_lv_shadow);
0281 kmem_cache_free(xfs_attrd_cache, attrdp);
0282 }
0283
0284 STATIC void
0285 xfs_attrd_item_size(
0286 struct xfs_log_item *lip,
0287 int *nvecs,
0288 int *nbytes)
0289 {
0290 *nvecs += 1;
0291 *nbytes += sizeof(struct xfs_attrd_log_format);
0292 }
0293
0294
0295
0296
0297
0298
0299 STATIC void
0300 xfs_attrd_item_format(
0301 struct xfs_log_item *lip,
0302 struct xfs_log_vec *lv)
0303 {
0304 struct xfs_attrd_log_item *attrdp = ATTRD_ITEM(lip);
0305 struct xfs_log_iovec *vecp = NULL;
0306
0307 attrdp->attrd_format.alfd_type = XFS_LI_ATTRD;
0308 attrdp->attrd_format.alfd_size = 1;
0309
0310 xlog_copy_iovec(lv, &vecp, XLOG_REG_TYPE_ATTRD_FORMAT,
0311 &attrdp->attrd_format,
0312 sizeof(struct xfs_attrd_log_format));
0313 }
0314
0315
0316
0317
0318
0319
0320 STATIC void
0321 xfs_attrd_item_release(
0322 struct xfs_log_item *lip)
0323 {
0324 struct xfs_attrd_log_item *attrdp = ATTRD_ITEM(lip);
0325
0326 xfs_attri_release(attrdp->attrd_attrip);
0327 xfs_attrd_item_free(attrdp);
0328 }
0329
0330 static struct xfs_log_item *
0331 xfs_attrd_item_intent(
0332 struct xfs_log_item *lip)
0333 {
0334 return &ATTRD_ITEM(lip)->attrd_attrip->attri_item;
0335 }
0336
0337
0338
0339
0340
0341
0342
0343 STATIC int
0344 xfs_xattri_finish_update(
0345 struct xfs_attr_intent *attr,
0346 struct xfs_attrd_log_item *attrdp)
0347 {
0348 struct xfs_da_args *args = attr->xattri_da_args;
0349 int error;
0350
0351 if (XFS_TEST_ERROR(false, args->dp->i_mount, XFS_ERRTAG_LARP)) {
0352 error = -EIO;
0353 goto out;
0354 }
0355
0356 error = xfs_attr_set_iter(attr);
0357 if (!error && attr->xattri_dela_state != XFS_DAS_DONE)
0358 error = -EAGAIN;
0359 out:
0360
0361
0362
0363
0364
0365
0366
0367 args->trans->t_flags |= XFS_TRANS_DIRTY | XFS_TRANS_HAS_INTENT_DONE;
0368
0369
0370
0371
0372 if (attrdp)
0373 set_bit(XFS_LI_DIRTY, &attrdp->attrd_item.li_flags);
0374
0375 return error;
0376 }
0377
0378
0379 STATIC void
0380 xfs_attr_log_item(
0381 struct xfs_trans *tp,
0382 struct xfs_attri_log_item *attrip,
0383 const struct xfs_attr_intent *attr)
0384 {
0385 struct xfs_attri_log_format *attrp;
0386
0387 tp->t_flags |= XFS_TRANS_DIRTY;
0388 set_bit(XFS_LI_DIRTY, &attrip->attri_item.li_flags);
0389
0390
0391
0392
0393
0394
0395 attrp = &attrip->attri_format;
0396 attrp->alfi_ino = attr->xattri_da_args->dp->i_ino;
0397 ASSERT(!(attr->xattri_op_flags & ~XFS_ATTRI_OP_FLAGS_TYPE_MASK));
0398 attrp->alfi_op_flags = attr->xattri_op_flags;
0399 attrp->alfi_value_len = attr->xattri_nameval->value.i_len;
0400 attrp->alfi_name_len = attr->xattri_nameval->name.i_len;
0401 ASSERT(!(attr->xattri_da_args->attr_filter & ~XFS_ATTRI_FILTER_MASK));
0402 attrp->alfi_attr_filter = attr->xattri_da_args->attr_filter;
0403 }
0404
0405
0406 static struct xfs_log_item *
0407 xfs_attr_create_intent(
0408 struct xfs_trans *tp,
0409 struct list_head *items,
0410 unsigned int count,
0411 bool sort)
0412 {
0413 struct xfs_mount *mp = tp->t_mountp;
0414 struct xfs_attri_log_item *attrip;
0415 struct xfs_attr_intent *attr;
0416 struct xfs_da_args *args;
0417
0418 ASSERT(count == 1);
0419
0420
0421
0422
0423
0424 attr = list_first_entry_or_null(items, struct xfs_attr_intent,
0425 xattri_list);
0426 args = attr->xattri_da_args;
0427
0428 if (!(args->op_flags & XFS_DA_OP_LOGGED))
0429 return NULL;
0430
0431
0432
0433
0434
0435
0436 if (!attr->xattri_nameval) {
0437
0438
0439
0440
0441 attr->xattri_nameval = xfs_attri_log_nameval_alloc(args->name,
0442 args->namelen, args->value, args->valuelen);
0443 }
0444 if (!attr->xattri_nameval)
0445 return ERR_PTR(-ENOMEM);
0446
0447 attrip = xfs_attri_init(mp, attr->xattri_nameval);
0448 xfs_trans_add_item(tp, &attrip->attri_item);
0449 xfs_attr_log_item(tp, attrip, attr);
0450
0451 return &attrip->attri_item;
0452 }
0453
0454 static inline void
0455 xfs_attr_free_item(
0456 struct xfs_attr_intent *attr)
0457 {
0458 if (attr->xattri_da_state)
0459 xfs_da_state_free(attr->xattri_da_state);
0460 xfs_attri_log_nameval_put(attr->xattri_nameval);
0461 if (attr->xattri_da_args->op_flags & XFS_DA_OP_RECOVERY)
0462 kmem_free(attr);
0463 else
0464 kmem_cache_free(xfs_attr_intent_cache, attr);
0465 }
0466
0467
0468 STATIC int
0469 xfs_attr_finish_item(
0470 struct xfs_trans *tp,
0471 struct xfs_log_item *done,
0472 struct list_head *item,
0473 struct xfs_btree_cur **state)
0474 {
0475 struct xfs_attr_intent *attr;
0476 struct xfs_attrd_log_item *done_item = NULL;
0477 int error;
0478
0479 attr = container_of(item, struct xfs_attr_intent, xattri_list);
0480 if (done)
0481 done_item = ATTRD_ITEM(done);
0482
0483
0484
0485
0486
0487 attr->xattri_da_args->trans = tp;
0488
0489 error = xfs_xattri_finish_update(attr, done_item);
0490 if (error != -EAGAIN)
0491 xfs_attr_free_item(attr);
0492
0493 return error;
0494 }
0495
0496
0497 STATIC void
0498 xfs_attr_abort_intent(
0499 struct xfs_log_item *intent)
0500 {
0501 xfs_attri_release(ATTRI_ITEM(intent));
0502 }
0503
0504
0505 STATIC void
0506 xfs_attr_cancel_item(
0507 struct list_head *item)
0508 {
0509 struct xfs_attr_intent *attr;
0510
0511 attr = container_of(item, struct xfs_attr_intent, xattri_list);
0512 xfs_attr_free_item(attr);
0513 }
0514
0515 STATIC bool
0516 xfs_attri_item_match(
0517 struct xfs_log_item *lip,
0518 uint64_t intent_id)
0519 {
0520 return ATTRI_ITEM(lip)->attri_format.alfi_id == intent_id;
0521 }
0522
0523
0524 static inline bool
0525 xfs_attri_validate(
0526 struct xfs_mount *mp,
0527 struct xfs_attri_log_format *attrp)
0528 {
0529 unsigned int op = attrp->alfi_op_flags &
0530 XFS_ATTRI_OP_FLAGS_TYPE_MASK;
0531
0532 if (attrp->__pad != 0)
0533 return false;
0534
0535 if (attrp->alfi_op_flags & ~XFS_ATTRI_OP_FLAGS_TYPE_MASK)
0536 return false;
0537
0538 if (attrp->alfi_attr_filter & ~XFS_ATTRI_FILTER_MASK)
0539 return false;
0540
0541
0542 switch (op) {
0543 case XFS_ATTRI_OP_FLAGS_SET:
0544 case XFS_ATTRI_OP_FLAGS_REPLACE:
0545 case XFS_ATTRI_OP_FLAGS_REMOVE:
0546 break;
0547 default:
0548 return false;
0549 }
0550
0551 if (attrp->alfi_value_len > XATTR_SIZE_MAX)
0552 return false;
0553
0554 if ((attrp->alfi_name_len > XATTR_NAME_MAX) ||
0555 (attrp->alfi_name_len == 0))
0556 return false;
0557
0558 return xfs_verify_ino(mp, attrp->alfi_ino);
0559 }
0560
0561
0562
0563
0564
0565 STATIC int
0566 xfs_attri_item_recover(
0567 struct xfs_log_item *lip,
0568 struct list_head *capture_list)
0569 {
0570 struct xfs_attri_log_item *attrip = ATTRI_ITEM(lip);
0571 struct xfs_attr_intent *attr;
0572 struct xfs_mount *mp = lip->li_log->l_mp;
0573 struct xfs_inode *ip;
0574 struct xfs_da_args *args;
0575 struct xfs_trans *tp;
0576 struct xfs_trans_res tres;
0577 struct xfs_attri_log_format *attrp;
0578 struct xfs_attri_log_nameval *nv = attrip->attri_nameval;
0579 int error;
0580 int total;
0581 int local;
0582 struct xfs_attrd_log_item *done_item = NULL;
0583
0584
0585
0586
0587
0588 attrp = &attrip->attri_format;
0589 if (!xfs_attri_validate(mp, attrp) ||
0590 !xfs_attr_namecheck(nv->name.i_addr, nv->name.i_len))
0591 return -EFSCORRUPTED;
0592
0593 error = xlog_recover_iget(mp, attrp->alfi_ino, &ip);
0594 if (error)
0595 return error;
0596
0597 attr = kmem_zalloc(sizeof(struct xfs_attr_intent) +
0598 sizeof(struct xfs_da_args), KM_NOFS);
0599 args = (struct xfs_da_args *)(attr + 1);
0600
0601 attr->xattri_da_args = args;
0602 attr->xattri_op_flags = attrp->alfi_op_flags &
0603 XFS_ATTRI_OP_FLAGS_TYPE_MASK;
0604
0605
0606
0607
0608
0609
0610 attr->xattri_nameval = xfs_attri_log_nameval_get(nv);
0611 ASSERT(attr->xattri_nameval);
0612
0613 args->dp = ip;
0614 args->geo = mp->m_attr_geo;
0615 args->whichfork = XFS_ATTR_FORK;
0616 args->name = nv->name.i_addr;
0617 args->namelen = nv->name.i_len;
0618 args->hashval = xfs_da_hashname(args->name, args->namelen);
0619 args->attr_filter = attrp->alfi_attr_filter & XFS_ATTRI_FILTER_MASK;
0620 args->op_flags = XFS_DA_OP_RECOVERY | XFS_DA_OP_OKNOENT |
0621 XFS_DA_OP_LOGGED;
0622
0623 ASSERT(xfs_sb_version_haslogxattrs(&mp->m_sb));
0624
0625 switch (attr->xattri_op_flags) {
0626 case XFS_ATTRI_OP_FLAGS_SET:
0627 case XFS_ATTRI_OP_FLAGS_REPLACE:
0628 args->value = nv->value.i_addr;
0629 args->valuelen = nv->value.i_len;
0630 args->total = xfs_attr_calc_size(args, &local);
0631 if (xfs_inode_hasattr(args->dp))
0632 attr->xattri_dela_state = xfs_attr_init_replace_state(args);
0633 else
0634 attr->xattri_dela_state = xfs_attr_init_add_state(args);
0635 break;
0636 case XFS_ATTRI_OP_FLAGS_REMOVE:
0637 if (!xfs_inode_hasattr(args->dp))
0638 goto out;
0639 attr->xattri_dela_state = xfs_attr_init_remove_state(args);
0640 break;
0641 default:
0642 ASSERT(0);
0643 error = -EFSCORRUPTED;
0644 goto out;
0645 }
0646
0647 xfs_init_attr_trans(args, &tres, &total);
0648 error = xfs_trans_alloc(mp, &tres, total, 0, XFS_TRANS_RESERVE, &tp);
0649 if (error)
0650 goto out;
0651
0652 args->trans = tp;
0653 done_item = xfs_trans_get_attrd(tp, attrip);
0654
0655 xfs_ilock(ip, XFS_ILOCK_EXCL);
0656 xfs_trans_ijoin(tp, ip, 0);
0657
0658 error = xfs_xattri_finish_update(attr, done_item);
0659 if (error == -EAGAIN) {
0660
0661
0662
0663
0664 xfs_defer_add(tp, XFS_DEFER_OPS_TYPE_ATTR, &attr->xattri_list);
0665 error = xfs_defer_ops_capture_and_commit(tp, capture_list);
0666 if (error)
0667 goto out_unlock;
0668
0669 xfs_iunlock(ip, XFS_ILOCK_EXCL);
0670 xfs_irele(ip);
0671 return 0;
0672 }
0673 if (error) {
0674 xfs_trans_cancel(tp);
0675 goto out_unlock;
0676 }
0677
0678 error = xfs_defer_ops_capture_and_commit(tp, capture_list);
0679 out_unlock:
0680 xfs_iunlock(ip, XFS_ILOCK_EXCL);
0681 xfs_irele(ip);
0682 out:
0683 xfs_attr_free_item(attr);
0684 return error;
0685 }
0686
0687
0688 static struct xfs_log_item *
0689 xfs_attri_item_relog(
0690 struct xfs_log_item *intent,
0691 struct xfs_trans *tp)
0692 {
0693 struct xfs_attrd_log_item *attrdp;
0694 struct xfs_attri_log_item *old_attrip;
0695 struct xfs_attri_log_item *new_attrip;
0696 struct xfs_attri_log_format *new_attrp;
0697 struct xfs_attri_log_format *old_attrp;
0698
0699 old_attrip = ATTRI_ITEM(intent);
0700 old_attrp = &old_attrip->attri_format;
0701
0702 tp->t_flags |= XFS_TRANS_DIRTY;
0703 attrdp = xfs_trans_get_attrd(tp, old_attrip);
0704 set_bit(XFS_LI_DIRTY, &attrdp->attrd_item.li_flags);
0705
0706
0707
0708
0709
0710 new_attrip = xfs_attri_init(tp->t_mountp, old_attrip->attri_nameval);
0711 new_attrp = &new_attrip->attri_format;
0712
0713 new_attrp->alfi_ino = old_attrp->alfi_ino;
0714 new_attrp->alfi_op_flags = old_attrp->alfi_op_flags;
0715 new_attrp->alfi_value_len = old_attrp->alfi_value_len;
0716 new_attrp->alfi_name_len = old_attrp->alfi_name_len;
0717 new_attrp->alfi_attr_filter = old_attrp->alfi_attr_filter;
0718
0719 xfs_trans_add_item(tp, &new_attrip->attri_item);
0720 set_bit(XFS_LI_DIRTY, &new_attrip->attri_item.li_flags);
0721
0722 return &new_attrip->attri_item;
0723 }
0724
0725 STATIC int
0726 xlog_recover_attri_commit_pass2(
0727 struct xlog *log,
0728 struct list_head *buffer_list,
0729 struct xlog_recover_item *item,
0730 xfs_lsn_t lsn)
0731 {
0732 struct xfs_mount *mp = log->l_mp;
0733 struct xfs_attri_log_item *attrip;
0734 struct xfs_attri_log_format *attri_formatp;
0735 struct xfs_attri_log_nameval *nv;
0736 const void *attr_value = NULL;
0737 const void *attr_name;
0738 int error;
0739
0740 attri_formatp = item->ri_buf[0].i_addr;
0741 attr_name = item->ri_buf[1].i_addr;
0742
0743
0744 if (!xfs_attri_validate(mp, attri_formatp)) {
0745 XFS_ERROR_REPORT(__func__, XFS_ERRLEVEL_LOW, mp);
0746 return -EFSCORRUPTED;
0747 }
0748
0749 if (!xfs_attr_namecheck(attr_name, attri_formatp->alfi_name_len)) {
0750 XFS_ERROR_REPORT(__func__, XFS_ERRLEVEL_LOW, mp);
0751 return -EFSCORRUPTED;
0752 }
0753
0754 if (attri_formatp->alfi_value_len)
0755 attr_value = item->ri_buf[2].i_addr;
0756
0757
0758
0759
0760
0761
0762 nv = xfs_attri_log_nameval_alloc(attr_name,
0763 attri_formatp->alfi_name_len, attr_value,
0764 attri_formatp->alfi_value_len);
0765 if (!nv)
0766 return -ENOMEM;
0767
0768 attrip = xfs_attri_init(mp, nv);
0769 error = xfs_attri_copy_format(&item->ri_buf[0], &attrip->attri_format);
0770 if (error)
0771 goto out;
0772
0773
0774
0775
0776
0777
0778
0779 xfs_trans_ail_insert(log->l_ailp, &attrip->attri_item, lsn);
0780 xfs_attri_release(attrip);
0781 xfs_attri_log_nameval_put(nv);
0782 return 0;
0783 out:
0784 xfs_attri_item_free(attrip);
0785 xfs_attri_log_nameval_put(nv);
0786 return error;
0787 }
0788
0789
0790
0791
0792 static struct xfs_attrd_log_item *
0793 xfs_trans_get_attrd(struct xfs_trans *tp,
0794 struct xfs_attri_log_item *attrip)
0795 {
0796 struct xfs_attrd_log_item *attrdp;
0797
0798 ASSERT(tp != NULL);
0799
0800 attrdp = kmem_cache_zalloc(xfs_attrd_cache, GFP_NOFS | __GFP_NOFAIL);
0801
0802 xfs_log_item_init(tp->t_mountp, &attrdp->attrd_item, XFS_LI_ATTRD,
0803 &xfs_attrd_item_ops);
0804 attrdp->attrd_attrip = attrip;
0805 attrdp->attrd_format.alfd_alf_id = attrip->attri_format.alfi_id;
0806
0807 xfs_trans_add_item(tp, &attrdp->attrd_item);
0808 return attrdp;
0809 }
0810
0811
0812 static struct xfs_log_item *
0813 xfs_attr_create_done(
0814 struct xfs_trans *tp,
0815 struct xfs_log_item *intent,
0816 unsigned int count)
0817 {
0818 if (!intent)
0819 return NULL;
0820
0821 return &xfs_trans_get_attrd(tp, ATTRI_ITEM(intent))->attrd_item;
0822 }
0823
0824 const struct xfs_defer_op_type xfs_attr_defer_type = {
0825 .max_items = 1,
0826 .create_intent = xfs_attr_create_intent,
0827 .abort_intent = xfs_attr_abort_intent,
0828 .create_done = xfs_attr_create_done,
0829 .finish_item = xfs_attr_finish_item,
0830 .cancel_item = xfs_attr_cancel_item,
0831 };
0832
0833
0834
0835
0836
0837
0838
0839
0840 STATIC int
0841 xlog_recover_attrd_commit_pass2(
0842 struct xlog *log,
0843 struct list_head *buffer_list,
0844 struct xlog_recover_item *item,
0845 xfs_lsn_t lsn)
0846 {
0847 struct xfs_attrd_log_format *attrd_formatp;
0848
0849 attrd_formatp = item->ri_buf[0].i_addr;
0850 if (item->ri_buf[0].i_len != sizeof(struct xfs_attrd_log_format)) {
0851 XFS_ERROR_REPORT(__func__, XFS_ERRLEVEL_LOW, NULL);
0852 return -EFSCORRUPTED;
0853 }
0854
0855 xlog_recover_release_intent(log, XFS_LI_ATTRI,
0856 attrd_formatp->alfd_alf_id);
0857 return 0;
0858 }
0859
0860 static const struct xfs_item_ops xfs_attri_item_ops = {
0861 .flags = XFS_ITEM_INTENT,
0862 .iop_size = xfs_attri_item_size,
0863 .iop_format = xfs_attri_item_format,
0864 .iop_unpin = xfs_attri_item_unpin,
0865 .iop_release = xfs_attri_item_release,
0866 .iop_recover = xfs_attri_item_recover,
0867 .iop_match = xfs_attri_item_match,
0868 .iop_relog = xfs_attri_item_relog,
0869 };
0870
0871 const struct xlog_recover_item_ops xlog_attri_item_ops = {
0872 .item_type = XFS_LI_ATTRI,
0873 .commit_pass2 = xlog_recover_attri_commit_pass2,
0874 };
0875
0876 static const struct xfs_item_ops xfs_attrd_item_ops = {
0877 .flags = XFS_ITEM_RELEASE_WHEN_COMMITTED |
0878 XFS_ITEM_INTENT_DONE,
0879 .iop_size = xfs_attrd_item_size,
0880 .iop_format = xfs_attrd_item_format,
0881 .iop_release = xfs_attrd_item_release,
0882 .iop_intent = xfs_attrd_item_intent,
0883 };
0884
0885 const struct xlog_recover_item_ops xlog_attrd_item_ops = {
0886 .item_type = XFS_LI_ATTRD,
0887 .commit_pass2 = xlog_recover_attrd_commit_pass2,
0888 };