1 // SPDX-License-Identifier: GPL-2.0-or-later 2 /* 3 * Copyright (C) 2022 Oracle. All Rights Reserved. 4 * Author: Allison Henderson <allison.henderson@oracle.com> 5 */ 6 7 #include "xfs.h" 8 #include "xfs_fs.h" 9 #include "xfs_format.h" 10 #include "xfs_trans_resv.h" 11 #include "xfs_shared.h" 12 #include "xfs_mount.h" 13 #include "xfs_defer.h" 14 #include "xfs_log_format.h" 15 #include "xfs_trans.h" 16 #include "xfs_bmap_btree.h" 17 #include "xfs_trans_priv.h" 18 #include "xfs_log.h" 19 #include "xfs_inode.h" 20 #include "xfs_da_format.h" 21 #include "xfs_da_btree.h" 22 #include "xfs_attr.h" 23 #include "xfs_attr_item.h" 24 #include "xfs_trace.h" 25 #include "xfs_inode.h" 26 #include "xfs_trans_space.h" 27 #include "xfs_errortag.h" 28 #include "xfs_error.h" 29 #include "xfs_log_priv.h" 30 #include "xfs_log_recover.h" 31 32 static const struct xfs_item_ops xfs_attri_item_ops; 33 static const struct xfs_item_ops xfs_attrd_item_ops; 34 static struct xfs_attrd_log_item *xfs_trans_get_attrd(struct xfs_trans *tp, 35 struct xfs_attri_log_item *attrip); 36 37 static inline struct xfs_attri_log_item *ATTRI_ITEM(struct xfs_log_item *lip) 38 { 39 return container_of(lip, struct xfs_attri_log_item, attri_item); 40 } 41 42 STATIC void 43 xfs_attri_item_free( 44 struct xfs_attri_log_item *attrip) 45 { 46 kmem_free(attrip->attri_item.li_lv_shadow); 47 kvfree(attrip); 48 } 49 50 /* 51 * Freeing the attrip requires that we remove it from the AIL if it has already 52 * been placed there. However, the ATTRI may not yet have been placed in the 53 * AIL when called by xfs_attri_release() from ATTRD processing due to the 54 * ordering of committed vs unpin operations in bulk insert operations. Hence 55 * the reference count to ensure only the last caller frees the ATTRI. 56 */ 57 STATIC void 58 xfs_attri_release( 59 struct xfs_attri_log_item *attrip) 60 { 61 ASSERT(atomic_read(&attrip->attri_refcount) > 0); 62 if (!atomic_dec_and_test(&attrip->attri_refcount)) 63 return; 64 65 xfs_trans_ail_delete(&attrip->attri_item, 0); 66 xfs_attri_item_free(attrip); 67 } 68 69 STATIC void 70 xfs_attri_item_size( 71 struct xfs_log_item *lip, 72 int *nvecs, 73 int *nbytes) 74 { 75 struct xfs_attri_log_item *attrip = ATTRI_ITEM(lip); 76 77 *nvecs += 2; 78 *nbytes += sizeof(struct xfs_attri_log_format) + 79 xlog_calc_iovec_len(attrip->attri_name_len); 80 81 if (!attrip->attri_value_len) 82 return; 83 84 *nvecs += 1; 85 *nbytes += xlog_calc_iovec_len(attrip->attri_value_len); 86 } 87 88 /* 89 * This is called to fill in the log iovecs for the given attri log 90 * item. We use 1 iovec for the attri_format_item, 1 for the name, and 91 * another for the value if it is present 92 */ 93 STATIC void 94 xfs_attri_item_format( 95 struct xfs_log_item *lip, 96 struct xfs_log_vec *lv) 97 { 98 struct xfs_attri_log_item *attrip = ATTRI_ITEM(lip); 99 struct xfs_log_iovec *vecp = NULL; 100 101 attrip->attri_format.alfi_type = XFS_LI_ATTRI; 102 attrip->attri_format.alfi_size = 1; 103 104 /* 105 * This size accounting must be done before copying the attrip into the 106 * iovec. If we do it after, the wrong size will be recorded to the log 107 * and we trip across assertion checks for bad region sizes later during 108 * the log recovery. 109 */ 110 111 ASSERT(attrip->attri_name_len > 0); 112 attrip->attri_format.alfi_size++; 113 114 if (attrip->attri_value_len > 0) 115 attrip->attri_format.alfi_size++; 116 117 xlog_copy_iovec(lv, &vecp, XLOG_REG_TYPE_ATTRI_FORMAT, 118 &attrip->attri_format, 119 sizeof(struct xfs_attri_log_format)); 120 xlog_copy_iovec(lv, &vecp, XLOG_REG_TYPE_ATTR_NAME, 121 attrip->attri_name, 122 attrip->attri_name_len); 123 if (attrip->attri_value_len > 0) 124 xlog_copy_iovec(lv, &vecp, XLOG_REG_TYPE_ATTR_VALUE, 125 attrip->attri_value, 126 attrip->attri_value_len); 127 } 128 129 /* 130 * The unpin operation is the last place an ATTRI is manipulated in the log. It 131 * is either inserted in the AIL or aborted in the event of a log I/O error. In 132 * either case, the ATTRI transaction has been successfully committed to make 133 * it this far. Therefore, we expect whoever committed the ATTRI to either 134 * construct and commit the ATTRD or drop the ATTRD's reference in the event of 135 * error. Simply drop the log's ATTRI reference now that the log is done with 136 * it. 137 */ 138 STATIC void 139 xfs_attri_item_unpin( 140 struct xfs_log_item *lip, 141 int remove) 142 { 143 xfs_attri_release(ATTRI_ITEM(lip)); 144 } 145 146 147 STATIC void 148 xfs_attri_item_release( 149 struct xfs_log_item *lip) 150 { 151 xfs_attri_release(ATTRI_ITEM(lip)); 152 } 153 154 /* 155 * Allocate and initialize an attri item. Caller may allocate an additional 156 * trailing buffer for name and value 157 */ 158 STATIC struct xfs_attri_log_item * 159 xfs_attri_init( 160 struct xfs_mount *mp, 161 uint32_t name_len, 162 uint32_t value_len) 163 164 { 165 struct xfs_attri_log_item *attrip; 166 uint32_t buffer_size = name_len + value_len; 167 168 if (buffer_size) { 169 /* 170 * This could be over 64kB in length, so we have to use 171 * kvmalloc() for this. But kvmalloc() utterly sucks, so we 172 * use own version. 173 */ 174 attrip = xlog_kvmalloc(sizeof(struct xfs_attri_log_item) + 175 buffer_size); 176 } else { 177 attrip = kmem_cache_alloc(xfs_attri_cache, 178 GFP_NOFS | __GFP_NOFAIL); 179 } 180 memset(attrip, 0, sizeof(struct xfs_attri_log_item)); 181 182 attrip->attri_name_len = name_len; 183 if (name_len) 184 attrip->attri_name = ((char *)attrip) + 185 sizeof(struct xfs_attri_log_item); 186 else 187 attrip->attri_name = NULL; 188 189 attrip->attri_value_len = value_len; 190 if (value_len) 191 attrip->attri_value = ((char *)attrip) + 192 sizeof(struct xfs_attri_log_item) + 193 name_len; 194 else 195 attrip->attri_value = NULL; 196 197 xfs_log_item_init(mp, &attrip->attri_item, XFS_LI_ATTRI, 198 &xfs_attri_item_ops); 199 attrip->attri_format.alfi_id = (uintptr_t)(void *)attrip; 200 atomic_set(&attrip->attri_refcount, 2); 201 202 return attrip; 203 } 204 205 /* 206 * Copy an attr format buffer from the given buf, and into the destination attr 207 * format structure. 208 */ 209 STATIC int 210 xfs_attri_copy_format( 211 struct xfs_log_iovec *buf, 212 struct xfs_attri_log_format *dst_attr_fmt) 213 { 214 struct xfs_attri_log_format *src_attr_fmt = buf->i_addr; 215 size_t len; 216 217 len = sizeof(struct xfs_attri_log_format); 218 if (buf->i_len != len) { 219 XFS_ERROR_REPORT(__func__, XFS_ERRLEVEL_LOW, NULL); 220 return -EFSCORRUPTED; 221 } 222 223 memcpy((char *)dst_attr_fmt, (char *)src_attr_fmt, len); 224 return 0; 225 } 226 227 static inline struct xfs_attrd_log_item *ATTRD_ITEM(struct xfs_log_item *lip) 228 { 229 return container_of(lip, struct xfs_attrd_log_item, attrd_item); 230 } 231 232 STATIC void 233 xfs_attrd_item_free(struct xfs_attrd_log_item *attrdp) 234 { 235 kmem_free(attrdp->attrd_item.li_lv_shadow); 236 kmem_free(attrdp); 237 } 238 239 STATIC void 240 xfs_attrd_item_size( 241 struct xfs_log_item *lip, 242 int *nvecs, 243 int *nbytes) 244 { 245 *nvecs += 1; 246 *nbytes += sizeof(struct xfs_attrd_log_format); 247 } 248 249 /* 250 * This is called to fill in the log iovecs for the given attrd log item. We use 251 * only 1 iovec for the attrd_format, and we point that at the attr_log_format 252 * structure embedded in the attrd item. 253 */ 254 STATIC void 255 xfs_attrd_item_format( 256 struct xfs_log_item *lip, 257 struct xfs_log_vec *lv) 258 { 259 struct xfs_attrd_log_item *attrdp = ATTRD_ITEM(lip); 260 struct xfs_log_iovec *vecp = NULL; 261 262 attrdp->attrd_format.alfd_type = XFS_LI_ATTRD; 263 attrdp->attrd_format.alfd_size = 1; 264 265 xlog_copy_iovec(lv, &vecp, XLOG_REG_TYPE_ATTRD_FORMAT, 266 &attrdp->attrd_format, 267 sizeof(struct xfs_attrd_log_format)); 268 } 269 270 /* 271 * The ATTRD is either committed or aborted if the transaction is canceled. If 272 * the transaction is canceled, drop our reference to the ATTRI and free the 273 * ATTRD. 274 */ 275 STATIC void 276 xfs_attrd_item_release( 277 struct xfs_log_item *lip) 278 { 279 struct xfs_attrd_log_item *attrdp = ATTRD_ITEM(lip); 280 281 xfs_attri_release(attrdp->attrd_attrip); 282 xfs_attrd_item_free(attrdp); 283 } 284 285 static struct xfs_log_item * 286 xfs_attrd_item_intent( 287 struct xfs_log_item *lip) 288 { 289 return &ATTRD_ITEM(lip)->attrd_attrip->attri_item; 290 } 291 292 /* 293 * Performs one step of an attribute update intent and marks the attrd item 294 * dirty.. An attr operation may be a set or a remove. Note that the 295 * transaction is marked dirty regardless of whether the operation succeeds or 296 * fails to support the ATTRI/ATTRD lifecycle rules. 297 */ 298 STATIC int 299 xfs_xattri_finish_update( 300 struct xfs_attr_item *attr, 301 struct xfs_attrd_log_item *attrdp) 302 { 303 struct xfs_da_args *args = attr->xattri_da_args; 304 int error; 305 306 if (XFS_TEST_ERROR(false, args->dp->i_mount, XFS_ERRTAG_LARP)) { 307 error = -EIO; 308 goto out; 309 } 310 311 error = xfs_attr_set_iter(attr); 312 if (!error && attr->xattri_dela_state != XFS_DAS_DONE) 313 error = -EAGAIN; 314 out: 315 /* 316 * Mark the transaction dirty, even on error. This ensures the 317 * transaction is aborted, which: 318 * 319 * 1.) releases the ATTRI and frees the ATTRD 320 * 2.) shuts down the filesystem 321 */ 322 args->trans->t_flags |= XFS_TRANS_DIRTY | XFS_TRANS_HAS_INTENT_DONE; 323 324 /* 325 * attr intent/done items are null when logged attributes are disabled 326 */ 327 if (attrdp) 328 set_bit(XFS_LI_DIRTY, &attrdp->attrd_item.li_flags); 329 330 return error; 331 } 332 333 /* Log an attr to the intent item. */ 334 STATIC void 335 xfs_attr_log_item( 336 struct xfs_trans *tp, 337 struct xfs_attri_log_item *attrip, 338 struct xfs_attr_item *attr) 339 { 340 struct xfs_attri_log_format *attrp; 341 342 tp->t_flags |= XFS_TRANS_DIRTY; 343 set_bit(XFS_LI_DIRTY, &attrip->attri_item.li_flags); 344 345 /* 346 * At this point the xfs_attr_item has been constructed, and we've 347 * created the log intent. Fill in the attri log item and log format 348 * structure with fields from this xfs_attr_item 349 */ 350 attrp = &attrip->attri_format; 351 attrp->alfi_ino = attr->xattri_da_args->dp->i_ino; 352 attrp->alfi_op_flags = attr->xattri_op_flags; 353 attrp->alfi_value_len = attr->xattri_da_args->valuelen; 354 attrp->alfi_name_len = attr->xattri_da_args->namelen; 355 attrp->alfi_attr_flags = attr->xattri_da_args->attr_filter; 356 357 memcpy(attrip->attri_name, attr->xattri_da_args->name, 358 attr->xattri_da_args->namelen); 359 memcpy(attrip->attri_value, attr->xattri_da_args->value, 360 attr->xattri_da_args->valuelen); 361 attrip->attri_name_len = attr->xattri_da_args->namelen; 362 attrip->attri_value_len = attr->xattri_da_args->valuelen; 363 } 364 365 /* Get an ATTRI. */ 366 static struct xfs_log_item * 367 xfs_attr_create_intent( 368 struct xfs_trans *tp, 369 struct list_head *items, 370 unsigned int count, 371 bool sort) 372 { 373 struct xfs_mount *mp = tp->t_mountp; 374 struct xfs_attri_log_item *attrip; 375 struct xfs_attr_item *attr; 376 377 ASSERT(count == 1); 378 379 if (!xfs_sb_version_haslogxattrs(&mp->m_sb)) 380 return NULL; 381 382 /* 383 * Each attr item only performs one attribute operation at a time, so 384 * this is a list of one 385 */ 386 list_for_each_entry(attr, items, xattri_list) { 387 attrip = xfs_attri_init(mp, attr->xattri_da_args->namelen, 388 attr->xattri_da_args->valuelen); 389 if (attrip == NULL) 390 return NULL; 391 392 xfs_trans_add_item(tp, &attrip->attri_item); 393 xfs_attr_log_item(tp, attrip, attr); 394 } 395 396 return &attrip->attri_item; 397 } 398 399 /* Process an attr. */ 400 STATIC int 401 xfs_attr_finish_item( 402 struct xfs_trans *tp, 403 struct xfs_log_item *done, 404 struct list_head *item, 405 struct xfs_btree_cur **state) 406 { 407 struct xfs_attr_item *attr; 408 struct xfs_attrd_log_item *done_item = NULL; 409 int error; 410 411 attr = container_of(item, struct xfs_attr_item, xattri_list); 412 if (done) 413 done_item = ATTRD_ITEM(done); 414 415 /* 416 * Always reset trans after EAGAIN cycle 417 * since the transaction is new 418 */ 419 attr->xattri_da_args->trans = tp; 420 421 error = xfs_xattri_finish_update(attr, done_item); 422 if (error != -EAGAIN) 423 kmem_free(attr); 424 425 return error; 426 } 427 428 /* Abort all pending ATTRs. */ 429 STATIC void 430 xfs_attr_abort_intent( 431 struct xfs_log_item *intent) 432 { 433 xfs_attri_release(ATTRI_ITEM(intent)); 434 } 435 436 /* Cancel an attr */ 437 STATIC void 438 xfs_attr_cancel_item( 439 struct list_head *item) 440 { 441 struct xfs_attr_item *attr; 442 443 attr = container_of(item, struct xfs_attr_item, xattri_list); 444 kmem_free(attr); 445 } 446 447 STATIC xfs_lsn_t 448 xfs_attri_item_committed( 449 struct xfs_log_item *lip, 450 xfs_lsn_t lsn) 451 { 452 struct xfs_attri_log_item *attrip = ATTRI_ITEM(lip); 453 454 /* 455 * The attrip refers to xfs_attr_item memory to log the name and value 456 * with the intent item. This already occurred when the intent was 457 * committed so these fields are no longer accessed. Clear them out of 458 * caution since we're about to free the xfs_attr_item. 459 */ 460 attrip->attri_name = NULL; 461 attrip->attri_value = NULL; 462 463 /* 464 * The ATTRI is logged only once and cannot be moved in the log, so 465 * simply return the lsn at which it's been logged. 466 */ 467 return lsn; 468 } 469 470 STATIC bool 471 xfs_attri_item_match( 472 struct xfs_log_item *lip, 473 uint64_t intent_id) 474 { 475 return ATTRI_ITEM(lip)->attri_format.alfi_id == intent_id; 476 } 477 478 /* Is this recovered ATTRI format ok? */ 479 static inline bool 480 xfs_attri_validate( 481 struct xfs_mount *mp, 482 struct xfs_attri_log_format *attrp) 483 { 484 unsigned int op = attrp->alfi_op_flags & 485 XFS_ATTR_OP_FLAGS_TYPE_MASK; 486 487 if (attrp->__pad != 0) 488 return false; 489 490 /* alfi_op_flags should be either a set or remove */ 491 switch (op) { 492 case XFS_ATTR_OP_FLAGS_SET: 493 case XFS_ATTR_OP_FLAGS_REPLACE: 494 case XFS_ATTR_OP_FLAGS_REMOVE: 495 break; 496 default: 497 return false; 498 } 499 500 if (attrp->alfi_value_len > XATTR_SIZE_MAX) 501 return false; 502 503 if ((attrp->alfi_name_len > XATTR_NAME_MAX) || 504 (attrp->alfi_name_len == 0)) 505 return false; 506 507 return xfs_verify_ino(mp, attrp->alfi_ino); 508 } 509 510 /* 511 * Process an attr intent item that was recovered from the log. We need to 512 * delete the attr that it describes. 513 */ 514 STATIC int 515 xfs_attri_item_recover( 516 struct xfs_log_item *lip, 517 struct list_head *capture_list) 518 { 519 struct xfs_attri_log_item *attrip = ATTRI_ITEM(lip); 520 struct xfs_attr_item *attr; 521 struct xfs_mount *mp = lip->li_log->l_mp; 522 struct xfs_inode *ip; 523 struct xfs_da_args *args; 524 struct xfs_trans *tp; 525 struct xfs_trans_res tres; 526 struct xfs_attri_log_format *attrp; 527 int error, ret = 0; 528 int total; 529 int local; 530 struct xfs_attrd_log_item *done_item = NULL; 531 532 /* 533 * First check the validity of the attr described by the ATTRI. If any 534 * are bad, then assume that all are bad and just toss the ATTRI. 535 */ 536 attrp = &attrip->attri_format; 537 if (!xfs_attri_validate(mp, attrp) || 538 !xfs_attr_namecheck(attrip->attri_name, attrip->attri_name_len)) 539 return -EFSCORRUPTED; 540 541 error = xlog_recover_iget(mp, attrp->alfi_ino, &ip); 542 if (error) 543 return error; 544 545 attr = kmem_zalloc(sizeof(struct xfs_attr_item) + 546 sizeof(struct xfs_da_args), KM_NOFS); 547 args = (struct xfs_da_args *)(attr + 1); 548 549 attr->xattri_da_args = args; 550 attr->xattri_op_flags = attrp->alfi_op_flags; 551 552 args->dp = ip; 553 args->geo = mp->m_attr_geo; 554 args->whichfork = XFS_ATTR_FORK; 555 args->name = attrip->attri_name; 556 args->namelen = attrp->alfi_name_len; 557 args->hashval = xfs_da_hashname(args->name, args->namelen); 558 args->attr_filter = attrp->alfi_attr_flags; 559 args->op_flags = XFS_DA_OP_RECOVERY | XFS_DA_OP_OKNOENT; 560 561 switch (attrp->alfi_op_flags & XFS_ATTR_OP_FLAGS_TYPE_MASK) { 562 case XFS_ATTR_OP_FLAGS_SET: 563 case XFS_ATTR_OP_FLAGS_REPLACE: 564 args->value = attrip->attri_value; 565 args->valuelen = attrp->alfi_value_len; 566 args->total = xfs_attr_calc_size(args, &local); 567 if (xfs_inode_hasattr(args->dp)) 568 attr->xattri_dela_state = xfs_attr_init_replace_state(args); 569 else 570 attr->xattri_dela_state = xfs_attr_init_add_state(args); 571 break; 572 case XFS_ATTR_OP_FLAGS_REMOVE: 573 if (!xfs_inode_hasattr(args->dp)) 574 goto out; 575 attr->xattri_dela_state = xfs_attr_init_remove_state(args); 576 break; 577 default: 578 ASSERT(0); 579 error = -EFSCORRUPTED; 580 goto out; 581 } 582 583 xfs_init_attr_trans(args, &tres, &total); 584 error = xfs_trans_alloc(mp, &tres, total, 0, XFS_TRANS_RESERVE, &tp); 585 if (error) 586 goto out; 587 588 args->trans = tp; 589 done_item = xfs_trans_get_attrd(tp, attrip); 590 591 xfs_ilock(ip, XFS_ILOCK_EXCL); 592 xfs_trans_ijoin(tp, ip, 0); 593 594 ret = xfs_xattri_finish_update(attr, done_item); 595 if (ret == -EAGAIN) { 596 /* There's more work to do, so add it to this transaction */ 597 xfs_defer_add(tp, XFS_DEFER_OPS_TYPE_ATTR, &attr->xattri_list); 598 } else 599 error = ret; 600 601 if (error) { 602 xfs_trans_cancel(tp); 603 goto out_unlock; 604 } 605 606 error = xfs_defer_ops_capture_and_commit(tp, capture_list); 607 608 out_unlock: 609 if (attr->xattri_leaf_bp) 610 xfs_buf_relse(attr->xattri_leaf_bp); 611 612 xfs_iunlock(ip, XFS_ILOCK_EXCL); 613 xfs_irele(ip); 614 out: 615 if (ret != -EAGAIN) 616 kmem_free(attr); 617 return error; 618 } 619 620 /* Re-log an intent item to push the log tail forward. */ 621 static struct xfs_log_item * 622 xfs_attri_item_relog( 623 struct xfs_log_item *intent, 624 struct xfs_trans *tp) 625 { 626 struct xfs_attrd_log_item *attrdp; 627 struct xfs_attri_log_item *old_attrip; 628 struct xfs_attri_log_item *new_attrip; 629 struct xfs_attri_log_format *new_attrp; 630 struct xfs_attri_log_format *old_attrp; 631 632 old_attrip = ATTRI_ITEM(intent); 633 old_attrp = &old_attrip->attri_format; 634 635 tp->t_flags |= XFS_TRANS_DIRTY; 636 attrdp = xfs_trans_get_attrd(tp, old_attrip); 637 set_bit(XFS_LI_DIRTY, &attrdp->attrd_item.li_flags); 638 639 new_attrip = xfs_attri_init(tp->t_mountp, old_attrp->alfi_name_len, 640 old_attrp->alfi_value_len); 641 new_attrp = &new_attrip->attri_format; 642 643 new_attrp->alfi_ino = old_attrp->alfi_ino; 644 new_attrp->alfi_op_flags = old_attrp->alfi_op_flags; 645 new_attrp->alfi_value_len = old_attrp->alfi_value_len; 646 new_attrp->alfi_name_len = old_attrp->alfi_name_len; 647 new_attrp->alfi_attr_flags = old_attrp->alfi_attr_flags; 648 649 memcpy(new_attrip->attri_name, old_attrip->attri_name, 650 new_attrip->attri_name_len); 651 652 if (new_attrip->attri_value_len > 0) 653 memcpy(new_attrip->attri_value, old_attrip->attri_value, 654 new_attrip->attri_value_len); 655 656 xfs_trans_add_item(tp, &new_attrip->attri_item); 657 set_bit(XFS_LI_DIRTY, &new_attrip->attri_item.li_flags); 658 659 return &new_attrip->attri_item; 660 } 661 662 STATIC int 663 xlog_recover_attri_commit_pass2( 664 struct xlog *log, 665 struct list_head *buffer_list, 666 struct xlog_recover_item *item, 667 xfs_lsn_t lsn) 668 { 669 int error; 670 struct xfs_mount *mp = log->l_mp; 671 struct xfs_attri_log_item *attrip; 672 struct xfs_attri_log_format *attri_formatp; 673 int region = 0; 674 675 attri_formatp = item->ri_buf[region].i_addr; 676 677 /* Validate xfs_attri_log_format */ 678 if (!xfs_attri_validate(mp, attri_formatp)) { 679 XFS_ERROR_REPORT(__func__, XFS_ERRLEVEL_LOW, mp); 680 return -EFSCORRUPTED; 681 } 682 683 /* memory alloc failure will cause replay to abort */ 684 attrip = xfs_attri_init(mp, attri_formatp->alfi_name_len, 685 attri_formatp->alfi_value_len); 686 if (attrip == NULL) 687 return -ENOMEM; 688 689 error = xfs_attri_copy_format(&item->ri_buf[region], 690 &attrip->attri_format); 691 if (error) 692 goto out; 693 694 region++; 695 memcpy(attrip->attri_name, item->ri_buf[region].i_addr, 696 attrip->attri_name_len); 697 698 if (!xfs_attr_namecheck(attrip->attri_name, attrip->attri_name_len)) { 699 XFS_ERROR_REPORT(__func__, XFS_ERRLEVEL_LOW, mp); 700 error = -EFSCORRUPTED; 701 goto out; 702 } 703 704 if (attrip->attri_value_len > 0) { 705 region++; 706 memcpy(attrip->attri_value, item->ri_buf[region].i_addr, 707 attrip->attri_value_len); 708 } 709 710 /* 711 * The ATTRI has two references. One for the ATTRD and one for ATTRI to 712 * ensure it makes it into the AIL. Insert the ATTRI into the AIL 713 * directly and drop the ATTRI reference. Note that 714 * xfs_trans_ail_update() drops the AIL lock. 715 */ 716 xfs_trans_ail_insert(log->l_ailp, &attrip->attri_item, lsn); 717 xfs_attri_release(attrip); 718 return 0; 719 out: 720 xfs_attri_item_free(attrip); 721 return error; 722 } 723 724 /* 725 * This routine is called to allocate an "attr free done" log item. 726 */ 727 static struct xfs_attrd_log_item * 728 xfs_trans_get_attrd(struct xfs_trans *tp, 729 struct xfs_attri_log_item *attrip) 730 { 731 struct xfs_attrd_log_item *attrdp; 732 733 ASSERT(tp != NULL); 734 735 attrdp = kmem_cache_zalloc(xfs_attrd_cache, GFP_NOFS | __GFP_NOFAIL); 736 737 xfs_log_item_init(tp->t_mountp, &attrdp->attrd_item, XFS_LI_ATTRD, 738 &xfs_attrd_item_ops); 739 attrdp->attrd_attrip = attrip; 740 attrdp->attrd_format.alfd_alf_id = attrip->attri_format.alfi_id; 741 742 xfs_trans_add_item(tp, &attrdp->attrd_item); 743 return attrdp; 744 } 745 746 /* Get an ATTRD so we can process all the attrs. */ 747 static struct xfs_log_item * 748 xfs_attr_create_done( 749 struct xfs_trans *tp, 750 struct xfs_log_item *intent, 751 unsigned int count) 752 { 753 if (!intent) 754 return NULL; 755 756 return &xfs_trans_get_attrd(tp, ATTRI_ITEM(intent))->attrd_item; 757 } 758 759 const struct xfs_defer_op_type xfs_attr_defer_type = { 760 .max_items = 1, 761 .create_intent = xfs_attr_create_intent, 762 .abort_intent = xfs_attr_abort_intent, 763 .create_done = xfs_attr_create_done, 764 .finish_item = xfs_attr_finish_item, 765 .cancel_item = xfs_attr_cancel_item, 766 }; 767 768 /* 769 * This routine is called when an ATTRD format structure is found in a committed 770 * transaction in the log. Its purpose is to cancel the corresponding ATTRI if 771 * it was still in the log. To do this it searches the AIL for the ATTRI with 772 * an id equal to that in the ATTRD format structure. If we find it we drop 773 * the ATTRD reference, which removes the ATTRI from the AIL and frees it. 774 */ 775 STATIC int 776 xlog_recover_attrd_commit_pass2( 777 struct xlog *log, 778 struct list_head *buffer_list, 779 struct xlog_recover_item *item, 780 xfs_lsn_t lsn) 781 { 782 struct xfs_attrd_log_format *attrd_formatp; 783 784 attrd_formatp = item->ri_buf[0].i_addr; 785 if (item->ri_buf[0].i_len != sizeof(struct xfs_attrd_log_format)) { 786 XFS_ERROR_REPORT(__func__, XFS_ERRLEVEL_LOW, NULL); 787 return -EFSCORRUPTED; 788 } 789 790 xlog_recover_release_intent(log, XFS_LI_ATTRI, 791 attrd_formatp->alfd_alf_id); 792 return 0; 793 } 794 795 static const struct xfs_item_ops xfs_attri_item_ops = { 796 .flags = XFS_ITEM_INTENT, 797 .iop_size = xfs_attri_item_size, 798 .iop_format = xfs_attri_item_format, 799 .iop_unpin = xfs_attri_item_unpin, 800 .iop_committed = xfs_attri_item_committed, 801 .iop_release = xfs_attri_item_release, 802 .iop_recover = xfs_attri_item_recover, 803 .iop_match = xfs_attri_item_match, 804 .iop_relog = xfs_attri_item_relog, 805 }; 806 807 const struct xlog_recover_item_ops xlog_attri_item_ops = { 808 .item_type = XFS_LI_ATTRI, 809 .commit_pass2 = xlog_recover_attri_commit_pass2, 810 }; 811 812 static const struct xfs_item_ops xfs_attrd_item_ops = { 813 .flags = XFS_ITEM_RELEASE_WHEN_COMMITTED | 814 XFS_ITEM_INTENT_DONE, 815 .iop_size = xfs_attrd_item_size, 816 .iop_format = xfs_attrd_item_format, 817 .iop_release = xfs_attrd_item_release, 818 .iop_intent = xfs_attrd_item_intent, 819 }; 820 821 const struct xlog_recover_item_ops xlog_attrd_item_ops = { 822 .item_type = XFS_LI_ATTRD, 823 .commit_pass2 = xlog_recover_attrd_commit_pass2, 824 }; 825