Branch data Line data Source code
1 : : /*
2 : : * Interface between ext4 and JBD
3 : : */
4 : :
5 : : #include "ext4_jbd2.h"
6 : :
7 : : #include <trace/events/ext4.h>
8 : :
9 : : /* Just increment the non-pointer handle value */
10 : 0 : static handle_t *ext4_get_nojournal(void)
11 : : {
12 : 0 : handle_t *handle = current->journal_info;
13 : 0 : unsigned long ref_cnt = (unsigned long)handle;
14 : :
15 [ # # ]: 0 : BUG_ON(ref_cnt >= EXT4_NOJOURNAL_MAX_REF_COUNT);
16 : :
17 : 0 : ref_cnt++;
18 : 0 : handle = (handle_t *)ref_cnt;
19 : :
20 : 0 : current->journal_info = handle;
21 : 0 : return handle;
22 : : }
23 : :
24 : :
25 : : /* Decrement the non-pointer handle value */
26 : 0 : static void ext4_put_nojournal(handle_t *handle)
27 : : {
28 : 0 : unsigned long ref_cnt = (unsigned long)handle;
29 : :
30 [ # # ]: 0 : BUG_ON(ref_cnt == 0);
31 : :
32 : 0 : ref_cnt--;
33 : 0 : handle = (handle_t *)ref_cnt;
34 : :
35 : 0 : current->journal_info = handle;
36 : 0 : }
37 : :
38 : : /*
39 : : * Wrappers for jbd2_journal_start/end.
40 : : */
41 : 0 : static int ext4_journal_check_start(struct super_block *sb)
42 : : {
43 : 13946279 : journal_t *journal;
44 : :
45 : : might_sleep();
46 [ + + ]: 13947214 : if (sb->s_flags & MS_RDONLY)
47 : : return -EROFS;
48 [ - + ]: 13946935 : WARN_ON(sb->s_writers.frozen == SB_FREEZE_COMPLETE);
49 : 13946279 : journal = EXT4_SB(sb)->s_journal;
50 : : /*
51 : : * Special case here: if the journal has aborted behind our
52 : : * backs (eg. EIO in the commit thread), then we still need to
53 : : * take the FS itself readonly cleanly.
54 : : */
55 [ + - ][ - + ]: 13946279 : if (journal && is_journal_aborted(journal)) {
56 : 0 : ext4_abort(sb, "Detected aborted journal");
57 : 0 : return -EROFS;
58 : : }
59 : : return 0;
60 : : }
61 : :
62 : 0 : handle_t *__ext4_journal_start_sb(struct super_block *sb, unsigned int line,
63 : : int type, int blocks, int rsv_blocks)
64 : : {
65 : : journal_t *journal;
66 : : int err;
67 : :
68 : 13945794 : trace_ext4_journal_start(sb, blocks, rsv_blocks, _RET_IP_);
69 : 13945764 : err = ext4_journal_check_start(sb);
70 [ - + ]: 13946775 : if (err < 0)
71 : 0 : return ERR_PTR(err);
72 : :
73 : 13946775 : journal = EXT4_SB(sb)->s_journal;
74 [ - + ]: 13946775 : if (!journal)
75 : 0 : return ext4_get_nojournal();
76 : 13946775 : return jbd2__journal_start(journal, blocks, rsv_blocks, GFP_NOFS,
77 : : type, line);
78 : : }
79 : :
80 : 0 : int __ext4_journal_stop(const char *where, unsigned int line, handle_t *handle)
81 : : {
82 : : struct super_block *sb;
83 : : int err;
84 : : int rc;
85 : :
86 [ - + ]: 13947312 : if (!ext4_handle_valid(handle)) {
87 : 0 : ext4_put_nojournal(handle);
88 : 0 : return 0;
89 : : }
90 : 13947312 : sb = handle->h_transaction->t_journal->j_private;
91 : 13947312 : err = handle->h_err;
92 : 13947312 : rc = jbd2_journal_stop(handle);
93 : :
94 [ + ]: 13947557 : if (!err)
95 : : err = rc;
96 [ - + ]: 13947557 : if (err)
97 : 0 : __ext4_std_error(sb, where, line, err);
98 : 13947578 : return err;
99 : : }
100 : :
101 : 0 : handle_t *__ext4_journal_start_reserved(handle_t *handle, unsigned int line,
102 : : int type)
103 : : {
104 : : struct super_block *sb;
105 : : int err;
106 : :
107 [ # # ]: 0 : if (!ext4_handle_valid(handle))
108 : 0 : return ext4_get_nojournal();
109 : :
110 : 0 : sb = handle->h_journal->j_private;
111 : 0 : trace_ext4_journal_start_reserved(sb, handle->h_buffer_credits,
112 : 0 : _RET_IP_);
113 : 0 : err = ext4_journal_check_start(sb);
114 [ # # ]: 0 : if (err < 0) {
115 : 0 : jbd2_journal_free_reserved(handle);
116 : 0 : return ERR_PTR(err);
117 : : }
118 : :
119 : 0 : err = jbd2_journal_start_reserved(handle, type, line);
120 [ # # ]: 0 : if (err < 0)
121 : 0 : return ERR_PTR(err);
122 : : return handle;
123 : : }
124 : :
125 : 0 : void ext4_journal_abort_handle(const char *caller, unsigned int line,
126 : : const char *err_fn, struct buffer_head *bh,
127 : : handle_t *handle, int err)
128 : : {
129 : : char nbuf[16];
130 : 0 : const char *errstr = ext4_decode_error(NULL, err, nbuf);
131 : :
132 [ # # ]: 0 : BUG_ON(!ext4_handle_valid(handle));
133 : :
134 : : if (bh)
135 : : BUFFER_TRACE(bh, "abort");
136 : :
137 [ # # ]: 0 : if (!handle->h_err)
138 : 0 : handle->h_err = err;
139 : :
140 [ # # ]: 0 : if (is_handle_aborted(handle))
141 : 0 : return;
142 : :
143 : 0 : printk(KERN_ERR "EXT4-fs: %s:%d: aborting transaction: %s in %s\n",
144 : : caller, line, errstr, err_fn);
145 : :
146 : : jbd2_journal_abort_handle(handle);
147 : : }
148 : :
149 : 0 : int __ext4_journal_get_write_access(const char *where, unsigned int line,
150 : : handle_t *handle, struct buffer_head *bh)
151 : : {
152 : : int err = 0;
153 : :
154 : : might_sleep();
155 : :
156 [ + + ]: 16021492 : if (ext4_handle_valid(handle)) {
157 : 16020819 : err = jbd2_journal_get_write_access(handle, bh);
158 [ - + ]: 16023572 : if (err)
159 : 0 : ext4_journal_abort_handle(where, line, __func__, bh,
160 : : handle, err);
161 : : }
162 : 2753 : return err;
163 : : }
164 : :
165 : : /*
166 : : * The ext4 forget function must perform a revoke if we are freeing data
167 : : * which has been journaled. Metadata (eg. indirect blocks) must be
168 : : * revoked in all cases.
169 : : *
170 : : * "bh" may be NULL: a metadata block may have been freed from memory
171 : : * but there may still be a record of it in the journal, and that record
172 : : * still needs to be revoked.
173 : : *
174 : : * If the handle isn't valid we're not journaling, but we still need to
175 : : * call into ext4_journal_revoke() to put the buffer head.
176 : : */
177 : 0 : int __ext4_forget(const char *where, unsigned int line, handle_t *handle,
178 : : int is_metadata, struct inode *inode,
179 : : struct buffer_head *bh, ext4_fsblk_t blocknr)
180 : : {
181 : : int err;
182 : :
183 : : might_sleep();
184 : :
185 : : trace_ext4_forget(inode, is_metadata, blocknr);
186 : : BUFFER_TRACE(bh, "enter");
187 : :
188 : : jbd_debug(4, "forgetting bh %p: is_metadata = %d, mode %o, "
189 : : "data mode %x\n",
190 : : bh, is_metadata, inode->i_mode,
191 : : test_opt(inode->i_sb, DATA_FLAGS));
192 : :
193 : : /* In the no journal case, we can just do a bforget and return */
194 [ - + ]: 42770 : if (!ext4_handle_valid(handle)) {
195 : : bforget(bh);
196 : : return 0;
197 : : }
198 : :
199 : : /* Never use the revoke function if we are doing full data
200 : : * journaling: there is no need to, and a V1 superblock won't
201 : : * support it. Otherwise, only skip the revoke on un-journaled
202 : : * data blocks. */
203 : :
204 [ + - ][ - + ]: 42770 : if (test_opt(inode->i_sb, DATA_FLAGS) == EXT4_MOUNT_JOURNAL_DATA ||
205 [ # # ]: 0 : (!is_metadata && !ext4_should_journal_data(inode))) {
206 [ # # ]: 0 : if (bh) {
207 : : BUFFER_TRACE(bh, "call jbd2_journal_forget");
208 : 0 : err = jbd2_journal_forget(handle, bh);
209 [ # # ]: 0 : if (err)
210 : 0 : ext4_journal_abort_handle(where, line, __func__,
211 : : bh, handle, err);
212 : 0 : return err;
213 : : }
214 : : return 0;
215 : : }
216 : :
217 : : /*
218 : : * data!=journal && (is_metadata || should_journal_data(inode))
219 : : */
220 : : BUFFER_TRACE(bh, "call jbd2_journal_revoke");
221 : 42770 : err = jbd2_journal_revoke(handle, blocknr, bh);
222 [ - + ]: 42770 : if (err) {
223 : 0 : ext4_journal_abort_handle(where, line, __func__,
224 : : bh, handle, err);
225 : 0 : __ext4_abort(inode->i_sb, where, line,
226 : : "error %d when attempting revoke", err);
227 : : }
228 : : BUFFER_TRACE(bh, "exit");
229 : 42770 : return err;
230 : : }
231 : :
232 : 0 : int __ext4_journal_get_create_access(const char *where, unsigned int line,
233 : : handle_t *handle, struct buffer_head *bh)
234 : : {
235 : : int err = 0;
236 : :
237 [ + - ]: 42385 : if (ext4_handle_valid(handle)) {
238 : 42385 : err = jbd2_journal_get_create_access(handle, bh);
239 [ - + ]: 42385 : if (err)
240 : 0 : ext4_journal_abort_handle(where, line, __func__,
241 : : bh, handle, err);
242 : : }
243 : 0 : return err;
244 : : }
245 : :
246 : 0 : int __ext4_handle_dirty_metadata(const char *where, unsigned int line,
247 : : handle_t *handle, struct inode *inode,
248 : : struct buffer_head *bh)
249 : : {
250 : : int err = 0;
251 : :
252 : : might_sleep();
253 : :
254 : : set_buffer_meta(bh);
255 : : set_buffer_prio(bh);
256 [ + - ]: 14868300 : if (ext4_handle_valid(handle)) {
257 : 14868300 : err = jbd2_journal_dirty_metadata(handle, bh);
258 : : /* Errors can only happen if there is a bug */
259 [ - + ][ # # ]: 14869925 : if (WARN_ON_ONCE(err)) {
[ - ][ - + ]
260 : 0 : ext4_journal_abort_handle(where, line, __func__, bh,
261 : : handle, err);
262 : 0 : ext4_error_inode(inode, where, line,
263 : : bh->b_blocknr,
264 : : "journal_dirty_metadata failed: "
265 : : "handle type %u started at line %u, "
266 : : "credits %u/%u, errcode %d",
267 : : handle->h_type,
268 : : handle->h_line_no,
269 : : handle->h_requested_credits,
270 : : handle->h_buffer_credits, err);
271 : : }
272 : : } else {
273 [ # # ]: 0 : if (inode)
274 : 0 : mark_buffer_dirty_inode(bh, inode);
275 : : else
276 : 0 : mark_buffer_dirty(bh);
277 [ # # ][ # # ]: 0 : if (inode && inode_needs_sync(inode)) {
278 : 0 : sync_dirty_buffer(bh);
279 [ # # ][ # # ]: 0 : if (buffer_req(bh) && !buffer_uptodate(bh)) {
280 : : struct ext4_super_block *es;
281 : :
282 : 0 : es = EXT4_SB(inode->i_sb)->s_es;
283 : 0 : es->s_last_error_block =
284 : 0 : cpu_to_le64(bh->b_blocknr);
285 : 0 : ext4_error_inode(inode, where, line,
286 : : bh->b_blocknr,
287 : : "IO error syncing itable block");
288 : : err = -EIO;
289 : : }
290 : : }
291 : : }
292 : 14869921 : return err;
293 : : }
294 : :
295 : 0 : int __ext4_handle_dirty_super(const char *where, unsigned int line,
296 : 1145822 : handle_t *handle, struct super_block *sb)
297 : : {
298 : 1145822 : struct buffer_head *bh = EXT4_SB(sb)->s_sbh;
299 : : int err = 0;
300 : :
301 : 1145822 : ext4_superblock_csum_set(sb);
302 [ + - ]: 1145822 : if (ext4_handle_valid(handle)) {
303 : 1145822 : err = jbd2_journal_dirty_metadata(handle, bh);
304 [ - + ]: 1145822 : if (err)
305 : 0 : ext4_journal_abort_handle(where, line, __func__,
306 : : bh, handle, err);
307 : : } else
308 : 0 : mark_buffer_dirty(bh);
309 : 1145822 : return err;
310 : : }
|