Blame view
fs/gfs2/trans.c
4.18 KB
b3b94faa5
|
1 2 |
/* * Copyright (C) Sistina Software, Inc. 1997-2003 All rights reserved. |
3a8a9a103
|
3 |
* Copyright (C) 2004-2006 Red Hat, Inc. All rights reserved. |
b3b94faa5
|
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
|
7 |
* of the GNU General Public License version 2. |
b3b94faa5
|
8 9 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> |
5c676f6d3
|
15 |
#include <linux/gfs2_ondisk.h> |
d0dc80dba
|
16 |
#include <linux/kallsyms.h> |
7d308590a
|
17 |
#include <linux/lm_interface.h> |
b3b94faa5
|
18 19 |
#include "gfs2.h" |
5c676f6d3
|
20 |
#include "incore.h" |
b3b94faa5
|
21 22 23 24 25 |
#include "glock.h" #include "log.h" #include "lops.h" #include "meta_io.h" #include "trans.h" |
5c676f6d3
|
26 |
#include "util.h" |
b3b94faa5
|
27 |
|
d0dc80dba
|
28 29 |
int gfs2_trans_begin(struct gfs2_sbd *sdp, unsigned int blocks, unsigned int revokes) |
b3b94faa5
|
30 31 32 |
{ struct gfs2_trans *tr; int error; |
d0dc80dba
|
33 34 |
BUG_ON(current->journal_info); BUG_ON(blocks == 0 && revokes == 0); |
b3b94faa5
|
35 |
|
f55ab26a8
|
36 |
tr = kzalloc(sizeof(struct gfs2_trans), GFP_NOFS); |
b3b94faa5
|
37 38 |
if (!tr) return -ENOMEM; |
d0dc80dba
|
39 |
tr->tr_ip = (unsigned long)__builtin_return_address(0); |
b3b94faa5
|
40 41 42 43 |
tr->tr_blocks = blocks; tr->tr_revokes = revokes; tr->tr_reserved = 1; if (blocks) |
f4154ea03
|
44 |
tr->tr_reserved += 6 + blocks; |
b3b94faa5
|
45 46 |
if (revokes) tr->tr_reserved += gfs2_struct2blk(sdp, revokes, |
cd915493f
|
47 |
sizeof(u64)); |
b3b94faa5
|
48 |
INIT_LIST_HEAD(&tr->tr_list_buf); |
579b78a43
|
49 |
gfs2_holder_init(sdp->sd_trans_gl, LM_ST_SHARED, 0, &tr->tr_t_gh); |
b3b94faa5
|
50 |
|
e317ffcb7
|
51 |
error = gfs2_glock_nq(&tr->tr_t_gh); |
b3b94faa5
|
52 |
if (error) |
e317ffcb7
|
53 |
goto fail_holder_uninit; |
b3b94faa5
|
54 55 |
if (!test_bit(SDF_JOURNAL_LIVE, &sdp->sd_flags)) { |
e317ffcb7
|
56 |
tr->tr_t_gh.gh_flags |= GL_NOCACHE; |
b3b94faa5
|
57 58 59 60 61 62 63 |
error = -EROFS; goto fail_gunlock; } error = gfs2_log_reserve(sdp, tr->tr_reserved); if (error) goto fail_gunlock; |
5c676f6d3
|
64 |
current->journal_info = tr; |
b3b94faa5
|
65 66 |
return 0; |
484adff8a
|
67 |
fail_gunlock: |
e317ffcb7
|
68 |
gfs2_glock_dq(&tr->tr_t_gh); |
b3b94faa5
|
69 |
|
484adff8a
|
70 |
fail_holder_uninit: |
e317ffcb7
|
71 |
gfs2_holder_uninit(&tr->tr_t_gh); |
b3b94faa5
|
72 73 74 75 76 77 78 |
kfree(tr); return error; } void gfs2_trans_end(struct gfs2_sbd *sdp) { |
f4154ea03
|
79 |
struct gfs2_trans *tr = current->journal_info; |
b3b94faa5
|
80 |
|
f4154ea03
|
81 |
BUG_ON(!tr); |
5c676f6d3
|
82 |
current->journal_info = NULL; |
b3b94faa5
|
83 |
|
b3b94faa5
|
84 85 |
if (!tr->tr_touched) { gfs2_log_release(sdp, tr->tr_reserved); |
b4dc72911
|
86 87 |
gfs2_glock_dq(&tr->tr_t_gh); gfs2_holder_uninit(&tr->tr_t_gh); |
e317ffcb7
|
88 |
kfree(tr); |
b3b94faa5
|
89 90 |
return; } |
d0dc80dba
|
91 92 93 94 95 96 |
if (gfs2_assert_withdraw(sdp, tr->tr_num_buf <= tr->tr_blocks)) { fs_err(sdp, "tr_num_buf = %u, tr_blocks = %u ", tr->tr_num_buf, tr->tr_blocks); print_symbol(KERN_WARNING "GFS2: Transaction created at: %s ", tr->tr_ip); } |
cd45697f0
|
97 |
if (gfs2_assert_withdraw(sdp, tr->tr_num_revoke <= tr->tr_revokes)) { |
d0dc80dba
|
98 99 100 101 |
fs_err(sdp, "tr_num_revoke = %u, tr_revokes = %u ", tr->tr_num_revoke, tr->tr_revokes); print_symbol(KERN_WARNING "GFS2: Transaction created at: %s ", tr->tr_ip); |
cd45697f0
|
102 |
} |
b3b94faa5
|
103 104 |
gfs2_log_commit(sdp, tr); |
b4dc72911
|
105 106 |
gfs2_glock_dq(&tr->tr_t_gh); gfs2_holder_uninit(&tr->tr_t_gh); |
b4dc72911
|
107 |
kfree(tr); |
b3b94faa5
|
108 109 |
if (sdp->sd_vfs->s_flags & MS_SYNCHRONOUS) |
b09e593d7
|
110 |
gfs2_log_flush(sdp, NULL); |
b3b94faa5
|
111 112 113 114 115 116 117 118 119 120 121 |
} void gfs2_trans_add_gl(struct gfs2_glock *gl) { lops_add(gl->gl_sbd, &gl->gl_le); } /** * gfs2_trans_add_bh - Add a to-be-modified buffer to the current transaction * @gl: the glock the buffer belongs to * @bh: The buffer to add |
d4e9c4c3b
|
122 |
* @meta: True in the case of adding metadata |
b3b94faa5
|
123 124 |
* */ |
d4e9c4c3b
|
125 |
void gfs2_trans_add_bh(struct gfs2_glock *gl, struct buffer_head *bh, int meta) |
b3b94faa5
|
126 127 128 |
{ struct gfs2_sbd *sdp = gl->gl_sbd; struct gfs2_bufdata *bd; |
5c676f6d3
|
129 |
bd = bh->b_private; |
b3b94faa5
|
130 131 132 |
if (bd) gfs2_assert(sdp, bd->bd_gl == gl); else { |
586dfdaaf
|
133 |
gfs2_attach_bufdata(gl, bh, meta); |
5c676f6d3
|
134 |
bd = bh->b_private; |
b3b94faa5
|
135 |
} |
b3b94faa5
|
136 137 |
lops_add(sdp, &bd->bd_le); } |
cd915493f
|
138 |
void gfs2_trans_add_revoke(struct gfs2_sbd *sdp, u64 blkno) |
b3b94faa5
|
139 140 |
{ struct gfs2_revoke *rv = kmalloc(sizeof(struct gfs2_revoke), |
18ec7d5c3
|
141 |
GFP_NOFS | __GFP_NOFAIL); |
b3b94faa5
|
142 143 144 145 |
lops_init_le(&rv->rv_le, &gfs2_revoke_lops); rv->rv_blkno = blkno; lops_add(sdp, &rv->rv_le); } |
cd915493f
|
146 |
void gfs2_trans_add_unrevoke(struct gfs2_sbd *sdp, u64 blkno) |
b3b94faa5
|
147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 |
{ struct gfs2_revoke *rv; int found = 0; gfs2_log_lock(sdp); list_for_each_entry(rv, &sdp->sd_log_le_revoke, rv_le.le_list) { if (rv->rv_blkno == blkno) { list_del(&rv->rv_le.le_list); gfs2_assert_withdraw(sdp, sdp->sd_log_num_revoke); sdp->sd_log_num_revoke--; found = 1; break; } } gfs2_log_unlock(sdp); if (found) { |
5c676f6d3
|
166 |
struct gfs2_trans *tr = current->journal_info; |
b3b94faa5
|
167 |
kfree(rv); |
5c676f6d3
|
168 |
tr->tr_num_revoke_rm++; |
b3b94faa5
|
169 170 171 172 173 174 175 |
} } void gfs2_trans_add_rg(struct gfs2_rgrpd *rgd) { lops_add(rgd->rd_sbd, &rgd->rd_le); } |