Blame view
fs/gfs2/trans.c
7.25 KB
b3b94faa5 [GFS2] The core o... |
1 2 |
/* * Copyright (C) Sistina Software, Inc. 1997-2003 All rights reserved. |
3a8a9a103 [GFS2] Update cop... |
3 |
* Copyright (C) 2004-2006 Red Hat, Inc. All rights reserved. |
b3b94faa5 [GFS2] The core o... |
4 5 6 |
* * This copyrighted material is made available to anyone wishing to use, * modify, copy, or redistribute it subject to the terms and conditions |
e9fc2aa09 [GFS2] Update cop... |
7 |
* of the GNU General Public License version 2. |
b3b94faa5 [GFS2] The core o... |
8 |
*/ |
d77d1b58a GFS2: Use pr_<lev... |
9 |
#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt |
b3b94faa5 [GFS2] The core o... |
10 11 12 13 14 |
#include <linux/sched.h> #include <linux/slab.h> #include <linux/spinlock.h> #include <linux/completion.h> #include <linux/buffer_head.h> |
d0dc80dba [GFS2] Update deb... |
15 |
#include <linux/kallsyms.h> |
f057f6cdf GFS2: Merge lock_... |
16 |
#include <linux/gfs2_ondisk.h> |
b3b94faa5 [GFS2] The core o... |
17 18 |
#include "gfs2.h" |
5c676f6d3 [GFS2] Macros rem... |
19 |
#include "incore.h" |
b3b94faa5 [GFS2] The core o... |
20 |
#include "glock.h" |
767f433f3 GFS2: Copy gfs2_t... |
21 |
#include "inode.h" |
b3b94faa5 [GFS2] The core o... |
22 23 24 25 |
#include "log.h" #include "lops.h" #include "meta_io.h" #include "trans.h" |
5c676f6d3 [GFS2] Macros rem... |
26 |
#include "util.h" |
5e687eac1 GFS2: Various gfs... |
27 |
#include "trace_gfs2.h" |
b3b94faa5 [GFS2] The core o... |
28 |
|
d0dc80dba [GFS2] Update deb... |
29 30 |
int gfs2_trans_begin(struct gfs2_sbd *sdp, unsigned int blocks, unsigned int revokes) |
b3b94faa5 [GFS2] The core o... |
31 32 33 |
{ struct gfs2_trans *tr; int error; |
d0dc80dba [GFS2] Update deb... |
34 35 |
BUG_ON(current->journal_info); BUG_ON(blocks == 0 && revokes == 0); |
b3b94faa5 [GFS2] The core o... |
36 |
|
a1c0643ff GFS2: Move journa... |
37 38 |
if (!test_bit(SDF_JOURNAL_LIVE, &sdp->sd_flags)) return -EROFS; |
f55ab26a8 [GFS2] Use mutice... |
39 |
tr = kzalloc(sizeof(struct gfs2_trans), GFP_NOFS); |
b3b94faa5 [GFS2] The core o... |
40 41 |
if (!tr) return -ENOMEM; |
d29c0afe4 GFS2: use _RET_IP... |
42 |
tr->tr_ip = _RET_IP_; |
b3b94faa5 [GFS2] The core o... |
43 44 45 |
tr->tr_blocks = blocks; tr->tr_revokes = revokes; tr->tr_reserved = 1; |
24972557b GFS2: remove tran... |
46 |
tr->tr_alloced = 1; |
b3b94faa5 [GFS2] The core o... |
47 |
if (blocks) |
f4154ea03 [GFS2] Update jou... |
48 |
tr->tr_reserved += 6 + blocks; |
b3b94faa5 [GFS2] The core o... |
49 50 |
if (revokes) tr->tr_reserved += gfs2_struct2blk(sdp, revokes, |
cd915493f [GFS2] Change all... |
51 |
sizeof(u64)); |
d69a3c656 GFS2: Move log bu... |
52 53 |
INIT_LIST_HEAD(&tr->tr_databuf); INIT_LIST_HEAD(&tr->tr_buf); |
39263d5e7 gfs2: Convert to ... |
54 |
sb_start_intwrite(sdp->sd_vfs); |
b3b94faa5 [GFS2] The core o... |
55 |
|
b3b94faa5 [GFS2] The core o... |
56 57 |
error = gfs2_log_reserve(sdp, tr->tr_reserved); if (error) |
24972557b GFS2: remove tran... |
58 |
goto fail; |
b3b94faa5 [GFS2] The core o... |
59 |
|
5c676f6d3 [GFS2] Macros rem... |
60 |
current->journal_info = tr; |
b3b94faa5 [GFS2] The core o... |
61 62 |
return 0; |
24972557b GFS2: remove tran... |
63 |
fail: |
39263d5e7 gfs2: Convert to ... |
64 |
sb_end_intwrite(sdp->sd_vfs); |
b3b94faa5 [GFS2] The core o... |
65 66 67 68 |
kfree(tr); return error; } |
c50b91c4b GFS2: Remove bd_l... |
69 70 |
static void gfs2_print_trans(const struct gfs2_trans *tr) { |
d77d1b58a GFS2: Use pr_<lev... |
71 72 73 74 75 76 77 78 79 80 |
pr_warn("Transaction created at: %pSR ", (void *)tr->tr_ip); pr_warn("blocks=%u revokes=%u reserved=%u touched=%u ", tr->tr_blocks, tr->tr_revokes, tr->tr_reserved, tr->tr_touched); pr_warn("Buf %u/%u Databuf %u/%u Revoke %u/%u ", tr->tr_num_buf_new, tr->tr_num_buf_rm, tr->tr_num_databuf_new, tr->tr_num_databuf_rm, tr->tr_num_revoke, tr->tr_num_revoke_rm); |
c50b91c4b GFS2: Remove bd_l... |
81 |
} |
b3b94faa5 [GFS2] The core o... |
82 83 |
void gfs2_trans_end(struct gfs2_sbd *sdp) { |
f4154ea03 [GFS2] Update jou... |
84 |
struct gfs2_trans *tr = current->journal_info; |
c50b91c4b GFS2: Remove bd_l... |
85 |
s64 nbuf; |
2e60d7683 GFS2: update free... |
86 |
int alloced = tr->tr_alloced; |
f4154ea03 [GFS2] Update jou... |
87 |
BUG_ON(!tr); |
5c676f6d3 [GFS2] Macros rem... |
88 |
current->journal_info = NULL; |
b3b94faa5 [GFS2] The core o... |
89 |
|
b3b94faa5 [GFS2] The core o... |
90 91 |
if (!tr->tr_touched) { gfs2_log_release(sdp, tr->tr_reserved); |
2e60d7683 GFS2: update free... |
92 |
if (alloced) { |
d8348de06 GFS2: Fix deadloc... |
93 |
kfree(tr); |
2e60d7683 GFS2: update free... |
94 95 |
sb_end_intwrite(sdp->sd_vfs); } |
b3b94faa5 [GFS2] The core o... |
96 97 |
return; } |
c50b91c4b GFS2: Remove bd_l... |
98 99 100 101 102 103 104 |
nbuf = tr->tr_num_buf_new + tr->tr_num_databuf_new; nbuf -= tr->tr_num_buf_rm; nbuf -= tr->tr_num_databuf_rm; if (gfs2_assert_withdraw(sdp, (nbuf <= tr->tr_blocks) && (tr->tr_num_revoke <= tr->tr_revokes))) gfs2_print_trans(tr); |
b3b94faa5 [GFS2] The core o... |
105 106 |
gfs2_log_commit(sdp, tr); |
2e60d7683 GFS2: update free... |
107 |
if (alloced && !tr->tr_attached) |
16ca9412d GFS2: replace gfs... |
108 |
kfree(tr); |
16ca9412d GFS2: replace gfs... |
109 |
up_read(&sdp->sd_log_flush_lock); |
b3b94faa5 [GFS2] The core o... |
110 111 |
if (sdp->sd_vfs->s_flags & MS_SYNCHRONOUS) |
24972557b GFS2: remove tran... |
112 |
gfs2_log_flush(sdp, NULL, NORMAL_FLUSH); |
2e60d7683 GFS2: update free... |
113 114 |
if (alloced) sb_end_intwrite(sdp->sd_vfs); |
b3b94faa5 [GFS2] The core o... |
115 |
} |
c76c4d96b GFS2: Merge gfs2_... |
116 117 118 119 120 121 122 123 124 125 126 127 128 129 |
static struct gfs2_bufdata *gfs2_alloc_bufdata(struct gfs2_glock *gl, struct buffer_head *bh, const struct gfs2_log_operations *lops) { struct gfs2_bufdata *bd; bd = kmem_cache_zalloc(gfs2_bufdata_cachep, GFP_NOFS | __GFP_NOFAIL); bd->bd_bh = bh; bd->bd_gl = gl; bd->bd_ops = lops; INIT_LIST_HEAD(&bd->bd_list); bh->b_private = bd; return bd; } |
b3b94faa5 [GFS2] The core o... |
130 |
/** |
451389909 GFS2: Use ->write... |
131 132 133 |
* gfs2_trans_add_data - Add a databuf to the transaction. * @gl: The inode glock associated with the buffer * @bh: The buffer to add |
b3b94faa5 [GFS2] The core o... |
134 |
* |
767f433f3 GFS2: Copy gfs2_t... |
135 136 137 138 139 140 141 142 143 144 145 146 |
* This is used in two distinct cases: * i) In ordered write mode * We put the data buffer on a list so that we can ensure that its * synced to disk at the right time * ii) In journaled data mode * We need to journal the data block in the same way as metadata in * the functions above. The difference is that here we have a tag * which is two __be64's being the block number (as per meta data) * and a flag which says whether the data block needs escaping or * not. This means we need a new log entry for each 251 or so data * blocks, which isn't an enormous overhead but twice as much as * for normal metadata blocks. |
b3b94faa5 [GFS2] The core o... |
147 |
*/ |
451389909 GFS2: Use ->write... |
148 |
void gfs2_trans_add_data(struct gfs2_glock *gl, struct buffer_head *bh) |
767f433f3 GFS2: Copy gfs2_t... |
149 150 |
{ struct gfs2_trans *tr = current->journal_info; |
15562c439 GFS2: Move glock ... |
151 |
struct gfs2_sbd *sdp = gl->gl_name.ln_sbd; |
451389909 GFS2: Use ->write... |
152 |
struct address_space *mapping = bh->b_page->mapping; |
767f433f3 GFS2: Copy gfs2_t... |
153 |
struct gfs2_inode *ip = GFS2_I(mapping->host); |
451389909 GFS2: Use ->write... |
154 |
struct gfs2_bufdata *bd; |
767f433f3 GFS2: Copy gfs2_t... |
155 |
|
451389909 GFS2: Use ->write... |
156 157 |
if (!gfs2_is_jdata(ip)) { gfs2_ordered_add_inode(ip); |
767f433f3 GFS2: Copy gfs2_t... |
158 |
return; |
767f433f3 GFS2: Copy gfs2_t... |
159 |
} |
b3b94faa5 [GFS2] The core o... |
160 |
|
96e5d1d3a GFS2: Test bufdat... |
161 162 |
lock_buffer(bh); gfs2_log_lock(sdp); |
5c676f6d3 [GFS2] Macros rem... |
163 |
bd = bh->b_private; |
c76c4d96b GFS2: Merge gfs2_... |
164 |
if (bd == NULL) { |
96e5d1d3a GFS2: Test bufdat... |
165 166 |
gfs2_log_unlock(sdp); unlock_buffer(bh); |
c76c4d96b GFS2: Merge gfs2_... |
167 168 |
if (bh->b_private == NULL) bd = gfs2_alloc_bufdata(gl, bh, &gfs2_databuf_lops); |
491e94f79 gfs2: Add missing... |
169 170 |
else bd = bh->b_private; |
96e5d1d3a GFS2: Test bufdat... |
171 172 |
lock_buffer(bh); gfs2_log_lock(sdp); |
b3b94faa5 [GFS2] The core o... |
173 |
} |
c76c4d96b GFS2: Merge gfs2_... |
174 |
gfs2_assert(sdp, bd->bd_gl == gl); |
451389909 GFS2: Use ->write... |
175 176 177 178 179 180 |
tr->tr_touched = 1; if (list_empty(&bd->bd_list)) { set_bit(GLF_LFLUSH, &bd->bd_gl->gl_flags); set_bit(GLF_DIRTY, &bd->bd_gl->gl_flags); gfs2_pin(sdp, bd->bd_bh); tr->tr_num_databuf_new++; |
d69a3c656 GFS2: Move log bu... |
181 |
list_add_tail(&bd->bd_list, &tr->tr_databuf); |
451389909 GFS2: Use ->write... |
182 |
} |
96e5d1d3a GFS2: Test bufdat... |
183 184 |
gfs2_log_unlock(sdp); unlock_buffer(bh); |
b3b94faa5 [GFS2] The core o... |
185 |
} |
767f433f3 GFS2: Copy gfs2_t... |
186 |
static void meta_lo_add(struct gfs2_sbd *sdp, struct gfs2_bufdata *bd) |
350a9b0a7 GFS2: Split gfs2_... |
187 |
{ |
767f433f3 GFS2: Copy gfs2_t... |
188 189 |
struct gfs2_meta_header *mh; struct gfs2_trans *tr; |
2e60d7683 GFS2: update free... |
190 |
enum gfs2_freeze_state state = atomic_read(&sdp->sd_freeze_state); |
767f433f3 GFS2: Copy gfs2_t... |
191 192 193 194 195 196 197 198 199 |
tr = current->journal_info; tr->tr_touched = 1; if (!list_empty(&bd->bd_list)) return; set_bit(GLF_LFLUSH, &bd->bd_gl->gl_flags); set_bit(GLF_DIRTY, &bd->bd_gl->gl_flags); mh = (struct gfs2_meta_header *)bd->bd_bh->b_data; if (unlikely(mh->mh_magic != cpu_to_be32(GFS2_MAGIC))) { |
d77d1b58a GFS2: Use pr_<lev... |
200 201 |
pr_err("Attempting to add uninitialised block to journal (inplace block=%lld) ", |
767f433f3 GFS2: Copy gfs2_t... |
202 203 204 |
(unsigned long long)bd->bd_bh->b_blocknr); BUG(); } |
2e60d7683 GFS2: update free... |
205 206 207 208 209 |
if (unlikely(state == SFS_FROZEN)) { printk(KERN_INFO "GFS2:adding buf while frozen "); gfs2_assert_withdraw(sdp, 0); } |
767f433f3 GFS2: Copy gfs2_t... |
210 211 212 |
gfs2_pin(sdp, bd->bd_bh); mh->__pad0 = cpu_to_be64(0); mh->mh_jid = cpu_to_be32(sdp->sd_jdesc->jd_jid); |
d69a3c656 GFS2: Move log bu... |
213 |
list_add(&bd->bd_list, &tr->tr_buf); |
767f433f3 GFS2: Copy gfs2_t... |
214 |
tr->tr_num_buf_new++; |
350a9b0a7 GFS2: Split gfs2_... |
215 216 217 218 |
} void gfs2_trans_add_meta(struct gfs2_glock *gl, struct buffer_head *bh) { |
767f433f3 GFS2: Copy gfs2_t... |
219 |
|
15562c439 GFS2: Move glock ... |
220 |
struct gfs2_sbd *sdp = gl->gl_name.ln_sbd; |
767f433f3 GFS2: Copy gfs2_t... |
221 222 223 224 225 |
struct gfs2_bufdata *bd; lock_buffer(bh); gfs2_log_lock(sdp); bd = bh->b_private; |
c76c4d96b GFS2: Merge gfs2_... |
226 |
if (bd == NULL) { |
767f433f3 GFS2: Copy gfs2_t... |
227 228 |
gfs2_log_unlock(sdp); unlock_buffer(bh); |
c76c4d96b GFS2: Merge gfs2_... |
229 230 231 |
lock_page(bh->b_page); if (bh->b_private == NULL) bd = gfs2_alloc_bufdata(gl, bh, &gfs2_buf_lops); |
491e94f79 gfs2: Add missing... |
232 233 |
else bd = bh->b_private; |
c76c4d96b GFS2: Merge gfs2_... |
234 |
unlock_page(bh->b_page); |
767f433f3 GFS2: Copy gfs2_t... |
235 236 237 |
lock_buffer(bh); gfs2_log_lock(sdp); } |
c76c4d96b GFS2: Merge gfs2_... |
238 |
gfs2_assert(sdp, bd->bd_gl == gl); |
767f433f3 GFS2: Copy gfs2_t... |
239 240 241 |
meta_lo_add(sdp, bd); gfs2_log_unlock(sdp); unlock_buffer(bh); |
350a9b0a7 GFS2: Split gfs2_... |
242 |
} |
1ad38c437 [GFS2] Clean up g... |
243 |
void gfs2_trans_add_revoke(struct gfs2_sbd *sdp, struct gfs2_bufdata *bd) |
b3b94faa5 [GFS2] The core o... |
244 |
{ |
75f2b879a GFS2: Merge revok... |
245 |
struct gfs2_trans *tr = current->journal_info; |
c0752aa7e GFS2: eliminate l... |
246 |
BUG_ON(!list_empty(&bd->bd_list)); |
5d054964f GFS2: aggressivel... |
247 |
gfs2_add_revoke(sdp, bd); |
75f2b879a GFS2: Merge revok... |
248 249 |
tr->tr_touched = 1; tr->tr_num_revoke++; |
b3b94faa5 [GFS2] The core o... |
250 |
} |
5731be53e [GFS2] Update gfs... |
251 |
void gfs2_trans_add_unrevoke(struct gfs2_sbd *sdp, u64 blkno, unsigned int len) |
b3b94faa5 [GFS2] The core o... |
252 |
{ |
5731be53e [GFS2] Update gfs... |
253 254 255 |
struct gfs2_bufdata *bd, *tmp; struct gfs2_trans *tr = current->journal_info; unsigned int n = len; |
b3b94faa5 [GFS2] The core o... |
256 257 |
gfs2_log_lock(sdp); |
c0752aa7e GFS2: eliminate l... |
258 |
list_for_each_entry_safe(bd, tmp, &sdp->sd_log_le_revoke, bd_list) { |
5731be53e [GFS2] Update gfs... |
259 |
if ((bd->bd_blkno >= blkno) && (bd->bd_blkno < (blkno + len))) { |
c0752aa7e GFS2: eliminate l... |
260 |
list_del_init(&bd->bd_list); |
b3b94faa5 [GFS2] The core o... |
261 262 |
gfs2_assert_withdraw(sdp, sdp->sd_log_num_revoke); sdp->sd_log_num_revoke--; |
5731be53e [GFS2] Update gfs... |
263 264 265 266 |
kmem_cache_free(gfs2_bufdata_cachep, bd); tr->tr_num_revoke_rm++; if (--n == 0) break; |
b3b94faa5 [GFS2] The core o... |
267 268 |
} } |
b3b94faa5 [GFS2] The core o... |
269 |
gfs2_log_unlock(sdp); |
b3b94faa5 [GFS2] The core o... |
270 |
} |