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 10b3b94faaSDavid Teigland #include <linux/sched.h> 11b3b94faaSDavid Teigland #include <linux/slab.h> 12b3b94faaSDavid Teigland #include <linux/spinlock.h> 13b3b94faaSDavid Teigland #include <linux/completion.h> 14b3b94faaSDavid Teigland #include <linux/buffer_head.h> 15d0dc80dbSSteven Whitehouse #include <linux/kallsyms.h> 16f057f6cdSSteven Whitehouse #include <linux/gfs2_ondisk.h> 17b3b94faaSDavid Teigland 18b3b94faaSDavid Teigland #include "gfs2.h" 195c676f6dSSteven Whitehouse #include "incore.h" 20b3b94faaSDavid Teigland #include "glock.h" 21767f433fSSteven Whitehouse #include "inode.h" 22b3b94faaSDavid Teigland #include "log.h" 23b3b94faaSDavid Teigland #include "lops.h" 24b3b94faaSDavid Teigland #include "meta_io.h" 25b3b94faaSDavid Teigland #include "trans.h" 265c676f6dSSteven Whitehouse #include "util.h" 275e687eacSBenjamin Marzinski #include "trace_gfs2.h" 28b3b94faaSDavid Teigland 29d0dc80dbSSteven Whitehouse int gfs2_trans_begin(struct gfs2_sbd *sdp, unsigned int blocks, 30d0dc80dbSSteven Whitehouse unsigned int revokes) 31b3b94faaSDavid Teigland { 32b3b94faaSDavid Teigland struct gfs2_trans *tr; 33b3b94faaSDavid Teigland int error; 34b3b94faaSDavid Teigland 35d0dc80dbSSteven Whitehouse BUG_ON(current->journal_info); 36d0dc80dbSSteven Whitehouse BUG_ON(blocks == 0 && revokes == 0); 37b3b94faaSDavid Teigland 38a1c0643fSSteven Whitehouse if (!test_bit(SDF_JOURNAL_LIVE, &sdp->sd_flags)) 39a1c0643fSSteven Whitehouse return -EROFS; 40a1c0643fSSteven Whitehouse 41f55ab26aSSteven Whitehouse tr = kzalloc(sizeof(struct gfs2_trans), GFP_NOFS); 42b3b94faaSDavid Teigland if (!tr) 43b3b94faaSDavid Teigland return -ENOMEM; 44b3b94faaSDavid Teigland 45d0dc80dbSSteven Whitehouse tr->tr_ip = (unsigned long)__builtin_return_address(0); 46b3b94faaSDavid Teigland tr->tr_blocks = blocks; 47b3b94faaSDavid Teigland tr->tr_revokes = revokes; 48b3b94faaSDavid Teigland tr->tr_reserved = 1; 49b3b94faaSDavid Teigland if (blocks) 50f4154ea0SSteven Whitehouse tr->tr_reserved += 6 + blocks; 51b3b94faaSDavid Teigland if (revokes) 52b3b94faaSDavid Teigland tr->tr_reserved += gfs2_struct2blk(sdp, revokes, 53cd915493SSteven Whitehouse sizeof(u64)); 54*d69a3c65SSteven Whitehouse INIT_LIST_HEAD(&tr->tr_databuf); 55*d69a3c65SSteven Whitehouse INIT_LIST_HEAD(&tr->tr_buf); 56*d69a3c65SSteven Whitehouse 5739263d5eSJan Kara sb_start_intwrite(sdp->sd_vfs); 58579b78a4SSteven Whitehouse gfs2_holder_init(sdp->sd_trans_gl, LM_ST_SHARED, 0, &tr->tr_t_gh); 59b3b94faaSDavid Teigland 60e317ffcbSSteven Whitehouse error = gfs2_glock_nq(&tr->tr_t_gh); 61b3b94faaSDavid Teigland if (error) 62e317ffcbSSteven Whitehouse goto fail_holder_uninit; 63b3b94faaSDavid Teigland 64b3b94faaSDavid Teigland error = gfs2_log_reserve(sdp, tr->tr_reserved); 65b3b94faaSDavid Teigland if (error) 66b3b94faaSDavid Teigland goto fail_gunlock; 67b3b94faaSDavid Teigland 685c676f6dSSteven Whitehouse current->journal_info = tr; 69b3b94faaSDavid Teigland 70b3b94faaSDavid Teigland return 0; 71b3b94faaSDavid Teigland 72b3b94faaSDavid Teigland fail_gunlock: 73e317ffcbSSteven Whitehouse gfs2_glock_dq(&tr->tr_t_gh); 74b3b94faaSDavid Teigland 75e317ffcbSSteven Whitehouse fail_holder_uninit: 7639263d5eSJan Kara sb_end_intwrite(sdp->sd_vfs); 77e317ffcbSSteven Whitehouse gfs2_holder_uninit(&tr->tr_t_gh); 78b3b94faaSDavid Teigland kfree(tr); 79b3b94faaSDavid Teigland 80b3b94faaSDavid Teigland return error; 81b3b94faaSDavid Teigland } 82b3b94faaSDavid Teigland 835e687eacSBenjamin Marzinski /** 845e687eacSBenjamin Marzinski * gfs2_log_release - Release a given number of log blocks 855e687eacSBenjamin Marzinski * @sdp: The GFS2 superblock 865e687eacSBenjamin Marzinski * @blks: The number of blocks 875e687eacSBenjamin Marzinski * 885e687eacSBenjamin Marzinski */ 895e687eacSBenjamin Marzinski 905e687eacSBenjamin Marzinski static void gfs2_log_release(struct gfs2_sbd *sdp, unsigned int blks) 915e687eacSBenjamin Marzinski { 925e687eacSBenjamin Marzinski 935e687eacSBenjamin Marzinski atomic_add(blks, &sdp->sd_log_blks_free); 945e687eacSBenjamin Marzinski trace_gfs2_log_blocks(sdp, blks); 955e687eacSBenjamin Marzinski gfs2_assert_withdraw(sdp, atomic_read(&sdp->sd_log_blks_free) <= 965e687eacSBenjamin Marzinski sdp->sd_jdesc->jd_blocks); 975e687eacSBenjamin Marzinski up_read(&sdp->sd_log_flush_lock); 985e687eacSBenjamin Marzinski } 995e687eacSBenjamin Marzinski 100c50b91c4SSteven Whitehouse static void gfs2_print_trans(const struct gfs2_trans *tr) 101c50b91c4SSteven Whitehouse { 1027af584d3SJoe Perches printk(KERN_WARNING "GFS2: Transaction created at: %pSR\n", 1037af584d3SJoe Perches (void *)tr->tr_ip); 104654a6d2fSSteven Whitehouse printk(KERN_WARNING "GFS2: blocks=%u revokes=%u reserved=%u touched=%u\n", 105c50b91c4SSteven Whitehouse tr->tr_blocks, tr->tr_revokes, tr->tr_reserved, tr->tr_touched); 106c50b91c4SSteven Whitehouse printk(KERN_WARNING "GFS2: Buf %u/%u Databuf %u/%u Revoke %u/%u\n", 107c50b91c4SSteven Whitehouse tr->tr_num_buf_new, tr->tr_num_buf_rm, 108c50b91c4SSteven Whitehouse tr->tr_num_databuf_new, tr->tr_num_databuf_rm, 109c50b91c4SSteven Whitehouse tr->tr_num_revoke, tr->tr_num_revoke_rm); 110c50b91c4SSteven Whitehouse } 111c50b91c4SSteven Whitehouse 112b3b94faaSDavid Teigland void gfs2_trans_end(struct gfs2_sbd *sdp) 113b3b94faaSDavid Teigland { 114f4154ea0SSteven Whitehouse struct gfs2_trans *tr = current->journal_info; 115c50b91c4SSteven Whitehouse s64 nbuf; 116f4154ea0SSteven Whitehouse BUG_ON(!tr); 1175c676f6dSSteven Whitehouse current->journal_info = NULL; 118b3b94faaSDavid Teigland 119b3b94faaSDavid Teigland if (!tr->tr_touched) { 120b3b94faaSDavid Teigland gfs2_log_release(sdp, tr->tr_reserved); 121d8348de0SSteven Whitehouse if (tr->tr_t_gh.gh_gl) { 122b4dc7291SSteven Whitehouse gfs2_glock_dq(&tr->tr_t_gh); 123b4dc7291SSteven Whitehouse gfs2_holder_uninit(&tr->tr_t_gh); 124e317ffcbSSteven Whitehouse kfree(tr); 125d8348de0SSteven Whitehouse } 12639263d5eSJan Kara sb_end_intwrite(sdp->sd_vfs); 127b3b94faaSDavid Teigland return; 128b3b94faaSDavid Teigland } 129b3b94faaSDavid Teigland 130c50b91c4SSteven Whitehouse nbuf = tr->tr_num_buf_new + tr->tr_num_databuf_new; 131c50b91c4SSteven Whitehouse nbuf -= tr->tr_num_buf_rm; 132c50b91c4SSteven Whitehouse nbuf -= tr->tr_num_databuf_rm; 133c50b91c4SSteven Whitehouse 134c50b91c4SSteven Whitehouse if (gfs2_assert_withdraw(sdp, (nbuf <= tr->tr_blocks) && 135c50b91c4SSteven Whitehouse (tr->tr_num_revoke <= tr->tr_revokes))) 136c50b91c4SSteven Whitehouse gfs2_print_trans(tr); 137b3b94faaSDavid Teigland 138b3b94faaSDavid Teigland gfs2_log_commit(sdp, tr); 139d8348de0SSteven Whitehouse if (tr->tr_t_gh.gh_gl) { 140b4dc7291SSteven Whitehouse gfs2_glock_dq(&tr->tr_t_gh); 141b4dc7291SSteven Whitehouse gfs2_holder_uninit(&tr->tr_t_gh); 14216ca9412SBenjamin Marzinski if (!tr->tr_attached) 143b4dc7291SSteven Whitehouse kfree(tr); 144d8348de0SSteven Whitehouse } 14516ca9412SBenjamin Marzinski up_read(&sdp->sd_log_flush_lock); 146b3b94faaSDavid Teigland 147b3b94faaSDavid Teigland if (sdp->sd_vfs->s_flags & MS_SYNCHRONOUS) 148b09e593dSSteven Whitehouse gfs2_log_flush(sdp, NULL); 14939263d5eSJan Kara sb_end_intwrite(sdp->sd_vfs); 150b3b94faaSDavid Teigland } 151b3b94faaSDavid Teigland 152c76c4d96SSteven Whitehouse static struct gfs2_bufdata *gfs2_alloc_bufdata(struct gfs2_glock *gl, 153c76c4d96SSteven Whitehouse struct buffer_head *bh, 154c76c4d96SSteven Whitehouse const struct gfs2_log_operations *lops) 155c76c4d96SSteven Whitehouse { 156c76c4d96SSteven Whitehouse struct gfs2_bufdata *bd; 157c76c4d96SSteven Whitehouse 158c76c4d96SSteven Whitehouse bd = kmem_cache_zalloc(gfs2_bufdata_cachep, GFP_NOFS | __GFP_NOFAIL); 159c76c4d96SSteven Whitehouse bd->bd_bh = bh; 160c76c4d96SSteven Whitehouse bd->bd_gl = gl; 161c76c4d96SSteven Whitehouse bd->bd_ops = lops; 162c76c4d96SSteven Whitehouse INIT_LIST_HEAD(&bd->bd_list); 163c76c4d96SSteven Whitehouse bh->b_private = bd; 164c76c4d96SSteven Whitehouse return bd; 165c76c4d96SSteven Whitehouse } 166c76c4d96SSteven Whitehouse 167b3b94faaSDavid Teigland /** 16845138990SSteven Whitehouse * gfs2_trans_add_data - Add a databuf to the transaction. 16945138990SSteven Whitehouse * @gl: The inode glock associated with the buffer 17045138990SSteven Whitehouse * @bh: The buffer to add 171b3b94faaSDavid Teigland * 172767f433fSSteven Whitehouse * This is used in two distinct cases: 173767f433fSSteven Whitehouse * i) In ordered write mode 174767f433fSSteven Whitehouse * We put the data buffer on a list so that we can ensure that its 175767f433fSSteven Whitehouse * synced to disk at the right time 176767f433fSSteven Whitehouse * ii) In journaled data mode 177767f433fSSteven Whitehouse * We need to journal the data block in the same way as metadata in 178767f433fSSteven Whitehouse * the functions above. The difference is that here we have a tag 179767f433fSSteven Whitehouse * which is two __be64's being the block number (as per meta data) 180767f433fSSteven Whitehouse * and a flag which says whether the data block needs escaping or 181767f433fSSteven Whitehouse * not. This means we need a new log entry for each 251 or so data 182767f433fSSteven Whitehouse * blocks, which isn't an enormous overhead but twice as much as 183767f433fSSteven Whitehouse * for normal metadata blocks. 184b3b94faaSDavid Teigland */ 185767f433fSSteven Whitehouse void gfs2_trans_add_data(struct gfs2_glock *gl, struct buffer_head *bh) 186767f433fSSteven Whitehouse { 18745138990SSteven Whitehouse struct gfs2_trans *tr = current->journal_info; 188b3b94faaSDavid Teigland struct gfs2_sbd *sdp = gl->gl_sbd; 18945138990SSteven Whitehouse struct address_space *mapping = bh->b_page->mapping; 19045138990SSteven Whitehouse struct gfs2_inode *ip = GFS2_I(mapping->host); 191b3b94faaSDavid Teigland struct gfs2_bufdata *bd; 192b3b94faaSDavid Teigland 19345138990SSteven Whitehouse if (!gfs2_is_jdata(ip)) { 19445138990SSteven Whitehouse gfs2_ordered_add_inode(ip); 19545138990SSteven Whitehouse return; 19645138990SSteven Whitehouse } 19745138990SSteven Whitehouse 19896e5d1d3SBenjamin Marzinski lock_buffer(bh); 19996e5d1d3SBenjamin Marzinski gfs2_log_lock(sdp); 2005c676f6dSSteven Whitehouse bd = bh->b_private; 201c76c4d96SSteven Whitehouse if (bd == NULL) { 20296e5d1d3SBenjamin Marzinski gfs2_log_unlock(sdp); 20396e5d1d3SBenjamin Marzinski unlock_buffer(bh); 204c76c4d96SSteven Whitehouse if (bh->b_private == NULL) 205c76c4d96SSteven Whitehouse bd = gfs2_alloc_bufdata(gl, bh, &gfs2_databuf_lops); 20696e5d1d3SBenjamin Marzinski lock_buffer(bh); 20796e5d1d3SBenjamin Marzinski gfs2_log_lock(sdp); 208b3b94faaSDavid Teigland } 209c76c4d96SSteven Whitehouse gfs2_assert(sdp, bd->bd_gl == gl); 21045138990SSteven Whitehouse tr->tr_touched = 1; 21145138990SSteven Whitehouse if (list_empty(&bd->bd_list)) { 21245138990SSteven Whitehouse set_bit(GLF_LFLUSH, &bd->bd_gl->gl_flags); 21345138990SSteven Whitehouse set_bit(GLF_DIRTY, &bd->bd_gl->gl_flags); 21445138990SSteven Whitehouse gfs2_pin(sdp, bd->bd_bh); 21545138990SSteven Whitehouse tr->tr_num_databuf_new++; 21645138990SSteven Whitehouse sdp->sd_log_num_databuf++; 217*d69a3c65SSteven Whitehouse list_add_tail(&bd->bd_list, &tr->tr_databuf); 21845138990SSteven Whitehouse } 21996e5d1d3SBenjamin Marzinski gfs2_log_unlock(sdp); 22096e5d1d3SBenjamin Marzinski unlock_buffer(bh); 221b3b94faaSDavid Teigland } 222b3b94faaSDavid Teigland 223767f433fSSteven Whitehouse static void meta_lo_add(struct gfs2_sbd *sdp, struct gfs2_bufdata *bd) 224350a9b0aSSteven Whitehouse { 225767f433fSSteven Whitehouse struct gfs2_meta_header *mh; 226767f433fSSteven Whitehouse struct gfs2_trans *tr; 227767f433fSSteven Whitehouse 228767f433fSSteven Whitehouse tr = current->journal_info; 229767f433fSSteven Whitehouse tr->tr_touched = 1; 230767f433fSSteven Whitehouse if (!list_empty(&bd->bd_list)) 231767f433fSSteven Whitehouse return; 232767f433fSSteven Whitehouse set_bit(GLF_LFLUSH, &bd->bd_gl->gl_flags); 233767f433fSSteven Whitehouse set_bit(GLF_DIRTY, &bd->bd_gl->gl_flags); 234767f433fSSteven Whitehouse mh = (struct gfs2_meta_header *)bd->bd_bh->b_data; 235767f433fSSteven Whitehouse if (unlikely(mh->mh_magic != cpu_to_be32(GFS2_MAGIC))) { 236767f433fSSteven Whitehouse printk(KERN_ERR 237767f433fSSteven Whitehouse "Attempting to add uninitialised block to journal (inplace block=%lld)\n", 238767f433fSSteven Whitehouse (unsigned long long)bd->bd_bh->b_blocknr); 239767f433fSSteven Whitehouse BUG(); 240767f433fSSteven Whitehouse } 241767f433fSSteven Whitehouse gfs2_pin(sdp, bd->bd_bh); 242767f433fSSteven Whitehouse mh->__pad0 = cpu_to_be64(0); 243767f433fSSteven Whitehouse mh->mh_jid = cpu_to_be32(sdp->sd_jdesc->jd_jid); 244767f433fSSteven Whitehouse sdp->sd_log_num_buf++; 245*d69a3c65SSteven Whitehouse list_add(&bd->bd_list, &tr->tr_buf); 246767f433fSSteven Whitehouse tr->tr_num_buf_new++; 247350a9b0aSSteven Whitehouse } 248350a9b0aSSteven Whitehouse 249350a9b0aSSteven Whitehouse void gfs2_trans_add_meta(struct gfs2_glock *gl, struct buffer_head *bh) 250350a9b0aSSteven Whitehouse { 251767f433fSSteven Whitehouse 252767f433fSSteven Whitehouse struct gfs2_sbd *sdp = gl->gl_sbd; 253767f433fSSteven Whitehouse struct gfs2_bufdata *bd; 254767f433fSSteven Whitehouse 255767f433fSSteven Whitehouse lock_buffer(bh); 256767f433fSSteven Whitehouse gfs2_log_lock(sdp); 257767f433fSSteven Whitehouse bd = bh->b_private; 258c76c4d96SSteven Whitehouse if (bd == NULL) { 259767f433fSSteven Whitehouse gfs2_log_unlock(sdp); 260767f433fSSteven Whitehouse unlock_buffer(bh); 261c76c4d96SSteven Whitehouse lock_page(bh->b_page); 262c76c4d96SSteven Whitehouse if (bh->b_private == NULL) 263c76c4d96SSteven Whitehouse bd = gfs2_alloc_bufdata(gl, bh, &gfs2_buf_lops); 264c76c4d96SSteven Whitehouse unlock_page(bh->b_page); 265767f433fSSteven Whitehouse lock_buffer(bh); 266767f433fSSteven Whitehouse gfs2_log_lock(sdp); 267767f433fSSteven Whitehouse } 268c76c4d96SSteven Whitehouse gfs2_assert(sdp, bd->bd_gl == gl); 269767f433fSSteven Whitehouse meta_lo_add(sdp, bd); 270767f433fSSteven Whitehouse gfs2_log_unlock(sdp); 271767f433fSSteven Whitehouse unlock_buffer(bh); 272350a9b0aSSteven Whitehouse } 273350a9b0aSSteven Whitehouse 2741ad38c43SSteven Whitehouse void gfs2_trans_add_revoke(struct gfs2_sbd *sdp, struct gfs2_bufdata *bd) 275b3b94faaSDavid Teigland { 27675f2b879SSteven Whitehouse struct gfs2_trans *tr = current->journal_info; 27775f2b879SSteven Whitehouse 278c0752aa7SBob Peterson BUG_ON(!list_empty(&bd->bd_list)); 2795d054964SBenjamin Marzinski gfs2_add_revoke(sdp, bd); 28075f2b879SSteven Whitehouse tr->tr_touched = 1; 28175f2b879SSteven Whitehouse tr->tr_num_revoke++; 282b3b94faaSDavid Teigland } 283b3b94faaSDavid Teigland 2845731be53SSteven Whitehouse void gfs2_trans_add_unrevoke(struct gfs2_sbd *sdp, u64 blkno, unsigned int len) 285b3b94faaSDavid Teigland { 2865731be53SSteven Whitehouse struct gfs2_bufdata *bd, *tmp; 2875731be53SSteven Whitehouse struct gfs2_trans *tr = current->journal_info; 2885731be53SSteven Whitehouse unsigned int n = len; 289b3b94faaSDavid Teigland 290b3b94faaSDavid Teigland gfs2_log_lock(sdp); 291c0752aa7SBob Peterson list_for_each_entry_safe(bd, tmp, &sdp->sd_log_le_revoke, bd_list) { 2925731be53SSteven Whitehouse if ((bd->bd_blkno >= blkno) && (bd->bd_blkno < (blkno + len))) { 293c0752aa7SBob Peterson list_del_init(&bd->bd_list); 294b3b94faaSDavid Teigland gfs2_assert_withdraw(sdp, sdp->sd_log_num_revoke); 295b3b94faaSDavid Teigland sdp->sd_log_num_revoke--; 2965731be53SSteven Whitehouse kmem_cache_free(gfs2_bufdata_cachep, bd); 2975731be53SSteven Whitehouse tr->tr_num_revoke_rm++; 2985731be53SSteven Whitehouse if (--n == 0) 299b3b94faaSDavid Teigland break; 300b3b94faaSDavid Teigland } 301b3b94faaSDavid Teigland } 302b3b94faaSDavid Teigland gfs2_log_unlock(sdp); 303b3b94faaSDavid Teigland } 304b3b94faaSDavid Teigland 305