17336d0e6SThomas Gleixner // SPDX-License-Identifier: GPL-2.0-only 2b3b94faaSDavid Teigland /* 3b3b94faaSDavid Teigland * Copyright (C) Sistina Software, Inc. 1997-2003 All rights reserved. 43a8a9a10SSteven Whitehouse * Copyright (C) 2004-2006 Red Hat, Inc. All rights reserved. 5b3b94faaSDavid Teigland */ 6b3b94faaSDavid Teigland 7d77d1b58SJoe Perches #define pr_fmt(fmt) KBUILD_MODNAME ": " fmt 8d77d1b58SJoe Perches 9b3b94faaSDavid Teigland #include <linux/sched.h> 10b3b94faaSDavid Teigland #include <linux/slab.h> 11b3b94faaSDavid Teigland #include <linux/spinlock.h> 12b3b94faaSDavid Teigland #include <linux/completion.h> 13b3b94faaSDavid Teigland #include <linux/buffer_head.h> 14d0dc80dbSSteven Whitehouse #include <linux/kallsyms.h> 15f057f6cdSSteven Whitehouse #include <linux/gfs2_ondisk.h> 16b3b94faaSDavid Teigland 17b3b94faaSDavid Teigland #include "gfs2.h" 185c676f6dSSteven Whitehouse #include "incore.h" 19b3b94faaSDavid Teigland #include "glock.h" 20767f433fSSteven Whitehouse #include "inode.h" 21b3b94faaSDavid Teigland #include "log.h" 22b3b94faaSDavid Teigland #include "lops.h" 23b3b94faaSDavid Teigland #include "meta_io.h" 24b3b94faaSDavid Teigland #include "trans.h" 255c676f6dSSteven Whitehouse #include "util.h" 265e687eacSBenjamin Marzinski #include "trace_gfs2.h" 27b3b94faaSDavid Teigland 28d0dc80dbSSteven Whitehouse int gfs2_trans_begin(struct gfs2_sbd *sdp, unsigned int blocks, 29d0dc80dbSSteven Whitehouse unsigned int revokes) 30b3b94faaSDavid Teigland { 31b3b94faaSDavid Teigland struct gfs2_trans *tr; 32b3b94faaSDavid Teigland int error; 33b3b94faaSDavid Teigland 34d0dc80dbSSteven Whitehouse BUG_ON(current->journal_info); 35d0dc80dbSSteven Whitehouse BUG_ON(blocks == 0 && revokes == 0); 36b3b94faaSDavid Teigland 37a1c0643fSSteven Whitehouse if (!test_bit(SDF_JOURNAL_LIVE, &sdp->sd_flags)) 38a1c0643fSSteven Whitehouse return -EROFS; 39a1c0643fSSteven Whitehouse 40f55ab26aSSteven Whitehouse tr = kzalloc(sizeof(struct gfs2_trans), GFP_NOFS); 41b3b94faaSDavid Teigland if (!tr) 42b3b94faaSDavid Teigland return -ENOMEM; 43b3b94faaSDavid Teigland 44d29c0afeSFabian Frederick tr->tr_ip = _RET_IP_; 45b3b94faaSDavid Teigland tr->tr_blocks = blocks; 46b3b94faaSDavid Teigland tr->tr_revokes = revokes; 47b3b94faaSDavid Teigland tr->tr_reserved = 1; 489862ca05SBob Peterson set_bit(TR_ALLOCED, &tr->tr_flags); 49b3b94faaSDavid Teigland if (blocks) 50f4154ea0SSteven Whitehouse tr->tr_reserved += 6 + blocks; 51b3b94faaSDavid Teigland if (revokes) 522e9eeaa1SBob Peterson tr->tr_reserved += gfs2_struct2blk(sdp, revokes); 53d69a3c65SSteven Whitehouse INIT_LIST_HEAD(&tr->tr_databuf); 54d69a3c65SSteven Whitehouse INIT_LIST_HEAD(&tr->tr_buf); 55d69a3c65SSteven Whitehouse 5639263d5eSJan Kara sb_start_intwrite(sdp->sd_vfs); 57b3b94faaSDavid Teigland 58b3b94faaSDavid Teigland error = gfs2_log_reserve(sdp, tr->tr_reserved); 59b3b94faaSDavid Teigland if (error) 6024972557SBenjamin Marzinski goto fail; 61b3b94faaSDavid Teigland 625c676f6dSSteven Whitehouse current->journal_info = tr; 63b3b94faaSDavid Teigland 64b3b94faaSDavid Teigland return 0; 65b3b94faaSDavid Teigland 6624972557SBenjamin Marzinski fail: 6739263d5eSJan Kara sb_end_intwrite(sdp->sd_vfs); 68b3b94faaSDavid Teigland kfree(tr); 69b3b94faaSDavid Teigland 70b3b94faaSDavid Teigland return error; 71b3b94faaSDavid Teigland } 72b3b94faaSDavid Teigland 73e54c78a2SBob Peterson static void gfs2_print_trans(struct gfs2_sbd *sdp, const struct gfs2_trans *tr) 74c50b91c4SSteven Whitehouse { 75e54c78a2SBob Peterson fs_warn(sdp, "Transaction created at: %pSR\n", (void *)tr->tr_ip); 76e54c78a2SBob Peterson fs_warn(sdp, "blocks=%u revokes=%u reserved=%u touched=%u\n", 779862ca05SBob Peterson tr->tr_blocks, tr->tr_revokes, tr->tr_reserved, 789862ca05SBob Peterson test_bit(TR_TOUCHED, &tr->tr_flags)); 79a31b4ec5SBob Peterson fs_warn(sdp, "Buf %u/%u Databuf %u/%u Revoke %u/%u\n", 80c50b91c4SSteven Whitehouse tr->tr_num_buf_new, tr->tr_num_buf_rm, 81c50b91c4SSteven Whitehouse tr->tr_num_databuf_new, tr->tr_num_databuf_rm, 82a31b4ec5SBob Peterson tr->tr_num_revoke, tr->tr_num_revoke_rm); 83c50b91c4SSteven Whitehouse } 84c50b91c4SSteven Whitehouse 85b3b94faaSDavid Teigland void gfs2_trans_end(struct gfs2_sbd *sdp) 86b3b94faaSDavid Teigland { 87f4154ea0SSteven Whitehouse struct gfs2_trans *tr = current->journal_info; 88c50b91c4SSteven Whitehouse s64 nbuf; 899862ca05SBob Peterson int alloced = test_bit(TR_ALLOCED, &tr->tr_flags); 902e60d768SBenjamin Marzinski 915c676f6dSSteven Whitehouse current->journal_info = NULL; 92b3b94faaSDavid Teigland 939862ca05SBob Peterson if (!test_bit(TR_TOUCHED, &tr->tr_flags)) { 94b3b94faaSDavid Teigland gfs2_log_release(sdp, tr->tr_reserved); 952e60d768SBenjamin Marzinski if (alloced) { 96e317ffcbSSteven Whitehouse kfree(tr); 9739263d5eSJan Kara sb_end_intwrite(sdp->sd_vfs); 982e60d768SBenjamin Marzinski } 99b3b94faaSDavid Teigland return; 100b3b94faaSDavid Teigland } 101b3b94faaSDavid Teigland 102c50b91c4SSteven Whitehouse nbuf = tr->tr_num_buf_new + tr->tr_num_databuf_new; 103c50b91c4SSteven Whitehouse nbuf -= tr->tr_num_buf_rm; 104c50b91c4SSteven Whitehouse nbuf -= tr->tr_num_databuf_rm; 105c50b91c4SSteven Whitehouse 106c50b91c4SSteven Whitehouse if (gfs2_assert_withdraw(sdp, (nbuf <= tr->tr_blocks) && 107c50b91c4SSteven Whitehouse (tr->tr_num_revoke <= tr->tr_revokes))) 108e54c78a2SBob Peterson gfs2_print_trans(sdp, tr); 109b3b94faaSDavid Teigland 110b3b94faaSDavid Teigland gfs2_log_commit(sdp, tr); 1119862ca05SBob Peterson if (alloced && !test_bit(TR_ATTACHED, &tr->tr_flags)) 112b4dc7291SSteven Whitehouse kfree(tr); 11316ca9412SBenjamin Marzinski up_read(&sdp->sd_log_flush_lock); 114b3b94faaSDavid Teigland 1151751e8a6SLinus Torvalds if (sdp->sd_vfs->s_flags & SB_SYNCHRONOUS) 116805c0907SBob Peterson gfs2_log_flush(sdp, NULL, GFS2_LOG_HEAD_FLUSH_NORMAL | 117805c0907SBob Peterson GFS2_LFC_TRANS_END); 1182e60d768SBenjamin Marzinski if (alloced) 11939263d5eSJan Kara sb_end_intwrite(sdp->sd_vfs); 120b3b94faaSDavid Teigland } 121b3b94faaSDavid Teigland 122c76c4d96SSteven Whitehouse static struct gfs2_bufdata *gfs2_alloc_bufdata(struct gfs2_glock *gl, 123cbbe76c8SBob Peterson struct buffer_head *bh) 124c76c4d96SSteven Whitehouse { 125c76c4d96SSteven Whitehouse struct gfs2_bufdata *bd; 126c76c4d96SSteven Whitehouse 127c76c4d96SSteven Whitehouse bd = kmem_cache_zalloc(gfs2_bufdata_cachep, GFP_NOFS | __GFP_NOFAIL); 128c76c4d96SSteven Whitehouse bd->bd_bh = bh; 129c76c4d96SSteven Whitehouse bd->bd_gl = gl; 130c76c4d96SSteven Whitehouse INIT_LIST_HEAD(&bd->bd_list); 131c76c4d96SSteven Whitehouse bh->b_private = bd; 132c76c4d96SSteven Whitehouse return bd; 133c76c4d96SSteven Whitehouse } 134c76c4d96SSteven Whitehouse 135b3b94faaSDavid Teigland /** 13645138990SSteven Whitehouse * gfs2_trans_add_data - Add a databuf to the transaction. 13745138990SSteven Whitehouse * @gl: The inode glock associated with the buffer 13845138990SSteven Whitehouse * @bh: The buffer to add 139b3b94faaSDavid Teigland * 140845802b1SAndreas Gruenbacher * This is used in journaled data mode. 141767f433fSSteven Whitehouse * We need to journal the data block in the same way as metadata in 142767f433fSSteven Whitehouse * the functions above. The difference is that here we have a tag 143767f433fSSteven Whitehouse * which is two __be64's being the block number (as per meta data) 144767f433fSSteven Whitehouse * and a flag which says whether the data block needs escaping or 145767f433fSSteven Whitehouse * not. This means we need a new log entry for each 251 or so data 146767f433fSSteven Whitehouse * blocks, which isn't an enormous overhead but twice as much as 147767f433fSSteven Whitehouse * for normal metadata blocks. 148b3b94faaSDavid Teigland */ 149767f433fSSteven Whitehouse void gfs2_trans_add_data(struct gfs2_glock *gl, struct buffer_head *bh) 150767f433fSSteven Whitehouse { 15145138990SSteven Whitehouse struct gfs2_trans *tr = current->journal_info; 15215562c43SBob Peterson struct gfs2_sbd *sdp = gl->gl_name.ln_sbd; 153b3b94faaSDavid Teigland struct gfs2_bufdata *bd; 154b3b94faaSDavid Teigland 15596e5d1d3SBenjamin Marzinski lock_buffer(bh); 156aacee720SBob Peterson if (buffer_pinned(bh)) { 157aacee720SBob Peterson set_bit(TR_TOUCHED, &tr->tr_flags); 158aacee720SBob Peterson goto out; 159aacee720SBob Peterson } 16096e5d1d3SBenjamin Marzinski gfs2_log_lock(sdp); 1615c676f6dSSteven Whitehouse bd = bh->b_private; 162c76c4d96SSteven Whitehouse if (bd == NULL) { 16396e5d1d3SBenjamin Marzinski gfs2_log_unlock(sdp); 16496e5d1d3SBenjamin Marzinski unlock_buffer(bh); 165c76c4d96SSteven Whitehouse if (bh->b_private == NULL) 166cbbe76c8SBob Peterson bd = gfs2_alloc_bufdata(gl, bh); 167491e94f7SBob Peterson else 168491e94f7SBob Peterson bd = bh->b_private; 16996e5d1d3SBenjamin Marzinski lock_buffer(bh); 17096e5d1d3SBenjamin Marzinski gfs2_log_lock(sdp); 171b3b94faaSDavid Teigland } 172c76c4d96SSteven Whitehouse gfs2_assert(sdp, bd->bd_gl == gl); 1739862ca05SBob Peterson set_bit(TR_TOUCHED, &tr->tr_flags); 17445138990SSteven Whitehouse if (list_empty(&bd->bd_list)) { 17545138990SSteven Whitehouse set_bit(GLF_LFLUSH, &bd->bd_gl->gl_flags); 17645138990SSteven Whitehouse set_bit(GLF_DIRTY, &bd->bd_gl->gl_flags); 17745138990SSteven Whitehouse gfs2_pin(sdp, bd->bd_bh); 17845138990SSteven Whitehouse tr->tr_num_databuf_new++; 179d69a3c65SSteven Whitehouse list_add_tail(&bd->bd_list, &tr->tr_databuf); 18045138990SSteven Whitehouse } 18196e5d1d3SBenjamin Marzinski gfs2_log_unlock(sdp); 182aacee720SBob Peterson out: 18396e5d1d3SBenjamin Marzinski unlock_buffer(bh); 184b3b94faaSDavid Teigland } 185b3b94faaSDavid Teigland 186350a9b0aSSteven Whitehouse void gfs2_trans_add_meta(struct gfs2_glock *gl, struct buffer_head *bh) 187350a9b0aSSteven Whitehouse { 188767f433fSSteven Whitehouse 18915562c43SBob Peterson struct gfs2_sbd *sdp = gl->gl_name.ln_sbd; 190767f433fSSteven Whitehouse struct gfs2_bufdata *bd; 191192738b7SBob Peterson struct gfs2_meta_header *mh; 192aacee720SBob Peterson struct gfs2_trans *tr = current->journal_info; 193192738b7SBob Peterson enum gfs2_freeze_state state = atomic_read(&sdp->sd_freeze_state); 194767f433fSSteven Whitehouse 195767f433fSSteven Whitehouse lock_buffer(bh); 196aacee720SBob Peterson if (buffer_pinned(bh)) { 197aacee720SBob Peterson set_bit(TR_TOUCHED, &tr->tr_flags); 198aacee720SBob Peterson goto out; 199aacee720SBob Peterson } 200767f433fSSteven Whitehouse gfs2_log_lock(sdp); 201767f433fSSteven Whitehouse bd = bh->b_private; 202c76c4d96SSteven Whitehouse if (bd == NULL) { 203767f433fSSteven Whitehouse gfs2_log_unlock(sdp); 204767f433fSSteven Whitehouse unlock_buffer(bh); 205c76c4d96SSteven Whitehouse lock_page(bh->b_page); 206c76c4d96SSteven Whitehouse if (bh->b_private == NULL) 207cbbe76c8SBob Peterson bd = gfs2_alloc_bufdata(gl, bh); 208491e94f7SBob Peterson else 209491e94f7SBob Peterson bd = bh->b_private; 210c76c4d96SSteven Whitehouse unlock_page(bh->b_page); 211767f433fSSteven Whitehouse lock_buffer(bh); 212767f433fSSteven Whitehouse gfs2_log_lock(sdp); 213767f433fSSteven Whitehouse } 214c76c4d96SSteven Whitehouse gfs2_assert(sdp, bd->bd_gl == gl); 215192738b7SBob Peterson set_bit(TR_TOUCHED, &tr->tr_flags); 216192738b7SBob Peterson if (!list_empty(&bd->bd_list)) 217192738b7SBob Peterson goto out_unlock; 218192738b7SBob Peterson set_bit(GLF_LFLUSH, &bd->bd_gl->gl_flags); 219192738b7SBob Peterson set_bit(GLF_DIRTY, &bd->bd_gl->gl_flags); 220192738b7SBob Peterson mh = (struct gfs2_meta_header *)bd->bd_bh->b_data; 221192738b7SBob Peterson if (unlikely(mh->mh_magic != cpu_to_be32(GFS2_MAGIC))) { 222e54c78a2SBob Peterson fs_err(sdp, "Attempting to add uninitialised block to " 223e54c78a2SBob Peterson "journal (inplace block=%lld)\n", 224192738b7SBob Peterson (unsigned long long)bd->bd_bh->b_blocknr); 225192738b7SBob Peterson BUG(); 226192738b7SBob Peterson } 227192738b7SBob Peterson if (unlikely(state == SFS_FROZEN)) { 228e54c78a2SBob Peterson fs_info(sdp, "GFS2:adding buf while frozen\n"); 229192738b7SBob Peterson gfs2_assert_withdraw(sdp, 0); 230192738b7SBob Peterson } 231*2ca0c2fbSBob Peterson if (unlikely(gfs2_withdrawn(sdp))) { 232*2ca0c2fbSBob Peterson fs_info(sdp, "GFS2:adding buf while withdrawn! 0x%llx\n", 233*2ca0c2fbSBob Peterson (unsigned long long)bd->bd_bh->b_blocknr); 234*2ca0c2fbSBob Peterson } 235192738b7SBob Peterson gfs2_pin(sdp, bd->bd_bh); 236192738b7SBob Peterson mh->__pad0 = cpu_to_be64(0); 237192738b7SBob Peterson mh->mh_jid = cpu_to_be32(sdp->sd_jdesc->jd_jid); 238192738b7SBob Peterson list_add(&bd->bd_list, &tr->tr_buf); 239192738b7SBob Peterson tr->tr_num_buf_new++; 240192738b7SBob Peterson out_unlock: 241767f433fSSteven Whitehouse gfs2_log_unlock(sdp); 242aacee720SBob Peterson out: 243767f433fSSteven Whitehouse unlock_buffer(bh); 244350a9b0aSSteven Whitehouse } 245350a9b0aSSteven Whitehouse 2461ad38c43SSteven Whitehouse void gfs2_trans_add_revoke(struct gfs2_sbd *sdp, struct gfs2_bufdata *bd) 247b3b94faaSDavid Teigland { 24875f2b879SSteven Whitehouse struct gfs2_trans *tr = current->journal_info; 24975f2b879SSteven Whitehouse 250c0752aa7SBob Peterson BUG_ON(!list_empty(&bd->bd_list)); 2515d054964SBenjamin Marzinski gfs2_add_revoke(sdp, bd); 2529862ca05SBob Peterson set_bit(TR_TOUCHED, &tr->tr_flags); 25375f2b879SSteven Whitehouse tr->tr_num_revoke++; 254b3b94faaSDavid Teigland } 255b3b94faaSDavid Teigland 256fbb27873SAndreas Gruenbacher void gfs2_trans_remove_revoke(struct gfs2_sbd *sdp, u64 blkno, unsigned int len) 257b3b94faaSDavid Teigland { 2585731be53SSteven Whitehouse struct gfs2_bufdata *bd, *tmp; 2595731be53SSteven Whitehouse struct gfs2_trans *tr = current->journal_info; 2605731be53SSteven Whitehouse unsigned int n = len; 261b3b94faaSDavid Teigland 262b3b94faaSDavid Teigland gfs2_log_lock(sdp); 263a5b1d3fcSAndreas Gruenbacher list_for_each_entry_safe(bd, tmp, &sdp->sd_log_revokes, bd_list) { 2645731be53SSteven Whitehouse if ((bd->bd_blkno >= blkno) && (bd->bd_blkno < (blkno + len))) { 265c0752aa7SBob Peterson list_del_init(&bd->bd_list); 266b3b94faaSDavid Teigland gfs2_assert_withdraw(sdp, sdp->sd_log_num_revoke); 267b3b94faaSDavid Teigland sdp->sd_log_num_revoke--; 268fe5e7ba1SBob Peterson if (bd->bd_gl) 269fe5e7ba1SBob Peterson gfs2_glock_remove_revoke(bd->bd_gl); 2705731be53SSteven Whitehouse kmem_cache_free(gfs2_bufdata_cachep, bd); 271a31b4ec5SBob Peterson tr->tr_num_revoke_rm++; 2725731be53SSteven Whitehouse if (--n == 0) 273b3b94faaSDavid Teigland break; 274b3b94faaSDavid Teigland } 275b3b94faaSDavid Teigland } 276b3b94faaSDavid Teigland gfs2_log_unlock(sdp); 277b3b94faaSDavid Teigland } 278b3b94faaSDavid Teigland 279