diff options
Diffstat (limited to 'fs/xfs/libxfs/xfs_sb.c')
| -rw-r--r-- | fs/xfs/libxfs/xfs_sb.c | 320 |
1 files changed, 136 insertions, 184 deletions
diff --git a/fs/xfs/libxfs/xfs_sb.c b/fs/xfs/libxfs/xfs_sb.c index 752915fa775a..b0a5fe95a3e2 100644 --- a/fs/xfs/libxfs/xfs_sb.c +++ b/fs/xfs/libxfs/xfs_sb.c | |||
| @@ -40,69 +40,6 @@ | |||
| 40 | * Physical superblock buffer manipulations. Shared with libxfs in userspace. | 40 | * Physical superblock buffer manipulations. Shared with libxfs in userspace. |
| 41 | */ | 41 | */ |
| 42 | 42 | ||
| 43 | static const struct { | ||
| 44 | short offset; | ||
| 45 | short type; /* 0 = integer | ||
| 46 | * 1 = binary / string (no translation) | ||
| 47 | */ | ||
| 48 | } xfs_sb_info[] = { | ||
| 49 | { offsetof(xfs_sb_t, sb_magicnum), 0 }, | ||
| 50 | { offsetof(xfs_sb_t, sb_blocksize), 0 }, | ||
| 51 | { offsetof(xfs_sb_t, sb_dblocks), 0 }, | ||
| 52 | { offsetof(xfs_sb_t, sb_rblocks), 0 }, | ||
| 53 | { offsetof(xfs_sb_t, sb_rextents), 0 }, | ||
| 54 | { offsetof(xfs_sb_t, sb_uuid), 1 }, | ||
| 55 | { offsetof(xfs_sb_t, sb_logstart), 0 }, | ||
| 56 | { offsetof(xfs_sb_t, sb_rootino), 0 }, | ||
| 57 | { offsetof(xfs_sb_t, sb_rbmino), 0 }, | ||
| 58 | { offsetof(xfs_sb_t, sb_rsumino), 0 }, | ||
| 59 | { offsetof(xfs_sb_t, sb_rextsize), 0 }, | ||
| 60 | { offsetof(xfs_sb_t, sb_agblocks), 0 }, | ||
| 61 | { offsetof(xfs_sb_t, sb_agcount), 0 }, | ||
| 62 | { offsetof(xfs_sb_t, sb_rbmblocks), 0 }, | ||
| 63 | { offsetof(xfs_sb_t, sb_logblocks), 0 }, | ||
| 64 | { offsetof(xfs_sb_t, sb_versionnum), 0 }, | ||
| 65 | { offsetof(xfs_sb_t, sb_sectsize), 0 }, | ||
| 66 | { offsetof(xfs_sb_t, sb_inodesize), 0 }, | ||
| 67 | { offsetof(xfs_sb_t, sb_inopblock), 0 }, | ||
| 68 | { offsetof(xfs_sb_t, sb_fname[0]), 1 }, | ||
| 69 | { offsetof(xfs_sb_t, sb_blocklog), 0 }, | ||
| 70 | { offsetof(xfs_sb_t, sb_sectlog), 0 }, | ||
| 71 | { offsetof(xfs_sb_t, sb_inodelog), 0 }, | ||
| 72 | { offsetof(xfs_sb_t, sb_inopblog), 0 }, | ||
| 73 | { offsetof(xfs_sb_t, sb_agblklog), 0 }, | ||
| 74 | { offsetof(xfs_sb_t, sb_rextslog), 0 }, | ||
| 75 | { offsetof(xfs_sb_t, sb_inprogress), 0 }, | ||
| 76 | { offsetof(xfs_sb_t, sb_imax_pct), 0 }, | ||
| 77 | { offsetof(xfs_sb_t, sb_icount), 0 }, | ||
| 78 | { offsetof(xfs_sb_t, sb_ifree), 0 }, | ||
| 79 | { offsetof(xfs_sb_t, sb_fdblocks), 0 }, | ||
| 80 | { offsetof(xfs_sb_t, sb_frextents), 0 }, | ||
| 81 | { offsetof(xfs_sb_t, sb_uquotino), 0 }, | ||
| 82 | { offsetof(xfs_sb_t, sb_gquotino), 0 }, | ||
| 83 | { offsetof(xfs_sb_t, sb_qflags), 0 }, | ||
| 84 | { offsetof(xfs_sb_t, sb_flags), 0 }, | ||
| 85 | { offsetof(xfs_sb_t, sb_shared_vn), 0 }, | ||
| 86 | { offsetof(xfs_sb_t, sb_inoalignmt), 0 }, | ||
| 87 | { offsetof(xfs_sb_t, sb_unit), 0 }, | ||
| 88 | { offsetof(xfs_sb_t, sb_width), 0 }, | ||
| 89 | { offsetof(xfs_sb_t, sb_dirblklog), 0 }, | ||
| 90 | { offsetof(xfs_sb_t, sb_logsectlog), 0 }, | ||
| 91 | { offsetof(xfs_sb_t, sb_logsectsize), 0 }, | ||
| 92 | { offsetof(xfs_sb_t, sb_logsunit), 0 }, | ||
| 93 | { offsetof(xfs_sb_t, sb_features2), 0 }, | ||
| 94 | { offsetof(xfs_sb_t, sb_bad_features2), 0 }, | ||
| 95 | { offsetof(xfs_sb_t, sb_features_compat), 0 }, | ||
| 96 | { offsetof(xfs_sb_t, sb_features_ro_compat), 0 }, | ||
| 97 | { offsetof(xfs_sb_t, sb_features_incompat), 0 }, | ||
| 98 | { offsetof(xfs_sb_t, sb_features_log_incompat), 0 }, | ||
| 99 | { offsetof(xfs_sb_t, sb_crc), 0 }, | ||
| 100 | { offsetof(xfs_sb_t, sb_pad), 0 }, | ||
| 101 | { offsetof(xfs_sb_t, sb_pquotino), 0 }, | ||
| 102 | { offsetof(xfs_sb_t, sb_lsn), 0 }, | ||
| 103 | { sizeof(xfs_sb_t), 0 } | ||
| 104 | }; | ||
| 105 | |||
| 106 | /* | 43 | /* |
| 107 | * Reference counting access wrappers to the perag structures. | 44 | * Reference counting access wrappers to the perag structures. |
| 108 | * Because we never free per-ag structures, the only thing we | 45 | * Because we never free per-ag structures, the only thing we |
| @@ -461,58 +398,49 @@ xfs_sb_from_disk( | |||
| 461 | __xfs_sb_from_disk(to, from, true); | 398 | __xfs_sb_from_disk(to, from, true); |
| 462 | } | 399 | } |
| 463 | 400 | ||
| 464 | static inline void | 401 | static void |
| 465 | xfs_sb_quota_to_disk( | 402 | xfs_sb_quota_to_disk( |
| 466 | xfs_dsb_t *to, | 403 | struct xfs_dsb *to, |
| 467 | xfs_sb_t *from, | 404 | struct xfs_sb *from) |
| 468 | __int64_t *fields) | ||
| 469 | { | 405 | { |
| 470 | __uint16_t qflags = from->sb_qflags; | 406 | __uint16_t qflags = from->sb_qflags; |
| 471 | 407 | ||
| 408 | to->sb_uquotino = cpu_to_be64(from->sb_uquotino); | ||
| 409 | if (xfs_sb_version_has_pquotino(from)) { | ||
| 410 | to->sb_qflags = cpu_to_be16(from->sb_qflags); | ||
| 411 | to->sb_gquotino = cpu_to_be64(from->sb_gquotino); | ||
| 412 | to->sb_pquotino = cpu_to_be64(from->sb_pquotino); | ||
| 413 | return; | ||
| 414 | } | ||
| 415 | |||
| 472 | /* | 416 | /* |
| 473 | * We need to do these manipilations only if we are working | 417 | * The in-core version of sb_qflags do not have XFS_OQUOTA_* |
| 474 | * with an older version of on-disk superblock. | 418 | * flags, whereas the on-disk version does. So, convert incore |
| 419 | * XFS_{PG}QUOTA_* flags to on-disk XFS_OQUOTA_* flags. | ||
| 475 | */ | 420 | */ |
| 476 | if (xfs_sb_version_has_pquotino(from)) | 421 | qflags &= ~(XFS_PQUOTA_ENFD | XFS_PQUOTA_CHKD | |
| 477 | return; | 422 | XFS_GQUOTA_ENFD | XFS_GQUOTA_CHKD); |
| 478 | 423 | ||
| 479 | if (*fields & XFS_SB_QFLAGS) { | 424 | if (from->sb_qflags & |
| 480 | /* | 425 | (XFS_PQUOTA_ENFD | XFS_GQUOTA_ENFD)) |
| 481 | * The in-core version of sb_qflags do not have | 426 | qflags |= XFS_OQUOTA_ENFD; |
| 482 | * XFS_OQUOTA_* flags, whereas the on-disk version | 427 | if (from->sb_qflags & |
| 483 | * does. So, convert incore XFS_{PG}QUOTA_* flags | 428 | (XFS_PQUOTA_CHKD | XFS_GQUOTA_CHKD)) |
| 484 | * to on-disk XFS_OQUOTA_* flags. | 429 | qflags |= XFS_OQUOTA_CHKD; |
| 485 | */ | 430 | to->sb_qflags = cpu_to_be16(qflags); |
| 486 | qflags &= ~(XFS_PQUOTA_ENFD | XFS_PQUOTA_CHKD | | ||
| 487 | XFS_GQUOTA_ENFD | XFS_GQUOTA_CHKD); | ||
| 488 | |||
| 489 | if (from->sb_qflags & | ||
| 490 | (XFS_PQUOTA_ENFD | XFS_GQUOTA_ENFD)) | ||
| 491 | qflags |= XFS_OQUOTA_ENFD; | ||
| 492 | if (from->sb_qflags & | ||
| 493 | (XFS_PQUOTA_CHKD | XFS_GQUOTA_CHKD)) | ||
| 494 | qflags |= XFS_OQUOTA_CHKD; | ||
| 495 | to->sb_qflags = cpu_to_be16(qflags); | ||
| 496 | *fields &= ~XFS_SB_QFLAGS; | ||
| 497 | } | ||
| 498 | 431 | ||
| 499 | /* | 432 | /* |
| 500 | * GQUOTINO and PQUOTINO cannot be used together in versions of | 433 | * GQUOTINO and PQUOTINO cannot be used together in versions |
| 501 | * superblock that do not have pquotino. from->sb_flags tells us which | 434 | * of superblock that do not have pquotino. from->sb_flags |
| 502 | * quota is active and should be copied to disk. If neither are active, | 435 | * tells us which quota is active and should be copied to |
| 503 | * make sure we write NULLFSINO to the sb_gquotino field as a quota | 436 | * disk. If neither are active, we should NULL the inode. |
| 504 | * inode value of "0" is invalid when the XFS_SB_VERSION_QUOTA feature | ||
| 505 | * bit is set. | ||
| 506 | * | 437 | * |
| 507 | * Note that we don't need to handle the sb_uquotino or sb_pquotino here | 438 | * In all cases, the separate pquotino must remain 0 because it |
| 508 | * as they do not require any translation. Hence the main sb field loop | 439 | * it beyond the "end" of the valid non-pquotino superblock. |
| 509 | * will write them appropriately from the in-core superblock. | ||
| 510 | */ | 440 | */ |
| 511 | if ((*fields & XFS_SB_GQUOTINO) && | 441 | if (from->sb_qflags & XFS_GQUOTA_ACCT) |
| 512 | (from->sb_qflags & XFS_GQUOTA_ACCT)) | ||
| 513 | to->sb_gquotino = cpu_to_be64(from->sb_gquotino); | 442 | to->sb_gquotino = cpu_to_be64(from->sb_gquotino); |
| 514 | else if ((*fields & XFS_SB_PQUOTINO) && | 443 | else if (from->sb_qflags & XFS_PQUOTA_ACCT) |
| 515 | (from->sb_qflags & XFS_PQUOTA_ACCT)) | ||
| 516 | to->sb_gquotino = cpu_to_be64(from->sb_pquotino); | 444 | to->sb_gquotino = cpu_to_be64(from->sb_pquotino); |
| 517 | else { | 445 | else { |
| 518 | /* | 446 | /* |
| @@ -526,63 +454,78 @@ xfs_sb_quota_to_disk( | |||
| 526 | to->sb_gquotino = cpu_to_be64(NULLFSINO); | 454 | to->sb_gquotino = cpu_to_be64(NULLFSINO); |
| 527 | } | 455 | } |
| 528 | 456 | ||
| 529 | *fields &= ~(XFS_SB_PQUOTINO | XFS_SB_GQUOTINO); | 457 | to->sb_pquotino = 0; |
| 530 | } | 458 | } |
| 531 | 459 | ||
| 532 | /* | ||
| 533 | * Copy in core superblock to ondisk one. | ||
| 534 | * | ||
| 535 | * The fields argument is mask of superblock fields to copy. | ||
| 536 | */ | ||
| 537 | void | 460 | void |
| 538 | xfs_sb_to_disk( | 461 | xfs_sb_to_disk( |
| 539 | xfs_dsb_t *to, | 462 | struct xfs_dsb *to, |
| 540 | xfs_sb_t *from, | 463 | struct xfs_sb *from) |
| 541 | __int64_t fields) | ||
| 542 | { | 464 | { |
| 543 | xfs_caddr_t to_ptr = (xfs_caddr_t)to; | 465 | xfs_sb_quota_to_disk(to, from); |
| 544 | xfs_caddr_t from_ptr = (xfs_caddr_t)from; | ||
| 545 | xfs_sb_field_t f; | ||
| 546 | int first; | ||
| 547 | int size; | ||
| 548 | |||
| 549 | ASSERT(fields); | ||
| 550 | if (!fields) | ||
| 551 | return; | ||
| 552 | 466 | ||
| 553 | /* We should never write the crc here, it's updated in the IO path */ | 467 | to->sb_magicnum = cpu_to_be32(from->sb_magicnum); |
| 554 | fields &= ~XFS_SB_CRC; | 468 | to->sb_blocksize = cpu_to_be32(from->sb_blocksize); |
| 555 | 469 | to->sb_dblocks = cpu_to_be64(from->sb_dblocks); | |
| 556 | xfs_sb_quota_to_disk(to, from, &fields); | 470 | to->sb_rblocks = cpu_to_be64(from->sb_rblocks); |
| 557 | while (fields) { | 471 | to->sb_rextents = cpu_to_be64(from->sb_rextents); |
| 558 | f = (xfs_sb_field_t)xfs_lowbit64((__uint64_t)fields); | 472 | memcpy(&to->sb_uuid, &from->sb_uuid, sizeof(to->sb_uuid)); |
| 559 | first = xfs_sb_info[f].offset; | 473 | to->sb_logstart = cpu_to_be64(from->sb_logstart); |
| 560 | size = xfs_sb_info[f + 1].offset - first; | 474 | to->sb_rootino = cpu_to_be64(from->sb_rootino); |
| 561 | 475 | to->sb_rbmino = cpu_to_be64(from->sb_rbmino); | |
| 562 | ASSERT(xfs_sb_info[f].type == 0 || xfs_sb_info[f].type == 1); | 476 | to->sb_rsumino = cpu_to_be64(from->sb_rsumino); |
| 563 | 477 | to->sb_rextsize = cpu_to_be32(from->sb_rextsize); | |
| 564 | if (size == 1 || xfs_sb_info[f].type == 1) { | 478 | to->sb_agblocks = cpu_to_be32(from->sb_agblocks); |
| 565 | memcpy(to_ptr + first, from_ptr + first, size); | 479 | to->sb_agcount = cpu_to_be32(from->sb_agcount); |
| 566 | } else { | 480 | to->sb_rbmblocks = cpu_to_be32(from->sb_rbmblocks); |
| 567 | switch (size) { | 481 | to->sb_logblocks = cpu_to_be32(from->sb_logblocks); |
| 568 | case 2: | 482 | to->sb_versionnum = cpu_to_be16(from->sb_versionnum); |
| 569 | *(__be16 *)(to_ptr + first) = | 483 | to->sb_sectsize = cpu_to_be16(from->sb_sectsize); |
| 570 | cpu_to_be16(*(__u16 *)(from_ptr + first)); | 484 | to->sb_inodesize = cpu_to_be16(from->sb_inodesize); |
| 571 | break; | 485 | to->sb_inopblock = cpu_to_be16(from->sb_inopblock); |
| 572 | case 4: | 486 | memcpy(&to->sb_fname, &from->sb_fname, sizeof(to->sb_fname)); |
| 573 | *(__be32 *)(to_ptr + first) = | 487 | to->sb_blocklog = from->sb_blocklog; |
| 574 | cpu_to_be32(*(__u32 *)(from_ptr + first)); | 488 | to->sb_sectlog = from->sb_sectlog; |
| 575 | break; | 489 | to->sb_inodelog = from->sb_inodelog; |
| 576 | case 8: | 490 | to->sb_inopblog = from->sb_inopblog; |
| 577 | *(__be64 *)(to_ptr + first) = | 491 | to->sb_agblklog = from->sb_agblklog; |
| 578 | cpu_to_be64(*(__u64 *)(from_ptr + first)); | 492 | to->sb_rextslog = from->sb_rextslog; |
| 579 | break; | 493 | to->sb_inprogress = from->sb_inprogress; |
| 580 | default: | 494 | to->sb_imax_pct = from->sb_imax_pct; |
| 581 | ASSERT(0); | 495 | to->sb_icount = cpu_to_be64(from->sb_icount); |
| 582 | } | 496 | to->sb_ifree = cpu_to_be64(from->sb_ifree); |
| 583 | } | 497 | to->sb_fdblocks = cpu_to_be64(from->sb_fdblocks); |
| 498 | to->sb_frextents = cpu_to_be64(from->sb_frextents); | ||
| 584 | 499 | ||
| 585 | fields &= ~(1LL << f); | 500 | to->sb_flags = from->sb_flags; |
| 501 | to->sb_shared_vn = from->sb_shared_vn; | ||
| 502 | to->sb_inoalignmt = cpu_to_be32(from->sb_inoalignmt); | ||
| 503 | to->sb_unit = cpu_to_be32(from->sb_unit); | ||
| 504 | to->sb_width = cpu_to_be32(from->sb_width); | ||
| 505 | to->sb_dirblklog = from->sb_dirblklog; | ||
| 506 | to->sb_logsectlog = from->sb_logsectlog; | ||
| 507 | to->sb_logsectsize = cpu_to_be16(from->sb_logsectsize); | ||
| 508 | to->sb_logsunit = cpu_to_be32(from->sb_logsunit); | ||
| 509 | |||
| 510 | /* | ||
| 511 | * We need to ensure that bad_features2 always matches features2. | ||
| 512 | * Hence we enforce that here rather than having to remember to do it | ||
| 513 | * everywhere else that updates features2. | ||
| 514 | */ | ||
| 515 | from->sb_bad_features2 = from->sb_features2; | ||
| 516 | to->sb_features2 = cpu_to_be32(from->sb_features2); | ||
| 517 | to->sb_bad_features2 = cpu_to_be32(from->sb_bad_features2); | ||
| 518 | |||
| 519 | if (xfs_sb_version_hascrc(from)) { | ||
| 520 | to->sb_features_compat = cpu_to_be32(from->sb_features_compat); | ||
| 521 | to->sb_features_ro_compat = | ||
| 522 | cpu_to_be32(from->sb_features_ro_compat); | ||
| 523 | to->sb_features_incompat = | ||
| 524 | cpu_to_be32(from->sb_features_incompat); | ||
| 525 | to->sb_features_log_incompat = | ||
| 526 | cpu_to_be32(from->sb_features_log_incompat); | ||
| 527 | to->sb_pad = 0; | ||
| 528 | to->sb_lsn = cpu_to_be64(from->sb_lsn); | ||
| 586 | } | 529 | } |
| 587 | } | 530 | } |
| 588 | 531 | ||
| @@ -816,42 +759,51 @@ xfs_initialize_perag_data( | |||
| 816 | } | 759 | } |
| 817 | 760 | ||
| 818 | /* | 761 | /* |
| 819 | * xfs_mod_sb() can be used to copy arbitrary changes to the | 762 | * xfs_log_sb() can be used to copy arbitrary changes to the in-core superblock |
| 820 | * in-core superblock into the superblock buffer to be logged. | 763 | * into the superblock buffer to be logged. It does not provide the higher |
| 821 | * It does not provide the higher level of locking that is | 764 | * level of locking that is needed to protect the in-core superblock from |
| 822 | * needed to protect the in-core superblock from concurrent | 765 | * concurrent access. |
| 823 | * access. | ||
| 824 | */ | 766 | */ |
| 825 | void | 767 | void |
| 826 | xfs_mod_sb(xfs_trans_t *tp, __int64_t fields) | 768 | xfs_log_sb( |
| 769 | struct xfs_trans *tp) | ||
| 827 | { | 770 | { |
| 828 | xfs_buf_t *bp; | 771 | struct xfs_mount *mp = tp->t_mountp; |
| 829 | int first; | 772 | struct xfs_buf *bp = xfs_trans_getsb(tp, mp, 0); |
| 830 | int last; | ||
| 831 | xfs_mount_t *mp; | ||
| 832 | xfs_sb_field_t f; | ||
| 833 | |||
| 834 | ASSERT(fields); | ||
| 835 | if (!fields) | ||
| 836 | return; | ||
| 837 | mp = tp->t_mountp; | ||
| 838 | bp = xfs_trans_getsb(tp, mp, 0); | ||
| 839 | first = sizeof(xfs_sb_t); | ||
| 840 | last = 0; | ||
| 841 | |||
| 842 | /* translate/copy */ | ||
| 843 | 773 | ||
| 844 | xfs_sb_to_disk(XFS_BUF_TO_SBP(bp), &mp->m_sb, fields); | 774 | xfs_sb_to_disk(XFS_BUF_TO_SBP(bp), &mp->m_sb); |
| 775 | xfs_trans_buf_set_type(tp, bp, XFS_BLFT_SB_BUF); | ||
| 776 | xfs_trans_log_buf(tp, bp, 0, sizeof(struct xfs_dsb)); | ||
| 777 | } | ||
| 845 | 778 | ||
| 846 | /* find modified range */ | 779 | /* |
| 847 | f = (xfs_sb_field_t)xfs_highbit64((__uint64_t)fields); | 780 | * xfs_sync_sb |
| 848 | ASSERT((1LL << f) & XFS_SB_MOD_BITS); | 781 | * |
| 849 | last = xfs_sb_info[f + 1].offset - 1; | 782 | * Sync the superblock to disk. |
| 783 | * | ||
| 784 | * Note that the caller is responsible for checking the frozen state of the | ||
| 785 | * filesystem. This procedure uses the non-blocking transaction allocator and | ||
| 786 | * thus will allow modifications to a frozen fs. This is required because this | ||
| 787 | * code can be called during the process of freezing where use of the high-level | ||
| 788 | * allocator would deadlock. | ||
| 789 | */ | ||
| 790 | int | ||
| 791 | xfs_sync_sb( | ||
| 792 | struct xfs_mount *mp, | ||
| 793 | bool wait) | ||
| 794 | { | ||
| 795 | struct xfs_trans *tp; | ||
| 796 | int error; | ||
| 850 | 797 | ||
| 851 | f = (xfs_sb_field_t)xfs_lowbit64((__uint64_t)fields); | 798 | tp = _xfs_trans_alloc(mp, XFS_TRANS_SB_CHANGE, KM_SLEEP); |
| 852 | ASSERT((1LL << f) & XFS_SB_MOD_BITS); | 799 | error = xfs_trans_reserve(tp, &M_RES(mp)->tr_sb, 0, 0); |
| 853 | first = xfs_sb_info[f].offset; | 800 | if (error) { |
| 801 | xfs_trans_cancel(tp, 0); | ||
| 802 | return error; | ||
| 803 | } | ||
| 854 | 804 | ||
| 855 | xfs_trans_buf_set_type(tp, bp, XFS_BLFT_SB_BUF); | 805 | xfs_log_sb(tp); |
| 856 | xfs_trans_log_buf(tp, bp, first, last); | 806 | if (wait) |
| 807 | xfs_trans_set_sync(tp); | ||
| 808 | return xfs_trans_commit(tp, 0); | ||
| 857 | } | 809 | } |
