Blame view
fs/gfs2/trans.c
7.69 KB
7336d0e65 treewide: Replace... |
1 |
// SPDX-License-Identifier: GPL-2.0-only |
b3b94faa5 [GFS2] The core o... |
2 3 |
/* * Copyright (C) Sistina Software, Inc. 1997-2003 All rights reserved. |
3a8a9a103 [GFS2] Update cop... |
4 |
* Copyright (C) 2004-2006 Red Hat, Inc. All rights reserved. |
b3b94faa5 [GFS2] The core o... |
5 |
*/ |
d77d1b58a GFS2: Use pr_<lev... |
6 |
#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt |
b3b94faa5 [GFS2] The core o... |
7 8 9 10 11 |
#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... |
12 |
#include <linux/kallsyms.h> |
f057f6cdf GFS2: Merge lock_... |
13 |
#include <linux/gfs2_ondisk.h> |
b3b94faa5 [GFS2] The core o... |
14 15 |
#include "gfs2.h" |
5c676f6d3 [GFS2] Macros rem... |
16 |
#include "incore.h" |
b3b94faa5 [GFS2] The core o... |
17 |
#include "glock.h" |
767f433f3 GFS2: Copy gfs2_t... |
18 |
#include "inode.h" |
b3b94faa5 [GFS2] The core o... |
19 20 21 22 |
#include "log.h" #include "lops.h" #include "meta_io.h" #include "trans.h" |
5c676f6d3 [GFS2] Macros rem... |
23 |
#include "util.h" |
5e687eac1 GFS2: Various gfs... |
24 |
#include "trace_gfs2.h" |
b3b94faa5 [GFS2] The core o... |
25 |
|
b0be23b23 gfs2: print detai... |
26 27 28 29 30 31 32 33 34 35 36 37 38 39 |
static void gfs2_print_trans(struct gfs2_sbd *sdp, const struct gfs2_trans *tr) { fs_warn(sdp, "Transaction created at: %pSR ", (void *)tr->tr_ip); fs_warn(sdp, "blocks=%u revokes=%u reserved=%u touched=%u ", tr->tr_blocks, tr->tr_revokes, tr->tr_reserved, test_bit(TR_TOUCHED, &tr->tr_flags)); fs_warn(sdp, "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); } |
d0dc80dba [GFS2] Update deb... |
40 41 |
int gfs2_trans_begin(struct gfs2_sbd *sdp, unsigned int blocks, unsigned int revokes) |
b3b94faa5 [GFS2] The core o... |
42 43 44 |
{ struct gfs2_trans *tr; int error; |
b0be23b23 gfs2: print detai... |
45 46 47 48 |
if (current->journal_info) { gfs2_print_trans(sdp, current->journal_info); BUG(); } |
d0dc80dba [GFS2] Update deb... |
49 |
BUG_ON(blocks == 0 && revokes == 0); |
b3b94faa5 [GFS2] The core o... |
50 |
|
a1c0643ff GFS2: Move journa... |
51 52 |
if (!test_bit(SDF_JOURNAL_LIVE, &sdp->sd_flags)) return -EROFS; |
b839dadae gfs2: new slab fo... |
53 |
tr = kmem_cache_zalloc(gfs2_trans_cachep, GFP_NOFS); |
b3b94faa5 [GFS2] The core o... |
54 55 |
if (!tr) return -ENOMEM; |
d29c0afe4 GFS2: use _RET_IP... |
56 |
tr->tr_ip = _RET_IP_; |
b3b94faa5 [GFS2] The core o... |
57 58 59 |
tr->tr_blocks = blocks; tr->tr_revokes = revokes; tr->tr_reserved = 1; |
9862ca056 GFS2: Switch tr_t... |
60 |
set_bit(TR_ALLOCED, &tr->tr_flags); |
b3b94faa5 [GFS2] The core o... |
61 |
if (blocks) |
f4154ea03 [GFS2] Update jou... |
62 |
tr->tr_reserved += 6 + blocks; |
b3b94faa5 [GFS2] The core o... |
63 |
if (revokes) |
2e9eeaa11 gfs2: eliminate s... |
64 |
tr->tr_reserved += gfs2_struct2blk(sdp, revokes); |
d69a3c656 GFS2: Move log bu... |
65 66 |
INIT_LIST_HEAD(&tr->tr_databuf); INIT_LIST_HEAD(&tr->tr_buf); |
462582b99 gfs2: add some mu... |
67 |
INIT_LIST_HEAD(&tr->tr_list); |
cbcc89b63 gfs2: initialize ... |
68 69 |
INIT_LIST_HEAD(&tr->tr_ail1_list); INIT_LIST_HEAD(&tr->tr_ail2_list); |
d69a3c656 GFS2: Move log bu... |
70 |
|
39263d5e7 gfs2: Convert to ... |
71 |
sb_start_intwrite(sdp->sd_vfs); |
b3b94faa5 [GFS2] The core o... |
72 |
|
b3b94faa5 [GFS2] The core o... |
73 74 |
error = gfs2_log_reserve(sdp, tr->tr_reserved); if (error) |
24972557b GFS2: remove tran... |
75 |
goto fail; |
b3b94faa5 [GFS2] The core o... |
76 |
|
5c676f6d3 [GFS2] Macros rem... |
77 |
current->journal_info = tr; |
b3b94faa5 [GFS2] The core o... |
78 79 |
return 0; |
24972557b GFS2: remove tran... |
80 |
fail: |
39263d5e7 gfs2: Convert to ... |
81 |
sb_end_intwrite(sdp->sd_vfs); |
b839dadae gfs2: new slab fo... |
82 |
kmem_cache_free(gfs2_trans_cachep, tr); |
b3b94faa5 [GFS2] The core o... |
83 84 85 86 87 88 |
return error; } void gfs2_trans_end(struct gfs2_sbd *sdp) { |
f4154ea03 [GFS2] Update jou... |
89 |
struct gfs2_trans *tr = current->journal_info; |
c50b91c4b GFS2: Remove bd_l... |
90 |
s64 nbuf; |
9862ca056 GFS2: Switch tr_t... |
91 |
int alloced = test_bit(TR_ALLOCED, &tr->tr_flags); |
2e60d7683 GFS2: update free... |
92 |
|
5c676f6d3 [GFS2] Macros rem... |
93 |
current->journal_info = NULL; |
b3b94faa5 [GFS2] The core o... |
94 |
|
9862ca056 GFS2: Switch tr_t... |
95 |
if (!test_bit(TR_TOUCHED, &tr->tr_flags)) { |
b3b94faa5 [GFS2] The core o... |
96 |
gfs2_log_release(sdp, tr->tr_reserved); |
2e60d7683 GFS2: update free... |
97 |
if (alloced) { |
b839dadae gfs2: new slab fo... |
98 |
gfs2_trans_free(sdp, tr); |
2e60d7683 GFS2: update free... |
99 100 |
sb_end_intwrite(sdp->sd_vfs); } |
b3b94faa5 [GFS2] The core o... |
101 102 |
return; } |
c50b91c4b GFS2: Remove bd_l... |
103 104 105 106 107 108 |
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))) |
e54c78a27 gfs2: Use fs_* fu... |
109 |
gfs2_print_trans(sdp, tr); |
b3b94faa5 [GFS2] The core o... |
110 111 |
gfs2_log_commit(sdp, tr); |
9862ca056 GFS2: Switch tr_t... |
112 |
if (alloced && !test_bit(TR_ATTACHED, &tr->tr_flags)) |
b839dadae gfs2: new slab fo... |
113 |
gfs2_trans_free(sdp, tr); |
16ca9412d GFS2: replace gfs... |
114 |
up_read(&sdp->sd_log_flush_lock); |
b3b94faa5 [GFS2] The core o... |
115 |
|
1751e8a6c Rename superblock... |
116 |
if (sdp->sd_vfs->s_flags & SB_SYNCHRONOUS) |
805c09075 GFS2: Log the rea... |
117 118 |
gfs2_log_flush(sdp, NULL, GFS2_LOG_HEAD_FLUSH_NORMAL | GFS2_LFC_TRANS_END); |
2e60d7683 GFS2: update free... |
119 120 |
if (alloced) sb_end_intwrite(sdp->sd_vfs); |
b3b94faa5 [GFS2] The core o... |
121 |
} |
c76c4d96b GFS2: Merge gfs2_... |
122 |
static struct gfs2_bufdata *gfs2_alloc_bufdata(struct gfs2_glock *gl, |
cbbe76c8b gfs2: Remove vest... |
123 |
struct buffer_head *bh) |
c76c4d96b GFS2: Merge gfs2_... |
124 125 126 127 128 129 |
{ struct gfs2_bufdata *bd; bd = kmem_cache_zalloc(gfs2_bufdata_cachep, GFP_NOFS | __GFP_NOFAIL); bd->bd_bh = bh; bd->bd_gl = gl; |
c76c4d96b GFS2: Merge gfs2_... |
130 131 132 133 |
INIT_LIST_HEAD(&bd->bd_list); bh->b_private = bd; return bd; } |
b3b94faa5 [GFS2] The core o... |
134 |
/** |
451389909 GFS2: Use ->write... |
135 136 137 |
* 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... |
138 |
* |
845802b11 gfs2: Remove orde... |
139 140 141 142 143 144 145 146 |
* This is used 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 gfs2_bufdata *bd; |
767f433f3 GFS2: Copy gfs2_t... |
153 |
|
96e5d1d3a GFS2: Test bufdat... |
154 |
lock_buffer(bh); |
aacee7206 GFS2: Reduce cont... |
155 156 157 158 |
if (buffer_pinned(bh)) { set_bit(TR_TOUCHED, &tr->tr_flags); goto out; } |
96e5d1d3a GFS2: Test bufdat... |
159 |
gfs2_log_lock(sdp); |
5c676f6d3 [GFS2] Macros rem... |
160 |
bd = bh->b_private; |
c76c4d96b GFS2: Merge gfs2_... |
161 |
if (bd == NULL) { |
96e5d1d3a GFS2: Test bufdat... |
162 163 |
gfs2_log_unlock(sdp); unlock_buffer(bh); |
c76c4d96b GFS2: Merge gfs2_... |
164 |
if (bh->b_private == NULL) |
cbbe76c8b gfs2: Remove vest... |
165 |
bd = gfs2_alloc_bufdata(gl, bh); |
491e94f79 gfs2: Add missing... |
166 167 |
else bd = bh->b_private; |
96e5d1d3a GFS2: Test bufdat... |
168 169 |
lock_buffer(bh); gfs2_log_lock(sdp); |
b3b94faa5 [GFS2] The core o... |
170 |
} |
c76c4d96b GFS2: Merge gfs2_... |
171 |
gfs2_assert(sdp, bd->bd_gl == gl); |
9862ca056 GFS2: Switch tr_t... |
172 |
set_bit(TR_TOUCHED, &tr->tr_flags); |
451389909 GFS2: Use ->write... |
173 174 175 176 177 |
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... |
178 |
list_add_tail(&bd->bd_list, &tr->tr_databuf); |
451389909 GFS2: Use ->write... |
179 |
} |
96e5d1d3a GFS2: Test bufdat... |
180 |
gfs2_log_unlock(sdp); |
aacee7206 GFS2: Reduce cont... |
181 |
out: |
96e5d1d3a GFS2: Test bufdat... |
182 |
unlock_buffer(bh); |
b3b94faa5 [GFS2] The core o... |
183 |
} |
192738b71 GFS2: Inline func... |
184 |
void gfs2_trans_add_meta(struct gfs2_glock *gl, struct buffer_head *bh) |
350a9b0a7 GFS2: Split gfs2_... |
185 |
{ |
192738b71 GFS2: Inline func... |
186 187 188 |
struct gfs2_sbd *sdp = gl->gl_name.ln_sbd; struct gfs2_bufdata *bd; |
767f433f3 GFS2: Copy gfs2_t... |
189 |
struct gfs2_meta_header *mh; |
aacee7206 GFS2: Reduce cont... |
190 |
struct gfs2_trans *tr = current->journal_info; |
2e60d7683 GFS2: update free... |
191 |
enum gfs2_freeze_state state = atomic_read(&sdp->sd_freeze_state); |
767f433f3 GFS2: Copy gfs2_t... |
192 |
|
192738b71 GFS2: Inline func... |
193 |
lock_buffer(bh); |
aacee7206 GFS2: Reduce cont... |
194 195 196 197 |
if (buffer_pinned(bh)) { set_bit(TR_TOUCHED, &tr->tr_flags); goto out; } |
192738b71 GFS2: Inline func... |
198 199 200 201 202 203 204 |
gfs2_log_lock(sdp); bd = bh->b_private; if (bd == NULL) { gfs2_log_unlock(sdp); unlock_buffer(bh); lock_page(bh->b_page); if (bh->b_private == NULL) |
cbbe76c8b gfs2: Remove vest... |
205 |
bd = gfs2_alloc_bufdata(gl, bh); |
192738b71 GFS2: Inline func... |
206 207 208 209 210 211 212 |
else bd = bh->b_private; unlock_page(bh->b_page); lock_buffer(bh); gfs2_log_lock(sdp); } gfs2_assert(sdp, bd->bd_gl == gl); |
9862ca056 GFS2: Switch tr_t... |
213 |
set_bit(TR_TOUCHED, &tr->tr_flags); |
767f433f3 GFS2: Copy gfs2_t... |
214 |
if (!list_empty(&bd->bd_list)) |
192738b71 GFS2: Inline func... |
215 |
goto out_unlock; |
767f433f3 GFS2: Copy gfs2_t... |
216 217 218 219 |
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))) { |
e54c78a27 gfs2: Use fs_* fu... |
220 221 222 |
fs_err(sdp, "Attempting to add uninitialised block to " "journal (inplace block=%lld) ", |
767f433f3 GFS2: Copy gfs2_t... |
223 224 225 |
(unsigned long long)bd->bd_bh->b_blocknr); BUG(); } |
2e60d7683 GFS2: update free... |
226 |
if (unlikely(state == SFS_FROZEN)) { |
e54c78a27 gfs2: Use fs_* fu... |
227 228 |
fs_info(sdp, "GFS2:adding buf while frozen "); |
2e60d7683 GFS2: update free... |
229 230 |
gfs2_assert_withdraw(sdp, 0); } |
2ca0c2fbf gfs2: drain the a... |
231 232 233 234 235 |
if (unlikely(gfs2_withdrawn(sdp))) { fs_info(sdp, "GFS2:adding buf while withdrawn! 0x%llx ", (unsigned long long)bd->bd_bh->b_blocknr); } |
767f433f3 GFS2: Copy gfs2_t... |
236 237 238 |
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... |
239 |
list_add(&bd->bd_list, &tr->tr_buf); |
767f433f3 GFS2: Copy gfs2_t... |
240 |
tr->tr_num_buf_new++; |
192738b71 GFS2: Inline func... |
241 |
out_unlock: |
767f433f3 GFS2: Copy gfs2_t... |
242 |
gfs2_log_unlock(sdp); |
aacee7206 GFS2: Reduce cont... |
243 |
out: |
767f433f3 GFS2: Copy gfs2_t... |
244 |
unlock_buffer(bh); |
350a9b0a7 GFS2: Split gfs2_... |
245 |
} |
1ad38c437 [GFS2] Clean up g... |
246 |
void gfs2_trans_add_revoke(struct gfs2_sbd *sdp, struct gfs2_bufdata *bd) |
b3b94faa5 [GFS2] The core o... |
247 |
{ |
75f2b879a GFS2: Merge revok... |
248 |
struct gfs2_trans *tr = current->journal_info; |
c0752aa7e GFS2: eliminate l... |
249 |
BUG_ON(!list_empty(&bd->bd_list)); |
5d054964f GFS2: aggressivel... |
250 |
gfs2_add_revoke(sdp, bd); |
9862ca056 GFS2: Switch tr_t... |
251 |
set_bit(TR_TOUCHED, &tr->tr_flags); |
75f2b879a GFS2: Merge revok... |
252 |
tr->tr_num_revoke++; |
b3b94faa5 [GFS2] The core o... |
253 |
} |
fbb27873f gfs2: Rename gfs2... |
254 |
void gfs2_trans_remove_revoke(struct gfs2_sbd *sdp, u64 blkno, unsigned int len) |
b3b94faa5 [GFS2] The core o... |
255 |
{ |
5731be53e [GFS2] Update gfs... |
256 257 258 |
struct gfs2_bufdata *bd, *tmp; struct gfs2_trans *tr = current->journal_info; unsigned int n = len; |
b3b94faa5 [GFS2] The core o... |
259 260 |
gfs2_log_lock(sdp); |
a5b1d3fc5 gfs2: Rename sd_l... |
261 |
list_for_each_entry_safe(bd, tmp, &sdp->sd_log_revokes, bd_list) { |
5731be53e [GFS2] Update gfs... |
262 |
if ((bd->bd_blkno >= blkno) && (bd->bd_blkno < (blkno + len))) { |
c0752aa7e GFS2: eliminate l... |
263 |
list_del_init(&bd->bd_list); |
b3b94faa5 [GFS2] The core o... |
264 265 |
gfs2_assert_withdraw(sdp, sdp->sd_log_num_revoke); sdp->sd_log_num_revoke--; |
fe5e7ba11 gfs2: fix glock r... |
266 267 |
if (bd->bd_gl) gfs2_glock_remove_revoke(bd->bd_gl); |
5731be53e [GFS2] Update gfs... |
268 |
kmem_cache_free(gfs2_bufdata_cachep, bd); |
a31b4ec53 Revert "gfs2: eli... |
269 |
tr->tr_num_revoke_rm++; |
5731be53e [GFS2] Update gfs... |
270 271 |
if (--n == 0) break; |
b3b94faa5 [GFS2] The core o... |
272 273 |
} } |
b3b94faa5 [GFS2] The core o... |
274 |
gfs2_log_unlock(sdp); |
b3b94faa5 [GFS2] The core o... |
275 |
} |
b839dadae gfs2: new slab fo... |
276 277 278 279 280 281 282 283 284 285 286 |
void gfs2_trans_free(struct gfs2_sbd *sdp, struct gfs2_trans *tr) { if (tr == NULL) return; gfs2_assert_warn(sdp, list_empty(&tr->tr_ail1_list)); gfs2_assert_warn(sdp, list_empty(&tr->tr_ail2_list)); gfs2_assert_warn(sdp, list_empty(&tr->tr_databuf)); gfs2_assert_warn(sdp, list_empty(&tr->tr_buf)); kmem_cache_free(gfs2_trans_cachep, tr); } |