xref: /linux/fs/gfs2/trans.c (revision 1ad38c43)
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>
155c676f6dSSteven Whitehouse #include <linux/gfs2_ondisk.h>
16d0dc80dbSSteven Whitehouse #include <linux/kallsyms.h>
177d308590SFabio Massimo Di Nitto #include <linux/lm_interface.h>
18b3b94faaSDavid Teigland 
19b3b94faaSDavid Teigland #include "gfs2.h"
205c676f6dSSteven Whitehouse #include "incore.h"
21b3b94faaSDavid Teigland #include "glock.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"
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 
37f55ab26aSSteven Whitehouse 	tr = kzalloc(sizeof(struct gfs2_trans), GFP_NOFS);
38b3b94faaSDavid Teigland 	if (!tr)
39b3b94faaSDavid Teigland 		return -ENOMEM;
40b3b94faaSDavid Teigland 
41d0dc80dbSSteven Whitehouse 	tr->tr_ip = (unsigned long)__builtin_return_address(0);
42b3b94faaSDavid Teigland 	tr->tr_blocks = blocks;
43b3b94faaSDavid Teigland 	tr->tr_revokes = revokes;
44b3b94faaSDavid Teigland 	tr->tr_reserved = 1;
45b3b94faaSDavid Teigland 	if (blocks)
46f4154ea0SSteven Whitehouse 		tr->tr_reserved += 6 + blocks;
47b3b94faaSDavid Teigland 	if (revokes)
48b3b94faaSDavid Teigland 		tr->tr_reserved += gfs2_struct2blk(sdp, revokes,
49cd915493SSteven Whitehouse 						   sizeof(u64));
50b3b94faaSDavid Teigland 	INIT_LIST_HEAD(&tr->tr_list_buf);
51b3b94faaSDavid Teigland 
52579b78a4SSteven Whitehouse 	gfs2_holder_init(sdp->sd_trans_gl, LM_ST_SHARED, 0, &tr->tr_t_gh);
53b3b94faaSDavid Teigland 
54e317ffcbSSteven Whitehouse 	error = gfs2_glock_nq(&tr->tr_t_gh);
55b3b94faaSDavid Teigland 	if (error)
56e317ffcbSSteven Whitehouse 		goto fail_holder_uninit;
57b3b94faaSDavid Teigland 
58b3b94faaSDavid Teigland 	if (!test_bit(SDF_JOURNAL_LIVE, &sdp->sd_flags)) {
59e317ffcbSSteven Whitehouse 		tr->tr_t_gh.gh_flags |= GL_NOCACHE;
60b3b94faaSDavid Teigland 		error = -EROFS;
61b3b94faaSDavid Teigland 		goto fail_gunlock;
62b3b94faaSDavid Teigland 	}
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:
76e317ffcbSSteven Whitehouse 	gfs2_holder_uninit(&tr->tr_t_gh);
77b3b94faaSDavid Teigland 	kfree(tr);
78b3b94faaSDavid Teigland 
79b3b94faaSDavid Teigland 	return error;
80b3b94faaSDavid Teigland }
81b3b94faaSDavid Teigland 
82b3b94faaSDavid Teigland void gfs2_trans_end(struct gfs2_sbd *sdp)
83b3b94faaSDavid Teigland {
84f4154ea0SSteven Whitehouse 	struct gfs2_trans *tr = current->journal_info;
85b3b94faaSDavid Teigland 
86f4154ea0SSteven Whitehouse 	BUG_ON(!tr);
875c676f6dSSteven Whitehouse 	current->journal_info = NULL;
88b3b94faaSDavid Teigland 
89b3b94faaSDavid Teigland 	if (!tr->tr_touched) {
90b3b94faaSDavid Teigland 		gfs2_log_release(sdp, tr->tr_reserved);
91b4dc7291SSteven Whitehouse 		gfs2_glock_dq(&tr->tr_t_gh);
92b4dc7291SSteven Whitehouse 		gfs2_holder_uninit(&tr->tr_t_gh);
93e317ffcbSSteven Whitehouse 		kfree(tr);
94b3b94faaSDavid Teigland 		return;
95b3b94faaSDavid Teigland 	}
96b3b94faaSDavid Teigland 
97d0dc80dbSSteven Whitehouse 	if (gfs2_assert_withdraw(sdp, tr->tr_num_buf <= tr->tr_blocks)) {
98d0dc80dbSSteven Whitehouse 		fs_err(sdp, "tr_num_buf = %u, tr_blocks = %u ",
99d0dc80dbSSteven Whitehouse 		       tr->tr_num_buf, tr->tr_blocks);
100d0dc80dbSSteven Whitehouse 		print_symbol(KERN_WARNING "GFS2: Transaction created at: %s\n", tr->tr_ip);
101d0dc80dbSSteven Whitehouse 	}
102cd45697fSSteven Whitehouse 	if (gfs2_assert_withdraw(sdp, tr->tr_num_revoke <= tr->tr_revokes)) {
103d0dc80dbSSteven Whitehouse 		fs_err(sdp, "tr_num_revoke = %u, tr_revokes = %u ",
104d0dc80dbSSteven Whitehouse 		       tr->tr_num_revoke, tr->tr_revokes);
105d0dc80dbSSteven Whitehouse 		print_symbol(KERN_WARNING "GFS2: Transaction created at: %s\n", tr->tr_ip);
106cd45697fSSteven Whitehouse 	}
107b3b94faaSDavid Teigland 
108b3b94faaSDavid Teigland 	gfs2_log_commit(sdp, tr);
109b4dc7291SSteven Whitehouse         gfs2_glock_dq(&tr->tr_t_gh);
110b4dc7291SSteven Whitehouse         gfs2_holder_uninit(&tr->tr_t_gh);
111b4dc7291SSteven Whitehouse         kfree(tr);
112b3b94faaSDavid Teigland 
113b3b94faaSDavid Teigland 	if (sdp->sd_vfs->s_flags & MS_SYNCHRONOUS)
114b09e593dSSteven Whitehouse 		gfs2_log_flush(sdp, NULL);
115b3b94faaSDavid Teigland }
116b3b94faaSDavid Teigland 
117b3b94faaSDavid Teigland void gfs2_trans_add_gl(struct gfs2_glock *gl)
118b3b94faaSDavid Teigland {
119b3b94faaSDavid Teigland 	lops_add(gl->gl_sbd, &gl->gl_le);
120b3b94faaSDavid Teigland }
121b3b94faaSDavid Teigland 
122b3b94faaSDavid Teigland /**
123b3b94faaSDavid Teigland  * gfs2_trans_add_bh - Add a to-be-modified buffer to the current transaction
124b3b94faaSDavid Teigland  * @gl: the glock the buffer belongs to
125b3b94faaSDavid Teigland  * @bh: The buffer to add
126d4e9c4c3SSteven Whitehouse  * @meta: True in the case of adding metadata
127b3b94faaSDavid Teigland  *
128b3b94faaSDavid Teigland  */
129b3b94faaSDavid Teigland 
130d4e9c4c3SSteven Whitehouse void gfs2_trans_add_bh(struct gfs2_glock *gl, struct buffer_head *bh, int meta)
131b3b94faaSDavid Teigland {
132b3b94faaSDavid Teigland 	struct gfs2_sbd *sdp = gl->gl_sbd;
133b3b94faaSDavid Teigland 	struct gfs2_bufdata *bd;
134b3b94faaSDavid Teigland 
1355c676f6dSSteven Whitehouse 	bd = bh->b_private;
136b3b94faaSDavid Teigland 	if (bd)
137b3b94faaSDavid Teigland 		gfs2_assert(sdp, bd->bd_gl == gl);
138b3b94faaSDavid Teigland 	else {
139586dfdaaSSteven Whitehouse 		gfs2_attach_bufdata(gl, bh, meta);
1405c676f6dSSteven Whitehouse 		bd = bh->b_private;
141b3b94faaSDavid Teigland 	}
142b3b94faaSDavid Teigland 	lops_add(sdp, &bd->bd_le);
143b3b94faaSDavid Teigland }
144b3b94faaSDavid Teigland 
145*1ad38c43SSteven Whitehouse void gfs2_trans_add_revoke(struct gfs2_sbd *sdp, struct gfs2_bufdata *bd)
146b3b94faaSDavid Teigland {
147*1ad38c43SSteven Whitehouse 	BUG_ON(!list_empty(&bd->bd_le.le_list));
148*1ad38c43SSteven Whitehouse 	BUG_ON(!list_empty(&bd->bd_ail_st_list));
149*1ad38c43SSteven Whitehouse 	BUG_ON(!list_empty(&bd->bd_ail_gl_list));
15082e86087SSteven Whitehouse 	lops_init_le(&bd->bd_le, &gfs2_revoke_lops);
15182e86087SSteven Whitehouse 	lops_add(sdp, &bd->bd_le);
152b3b94faaSDavid Teigland }
153b3b94faaSDavid Teigland 
154cd915493SSteven Whitehouse void gfs2_trans_add_unrevoke(struct gfs2_sbd *sdp, u64 blkno)
155b3b94faaSDavid Teigland {
15682e86087SSteven Whitehouse 	struct gfs2_bufdata *bd;
157b3b94faaSDavid Teigland 	int found = 0;
158b3b94faaSDavid Teigland 
159b3b94faaSDavid Teigland 	gfs2_log_lock(sdp);
160b3b94faaSDavid Teigland 
16182e86087SSteven Whitehouse 	list_for_each_entry(bd, &sdp->sd_log_le_revoke, bd_le.le_list) {
16282e86087SSteven Whitehouse 		if (bd->bd_blkno == blkno) {
163*1ad38c43SSteven Whitehouse 			list_del_init(&bd->bd_le.le_list);
164b3b94faaSDavid Teigland 			gfs2_assert_withdraw(sdp, sdp->sd_log_num_revoke);
165b3b94faaSDavid Teigland 			sdp->sd_log_num_revoke--;
166b3b94faaSDavid Teigland 			found = 1;
167b3b94faaSDavid Teigland 			break;
168b3b94faaSDavid Teigland 		}
169b3b94faaSDavid Teigland 	}
170b3b94faaSDavid Teigland 
171b3b94faaSDavid Teigland 	gfs2_log_unlock(sdp);
172b3b94faaSDavid Teigland 
173b3b94faaSDavid Teigland 	if (found) {
1745c676f6dSSteven Whitehouse 		struct gfs2_trans *tr = current->journal_info;
1750820ab51SSteven Whitehouse 		kmem_cache_free(gfs2_bufdata_cachep, bd);
1765c676f6dSSteven Whitehouse 		tr->tr_num_revoke_rm++;
177b3b94faaSDavid Teigland 	}
178b3b94faaSDavid Teigland }
179b3b94faaSDavid Teigland 
180b3b94faaSDavid Teigland void gfs2_trans_add_rg(struct gfs2_rgrpd *rgd)
181b3b94faaSDavid Teigland {
182b3b94faaSDavid Teigland 	lops_add(rgd->rd_sbd, &rgd->rd_le);
183b3b94faaSDavid Teigland }
184b3b94faaSDavid Teigland 
185