| .. | .. |
|---|
| 1 | +// SPDX-License-Identifier: GPL-2.0-only |
|---|
| 1 | 2 | /* |
|---|
| 2 | 3 | * Copyright (C) Sistina Software, Inc. 1997-2003 All rights reserved. |
|---|
| 3 | 4 | * Copyright (C) 2004-2006 Red Hat, Inc. All rights reserved. |
|---|
| 4 | | - * |
|---|
| 5 | | - * This copyrighted material is made available to anyone wishing to use, |
|---|
| 6 | | - * modify, copy, or redistribute it subject to the terms and conditions |
|---|
| 7 | | - * of the GNU General Public License version 2. |
|---|
| 8 | 5 | */ |
|---|
| 9 | 6 | |
|---|
| 10 | 7 | #define pr_fmt(fmt) KBUILD_MODNAME ": " fmt |
|---|
| .. | .. |
|---|
| 28 | 25 | #include "util.h" |
|---|
| 29 | 26 | #include "trace_gfs2.h" |
|---|
| 30 | 27 | |
|---|
| 28 | +static void gfs2_print_trans(struct gfs2_sbd *sdp, const struct gfs2_trans *tr) |
|---|
| 29 | +{ |
|---|
| 30 | + fs_warn(sdp, "Transaction created at: %pSR\n", (void *)tr->tr_ip); |
|---|
| 31 | + fs_warn(sdp, "blocks=%u revokes=%u reserved=%u touched=%u\n", |
|---|
| 32 | + tr->tr_blocks, tr->tr_revokes, tr->tr_reserved, |
|---|
| 33 | + test_bit(TR_TOUCHED, &tr->tr_flags)); |
|---|
| 34 | + fs_warn(sdp, "Buf %u/%u Databuf %u/%u Revoke %u/%u\n", |
|---|
| 35 | + tr->tr_num_buf_new, tr->tr_num_buf_rm, |
|---|
| 36 | + tr->tr_num_databuf_new, tr->tr_num_databuf_rm, |
|---|
| 37 | + tr->tr_num_revoke, tr->tr_num_revoke_rm); |
|---|
| 38 | +} |
|---|
| 39 | + |
|---|
| 31 | 40 | int gfs2_trans_begin(struct gfs2_sbd *sdp, unsigned int blocks, |
|---|
| 32 | 41 | unsigned int revokes) |
|---|
| 33 | 42 | { |
|---|
| 34 | 43 | struct gfs2_trans *tr; |
|---|
| 35 | 44 | int error; |
|---|
| 36 | 45 | |
|---|
| 37 | | - BUG_ON(current->journal_info); |
|---|
| 46 | + if (current->journal_info) { |
|---|
| 47 | + gfs2_print_trans(sdp, current->journal_info); |
|---|
| 48 | + BUG(); |
|---|
| 49 | + } |
|---|
| 38 | 50 | BUG_ON(blocks == 0 && revokes == 0); |
|---|
| 39 | 51 | |
|---|
| 40 | 52 | if (!test_bit(SDF_JOURNAL_LIVE, &sdp->sd_flags)) |
|---|
| 41 | 53 | return -EROFS; |
|---|
| 42 | 54 | |
|---|
| 43 | | - tr = kzalloc(sizeof(struct gfs2_trans), GFP_NOFS); |
|---|
| 55 | + tr = kmem_cache_zalloc(gfs2_trans_cachep, GFP_NOFS); |
|---|
| 44 | 56 | if (!tr) |
|---|
| 45 | 57 | return -ENOMEM; |
|---|
| 46 | 58 | |
|---|
| .. | .. |
|---|
| 52 | 64 | if (blocks) |
|---|
| 53 | 65 | tr->tr_reserved += 6 + blocks; |
|---|
| 54 | 66 | if (revokes) |
|---|
| 55 | | - tr->tr_reserved += gfs2_struct2blk(sdp, revokes, |
|---|
| 56 | | - sizeof(u64)); |
|---|
| 67 | + tr->tr_reserved += gfs2_struct2blk(sdp, revokes); |
|---|
| 57 | 68 | INIT_LIST_HEAD(&tr->tr_databuf); |
|---|
| 58 | 69 | INIT_LIST_HEAD(&tr->tr_buf); |
|---|
| 70 | + INIT_LIST_HEAD(&tr->tr_list); |
|---|
| 59 | 71 | INIT_LIST_HEAD(&tr->tr_ail1_list); |
|---|
| 60 | 72 | INIT_LIST_HEAD(&tr->tr_ail2_list); |
|---|
| 61 | 73 | |
|---|
| .. | .. |
|---|
| 71 | 83 | |
|---|
| 72 | 84 | fail: |
|---|
| 73 | 85 | sb_end_intwrite(sdp->sd_vfs); |
|---|
| 74 | | - kfree(tr); |
|---|
| 86 | + kmem_cache_free(gfs2_trans_cachep, tr); |
|---|
| 75 | 87 | |
|---|
| 76 | 88 | return error; |
|---|
| 77 | | -} |
|---|
| 78 | | - |
|---|
| 79 | | -static void gfs2_print_trans(const struct gfs2_trans *tr) |
|---|
| 80 | | -{ |
|---|
| 81 | | - pr_warn("Transaction created at: %pSR\n", (void *)tr->tr_ip); |
|---|
| 82 | | - pr_warn("blocks=%u revokes=%u reserved=%u touched=%u\n", |
|---|
| 83 | | - tr->tr_blocks, tr->tr_revokes, tr->tr_reserved, |
|---|
| 84 | | - test_bit(TR_TOUCHED, &tr->tr_flags)); |
|---|
| 85 | | - pr_warn("Buf %u/%u Databuf %u/%u Revoke %u/%u\n", |
|---|
| 86 | | - tr->tr_num_buf_new, tr->tr_num_buf_rm, |
|---|
| 87 | | - tr->tr_num_databuf_new, tr->tr_num_databuf_rm, |
|---|
| 88 | | - tr->tr_num_revoke, tr->tr_num_revoke_rm); |
|---|
| 89 | 89 | } |
|---|
| 90 | 90 | |
|---|
| 91 | 91 | void gfs2_trans_end(struct gfs2_sbd *sdp) |
|---|
| .. | .. |
|---|
| 99 | 99 | if (!test_bit(TR_TOUCHED, &tr->tr_flags)) { |
|---|
| 100 | 100 | gfs2_log_release(sdp, tr->tr_reserved); |
|---|
| 101 | 101 | if (alloced) { |
|---|
| 102 | | - kfree(tr); |
|---|
| 102 | + gfs2_trans_free(sdp, tr); |
|---|
| 103 | 103 | sb_end_intwrite(sdp->sd_vfs); |
|---|
| 104 | 104 | } |
|---|
| 105 | 105 | return; |
|---|
| .. | .. |
|---|
| 111 | 111 | |
|---|
| 112 | 112 | if (gfs2_assert_withdraw(sdp, (nbuf <= tr->tr_blocks) && |
|---|
| 113 | 113 | (tr->tr_num_revoke <= tr->tr_revokes))) |
|---|
| 114 | | - gfs2_print_trans(tr); |
|---|
| 114 | + gfs2_print_trans(sdp, tr); |
|---|
| 115 | 115 | |
|---|
| 116 | 116 | gfs2_log_commit(sdp, tr); |
|---|
| 117 | 117 | if (alloced && !test_bit(TR_ATTACHED, &tr->tr_flags)) |
|---|
| 118 | | - kfree(tr); |
|---|
| 118 | + gfs2_trans_free(sdp, tr); |
|---|
| 119 | 119 | up_read(&sdp->sd_log_flush_lock); |
|---|
| 120 | 120 | |
|---|
| 121 | 121 | if (sdp->sd_vfs->s_flags & SB_SYNCHRONOUS) |
|---|
| .. | .. |
|---|
| 126 | 126 | } |
|---|
| 127 | 127 | |
|---|
| 128 | 128 | static struct gfs2_bufdata *gfs2_alloc_bufdata(struct gfs2_glock *gl, |
|---|
| 129 | | - struct buffer_head *bh, |
|---|
| 130 | | - const struct gfs2_log_operations *lops) |
|---|
| 129 | + struct buffer_head *bh) |
|---|
| 131 | 130 | { |
|---|
| 132 | 131 | struct gfs2_bufdata *bd; |
|---|
| 133 | 132 | |
|---|
| 134 | 133 | bd = kmem_cache_zalloc(gfs2_bufdata_cachep, GFP_NOFS | __GFP_NOFAIL); |
|---|
| 135 | 134 | bd->bd_bh = bh; |
|---|
| 136 | 135 | bd->bd_gl = gl; |
|---|
| 137 | | - bd->bd_ops = lops; |
|---|
| 138 | 136 | INIT_LIST_HEAD(&bd->bd_list); |
|---|
| 137 | + INIT_LIST_HEAD(&bd->bd_ail_st_list); |
|---|
| 138 | + INIT_LIST_HEAD(&bd->bd_ail_gl_list); |
|---|
| 139 | 139 | bh->b_private = bd; |
|---|
| 140 | 140 | return bd; |
|---|
| 141 | 141 | } |
|---|
| .. | .. |
|---|
| 171 | 171 | gfs2_log_unlock(sdp); |
|---|
| 172 | 172 | unlock_buffer(bh); |
|---|
| 173 | 173 | if (bh->b_private == NULL) |
|---|
| 174 | | - bd = gfs2_alloc_bufdata(gl, bh, &gfs2_databuf_lops); |
|---|
| 174 | + bd = gfs2_alloc_bufdata(gl, bh); |
|---|
| 175 | 175 | else |
|---|
| 176 | 176 | bd = bh->b_private; |
|---|
| 177 | 177 | lock_buffer(bh); |
|---|
| .. | .. |
|---|
| 212 | 212 | unlock_buffer(bh); |
|---|
| 213 | 213 | lock_page(bh->b_page); |
|---|
| 214 | 214 | if (bh->b_private == NULL) |
|---|
| 215 | | - bd = gfs2_alloc_bufdata(gl, bh, &gfs2_buf_lops); |
|---|
| 215 | + bd = gfs2_alloc_bufdata(gl, bh); |
|---|
| 216 | 216 | else |
|---|
| 217 | 217 | bd = bh->b_private; |
|---|
| 218 | 218 | unlock_page(bh->b_page); |
|---|
| .. | .. |
|---|
| 227 | 227 | set_bit(GLF_DIRTY, &bd->bd_gl->gl_flags); |
|---|
| 228 | 228 | mh = (struct gfs2_meta_header *)bd->bd_bh->b_data; |
|---|
| 229 | 229 | if (unlikely(mh->mh_magic != cpu_to_be32(GFS2_MAGIC))) { |
|---|
| 230 | | - pr_err("Attempting to add uninitialised block to journal (inplace block=%lld)\n", |
|---|
| 230 | + fs_err(sdp, "Attempting to add uninitialised block to " |
|---|
| 231 | + "journal (inplace block=%lld)\n", |
|---|
| 231 | 232 | (unsigned long long)bd->bd_bh->b_blocknr); |
|---|
| 232 | 233 | BUG(); |
|---|
| 233 | 234 | } |
|---|
| 234 | 235 | if (unlikely(state == SFS_FROZEN)) { |
|---|
| 235 | | - printk(KERN_INFO "GFS2:adding buf while frozen\n"); |
|---|
| 236 | + fs_info(sdp, "GFS2:adding buf while frozen\n"); |
|---|
| 236 | 237 | gfs2_assert_withdraw(sdp, 0); |
|---|
| 238 | + } |
|---|
| 239 | + if (unlikely(gfs2_withdrawn(sdp))) { |
|---|
| 240 | + fs_info(sdp, "GFS2:adding buf while withdrawn! 0x%llx\n", |
|---|
| 241 | + (unsigned long long)bd->bd_bh->b_blocknr); |
|---|
| 237 | 242 | } |
|---|
| 238 | 243 | gfs2_pin(sdp, bd->bd_bh); |
|---|
| 239 | 244 | mh->__pad0 = cpu_to_be64(0); |
|---|
| .. | .. |
|---|
| 256 | 261 | tr->tr_num_revoke++; |
|---|
| 257 | 262 | } |
|---|
| 258 | 263 | |
|---|
| 259 | | -void gfs2_trans_add_unrevoke(struct gfs2_sbd *sdp, u64 blkno, unsigned int len) |
|---|
| 264 | +void gfs2_trans_remove_revoke(struct gfs2_sbd *sdp, u64 blkno, unsigned int len) |
|---|
| 260 | 265 | { |
|---|
| 261 | 266 | struct gfs2_bufdata *bd, *tmp; |
|---|
| 262 | 267 | struct gfs2_trans *tr = current->journal_info; |
|---|
| 263 | 268 | unsigned int n = len; |
|---|
| 264 | 269 | |
|---|
| 265 | 270 | gfs2_log_lock(sdp); |
|---|
| 266 | | - list_for_each_entry_safe(bd, tmp, &sdp->sd_log_le_revoke, bd_list) { |
|---|
| 271 | + list_for_each_entry_safe(bd, tmp, &sdp->sd_log_revokes, bd_list) { |
|---|
| 267 | 272 | if ((bd->bd_blkno >= blkno) && (bd->bd_blkno < (blkno + len))) { |
|---|
| 268 | 273 | list_del_init(&bd->bd_list); |
|---|
| 269 | 274 | gfs2_assert_withdraw(sdp, sdp->sd_log_num_revoke); |
|---|
| .. | .. |
|---|
| 279 | 284 | gfs2_log_unlock(sdp); |
|---|
| 280 | 285 | } |
|---|
| 281 | 286 | |
|---|
| 287 | +void gfs2_trans_free(struct gfs2_sbd *sdp, struct gfs2_trans *tr) |
|---|
| 288 | +{ |
|---|
| 289 | + if (tr == NULL) |
|---|
| 290 | + return; |
|---|
| 291 | + |
|---|
| 292 | + gfs2_assert_warn(sdp, list_empty(&tr->tr_ail1_list)); |
|---|
| 293 | + gfs2_assert_warn(sdp, list_empty(&tr->tr_ail2_list)); |
|---|
| 294 | + gfs2_assert_warn(sdp, list_empty(&tr->tr_databuf)); |
|---|
| 295 | + gfs2_assert_warn(sdp, list_empty(&tr->tr_buf)); |
|---|
| 296 | + kmem_cache_free(gfs2_trans_cachep, tr); |
|---|
| 297 | +} |
|---|