fast_commit.c (8415ce07ecf0cc25efdd5db264a7133716e503cf) | fast_commit.c (48a6a66db82b8043d298a630f22c62d43550cae5) |
---|---|
1// SPDX-License-Identifier: GPL-2.0 2 3/* 4 * fs/ext4/fast_commit.c 5 * 6 * Written by Harshad Shirwadkar <harshadshirwadkar@gmail.com> 7 * 8 * Ext4 fast commits routines. --- 700 unchanged lines hidden (view full) --- 709 */ 710static u8 *ext4_fc_reserve_space(struct super_block *sb, int len, u32 *crc) 711{ 712 struct ext4_fc_tl tl; 713 struct ext4_sb_info *sbi = EXT4_SB(sb); 714 struct buffer_head *bh; 715 int bsize = sbi->s_journal->j_blocksize; 716 int ret, off = sbi->s_fc_bytes % bsize; | 1// SPDX-License-Identifier: GPL-2.0 2 3/* 4 * fs/ext4/fast_commit.c 5 * 6 * Written by Harshad Shirwadkar <harshadshirwadkar@gmail.com> 7 * 8 * Ext4 fast commits routines. --- 700 unchanged lines hidden (view full) --- 709 */ 710static u8 *ext4_fc_reserve_space(struct super_block *sb, int len, u32 *crc) 711{ 712 struct ext4_fc_tl tl; 713 struct ext4_sb_info *sbi = EXT4_SB(sb); 714 struct buffer_head *bh; 715 int bsize = sbi->s_journal->j_blocksize; 716 int ret, off = sbi->s_fc_bytes % bsize; |
717 int pad_len; | 717 int remaining; |
718 u8 *dst; 719 720 /* | 718 u8 *dst; 719 720 /* |
721 * After allocating len, we should have space at least for a 0 byte 722 * padding. | 721 * If 'len' is too long to fit in any block alongside a PAD tlv, then we 722 * cannot fulfill the request. |
723 */ | 723 */ |
724 if (len + EXT4_FC_TAG_BASE_LEN > bsize) | 724 if (len > bsize - EXT4_FC_TAG_BASE_LEN) |
725 return NULL; 726 | 725 return NULL; 726 |
727 if (bsize - off - 1 > len + EXT4_FC_TAG_BASE_LEN) { 728 /* 729 * Only allocate from current buffer if we have enough space for 730 * this request AND we have space to add a zero byte padding. 731 */ 732 if (!sbi->s_fc_bh) { 733 ret = jbd2_fc_get_buf(EXT4_SB(sb)->s_journal, &bh); 734 if (ret) 735 return NULL; 736 sbi->s_fc_bh = bh; 737 } 738 sbi->s_fc_bytes += len; 739 return sbi->s_fc_bh->b_data + off; | 727 if (!sbi->s_fc_bh) { 728 ret = jbd2_fc_get_buf(EXT4_SB(sb)->s_journal, &bh); 729 if (ret) 730 return NULL; 731 sbi->s_fc_bh = bh; |
740 } | 732 } |
741 /* Need to add PAD tag */ | |
742 dst = sbi->s_fc_bh->b_data + off; | 733 dst = sbi->s_fc_bh->b_data + off; |
734 735 /* 736 * Allocate the bytes in the current block if we can do so while still 737 * leaving enough space for a PAD tlv. 738 */ 739 remaining = bsize - EXT4_FC_TAG_BASE_LEN - off; 740 if (len <= remaining) { 741 sbi->s_fc_bytes += len; 742 return dst; 743 } 744 745 /* 746 * Else, terminate the current block with a PAD tlv, then allocate a new 747 * block and allocate the bytes at the start of that new block. 748 */ 749 |
|
743 tl.fc_tag = cpu_to_le16(EXT4_FC_TAG_PAD); | 750 tl.fc_tag = cpu_to_le16(EXT4_FC_TAG_PAD); |
744 pad_len = bsize - off - 1 - EXT4_FC_TAG_BASE_LEN; 745 tl.fc_len = cpu_to_le16(pad_len); | 751 tl.fc_len = cpu_to_le16(remaining); |
746 ext4_fc_memcpy(sb, dst, &tl, EXT4_FC_TAG_BASE_LEN, crc); | 752 ext4_fc_memcpy(sb, dst, &tl, EXT4_FC_TAG_BASE_LEN, crc); |
747 dst += EXT4_FC_TAG_BASE_LEN; 748 if (pad_len > 0) { 749 ext4_fc_memzero(sb, dst, pad_len, crc); 750 dst += pad_len; 751 } 752 /* Don't leak uninitialized memory in the unused last byte. */ 753 *dst = 0; | 753 ext4_fc_memzero(sb, dst + EXT4_FC_TAG_BASE_LEN, remaining, crc); |
754 755 ext4_fc_submit_bh(sb, false); 756 757 ret = jbd2_fc_get_buf(EXT4_SB(sb)->s_journal, &bh); 758 if (ret) 759 return NULL; 760 sbi->s_fc_bh = bh; | 754 755 ext4_fc_submit_bh(sb, false); 756 757 ret = jbd2_fc_get_buf(EXT4_SB(sb)->s_journal, &bh); 758 if (ret) 759 return NULL; 760 sbi->s_fc_bh = bh; |
761 sbi->s_fc_bytes = (sbi->s_fc_bytes / bsize + 1) * bsize + len; | 761 sbi->s_fc_bytes += bsize - off + len; |
762 return sbi->s_fc_bh->b_data; 763} 764 765/* 766 * Complete a fast commit by writing tail tag. 767 * 768 * Writing tail tag marks the end of a fast commit. In order to guarantee 769 * atomicity, after writing tail tag, even if there's space remaining --- 14 unchanged lines hidden (view full) --- 784 */ 785 dst = ext4_fc_reserve_space(sb, EXT4_FC_TAG_BASE_LEN + sizeof(tail), &crc); 786 if (!dst) 787 return -ENOSPC; 788 789 off = sbi->s_fc_bytes % bsize; 790 791 tl.fc_tag = cpu_to_le16(EXT4_FC_TAG_TAIL); | 762 return sbi->s_fc_bh->b_data; 763} 764 765/* 766 * Complete a fast commit by writing tail tag. 767 * 768 * Writing tail tag marks the end of a fast commit. In order to guarantee 769 * atomicity, after writing tail tag, even if there's space remaining --- 14 unchanged lines hidden (view full) --- 784 */ 785 dst = ext4_fc_reserve_space(sb, EXT4_FC_TAG_BASE_LEN + sizeof(tail), &crc); 786 if (!dst) 787 return -ENOSPC; 788 789 off = sbi->s_fc_bytes % bsize; 790 791 tl.fc_tag = cpu_to_le16(EXT4_FC_TAG_TAIL); |
792 tl.fc_len = cpu_to_le16(bsize - off - 1 + sizeof(struct ext4_fc_tail)); | 792 tl.fc_len = cpu_to_le16(bsize - off + sizeof(struct ext4_fc_tail)); |
793 sbi->s_fc_bytes = round_up(sbi->s_fc_bytes, bsize); 794 795 ext4_fc_memcpy(sb, dst, &tl, EXT4_FC_TAG_BASE_LEN, &crc); 796 dst += EXT4_FC_TAG_BASE_LEN; 797 tail.fc_tid = cpu_to_le32(sbi->s_journal->j_running_transaction->t_tid); 798 ext4_fc_memcpy(sb, dst, &tail.fc_tid, sizeof(tail.fc_tid), &crc); 799 dst += sizeof(tail.fc_tid); 800 tail.fc_crc = cpu_to_le32(crc); --- 1250 unchanged lines hidden (view full) --- 2051 struct ext4_fc_tail tail; 2052 __u8 *start, *end, *cur, *val; 2053 struct ext4_fc_head head; 2054 struct ext4_extent *ex; 2055 2056 state = &sbi->s_fc_replay_state; 2057 2058 start = (u8 *)bh->b_data; | 793 sbi->s_fc_bytes = round_up(sbi->s_fc_bytes, bsize); 794 795 ext4_fc_memcpy(sb, dst, &tl, EXT4_FC_TAG_BASE_LEN, &crc); 796 dst += EXT4_FC_TAG_BASE_LEN; 797 tail.fc_tid = cpu_to_le32(sbi->s_journal->j_running_transaction->t_tid); 798 ext4_fc_memcpy(sb, dst, &tail.fc_tid, sizeof(tail.fc_tid), &crc); 799 dst += sizeof(tail.fc_tid); 800 tail.fc_crc = cpu_to_le32(crc); --- 1250 unchanged lines hidden (view full) --- 2051 struct ext4_fc_tail tail; 2052 __u8 *start, *end, *cur, *val; 2053 struct ext4_fc_head head; 2054 struct ext4_extent *ex; 2055 2056 state = &sbi->s_fc_replay_state; 2057 2058 start = (u8 *)bh->b_data; |
2059 end = (__u8 *)bh->b_data + journal->j_blocksize - 1; | 2059 end = start + journal->j_blocksize; |
2060 2061 if (state->fc_replay_expected_off == 0) { 2062 state->fc_cur_tag = 0; 2063 state->fc_replay_num_tags = 0; 2064 state->fc_crc = 0; 2065 state->fc_regions = NULL; 2066 state->fc_regions_valid = state->fc_regions_used = 2067 state->fc_regions_size = 0; --- 4 unchanged lines hidden (view full) --- 2072 } 2073 2074 if (off != state->fc_replay_expected_off) { 2075 ret = -EFSCORRUPTED; 2076 goto out_err; 2077 } 2078 2079 state->fc_replay_expected_off++; | 2060 2061 if (state->fc_replay_expected_off == 0) { 2062 state->fc_cur_tag = 0; 2063 state->fc_replay_num_tags = 0; 2064 state->fc_crc = 0; 2065 state->fc_regions = NULL; 2066 state->fc_regions_valid = state->fc_regions_used = 2067 state->fc_regions_size = 0; --- 4 unchanged lines hidden (view full) --- 2072 } 2073 2074 if (off != state->fc_replay_expected_off) { 2075 ret = -EFSCORRUPTED; 2076 goto out_err; 2077 } 2078 2079 state->fc_replay_expected_off++; |
2080 for (cur = start; cur < end - EXT4_FC_TAG_BASE_LEN; | 2080 for (cur = start; cur <= end - EXT4_FC_TAG_BASE_LEN; |
2081 cur = cur + EXT4_FC_TAG_BASE_LEN + tl.fc_len) { 2082 ext4_fc_get_tl(&tl, cur); 2083 val = cur + EXT4_FC_TAG_BASE_LEN; 2084 if (tl.fc_len > end - val || 2085 !ext4_fc_value_len_isvalid(sbi, tl.fc_tag, tl.fc_len)) { 2086 ret = state->fc_replay_num_tags ? 2087 JBD2_FC_REPLAY_STOP : -ECANCELED; 2088 goto out_err; --- 101 unchanged lines hidden (view full) --- 2190#ifdef CONFIG_EXT4_DEBUG 2191 if (sbi->s_fc_debug_max_replay && off >= sbi->s_fc_debug_max_replay) { 2192 pr_warn("Dropping fc block %d because max_replay set\n", off); 2193 return JBD2_FC_REPLAY_STOP; 2194 } 2195#endif 2196 2197 start = (u8 *)bh->b_data; | 2081 cur = cur + EXT4_FC_TAG_BASE_LEN + tl.fc_len) { 2082 ext4_fc_get_tl(&tl, cur); 2083 val = cur + EXT4_FC_TAG_BASE_LEN; 2084 if (tl.fc_len > end - val || 2085 !ext4_fc_value_len_isvalid(sbi, tl.fc_tag, tl.fc_len)) { 2086 ret = state->fc_replay_num_tags ? 2087 JBD2_FC_REPLAY_STOP : -ECANCELED; 2088 goto out_err; --- 101 unchanged lines hidden (view full) --- 2190#ifdef CONFIG_EXT4_DEBUG 2191 if (sbi->s_fc_debug_max_replay && off >= sbi->s_fc_debug_max_replay) { 2192 pr_warn("Dropping fc block %d because max_replay set\n", off); 2193 return JBD2_FC_REPLAY_STOP; 2194 } 2195#endif 2196 2197 start = (u8 *)bh->b_data; |
2198 end = (__u8 *)bh->b_data + journal->j_blocksize - 1; | 2198 end = start + journal->j_blocksize; |
2199 | 2199 |
2200 for (cur = start; cur < end - EXT4_FC_TAG_BASE_LEN; | 2200 for (cur = start; cur <= end - EXT4_FC_TAG_BASE_LEN; |
2201 cur = cur + EXT4_FC_TAG_BASE_LEN + tl.fc_len) { 2202 ext4_fc_get_tl(&tl, cur); 2203 val = cur + EXT4_FC_TAG_BASE_LEN; 2204 2205 if (state->fc_replay_num_tags == 0) { 2206 ret = JBD2_FC_REPLAY_STOP; 2207 ext4_fc_set_bitmaps_and_counters(sb); 2208 break; --- 110 unchanged lines hidden --- | 2201 cur = cur + EXT4_FC_TAG_BASE_LEN + tl.fc_len) { 2202 ext4_fc_get_tl(&tl, cur); 2203 val = cur + EXT4_FC_TAG_BASE_LEN; 2204 2205 if (state->fc_replay_num_tags == 0) { 2206 ret = JBD2_FC_REPLAY_STOP; 2207 ext4_fc_set_bitmaps_and_counters(sb); 2208 break; --- 110 unchanged lines hidden --- |