Linux Kernel
3.7.1
Main Page
Related Pages
Modules
Namespaces
Data Structures
Files
File List
Globals
All
Data Structures
Namespaces
Files
Functions
Variables
Typedefs
Enumerations
Enumerator
Macros
Groups
Pages
fs
gfs2
trans.c
Go to the documentation of this file.
1
/*
2
* Copyright (C) Sistina Software, Inc. 1997-2003 All rights reserved.
3
* Copyright (C) 2004-2006 Red Hat, Inc. All rights reserved.
4
*
5
* This copyrighted material is made available to anyone wishing to use,
6
* modify, copy, or redistribute it subject to the terms and conditions
7
* of the GNU General Public License version 2.
8
*/
9
10
#include <linux/sched.h>
11
#include <linux/slab.h>
12
#include <
linux/spinlock.h
>
13
#include <
linux/completion.h
>
14
#include <
linux/buffer_head.h
>
15
#include <
linux/kallsyms.h
>
16
#include <
linux/gfs2_ondisk.h
>
17
18
#include "
gfs2.h
"
19
#include "
incore.h
"
20
#include "
glock.h
"
21
#include "
log.h
"
22
#include "
lops.h
"
23
#include "
meta_io.h
"
24
#include "
trans.h
"
25
#include "
util.h
"
26
#include "
trace_gfs2.h
"
27
28
int
gfs2_trans_begin
(
struct
gfs2_sbd
*sdp,
unsigned
int
blocks,
29
unsigned
int
revokes)
30
{
31
struct
gfs2_trans
*
tr
;
32
int
error
;
33
34
BUG_ON
(
current
->journal_info);
35
BUG_ON
(blocks == 0 && revokes == 0);
36
37
if
(!
test_bit
(
SDF_JOURNAL_LIVE
, &sdp->
sd_flags
))
38
return
-
EROFS
;
39
40
tr = kzalloc(
sizeof
(
struct
gfs2_trans
),
GFP_NOFS
);
41
if
(!tr)
42
return
-
ENOMEM
;
43
44
tr->
tr_ip
= (
unsigned
long
)__builtin_return_address(0);
45
tr->
tr_blocks
= blocks;
46
tr->
tr_revokes
= revokes;
47
tr->
tr_reserved
= 1;
48
if
(blocks)
49
tr->
tr_reserved
+= 6 + blocks;
50
if
(revokes)
51
tr->
tr_reserved
+=
gfs2_struct2blk
(sdp, revokes,
52
sizeof
(
u64
));
53
sb_start_intwrite(sdp->
sd_vfs
);
54
gfs2_holder_init
(sdp->
sd_trans_gl
,
LM_ST_SHARED
, 0, &tr->
tr_t_gh
);
55
56
error =
gfs2_glock_nq
(&tr->
tr_t_gh
);
57
if
(error)
58
goto
fail_holder_uninit;
59
60
error =
gfs2_log_reserve
(sdp, tr->
tr_reserved
);
61
if
(error)
62
goto
fail_gunlock;
63
64
current
->journal_info = tr;
65
66
return
0;
67
68
fail_gunlock:
69
gfs2_glock_dq
(&tr->
tr_t_gh
);
70
71
fail_holder_uninit:
72
sb_end_intwrite(sdp->
sd_vfs
);
73
gfs2_holder_uninit
(&tr->
tr_t_gh
);
74
kfree
(tr);
75
76
return
error
;
77
}
78
86
static
void
gfs2_log_release(
struct
gfs2_sbd
*sdp,
unsigned
int
blks)
87
{
88
89
atomic_add
(blks, &sdp->
sd_log_blks_free
);
90
trace_gfs2_log_blocks(sdp, blks);
91
gfs2_assert_withdraw
(sdp,
atomic_read
(&sdp->
sd_log_blks_free
) <=
92
sdp->
sd_jdesc
->jd_blocks);
93
up_read
(&sdp->
sd_log_flush_lock
);
94
}
95
96
static
void
gfs2_print_trans(
const
struct
gfs2_trans
*
tr
)
97
{
98
print_symbol(
KERN_WARNING
"GFS2: Transaction created at: %s\n"
, tr->
tr_ip
);
99
printk
(
KERN_WARNING
"GFS2: blocks=%u revokes=%u reserved=%u touched=%d\n"
,
100
tr->
tr_blocks
, tr->
tr_revokes
, tr->
tr_reserved
, tr->
tr_touched
);
101
printk
(
KERN_WARNING
"GFS2: Buf %u/%u Databuf %u/%u Revoke %u/%u\n"
,
102
tr->
tr_num_buf_new
, tr->
tr_num_buf_rm
,
103
tr->
tr_num_databuf_new
, tr->
tr_num_databuf_rm
,
104
tr->
tr_num_revoke
, tr->
tr_num_revoke_rm
);
105
}
106
107
void
gfs2_trans_end
(
struct
gfs2_sbd
*sdp)
108
{
109
struct
gfs2_trans
*
tr
=
current
->journal_info;
110
s64
nbuf;
111
BUG_ON
(!tr);
112
current
->journal_info =
NULL
;
113
114
if
(!tr->
tr_touched
) {
115
gfs2_log_release(sdp, tr->
tr_reserved
);
116
if
(tr->
tr_t_gh
.gh_gl) {
117
gfs2_glock_dq
(&tr->
tr_t_gh
);
118
gfs2_holder_uninit
(&tr->
tr_t_gh
);
119
kfree
(tr);
120
}
121
sb_end_intwrite(sdp->
sd_vfs
);
122
return
;
123
}
124
125
nbuf = tr->
tr_num_buf_new
+ tr->
tr_num_databuf_new
;
126
nbuf -= tr->
tr_num_buf_rm
;
127
nbuf -= tr->
tr_num_databuf_rm
;
128
129
if
(
gfs2_assert_withdraw
(sdp, (nbuf <= tr->
tr_blocks
) &&
130
(tr->
tr_num_revoke
<= tr->
tr_revokes
)))
131
gfs2_print_trans(tr);
132
133
gfs2_log_commit
(sdp, tr);
134
if
(tr->
tr_t_gh
.gh_gl) {
135
gfs2_glock_dq
(&tr->
tr_t_gh
);
136
gfs2_holder_uninit
(&tr->
tr_t_gh
);
137
kfree
(tr);
138
}
139
140
if
(sdp->
sd_vfs
->s_flags &
MS_SYNCHRONOUS
)
141
gfs2_log_flush
(sdp,
NULL
);
142
sb_end_intwrite(sdp->
sd_vfs
);
143
}
144
153
void
gfs2_trans_add_bh
(
struct
gfs2_glock
*gl,
struct
buffer_head *bh,
int
meta
)
154
{
155
struct
gfs2_sbd
*sdp = gl->
gl_sbd
;
156
struct
gfs2_bufdata
*bd;
157
158
lock_buffer(bh);
159
gfs2_log_lock(sdp);
160
bd = bh->b_private;
161
if
(bd)
162
gfs2_assert
(sdp, bd->
bd_gl
== gl);
163
else
{
164
gfs2_log_unlock(sdp);
165
unlock_buffer
(bh);
166
gfs2_attach_bufdata
(gl, bh, meta);
167
bd = bh->b_private;
168
lock_buffer(bh);
169
gfs2_log_lock(sdp);
170
}
171
lops_add(sdp, bd);
172
gfs2_log_unlock(sdp);
173
unlock_buffer
(bh);
174
}
175
176
void
gfs2_trans_add_revoke
(
struct
gfs2_sbd
*sdp,
struct
gfs2_bufdata
*bd)
177
{
178
BUG_ON
(!list_empty(&bd->
bd_list
));
179
BUG_ON
(!list_empty(&bd->
bd_ail_st_list
));
180
BUG_ON
(!list_empty(&bd->
bd_ail_gl_list
));
181
lops_init_le(bd, &
gfs2_revoke_lops
);
182
lops_add(sdp, bd);
183
}
184
185
void
gfs2_trans_add_unrevoke
(
struct
gfs2_sbd
*sdp,
u64
blkno,
unsigned
int
len)
186
{
187
struct
gfs2_bufdata
*bd, *
tmp
;
188
struct
gfs2_trans
*
tr
=
current
->journal_info;
189
unsigned
int
n
= len;
190
191
gfs2_log_lock(sdp);
192
list_for_each_entry_safe
(bd, tmp, &sdp->
sd_log_le_revoke
, bd_list) {
193
if
((bd->
bd_blkno
>= blkno) && (bd->
bd_blkno
< (blkno + len))) {
194
list_del_init(&bd->
bd_list
);
195
gfs2_assert_withdraw
(sdp, sdp->
sd_log_num_revoke
);
196
sdp->
sd_log_num_revoke
--;
197
kmem_cache_free
(
gfs2_bufdata_cachep
, bd);
198
tr->
tr_num_revoke_rm
++;
199
if
(--n == 0)
200
break
;
201
}
202
}
203
gfs2_log_unlock(sdp);
204
}
205
Generated on Thu Jan 10 2013 14:11:53 for Linux Kernel by
1.8.2