1b3b94faaSDavid Teigland /* 2b3b94faaSDavid Teigland * Copyright (C) Sistina Software, Inc. 1997-2003 All rights reserved. 33a8a9a10SSteven Whitehouse * Copyright (C) 2004-2006 Red Hat, Inc. All rights reserved. 4b3b94faaSDavid Teigland * 5b3b94faaSDavid Teigland * This copyrighted material is made available to anyone wishing to use, 6b3b94faaSDavid Teigland * modify, copy, or redistribute it subject to the terms and conditions 7e9fc2aa0SSteven Whitehouse * of the GNU General Public License version 2. 8b3b94faaSDavid Teigland */ 9b3b94faaSDavid Teigland 10d77d1b58SJoe Perches #define pr_fmt(fmt) KBUILD_MODNAME ": " fmt 11d77d1b58SJoe Perches 12b3b94faaSDavid Teigland #include <linux/sched.h> 13b3b94faaSDavid Teigland #include <linux/slab.h> 14b3b94faaSDavid Teigland #include <linux/spinlock.h> 15b3b94faaSDavid Teigland #include <linux/completion.h> 16b3b94faaSDavid Teigland #include <linux/buffer_head.h> 17d0dc80dbSSteven Whitehouse #include <linux/kallsyms.h> 18f057f6cdSSteven Whitehouse #include <linux/gfs2_ondisk.h> 19b3b94faaSDavid Teigland 20b3b94faaSDavid Teigland #include "gfs2.h" 215c676f6dSSteven Whitehouse #include "incore.h" 22b3b94faaSDavid Teigland #include "glock.h" 23767f433fSSteven Whitehouse #include "inode.h" 24b3b94faaSDavid Teigland #include "log.h" 25b3b94faaSDavid Teigland #include "lops.h" 26b3b94faaSDavid Teigland #include "meta_io.h" 27b3b94faaSDavid Teigland #include "trans.h" 285c676f6dSSteven Whitehouse #include "util.h" 295e687eacSBenjamin Marzinski #include "trace_gfs2.h" 30b3b94faaSDavid Teigland 31d0dc80dbSSteven Whitehouse int gfs2_trans_begin(struct gfs2_sbd *sdp, unsigned int blocks, 32d0dc80dbSSteven Whitehouse unsigned int revokes) 33b3b94faaSDavid Teigland { 34b3b94faaSDavid Teigland struct gfs2_trans *tr; 35b3b94faaSDavid Teigland int error; 36b3b94faaSDavid Teigland 37d0dc80dbSSteven Whitehouse BUG_ON(current->journal_info); 38d0dc80dbSSteven Whitehouse BUG_ON(blocks == 0 && revokes == 0); 39b3b94faaSDavid Teigland 40a1c0643fSSteven Whitehouse if (!test_bit(SDF_JOURNAL_LIVE, &sdp->sd_flags)) 41a1c0643fSSteven Whitehouse return -EROFS; 42a1c0643fSSteven Whitehouse 43f55ab26aSSteven Whitehouse tr = kzalloc(sizeof(struct gfs2_trans), GFP_NOFS); 44b3b94faaSDavid Teigland if (!tr) 45b3b94faaSDavid Teigland return -ENOMEM; 46b3b94faaSDavid Teigland 47d29c0afeSFabian Frederick tr->tr_ip = _RET_IP_; 48b3b94faaSDavid Teigland tr->tr_blocks = blocks; 49b3b94faaSDavid Teigland tr->tr_revokes = revokes; 50b3b94faaSDavid Teigland tr->tr_reserved = 1; 519862ca05SBob Peterson set_bit(TR_ALLOCED, &tr->tr_flags); 52b3b94faaSDavid Teigland if (blocks) 53f4154ea0SSteven Whitehouse tr->tr_reserved += 6 + blocks; 54b3b94faaSDavid Teigland if (revokes) 55b3b94faaSDavid Teigland tr->tr_reserved += gfs2_struct2blk(sdp, revokes, 56cd915493SSteven Whitehouse sizeof(u64)); 57d69a3c65SSteven Whitehouse INIT_LIST_HEAD(&tr->tr_databuf); 58d69a3c65SSteven Whitehouse INIT_LIST_HEAD(&tr->tr_buf); 59d69a3c65SSteven Whitehouse 6039263d5eSJan Kara sb_start_intwrite(sdp->sd_vfs); 61b3b94faaSDavid Teigland 62b3b94faaSDavid Teigland error = gfs2_log_reserve(sdp, tr->tr_reserved); 63b3b94faaSDavid Teigland if (error) 6424972557SBenjamin Marzinski goto fail; 65b3b94faaSDavid Teigland 665c676f6dSSteven Whitehouse current->journal_info = tr; 67b3b94faaSDavid Teigland 68b3b94faaSDavid Teigland return 0; 69b3b94faaSDavid Teigland 7024972557SBenjamin Marzinski fail: 7139263d5eSJan Kara sb_end_intwrite(sdp->sd_vfs); 72b3b94faaSDavid Teigland kfree(tr); 73b3b94faaSDavid Teigland 74b3b94faaSDavid Teigland return error; 75b3b94faaSDavid Teigland } 76b3b94faaSDavid Teigland 77*e54c78a2SBob Peterson static void gfs2_print_trans(struct gfs2_sbd *sdp, const struct gfs2_trans *tr) 78c50b91c4SSteven Whitehouse { 79*e54c78a2SBob Peterson fs_warn(sdp, "Transaction created at: %pSR\n", (void *)tr->tr_ip); 80*e54c78a2SBob Peterson fs_warn(sdp, "blocks=%u revokes=%u reserved=%u touched=%u\n", 819862ca05SBob Peterson tr->tr_blocks, tr->tr_revokes, tr->tr_reserved, 829862ca05SBob Peterson test_bit(TR_TOUCHED, &tr->tr_flags)); 83*e54c78a2SBob Peterson fs_warn(sdp, "Buf %u/%u Databuf %u/%u Revoke %u/%u\n", 84c50b91c4SSteven Whitehouse tr->tr_num_buf_new, tr->tr_num_buf_rm, 85c50b91c4SSteven Whitehouse tr->tr_num_databuf_new, tr->tr_num_databuf_rm, 86c50b91c4SSteven Whitehouse tr->tr_num_revoke, tr->tr_num_revoke_rm); 87c50b91c4SSteven Whitehouse } 88c50b91c4SSteven Whitehouse 89b3b94faaSDavid Teigland void gfs2_trans_end(struct gfs2_sbd *sdp) 90b3b94faaSDavid Teigland { 91f4154ea0SSteven Whitehouse struct gfs2_trans *tr = current->journal_info; 92c50b91c4SSteven Whitehouse s64 nbuf; 939862ca05SBob Peterson int alloced = test_bit(TR_ALLOCED, &tr->tr_flags); 942e60d768SBenjamin Marzinski 955c676f6dSSteven Whitehouse current->journal_info = NULL; 96b3b94faaSDavid Teigland 979862ca05SBob Peterson if (!test_bit(TR_TOUCHED, &tr->tr_flags)) { 98b3b94faaSDavid Teigland gfs2_log_release(sdp, tr->tr_reserved); 992e60d768SBenjamin Marzinski if (alloced) { 100e317ffcbSSteven Whitehouse kfree(tr); 10139263d5eSJan Kara sb_end_intwrite(sdp->sd_vfs); 1022e60d768SBenjamin Marzinski } 103b3b94faaSDavid Teigland return; 104b3b94faaSDavid Teigland } 105b3b94faaSDavid Teigland 106c50b91c4SSteven Whitehouse nbuf = tr->tr_num_buf_new + tr->tr_num_databuf_new; 107c50b91c4SSteven Whitehouse nbuf -= tr->tr_num_buf_rm; 108c50b91c4SSteven Whitehouse nbuf -= tr->tr_num_databuf_rm; 109c50b91c4SSteven Whitehouse 110c50b91c4SSteven Whitehouse if (gfs2_assert_withdraw(sdp, (nbuf <= tr->tr_blocks) && 111c50b91c4SSteven Whitehouse (tr->tr_num_revoke <= tr->tr_revokes))) 112*e54c78a2SBob Peterson gfs2_print_trans(sdp, tr); 113b3b94faaSDavid Teigland 114b3b94faaSDavid Teigland gfs2_log_commit(sdp, tr); 1159862ca05SBob Peterson if (alloced && !test_bit(TR_ATTACHED, &tr->tr_flags)) 116b4dc7291SSteven Whitehouse kfree(tr); 11716ca9412SBenjamin Marzinski up_read(&sdp->sd_log_flush_lock); 118b3b94faaSDavid Teigland 1191751e8a6SLinus Torvalds if (sdp->sd_vfs->s_flags & SB_SYNCHRONOUS) 120805c0907SBob Peterson gfs2_log_flush(sdp, NULL, GFS2_LOG_HEAD_FLUSH_NORMAL | 121805c0907SBob Peterson GFS2_LFC_TRANS_END); 1222e60d768SBenjamin Marzinski if (alloced) 12339263d5eSJan Kara sb_end_intwrite(sdp->sd_vfs); 124b3b94faaSDavid Teigland } 125b3b94faaSDavid Teigland 126c76c4d96SSteven Whitehouse static struct gfs2_bufdata *gfs2_alloc_bufdata(struct gfs2_glock *gl, 127c76c4d96SSteven Whitehouse struct buffer_head *bh, 128c76c4d96SSteven Whitehouse const struct gfs2_log_operations *lops) 129c76c4d96SSteven Whitehouse { 130c76c4d96SSteven Whitehouse struct gfs2_bufdata *bd; 131c76c4d96SSteven Whitehouse 132c76c4d96SSteven Whitehouse bd = kmem_cache_zalloc(gfs2_bufdata_cachep, GFP_NOFS | __GFP_NOFAIL); 133c76c4d96SSteven Whitehouse bd->bd_bh = bh; 134c76c4d96SSteven Whitehouse bd->bd_gl = gl; 135c76c4d96SSteven Whitehouse bd->bd_ops = lops; 136c76c4d96SSteven Whitehouse INIT_LIST_HEAD(&bd->bd_list); 137c76c4d96SSteven Whitehouse bh->b_private = bd; 138c76c4d96SSteven Whitehouse return bd; 139c76c4d96SSteven Whitehouse } 140c76c4d96SSteven Whitehouse 141b3b94faaSDavid Teigland /** 14245138990SSteven Whitehouse * gfs2_trans_add_data - Add a databuf to the transaction. 14345138990SSteven Whitehouse * @gl: The inode glock associated with the buffer 14445138990SSteven Whitehouse * @bh: The buffer to add 145b3b94faaSDavid Teigland * 146845802b1SAndreas Gruenbacher * This is used in journaled data mode. 147767f433fSSteven Whitehouse * We need to journal the data block in the same way as metadata in 148767f433fSSteven Whitehouse * the functions above. The difference is that here we have a tag 149767f433fSSteven Whitehouse * which is two __be64's being the block number (as per meta data) 150767f433fSSteven Whitehouse * and a flag which says whether the data block needs escaping or 151767f433fSSteven Whitehouse * not. This means we need a new log entry for each 251 or so data 152767f433fSSteven Whitehouse * blocks, which isn't an enormous overhead but twice as much as 153767f433fSSteven Whitehouse * for normal metadata blocks. 154b3b94faaSDavid Teigland */ 155767f433fSSteven Whitehouse void gfs2_trans_add_data(struct gfs2_glock *gl, struct buffer_head *bh) 156767f433fSSteven Whitehouse { 15745138990SSteven Whitehouse struct gfs2_trans *tr = current->journal_info; 15815562c43SBob Peterson struct gfs2_sbd *sdp = gl->gl_name.ln_sbd; 159b3b94faaSDavid Teigland struct gfs2_bufdata *bd; 160b3b94faaSDavid Teigland 16196e5d1d3SBenjamin Marzinski lock_buffer(bh); 162aacee720SBob Peterson if (buffer_pinned(bh)) { 163aacee720SBob Peterson set_bit(TR_TOUCHED, &tr->tr_flags); 164aacee720SBob Peterson goto out; 165aacee720SBob Peterson } 16696e5d1d3SBenjamin Marzinski gfs2_log_lock(sdp); 1675c676f6dSSteven Whitehouse bd = bh->b_private; 168c76c4d96SSteven Whitehouse if (bd == NULL) { 16996e5d1d3SBenjamin Marzinski gfs2_log_unlock(sdp); 17096e5d1d3SBenjamin Marzinski unlock_buffer(bh); 171c76c4d96SSteven Whitehouse if (bh->b_private == NULL) 172c76c4d96SSteven Whitehouse bd = gfs2_alloc_bufdata(gl, bh, &gfs2_databuf_lops); 173491e94f7SBob Peterson else 174491e94f7SBob Peterson bd = bh->b_private; 17596e5d1d3SBenjamin Marzinski lock_buffer(bh); 17696e5d1d3SBenjamin Marzinski gfs2_log_lock(sdp); 177b3b94faaSDavid Teigland } 178c76c4d96SSteven Whitehouse gfs2_assert(sdp, bd->bd_gl == gl); 1799862ca05SBob Peterson set_bit(TR_TOUCHED, &tr->tr_flags); 18045138990SSteven Whitehouse if (list_empty(&bd->bd_list)) { 18145138990SSteven Whitehouse set_bit(GLF_LFLUSH, &bd->bd_gl->gl_flags); 18245138990SSteven Whitehouse set_bit(GLF_DIRTY, &bd->bd_gl->gl_flags); 18345138990SSteven Whitehouse gfs2_pin(sdp, bd->bd_bh); 18445138990SSteven Whitehouse tr->tr_num_databuf_new++; 185d69a3c65SSteven Whitehouse list_add_tail(&bd->bd_list, &tr->tr_databuf); 18645138990SSteven Whitehouse } 18796e5d1d3SBenjamin Marzinski gfs2_log_unlock(sdp); 188aacee720SBob Peterson out: 18996e5d1d3SBenjamin Marzinski unlock_buffer(bh); 190b3b94faaSDavid Teigland } 191b3b94faaSDavid Teigland 192350a9b0aSSteven Whitehouse void gfs2_trans_add_meta(struct gfs2_glock *gl, struct buffer_head *bh) 193350a9b0aSSteven Whitehouse { 194767f433fSSteven Whitehouse 19515562c43SBob Peterson struct gfs2_sbd *sdp = gl->gl_name.ln_sbd; 196767f433fSSteven Whitehouse struct gfs2_bufdata *bd; 197192738b7SBob Peterson struct gfs2_meta_header *mh; 198aacee720SBob Peterson struct gfs2_trans *tr = current->journal_info; 199192738b7SBob Peterson enum gfs2_freeze_state state = atomic_read(&sdp->sd_freeze_state); 200767f433fSSteven Whitehouse 201767f433fSSteven Whitehouse lock_buffer(bh); 202aacee720SBob Peterson if (buffer_pinned(bh)) { 203aacee720SBob Peterson set_bit(TR_TOUCHED, &tr->tr_flags); 204aacee720SBob Peterson goto out; 205aacee720SBob Peterson } 206767f433fSSteven Whitehouse gfs2_log_lock(sdp); 207767f433fSSteven Whitehouse bd = bh->b_private; 208c76c4d96SSteven Whitehouse if (bd == NULL) { 209767f433fSSteven Whitehouse gfs2_log_unlock(sdp); 210767f433fSSteven Whitehouse unlock_buffer(bh); 211c76c4d96SSteven Whitehouse lock_page(bh->b_page); 212c76c4d96SSteven Whitehouse if (bh->b_private == NULL) 213c76c4d96SSteven Whitehouse bd = gfs2_alloc_bufdata(gl, bh, &gfs2_buf_lops); 214491e94f7SBob Peterson else 215491e94f7SBob Peterson bd = bh->b_private; 216c76c4d96SSteven Whitehouse unlock_page(bh->b_page); 217767f433fSSteven Whitehouse lock_buffer(bh); 218767f433fSSteven Whitehouse gfs2_log_lock(sdp); 219767f433fSSteven Whitehouse } 220c76c4d96SSteven Whitehouse gfs2_assert(sdp, bd->bd_gl == gl); 221192738b7SBob Peterson set_bit(TR_TOUCHED, &tr->tr_flags); 222192738b7SBob Peterson if (!list_empty(&bd->bd_list)) 223192738b7SBob Peterson goto out_unlock; 224192738b7SBob Peterson set_bit(GLF_LFLUSH, &bd->bd_gl->gl_flags); 225192738b7SBob Peterson set_bit(GLF_DIRTY, &bd->bd_gl->gl_flags); 226192738b7SBob Peterson mh = (struct gfs2_meta_header *)bd->bd_bh->b_data; 227192738b7SBob Peterson if (unlikely(mh->mh_magic != cpu_to_be32(GFS2_MAGIC))) { 228*e54c78a2SBob Peterson fs_err(sdp, "Attempting to add uninitialised block to " 229*e54c78a2SBob Peterson "journal (inplace block=%lld)\n", 230192738b7SBob Peterson (unsigned long long)bd->bd_bh->b_blocknr); 231192738b7SBob Peterson BUG(); 232192738b7SBob Peterson } 233192738b7SBob Peterson if (unlikely(state == SFS_FROZEN)) { 234*e54c78a2SBob Peterson fs_info(sdp, "GFS2:adding buf while frozen\n"); 235192738b7SBob Peterson gfs2_assert_withdraw(sdp, 0); 236192738b7SBob Peterson } 237192738b7SBob Peterson gfs2_pin(sdp, bd->bd_bh); 238192738b7SBob Peterson mh->__pad0 = cpu_to_be64(0); 239192738b7SBob Peterson mh->mh_jid = cpu_to_be32(sdp->sd_jdesc->jd_jid); 240192738b7SBob Peterson list_add(&bd->bd_list, &tr->tr_buf); 241192738b7SBob Peterson tr->tr_num_buf_new++; 242192738b7SBob Peterson out_unlock: 243767f433fSSteven Whitehouse gfs2_log_unlock(sdp); 244aacee720SBob Peterson out: 245767f433fSSteven Whitehouse unlock_buffer(bh); 246350a9b0aSSteven Whitehouse } 247350a9b0aSSteven Whitehouse 2481ad38c43SSteven Whitehouse void gfs2_trans_add_revoke(struct gfs2_sbd *sdp, struct gfs2_bufdata *bd) 249b3b94faaSDavid Teigland { 25075f2b879SSteven Whitehouse struct gfs2_trans *tr = current->journal_info; 25175f2b879SSteven Whitehouse 252c0752aa7SBob Peterson BUG_ON(!list_empty(&bd->bd_list)); 2535d054964SBenjamin Marzinski gfs2_add_revoke(sdp, bd); 2549862ca05SBob Peterson set_bit(TR_TOUCHED, &tr->tr_flags); 25575f2b879SSteven Whitehouse tr->tr_num_revoke++; 256b3b94faaSDavid Teigland } 257b3b94faaSDavid Teigland 2585731be53SSteven Whitehouse void gfs2_trans_add_unrevoke(struct gfs2_sbd *sdp, u64 blkno, unsigned int len) 259b3b94faaSDavid Teigland { 2605731be53SSteven Whitehouse struct gfs2_bufdata *bd, *tmp; 2615731be53SSteven Whitehouse struct gfs2_trans *tr = current->journal_info; 2625731be53SSteven Whitehouse unsigned int n = len; 263b3b94faaSDavid Teigland 264b3b94faaSDavid Teigland gfs2_log_lock(sdp); 265c0752aa7SBob Peterson list_for_each_entry_safe(bd, tmp, &sdp->sd_log_le_revoke, bd_list) { 2665731be53SSteven Whitehouse if ((bd->bd_blkno >= blkno) && (bd->bd_blkno < (blkno + len))) { 267c0752aa7SBob Peterson list_del_init(&bd->bd_list); 268b3b94faaSDavid Teigland gfs2_assert_withdraw(sdp, sdp->sd_log_num_revoke); 269b3b94faaSDavid Teigland sdp->sd_log_num_revoke--; 2705731be53SSteven Whitehouse kmem_cache_free(gfs2_bufdata_cachep, bd); 2715731be53SSteven Whitehouse 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