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; 5124972557SBenjamin Marzinski tr->tr_alloced = 1; 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 77c50b91c4SSteven Whitehouse static void gfs2_print_trans(const struct gfs2_trans *tr) 78c50b91c4SSteven Whitehouse { 79d77d1b58SJoe Perches pr_warn("Transaction created at: %pSR\n", (void *)tr->tr_ip); 80d77d1b58SJoe Perches pr_warn("blocks=%u revokes=%u reserved=%u touched=%u\n", 81c50b91c4SSteven Whitehouse tr->tr_blocks, tr->tr_revokes, tr->tr_reserved, tr->tr_touched); 82d77d1b58SJoe Perches pr_warn("Buf %u/%u Databuf %u/%u Revoke %u/%u\n", 83c50b91c4SSteven Whitehouse tr->tr_num_buf_new, tr->tr_num_buf_rm, 84c50b91c4SSteven Whitehouse tr->tr_num_databuf_new, tr->tr_num_databuf_rm, 85c50b91c4SSteven Whitehouse tr->tr_num_revoke, tr->tr_num_revoke_rm); 86c50b91c4SSteven Whitehouse } 87c50b91c4SSteven Whitehouse 88b3b94faaSDavid Teigland void gfs2_trans_end(struct gfs2_sbd *sdp) 89b3b94faaSDavid Teigland { 90f4154ea0SSteven Whitehouse struct gfs2_trans *tr = current->journal_info; 91c50b91c4SSteven Whitehouse s64 nbuf; 92f4154ea0SSteven Whitehouse BUG_ON(!tr); 935c676f6dSSteven Whitehouse current->journal_info = NULL; 94b3b94faaSDavid Teigland 95b3b94faaSDavid Teigland if (!tr->tr_touched) { 96b3b94faaSDavid Teigland gfs2_log_release(sdp, tr->tr_reserved); 9724972557SBenjamin Marzinski if (tr->tr_alloced) 98e317ffcbSSteven Whitehouse kfree(tr); 9939263d5eSJan Kara sb_end_intwrite(sdp->sd_vfs); 100b3b94faaSDavid Teigland return; 101b3b94faaSDavid Teigland } 102b3b94faaSDavid Teigland 103c50b91c4SSteven Whitehouse nbuf = tr->tr_num_buf_new + tr->tr_num_databuf_new; 104c50b91c4SSteven Whitehouse nbuf -= tr->tr_num_buf_rm; 105c50b91c4SSteven Whitehouse nbuf -= tr->tr_num_databuf_rm; 106c50b91c4SSteven Whitehouse 107c50b91c4SSteven Whitehouse if (gfs2_assert_withdraw(sdp, (nbuf <= tr->tr_blocks) && 108c50b91c4SSteven Whitehouse (tr->tr_num_revoke <= tr->tr_revokes))) 109c50b91c4SSteven Whitehouse gfs2_print_trans(tr); 110b3b94faaSDavid Teigland 111b3b94faaSDavid Teigland gfs2_log_commit(sdp, tr); 11224972557SBenjamin Marzinski if (tr->tr_alloced && !tr->tr_attached) 113b4dc7291SSteven Whitehouse kfree(tr); 11416ca9412SBenjamin Marzinski up_read(&sdp->sd_log_flush_lock); 115b3b94faaSDavid Teigland 116b3b94faaSDavid Teigland if (sdp->sd_vfs->s_flags & MS_SYNCHRONOUS) 11724972557SBenjamin Marzinski gfs2_log_flush(sdp, NULL, NORMAL_FLUSH); 11839263d5eSJan Kara sb_end_intwrite(sdp->sd_vfs); 119b3b94faaSDavid Teigland } 120b3b94faaSDavid Teigland 121c76c4d96SSteven Whitehouse static struct gfs2_bufdata *gfs2_alloc_bufdata(struct gfs2_glock *gl, 122c76c4d96SSteven Whitehouse struct buffer_head *bh, 123c76c4d96SSteven Whitehouse const struct gfs2_log_operations *lops) 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 bd->bd_ops = lops; 131c76c4d96SSteven Whitehouse INIT_LIST_HEAD(&bd->bd_list); 132c76c4d96SSteven Whitehouse bh->b_private = bd; 133c76c4d96SSteven Whitehouse return bd; 134c76c4d96SSteven Whitehouse } 135c76c4d96SSteven Whitehouse 136b3b94faaSDavid Teigland /** 13745138990SSteven Whitehouse * gfs2_trans_add_data - Add a databuf to the transaction. 13845138990SSteven Whitehouse * @gl: The inode glock associated with the buffer 13945138990SSteven Whitehouse * @bh: The buffer to add 140b3b94faaSDavid Teigland * 141767f433fSSteven Whitehouse * This is used in two distinct cases: 142767f433fSSteven Whitehouse * i) In ordered write mode 143767f433fSSteven Whitehouse * We put the data buffer on a list so that we can ensure that its 144767f433fSSteven Whitehouse * synced to disk at the right time 145767f433fSSteven Whitehouse * ii) In journaled data mode 146767f433fSSteven Whitehouse * We need to journal the data block in the same way as metadata in 147767f433fSSteven Whitehouse * the functions above. The difference is that here we have a tag 148767f433fSSteven Whitehouse * which is two __be64's being the block number (as per meta data) 149767f433fSSteven Whitehouse * and a flag which says whether the data block needs escaping or 150767f433fSSteven Whitehouse * not. This means we need a new log entry for each 251 or so data 151767f433fSSteven Whitehouse * blocks, which isn't an enormous overhead but twice as much as 152767f433fSSteven Whitehouse * for normal metadata blocks. 153b3b94faaSDavid Teigland */ 154767f433fSSteven Whitehouse void gfs2_trans_add_data(struct gfs2_glock *gl, struct buffer_head *bh) 155767f433fSSteven Whitehouse { 15645138990SSteven Whitehouse struct gfs2_trans *tr = current->journal_info; 157b3b94faaSDavid Teigland struct gfs2_sbd *sdp = gl->gl_sbd; 15845138990SSteven Whitehouse struct address_space *mapping = bh->b_page->mapping; 15945138990SSteven Whitehouse struct gfs2_inode *ip = GFS2_I(mapping->host); 160b3b94faaSDavid Teigland struct gfs2_bufdata *bd; 161b3b94faaSDavid Teigland 16245138990SSteven Whitehouse if (!gfs2_is_jdata(ip)) { 16345138990SSteven Whitehouse gfs2_ordered_add_inode(ip); 16445138990SSteven Whitehouse return; 16545138990SSteven Whitehouse } 16645138990SSteven Whitehouse 16796e5d1d3SBenjamin Marzinski lock_buffer(bh); 16896e5d1d3SBenjamin Marzinski gfs2_log_lock(sdp); 1695c676f6dSSteven Whitehouse bd = bh->b_private; 170c76c4d96SSteven Whitehouse if (bd == NULL) { 17196e5d1d3SBenjamin Marzinski gfs2_log_unlock(sdp); 17296e5d1d3SBenjamin Marzinski unlock_buffer(bh); 173c76c4d96SSteven Whitehouse if (bh->b_private == NULL) 174c76c4d96SSteven Whitehouse bd = gfs2_alloc_bufdata(gl, bh, &gfs2_databuf_lops); 17596e5d1d3SBenjamin Marzinski lock_buffer(bh); 17696e5d1d3SBenjamin Marzinski gfs2_log_lock(sdp); 177b3b94faaSDavid Teigland } 178c76c4d96SSteven Whitehouse gfs2_assert(sdp, bd->bd_gl == gl); 17945138990SSteven Whitehouse tr->tr_touched = 1; 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); 18896e5d1d3SBenjamin Marzinski unlock_buffer(bh); 189b3b94faaSDavid Teigland } 190b3b94faaSDavid Teigland 191767f433fSSteven Whitehouse static void meta_lo_add(struct gfs2_sbd *sdp, struct gfs2_bufdata *bd) 192350a9b0aSSteven Whitehouse { 193767f433fSSteven Whitehouse struct gfs2_meta_header *mh; 194767f433fSSteven Whitehouse struct gfs2_trans *tr; 195767f433fSSteven Whitehouse 196767f433fSSteven Whitehouse tr = current->journal_info; 197767f433fSSteven Whitehouse tr->tr_touched = 1; 198767f433fSSteven Whitehouse if (!list_empty(&bd->bd_list)) 199767f433fSSteven Whitehouse return; 200767f433fSSteven Whitehouse set_bit(GLF_LFLUSH, &bd->bd_gl->gl_flags); 201767f433fSSteven Whitehouse set_bit(GLF_DIRTY, &bd->bd_gl->gl_flags); 202767f433fSSteven Whitehouse mh = (struct gfs2_meta_header *)bd->bd_bh->b_data; 203767f433fSSteven Whitehouse if (unlikely(mh->mh_magic != cpu_to_be32(GFS2_MAGIC))) { 204d77d1b58SJoe Perches pr_err("Attempting to add uninitialised block to journal (inplace block=%lld)\n", 205767f433fSSteven Whitehouse (unsigned long long)bd->bd_bh->b_blocknr); 206767f433fSSteven Whitehouse BUG(); 207767f433fSSteven Whitehouse } 208767f433fSSteven Whitehouse gfs2_pin(sdp, bd->bd_bh); 209767f433fSSteven Whitehouse mh->__pad0 = cpu_to_be64(0); 210767f433fSSteven Whitehouse mh->mh_jid = cpu_to_be32(sdp->sd_jdesc->jd_jid); 211d69a3c65SSteven Whitehouse list_add(&bd->bd_list, &tr->tr_buf); 212767f433fSSteven Whitehouse tr->tr_num_buf_new++; 213350a9b0aSSteven Whitehouse } 214350a9b0aSSteven Whitehouse 215350a9b0aSSteven Whitehouse void gfs2_trans_add_meta(struct gfs2_glock *gl, struct buffer_head *bh) 216350a9b0aSSteven Whitehouse { 217767f433fSSteven Whitehouse 218767f433fSSteven Whitehouse struct gfs2_sbd *sdp = gl->gl_sbd; 219767f433fSSteven Whitehouse struct gfs2_bufdata *bd; 220767f433fSSteven Whitehouse 221767f433fSSteven Whitehouse lock_buffer(bh); 222767f433fSSteven Whitehouse gfs2_log_lock(sdp); 223767f433fSSteven Whitehouse bd = bh->b_private; 224c76c4d96SSteven Whitehouse if (bd == NULL) { 225767f433fSSteven Whitehouse gfs2_log_unlock(sdp); 226767f433fSSteven Whitehouse unlock_buffer(bh); 227c76c4d96SSteven Whitehouse lock_page(bh->b_page); 228c76c4d96SSteven Whitehouse if (bh->b_private == NULL) 229c76c4d96SSteven Whitehouse bd = gfs2_alloc_bufdata(gl, bh, &gfs2_buf_lops); 230c76c4d96SSteven Whitehouse unlock_page(bh->b_page); 231767f433fSSteven Whitehouse lock_buffer(bh); 232767f433fSSteven Whitehouse gfs2_log_lock(sdp); 233767f433fSSteven Whitehouse } 234c76c4d96SSteven Whitehouse gfs2_assert(sdp, bd->bd_gl == gl); 235767f433fSSteven Whitehouse meta_lo_add(sdp, bd); 236767f433fSSteven Whitehouse gfs2_log_unlock(sdp); 237767f433fSSteven Whitehouse unlock_buffer(bh); 238350a9b0aSSteven Whitehouse } 239350a9b0aSSteven Whitehouse 2401ad38c43SSteven Whitehouse void gfs2_trans_add_revoke(struct gfs2_sbd *sdp, struct gfs2_bufdata *bd) 241b3b94faaSDavid Teigland { 24275f2b879SSteven Whitehouse struct gfs2_trans *tr = current->journal_info; 24375f2b879SSteven Whitehouse 244c0752aa7SBob Peterson BUG_ON(!list_empty(&bd->bd_list)); 2455d054964SBenjamin Marzinski gfs2_add_revoke(sdp, bd); 24675f2b879SSteven Whitehouse tr->tr_touched = 1; 24775f2b879SSteven Whitehouse tr->tr_num_revoke++; 248b3b94faaSDavid Teigland } 249b3b94faaSDavid Teigland 2505731be53SSteven Whitehouse void gfs2_trans_add_unrevoke(struct gfs2_sbd *sdp, u64 blkno, unsigned int len) 251b3b94faaSDavid Teigland { 2525731be53SSteven Whitehouse struct gfs2_bufdata *bd, *tmp; 2535731be53SSteven Whitehouse struct gfs2_trans *tr = current->journal_info; 2545731be53SSteven Whitehouse unsigned int n = len; 255b3b94faaSDavid Teigland 256b3b94faaSDavid Teigland gfs2_log_lock(sdp); 257c0752aa7SBob Peterson list_for_each_entry_safe(bd, tmp, &sdp->sd_log_le_revoke, bd_list) { 2585731be53SSteven Whitehouse if ((bd->bd_blkno >= blkno) && (bd->bd_blkno < (blkno + len))) { 259c0752aa7SBob Peterson list_del_init(&bd->bd_list); 260b3b94faaSDavid Teigland gfs2_assert_withdraw(sdp, sdp->sd_log_num_revoke); 261b3b94faaSDavid Teigland sdp->sd_log_num_revoke--; 2625731be53SSteven Whitehouse kmem_cache_free(gfs2_bufdata_cachep, bd); 2635731be53SSteven Whitehouse tr->tr_num_revoke_rm++; 2645731be53SSteven Whitehouse if (--n == 0) 265b3b94faaSDavid Teigland break; 266b3b94faaSDavid Teigland } 267b3b94faaSDavid Teigland } 268b3b94faaSDavid Teigland gfs2_log_unlock(sdp); 269b3b94faaSDavid Teigland } 270b3b94faaSDavid Teigland 271