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 ---