Blame view
fs/jbd2/commit.c
33.9 KB
470decc61 [PATCH] jbd2: ini... |
1 |
/* |
f7f4bccb7 [PATCH] jbd2: ren... |
2 |
* linux/fs/jbd2/commit.c |
470decc61 [PATCH] jbd2: ini... |
3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 |
* * Written by Stephen C. Tweedie <sct@redhat.com>, 1998 * * Copyright 1998 Red Hat corp --- All Rights Reserved * * This file is part of the Linux kernel and is made available under * the terms of the GNU General Public License, version 2, or at your * option, any later version, incorporated herein by reference. * * Journal commit routines for the generic filesystem journaling code; * part of the ext2fs journaling system. */ #include <linux/time.h> #include <linux/fs.h> |
f7f4bccb7 [PATCH] jbd2: ren... |
18 |
#include <linux/jbd2.h> |
470decc61 [PATCH] jbd2: ini... |
19 20 21 22 |
#include <linux/errno.h> #include <linux/slab.h> #include <linux/mm.h> #include <linux/pagemap.h> |
8e85fb3f3 jbd2: jbd2 stats ... |
23 |
#include <linux/jiffies.h> |
818d276ce ext4: Add the jou... |
24 |
#include <linux/crc32.h> |
cd1aac329 ext4: Add ordered... |
25 26 |
#include <linux/writeback.h> #include <linux/backing-dev.h> |
fd98496f4 jbd2: Add barrier... |
27 |
#include <linux/bio.h> |
0e3d2a631 ext4: Fix async c... |
28 |
#include <linux/blkdev.h> |
39e3ac259 jbd2: Fix I/O han... |
29 |
#include <linux/bitops.h> |
879c5e6b7 jbd2: convert ins... |
30 |
#include <trace/events/jbd2.h> |
470decc61 [PATCH] jbd2: ini... |
31 32 |
/* |
b34090e5e jbd2: refine wait... |
33 |
* IO end handler for temporary buffer_heads handling writes to the journal. |
470decc61 [PATCH] jbd2: ini... |
34 35 36 |
*/ static void journal_end_buffer_io_sync(struct buffer_head *bh, int uptodate) { |
b34090e5e jbd2: refine wait... |
37 |
struct buffer_head *orig_bh = bh->b_private; |
470decc61 [PATCH] jbd2: ini... |
38 39 40 41 42 |
BUFFER_TRACE(bh, ""); if (uptodate) set_buffer_uptodate(bh); else clear_buffer_uptodate(bh); |
b34090e5e jbd2: refine wait... |
43 44 |
if (orig_bh) { clear_bit_unlock(BH_Shadow, &orig_bh->b_state); |
4e857c58e arch: Mass conver... |
45 |
smp_mb__after_atomic(); |
b34090e5e jbd2: refine wait... |
46 47 |
wake_up_bit(&orig_bh->b_state, BH_Shadow); } |
470decc61 [PATCH] jbd2: ini... |
48 49 50 51 |
unlock_buffer(bh); } /* |
87c89c232 jbd2: Remove data... |
52 53 |
* When an ext4 file is truncated, it is possible that some pages are not * successfully freed, because they are attached to a committing transaction. |
470decc61 [PATCH] jbd2: ini... |
54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 |
* After the transaction commits, these pages are left on the LRU, with no * ->mapping, and with attached buffers. These pages are trivially reclaimable * by the VM, but their apparent absence upsets the VM accounting, and it makes * the numbers in /proc/meminfo look odd. * * So here, we have a buffer which has just come off the forget list. Look to * see if we can strip all buffers from the backing page. * * Called under lock_journal(), and possibly under journal_datalist_lock. The * caller provided us with a ref against the buffer, and we drop that here. */ static void release_buffer_page(struct buffer_head *bh) { struct page *page; if (buffer_dirty(bh)) goto nope; if (atomic_read(&bh->b_count) != 1) goto nope; page = bh->b_page; if (!page) goto nope; if (page->mapping) goto nope; /* OK, it's a truncated page */ |
529ae9aaa mm: rename page t... |
80 |
if (!trylock_page(page)) |
470decc61 [PATCH] jbd2: ini... |
81 |
goto nope; |
09cbfeaf1 mm, fs: get rid o... |
82 |
get_page(page); |
470decc61 [PATCH] jbd2: ini... |
83 84 85 |
__brelse(bh); try_to_free_buffers(page); unlock_page(page); |
09cbfeaf1 mm, fs: get rid o... |
86 |
put_page(page); |
470decc61 [PATCH] jbd2: ini... |
87 88 89 90 91 |
return; nope: __brelse(bh); } |
e5a120aeb jbd2: remove jour... |
92 |
static void jbd2_commit_block_csum_set(journal_t *j, struct buffer_head *bh) |
1f56c5890 jbd2: checksum co... |
93 94 95 |
{ struct commit_header *h; __u32 csum; |
db9ee2203 jbd2: fix descrip... |
96 |
if (!jbd2_journal_has_csum_v2or3(j)) |
1f56c5890 jbd2: checksum co... |
97 |
return; |
e5a120aeb jbd2: remove jour... |
98 |
h = (struct commit_header *)(bh->b_data); |
1f56c5890 jbd2: checksum co... |
99 100 101 |
h->h_chksum_type = 0; h->h_chksum_size = 0; h->h_chksum[0] = 0; |
e5a120aeb jbd2: remove jour... |
102 |
csum = jbd2_chksum(j, j->j_csum_seed, bh->b_data, j->j_blocksize); |
1f56c5890 jbd2: checksum co... |
103 104 |
h->h_chksum[0] = cpu_to_be32(csum); } |
470decc61 [PATCH] jbd2: ini... |
105 |
/* |
818d276ce ext4: Add the jou... |
106 |
* Done it all: now submit the commit record. We should have |
470decc61 [PATCH] jbd2: ini... |
107 108 109 110 111 112 |
* cleaned up our previous buffers by now, so if we are in abort * mode we can now just skip the rest of the journal write * entirely. * * Returns 1 if the journal needs to be aborted or 0 on success */ |
818d276ce ext4: Add the jou... |
113 114 115 116 |
static int journal_submit_commit_record(journal_t *journal, transaction_t *commit_transaction, struct buffer_head **cbh, __u32 crc32_sum) |
470decc61 [PATCH] jbd2: ini... |
117 |
{ |
818d276ce ext4: Add the jou... |
118 |
struct commit_header *tmp; |
470decc61 [PATCH] jbd2: ini... |
119 |
struct buffer_head *bh; |
818d276ce ext4: Add the jou... |
120 |
int ret; |
736603ab2 jbd2: Add commit ... |
121 |
struct timespec now = current_kernel_time(); |
470decc61 [PATCH] jbd2: ini... |
122 |
|
6cba611e6 jbd2: fix potenti... |
123 |
*cbh = NULL; |
470decc61 [PATCH] jbd2: ini... |
124 125 |
if (is_journal_aborted(journal)) return 0; |
32ab67159 jbd2: factor out ... |
126 127 |
bh = jbd2_journal_get_descriptor_buffer(commit_transaction, JBD2_COMMIT_BLOCK); |
e5a120aeb jbd2: remove jour... |
128 |
if (!bh) |
470decc61 [PATCH] jbd2: ini... |
129 |
return 1; |
818d276ce ext4: Add the jou... |
130 |
tmp = (struct commit_header *)bh->b_data; |
736603ab2 jbd2: Add commit ... |
131 132 |
tmp->h_commit_sec = cpu_to_be64(now.tv_sec); tmp->h_commit_nsec = cpu_to_be32(now.tv_nsec); |
818d276ce ext4: Add the jou... |
133 |
|
56316a0d2 jbd2: clean up fe... |
134 |
if (jbd2_has_feature_checksum(journal)) { |
818d276ce ext4: Add the jou... |
135 136 137 |
tmp->h_chksum_type = JBD2_CRC32_CHKSUM; tmp->h_chksum_size = JBD2_CRC32_CHKSUM_SIZE; tmp->h_chksum[0] = cpu_to_be32(crc32_sum); |
470decc61 [PATCH] jbd2: ini... |
138 |
} |
e5a120aeb jbd2: remove jour... |
139 |
jbd2_commit_block_csum_set(journal, bh); |
470decc61 [PATCH] jbd2: ini... |
140 |
|
e5a120aeb jbd2: remove jour... |
141 |
BUFFER_TRACE(bh, "submit commit block"); |
818d276ce ext4: Add the jou... |
142 |
lock_buffer(bh); |
45a90bfd9 jbd2: Fix buffer ... |
143 |
clear_buffer_dirty(bh); |
818d276ce ext4: Add the jou... |
144 145 146 147 |
set_buffer_uptodate(bh); bh->b_end_io = journal_end_buffer_io_sync; if (journal->j_flags & JBD2_BARRIER && |
56316a0d2 jbd2: clean up fe... |
148 |
!jbd2_has_feature_async_commit(journal)) |
721a9602e block: kill off R... |
149 |
ret = submit_bh(WRITE_SYNC | WRITE_FLUSH_FUA, bh); |
9c35575bb jbd2: replace bar... |
150 |
else |
721a9602e block: kill off R... |
151 |
ret = submit_bh(WRITE_SYNC, bh); |
9c35575bb jbd2: replace bar... |
152 |
|
818d276ce ext4: Add the jou... |
153 154 155 156 157 158 159 160 |
*cbh = bh; return ret; } /* * This function along with journal_submit_commit_record * allows to write the commit record asynchronously. */ |
fd98496f4 jbd2: Add barrier... |
161 162 |
static int journal_wait_on_commit_record(journal_t *journal, struct buffer_head *bh) |
818d276ce ext4: Add the jou... |
163 164 165 166 167 |
{ int ret = 0; clear_buffer_dirty(bh); wait_on_buffer(bh); |
470decc61 [PATCH] jbd2: ini... |
168 |
|
818d276ce ext4: Add the jou... |
169 170 171 |
if (unlikely(!buffer_uptodate(bh))) ret = -EIO; put_bh(bh); /* One for getblk() */ |
818d276ce ext4: Add the jou... |
172 173 |
return ret; |
470decc61 [PATCH] jbd2: ini... |
174 |
} |
818d276ce ext4: Add the jou... |
175 |
/* |
cd1aac329 ext4: Add ordered... |
176 177 178 179 180 181 182 183 184 185 186 187 188 |
* write the filemap data using writepage() address_space_operations. * We don't do block allocation here even for delalloc. We don't * use writepages() because with dealyed allocation we may be doing * block allocation in writepages(). */ static int journal_submit_inode_data_buffers(struct address_space *mapping) { int ret; struct writeback_control wbc = { .sync_mode = WB_SYNC_ALL, .nr_to_write = mapping->nrpages * 2, .range_start = 0, .range_end = i_size_read(mapping->host), |
cd1aac329 ext4: Add ordered... |
189 190 191 192 193 194 195 |
}; ret = generic_writepages(mapping, &wbc); return ret; } /* |
c851ed540 jbd2: Implement d... |
196 197 198 199 200 201 202 |
* Submit all the data buffers of inode associated with the transaction to * disk. * * We are in a committing transaction. Therefore no new inode can be added to * our inode list. We use JI_COMMIT_RUNNING flag to protect inode we currently * operate on from being released while we write out pages. */ |
cd1aac329 ext4: Add ordered... |
203 |
static int journal_submit_data_buffers(journal_t *journal, |
c851ed540 jbd2: Implement d... |
204 205 206 207 208 209 210 211 |
transaction_t *commit_transaction) { struct jbd2_inode *jinode; int err, ret = 0; struct address_space *mapping; spin_lock(&journal->j_list_lock); list_for_each_entry(jinode, &commit_transaction->t_inode_list, i_list) { |
41617e1a8 jbd2: add support... |
212 213 |
if (!(jinode->i_flags & JI_WRITE_DATA)) continue; |
c851ed540 jbd2: Implement d... |
214 |
mapping = jinode->i_vfs_inode->i_mapping; |
cb0d9d47a jbd2: save some a... |
215 |
jinode->i_flags |= JI_COMMIT_RUNNING; |
c851ed540 jbd2: Implement d... |
216 |
spin_unlock(&journal->j_list_lock); |
cd1aac329 ext4: Add ordered... |
217 218 219 220 221 222 |
/* * submit the inode data buffers. We use writepage * instead of writepages. Because writepages can do * block allocation with delalloc. We need to write * only allocated blocks here. */ |
879c5e6b7 jbd2: convert ins... |
223 |
trace_jbd2_submit_inode_data(jinode->i_vfs_inode); |
cd1aac329 ext4: Add ordered... |
224 |
err = journal_submit_inode_data_buffers(mapping); |
c851ed540 jbd2: Implement d... |
225 226 227 228 |
if (!ret) ret = err; spin_lock(&journal->j_list_lock); J_ASSERT(jinode->i_transaction == commit_transaction); |
cb0d9d47a jbd2: save some a... |
229 230 |
jinode->i_flags &= ~JI_COMMIT_RUNNING; smp_mb(); |
c851ed540 jbd2: Implement d... |
231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 |
wake_up_bit(&jinode->i_flags, __JI_COMMIT_RUNNING); } spin_unlock(&journal->j_list_lock); return ret; } /* * Wait for data submitted for writeout, refile inodes to proper * transaction if needed. * */ static int journal_finish_inode_data_buffers(journal_t *journal, transaction_t *commit_transaction) { struct jbd2_inode *jinode, *next_i; int err, ret = 0; |
cd1aac329 ext4: Add ordered... |
247 |
/* For locking, see the comment in journal_submit_data_buffers() */ |
c851ed540 jbd2: Implement d... |
248 249 |
spin_lock(&journal->j_list_lock); list_for_each_entry(jinode, &commit_transaction->t_inode_list, i_list) { |
41617e1a8 jbd2: add support... |
250 251 |
if (!(jinode->i_flags & JI_WAIT_DATA)) continue; |
cb0d9d47a jbd2: save some a... |
252 |
jinode->i_flags |= JI_COMMIT_RUNNING; |
c851ed540 jbd2: Implement d... |
253 254 |
spin_unlock(&journal->j_list_lock); err = filemap_fdatawait(jinode->i_vfs_inode->i_mapping); |
e9e34f4e8 jbd2: don't abort... |
255 256 257 |
if (err) { /* * Because AS_EIO is cleared by |
94004ed72 kill wait_on_page... |
258 |
* filemap_fdatawait_range(), set it again so |
e9e34f4e8 jbd2: don't abort... |
259 260 261 262 263 264 265 266 |
* that user process can get -EIO from fsync(). */ set_bit(AS_EIO, &jinode->i_vfs_inode->i_mapping->flags); if (!ret) ret = err; } |
c851ed540 jbd2: Implement d... |
267 |
spin_lock(&journal->j_list_lock); |
cb0d9d47a jbd2: save some a... |
268 269 |
jinode->i_flags &= ~JI_COMMIT_RUNNING; smp_mb(); |
c851ed540 jbd2: Implement d... |
270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 |
wake_up_bit(&jinode->i_flags, __JI_COMMIT_RUNNING); } /* Now refile inode to proper lists */ list_for_each_entry_safe(jinode, next_i, &commit_transaction->t_inode_list, i_list) { list_del(&jinode->i_list); if (jinode->i_next_transaction) { jinode->i_transaction = jinode->i_next_transaction; jinode->i_next_transaction = NULL; list_add(&jinode->i_list, &jinode->i_transaction->t_inode_list); } else { jinode->i_transaction = NULL; } } spin_unlock(&journal->j_list_lock); return ret; } |
818d276ce ext4: Add the jou... |
290 291 292 293 294 |
static __u32 jbd2_checksum_data(__u32 crc32_sum, struct buffer_head *bh) { struct page *page = bh->b_page; char *addr; __u32 checksum; |
303a8f2af jbd2: remove the ... |
295 |
addr = kmap_atomic(page); |
818d276ce ext4: Add the jou... |
296 297 |
checksum = crc32_be(crc32_sum, (void *)(addr + offset_in_page(bh->b_data)), bh->b_size); |
303a8f2af jbd2: remove the ... |
298 |
kunmap_atomic(addr); |
818d276ce ext4: Add the jou... |
299 300 301 |
return checksum; } |
db9ee2203 jbd2: fix descrip... |
302 |
static void write_tag_block(journal_t *j, journal_block_tag_t *tag, |
18eba7aae [PATCH] jbd2: swi... |
303 |
unsigned long long block) |
b517bea1c [PATCH] 64-bit jb... |
304 305 |
{ tag->t_blocknr = cpu_to_be32(block & (u32)~0); |
56316a0d2 jbd2: clean up fe... |
306 |
if (jbd2_has_feature_64bit(j)) |
b517bea1c [PATCH] 64-bit jb... |
307 308 |
tag->t_blocknr_high = cpu_to_be32((block >> 31) >> 1); } |
c39008759 jbd2: checksum da... |
309 310 311 |
static void jbd2_block_tag_csum_set(journal_t *j, journal_block_tag_t *tag, struct buffer_head *bh, __u32 sequence) { |
db9ee2203 jbd2: fix descrip... |
312 |
journal_block_tag3_t *tag3 = (journal_block_tag3_t *)tag; |
c39008759 jbd2: checksum da... |
313 314 |
struct page *page = bh->b_page; __u8 *addr; |
eee06c567 jbd2: fix block t... |
315 |
__u32 csum32; |
18a6ea1e5 jbd2: Fix endian ... |
316 |
__be32 seq; |
c39008759 jbd2: checksum da... |
317 |
|
db9ee2203 jbd2: fix descrip... |
318 |
if (!jbd2_journal_has_csum_v2or3(j)) |
c39008759 jbd2: checksum da... |
319 |
return; |
18a6ea1e5 jbd2: Fix endian ... |
320 |
seq = cpu_to_be32(sequence); |
906adea15 jbd2: remove the ... |
321 |
addr = kmap_atomic(page); |
18a6ea1e5 jbd2: Fix endian ... |
322 |
csum32 = jbd2_chksum(j, j->j_csum_seed, (__u8 *)&seq, sizeof(seq)); |
eee06c567 jbd2: fix block t... |
323 324 |
csum32 = jbd2_chksum(j, csum32, addr + offset_in_page(bh->b_data), bh->b_size); |
906adea15 jbd2: remove the ... |
325 |
kunmap_atomic(addr); |
c39008759 jbd2: checksum da... |
326 |
|
56316a0d2 jbd2: clean up fe... |
327 |
if (jbd2_has_feature_csum3(j)) |
db9ee2203 jbd2: fix descrip... |
328 329 330 |
tag3->t_checksum = cpu_to_be32(csum32); else tag->t_checksum = cpu_to_be16(csum32); |
c39008759 jbd2: checksum da... |
331 |
} |
470decc61 [PATCH] jbd2: ini... |
332 |
/* |
f7f4bccb7 [PATCH] jbd2: ren... |
333 |
* jbd2_journal_commit_transaction |
470decc61 [PATCH] jbd2: ini... |
334 335 336 337 |
* * The primary function for committing a transaction to the log. This * function is called by the journal thread to begin a complete commit. */ |
f7f4bccb7 [PATCH] jbd2: ren... |
338 |
void jbd2_journal_commit_transaction(journal_t *journal) |
470decc61 [PATCH] jbd2: ini... |
339 |
{ |
8e85fb3f3 jbd2: jbd2 stats ... |
340 |
struct transaction_stats_s stats; |
470decc61 [PATCH] jbd2: ini... |
341 |
transaction_t *commit_transaction; |
e5a120aeb jbd2: remove jour... |
342 343 |
struct journal_head *jh; struct buffer_head *descriptor; |
470decc61 [PATCH] jbd2: ini... |
344 345 346 347 |
struct buffer_head **wbuf = journal->j_wbuf; int bufs; int flags; int err; |
18eba7aae [PATCH] jbd2: swi... |
348 |
unsigned long long blocknr; |
e07f7183a jbd2: improve jbd... |
349 350 |
ktime_t start_time; u64 commit_time; |
470decc61 [PATCH] jbd2: ini... |
351 |
char *tagp = NULL; |
470decc61 [PATCH] jbd2: ini... |
352 353 354 355 |
journal_block_tag_t *tag = NULL; int space_left = 0; int first_tag = 0; int tag_flag; |
794446c69 jbd2: fix race be... |
356 |
int i; |
b517bea1c [PATCH] 64-bit jb... |
357 |
int tag_bytes = journal_tag_bytes(journal); |
818d276ce ext4: Add the jou... |
358 359 |
struct buffer_head *cbh = NULL; /* For transactional checksums */ __u32 crc32_sum = ~0; |
82f04ab47 jbd2: finish conv... |
360 |
struct blk_plug plug; |
3339578f0 jbd2: cleanup jou... |
361 362 363 364 |
/* Tail of the journal */ unsigned long first_block; tid_t first_tid; int update_tail; |
3caa487f5 jbd2: checksum de... |
365 |
int csum_size = 0; |
f5113effc jbd2: don't creat... |
366 |
LIST_HEAD(io_bufs); |
e5a120aeb jbd2: remove jour... |
367 |
LIST_HEAD(log_bufs); |
3caa487f5 jbd2: checksum de... |
368 |
|
db9ee2203 jbd2: fix descrip... |
369 |
if (jbd2_journal_has_csum_v2or3(journal)) |
3caa487f5 jbd2: checksum de... |
370 |
csum_size = sizeof(struct jbd2_journal_block_tail); |
470decc61 [PATCH] jbd2: ini... |
371 372 373 374 375 |
/* * First job: lock down the current transaction and wait for * all outstanding updates to complete. */ |
f7f4bccb7 [PATCH] jbd2: ren... |
376 377 |
/* Do we need to erase the effects of a prior jbd2_journal_flush? */ if (journal->j_flags & JBD2_FLUSHED) { |
470decc61 [PATCH] jbd2: ini... |
378 379 |
jbd_debug(3, "super block updated "); |
a78bb11d7 jbd2: protect all... |
380 |
mutex_lock(&journal->j_checkpoint_mutex); |
79feb521a jbd2: issue cache... |
381 382 383 384 385 386 387 388 389 390 |
/* * We hold j_checkpoint_mutex so tail cannot change under us. * We don't need any special data guarantees for writing sb * since journal is empty and it is ok for write to be * flushed only with transaction commit. */ jbd2_journal_update_sb_log_tail(journal, journal->j_tail_sequence, journal->j_tail, WRITE_SYNC); |
a78bb11d7 jbd2: protect all... |
391 |
mutex_unlock(&journal->j_checkpoint_mutex); |
470decc61 [PATCH] jbd2: ini... |
392 393 394 395 396 397 398 399 400 |
} else { jbd_debug(3, "superblock not updated "); } J_ASSERT(journal->j_running_transaction != NULL); J_ASSERT(journal->j_committing_transaction == NULL); commit_transaction = journal->j_running_transaction; |
470decc61 [PATCH] jbd2: ini... |
401 |
|
879c5e6b7 jbd2: convert ins... |
402 |
trace_jbd2_start_commit(journal, commit_transaction); |
f2a44523b jbd2: Unify log m... |
403 404 |
jbd_debug(1, "JBD2: starting commit of transaction %d ", |
470decc61 [PATCH] jbd2: ini... |
405 |
commit_transaction->t_tid); |
a931da6ac jbd2: Change j_st... |
406 |
write_lock(&journal->j_state_lock); |
3ca841c10 jbd2: relocate as... |
407 |
J_ASSERT(commit_transaction->t_state == T_RUNNING); |
470decc61 [PATCH] jbd2: ini... |
408 |
commit_transaction->t_state = T_LOCKED; |
879c5e6b7 jbd2: convert ins... |
409 |
trace_jbd2_commit_locking(journal, commit_transaction); |
bf6993276 jbd2: Use tracepo... |
410 |
stats.run.rs_wait = commit_transaction->t_max_wait; |
9fff24aa2 jbd2: track reque... |
411 |
stats.run.rs_request_delay = 0; |
bf6993276 jbd2: Use tracepo... |
412 |
stats.run.rs_locked = jiffies; |
9fff24aa2 jbd2: track reque... |
413 414 415 416 |
if (commit_transaction->t_requested) stats.run.rs_request_delay = jbd2_time_diff(commit_transaction->t_requested, stats.run.rs_locked); |
bf6993276 jbd2: Use tracepo... |
417 418 |
stats.run.rs_running = jbd2_time_diff(commit_transaction->t_start, stats.run.rs_locked); |
8e85fb3f3 jbd2: jbd2 stats ... |
419 |
|
470decc61 [PATCH] jbd2: ini... |
420 |
spin_lock(&commit_transaction->t_handle_lock); |
a51dca9cd jbd2: Use atomic ... |
421 |
while (atomic_read(&commit_transaction->t_updates)) { |
470decc61 [PATCH] jbd2: ini... |
422 423 424 425 |
DEFINE_WAIT(wait); prepare_to_wait(&journal->j_wait_updates, &wait, TASK_UNINTERRUPTIBLE); |
a51dca9cd jbd2: Use atomic ... |
426 |
if (atomic_read(&commit_transaction->t_updates)) { |
470decc61 [PATCH] jbd2: ini... |
427 |
spin_unlock(&commit_transaction->t_handle_lock); |
a931da6ac jbd2: Change j_st... |
428 |
write_unlock(&journal->j_state_lock); |
470decc61 [PATCH] jbd2: ini... |
429 |
schedule(); |
a931da6ac jbd2: Change j_st... |
430 |
write_lock(&journal->j_state_lock); |
470decc61 [PATCH] jbd2: ini... |
431 432 433 434 435 |
spin_lock(&commit_transaction->t_handle_lock); } finish_wait(&journal->j_wait_updates, &wait); } spin_unlock(&commit_transaction->t_handle_lock); |
a51dca9cd jbd2: Use atomic ... |
436 |
J_ASSERT (atomic_read(&commit_transaction->t_outstanding_credits) <= |
470decc61 [PATCH] jbd2: ini... |
437 438 439 440 441 442 443 |
journal->j_max_transaction_buffers); /* * First thing we are allowed to do is to discard any remaining * BJ_Reserved buffers. Note, it is _not_ permissible to assume * that there are no such buffers: if a large filesystem * operation like a truncate needs to split itself over multiple |
f7f4bccb7 [PATCH] jbd2: ren... |
444 |
* transactions, then it may try to do a jbd2_journal_restart() while |
470decc61 [PATCH] jbd2: ini... |
445 446 447 448 449 450 451 |
* there are still BJ_Reserved buffers outstanding. These must * be released cleanly from the current transaction. * * In this case, the filesystem must still reserve write access * again before modifying the buffer in the new transaction, but * we do not require it to remember exactly which old buffers it * has reserved. This is consistent with the existing behaviour |
f7f4bccb7 [PATCH] jbd2: ren... |
452 |
* that multiple jbd2_journal_get_write_access() calls to the same |
25985edce Fix common misspe... |
453 |
* buffer are perfectly permissible. |
470decc61 [PATCH] jbd2: ini... |
454 455 456 457 458 |
*/ while (commit_transaction->t_reserved_list) { jh = commit_transaction->t_reserved_list; JBUFFER_TRACE(jh, "reserved, unused: refile"); /* |
f7f4bccb7 [PATCH] jbd2: ren... |
459 |
* A jbd2_journal_get_undo_access()+jbd2_journal_release_buffer() may |
470decc61 [PATCH] jbd2: ini... |
460 461 462 463 464 465 |
* leave undo-committed data. */ if (jh->b_committed_data) { struct buffer_head *bh = jh2bh(jh); jbd_lock_bh_state(bh); |
af1e76d6b JBD2: jbd2 slab a... |
466 |
jbd2_free(jh->b_committed_data, bh->b_size); |
470decc61 [PATCH] jbd2: ini... |
467 468 469 |
jh->b_committed_data = NULL; jbd_unlock_bh_state(bh); } |
f7f4bccb7 [PATCH] jbd2: ren... |
470 |
jbd2_journal_refile_buffer(journal, jh); |
470decc61 [PATCH] jbd2: ini... |
471 472 473 474 475 476 477 478 |
} /* * Now try to drop any written-back buffers from the journal's * checkpoint lists. We do this *before* commit because it potentially * frees some memory */ spin_lock(&journal->j_list_lock); |
841df7df1 jbd2: avoid infin... |
479 |
__jbd2_journal_clean_checkpoint_list(journal, false); |
470decc61 [PATCH] jbd2: ini... |
480 |
spin_unlock(&journal->j_list_lock); |
f2a44523b jbd2: Unify log m... |
481 482 |
jbd_debug(3, "JBD2: commit phase 1 "); |
470decc61 [PATCH] jbd2: ini... |
483 484 |
/* |
1ba37268c jbd2: clear revok... |
485 486 487 488 489 490 |
* Clear revoked flag to reflect there is no revoked buffers * in the next transaction which is going to be started. */ jbd2_clear_buffer_revoked_flags(journal); /* |
470decc61 [PATCH] jbd2: ini... |
491 492 |
* Switch to a new revoke table. */ |
f7f4bccb7 [PATCH] jbd2: ren... |
493 |
jbd2_journal_switch_revoke_table(journal); |
470decc61 [PATCH] jbd2: ini... |
494 |
|
8f7d89f36 jbd2: transaction... |
495 496 497 498 499 |
/* * Reserved credits cannot be claimed anymore, free them */ atomic_sub(atomic_read(&journal->j_reserved_credits), &commit_transaction->t_outstanding_credits); |
879c5e6b7 jbd2: convert ins... |
500 |
trace_jbd2_commit_flushing(journal, commit_transaction); |
bf6993276 jbd2: Use tracepo... |
501 502 503 |
stats.run.rs_flushing = jiffies; stats.run.rs_locked = jbd2_time_diff(stats.run.rs_locked, stats.run.rs_flushing); |
8e85fb3f3 jbd2: jbd2 stats ... |
504 |
|
470decc61 [PATCH] jbd2: ini... |
505 506 507 |
commit_transaction->t_state = T_FLUSH; journal->j_committing_transaction = commit_transaction; journal->j_running_transaction = NULL; |
e07f7183a jbd2: improve jbd... |
508 |
start_time = ktime_get(); |
470decc61 [PATCH] jbd2: ini... |
509 510 |
commit_transaction->t_log_start = journal->j_head; wake_up(&journal->j_wait_transaction_locked); |
a931da6ac jbd2: Change j_st... |
511 |
write_unlock(&journal->j_state_lock); |
470decc61 [PATCH] jbd2: ini... |
512 |
|
cfc7bc896 jbd2: fix duplica... |
513 514 |
jbd_debug(3, "JBD2: commit phase 2a "); |
470decc61 [PATCH] jbd2: ini... |
515 516 |
/* |
470decc61 [PATCH] jbd2: ini... |
517 518 519 |
* Now start flushing things to disk, in the order they appear * on the transaction lists. Data blocks go first. */ |
cd1aac329 ext4: Add ordered... |
520 |
err = journal_submit_data_buffers(journal, commit_transaction); |
c851ed540 jbd2: Implement d... |
521 522 |
if (err) jbd2_journal_abort(journal, err); |
470decc61 [PATCH] jbd2: ini... |
523 |
|
82f04ab47 jbd2: finish conv... |
524 |
blk_start_plug(&plug); |
9bcf976cb jbd2: remove unne... |
525 |
jbd2_journal_write_revoke_records(commit_transaction, &log_bufs); |
470decc61 [PATCH] jbd2: ini... |
526 |
|
cfc7bc896 jbd2: fix duplica... |
527 528 |
jbd_debug(3, "JBD2: commit phase 2b "); |
470decc61 [PATCH] jbd2: ini... |
529 530 |
/* |
470decc61 [PATCH] jbd2: ini... |
531 532 533 534 |
* Way to go: we have now written out all of the data for a * transaction! Now comes the tricky part: we need to write out * metadata. Loop over the transaction's entire buffer list: */ |
a931da6ac jbd2: Change j_st... |
535 |
write_lock(&journal->j_state_lock); |
470decc61 [PATCH] jbd2: ini... |
536 |
commit_transaction->t_state = T_COMMIT; |
a931da6ac jbd2: Change j_st... |
537 |
write_unlock(&journal->j_state_lock); |
470decc61 [PATCH] jbd2: ini... |
538 |
|
879c5e6b7 jbd2: convert ins... |
539 |
trace_jbd2_commit_logging(journal, commit_transaction); |
bf6993276 jbd2: Use tracepo... |
540 541 542 |
stats.run.rs_logging = jiffies; stats.run.rs_flushing = jbd2_time_diff(stats.run.rs_flushing, stats.run.rs_logging); |
a51dca9cd jbd2: Use atomic ... |
543 544 |
stats.run.rs_blocks = atomic_read(&commit_transaction->t_outstanding_credits); |
bf6993276 jbd2: Use tracepo... |
545 |
stats.run.rs_blocks_logged = 0; |
8e85fb3f3 jbd2: jbd2 stats ... |
546 |
|
1dfc3220d jbd2: fix possibl... |
547 |
J_ASSERT(commit_transaction->t_nr_buffers <= |
a51dca9cd jbd2: Use atomic ... |
548 |
atomic_read(&commit_transaction->t_outstanding_credits)); |
1dfc3220d jbd2: fix possibl... |
549 |
|
87c89c232 jbd2: Remove data... |
550 |
err = 0; |
470decc61 [PATCH] jbd2: ini... |
551 |
bufs = 0; |
e5a120aeb jbd2: remove jour... |
552 |
descriptor = NULL; |
470decc61 [PATCH] jbd2: ini... |
553 554 555 556 557 558 559 |
while (commit_transaction->t_buffers) { /* Find the next buffer to be journaled... */ jh = commit_transaction->t_buffers; /* If we're in abort mode, we just un-journal the buffer and |
7ad7445f6 jbd2: don't dirty... |
560 |
release it. */ |
470decc61 [PATCH] jbd2: ini... |
561 562 |
if (is_journal_aborted(journal)) { |
7ad7445f6 jbd2: don't dirty... |
563 |
clear_buffer_jbddirty(jh2bh(jh)); |
470decc61 [PATCH] jbd2: ini... |
564 |
JBUFFER_TRACE(jh, "journal is aborting: refile"); |
e06c8227f jbd2: Add buffer ... |
565 566 567 568 |
jbd2_buffer_abort_trigger(jh, jh->b_frozen_data ? jh->b_frozen_triggers : jh->b_triggers); |
f7f4bccb7 [PATCH] jbd2: ren... |
569 |
jbd2_journal_refile_buffer(journal, jh); |
470decc61 [PATCH] jbd2: ini... |
570 571 572 573 574 575 576 577 578 579 580 581 582 |
/* If that was the last one, we need to clean up * any descriptor buffers which may have been * already allocated, even if we are now * aborting. */ if (!commit_transaction->t_buffers) goto start_journal_io; continue; } /* Make sure we have a descriptor block in which to record the metadata buffer. */ if (!descriptor) { |
470decc61 [PATCH] jbd2: ini... |
583 |
J_ASSERT (bufs == 0); |
f2a44523b jbd2: Unify log m... |
584 585 |
jbd_debug(4, "JBD2: get descriptor "); |
470decc61 [PATCH] jbd2: ini... |
586 |
|
32ab67159 jbd2: factor out ... |
587 588 589 |
descriptor = jbd2_journal_get_descriptor_buffer( commit_transaction, JBD2_DESCRIPTOR_BLOCK); |
470decc61 [PATCH] jbd2: ini... |
590 |
if (!descriptor) { |
a7fa2baf8 jbd2: fix commit ... |
591 |
jbd2_journal_abort(journal, -EIO); |
470decc61 [PATCH] jbd2: ini... |
592 593 |
continue; } |
f2a44523b jbd2: Unify log m... |
594 595 |
jbd_debug(4, "JBD2: got buffer %llu (%p) ", |
e5a120aeb jbd2: remove jour... |
596 597 |
(unsigned long long)descriptor->b_blocknr, descriptor->b_data); |
e5a120aeb jbd2: remove jour... |
598 599 600 |
tagp = &descriptor->b_data[sizeof(journal_header_t)]; space_left = descriptor->b_size - sizeof(journal_header_t); |
470decc61 [PATCH] jbd2: ini... |
601 |
first_tag = 1; |
e5a120aeb jbd2: remove jour... |
602 603 604 |
set_buffer_jwrite(descriptor); set_buffer_dirty(descriptor); wbuf[bufs++] = descriptor; |
470decc61 [PATCH] jbd2: ini... |
605 606 607 |
/* Record it so that we can wait for IO completion later */ |
e5a120aeb jbd2: remove jour... |
608 609 |
BUFFER_TRACE(descriptor, "ph3: file as descriptor"); jbd2_file_log_bh(&log_bufs, descriptor); |
470decc61 [PATCH] jbd2: ini... |
610 611 612 |
} /* Where is the buffer to be written? */ |
f7f4bccb7 [PATCH] jbd2: ren... |
613 |
err = jbd2_journal_next_log_block(journal, &blocknr); |
470decc61 [PATCH] jbd2: ini... |
614 615 616 617 |
/* If the block mapping failed, just abandon the buffer and repeat this loop: we'll fall into the refile-on-abort condition above. */ if (err) { |
a7fa2baf8 jbd2: fix commit ... |
618 |
jbd2_journal_abort(journal, err); |
470decc61 [PATCH] jbd2: ini... |
619 620 621 622 623 624 |
continue; } /* * start_this_handle() uses t_outstanding_credits to determine * the free space in the log, but this counter is changed |
f7f4bccb7 [PATCH] jbd2: ren... |
625 |
* by jbd2_journal_next_log_block() also. |
470decc61 [PATCH] jbd2: ini... |
626 |
*/ |
a51dca9cd jbd2: Use atomic ... |
627 |
atomic_dec(&commit_transaction->t_outstanding_credits); |
470decc61 [PATCH] jbd2: ini... |
628 629 630 |
/* Bump b_count to prevent truncate from stumbling over the shadowed buffer! @@@ This can go if we ever get |
f5113effc jbd2: don't creat... |
631 |
rid of the shadow pairing of buffers. */ |
470decc61 [PATCH] jbd2: ini... |
632 |
atomic_inc(&jh2bh(jh)->b_count); |
470decc61 [PATCH] jbd2: ini... |
633 |
/* |
f5113effc jbd2: don't creat... |
634 635 |
* Make a temporary IO buffer with which to write it out * (this will requeue the metadata buffer to BJ_Shadow). |
470decc61 [PATCH] jbd2: ini... |
636 |
*/ |
f5113effc jbd2: don't creat... |
637 |
set_bit(BH_JWrite, &jh2bh(jh)->b_state); |
470decc61 [PATCH] jbd2: ini... |
638 |
JBUFFER_TRACE(jh, "ph3: write metadata"); |
f7f4bccb7 [PATCH] jbd2: ren... |
639 |
flags = jbd2_journal_write_metadata_buffer(commit_transaction, |
f5113effc jbd2: don't creat... |
640 |
jh, &wbuf[bufs], blocknr); |
e6ec116b6 jbd2: Add ENOMEM ... |
641 642 643 644 |
if (flags < 0) { jbd2_journal_abort(journal, flags); continue; } |
f5113effc jbd2: don't creat... |
645 |
jbd2_file_log_bh(&io_bufs, wbuf[bufs]); |
470decc61 [PATCH] jbd2: ini... |
646 647 648 649 650 651 |
/* Record the new block's tag in the current descriptor buffer */ tag_flag = 0; if (flags & 1) |
f7f4bccb7 [PATCH] jbd2: ren... |
652 |
tag_flag |= JBD2_FLAG_ESCAPE; |
470decc61 [PATCH] jbd2: ini... |
653 |
if (!first_tag) |
f7f4bccb7 [PATCH] jbd2: ren... |
654 |
tag_flag |= JBD2_FLAG_SAME_UUID; |
470decc61 [PATCH] jbd2: ini... |
655 656 |
tag = (journal_block_tag_t *) tagp; |
db9ee2203 jbd2: fix descrip... |
657 |
write_tag_block(journal, tag, jh2bh(jh)->b_blocknr); |
8f888ef84 jbd2: change disk... |
658 |
tag->t_flags = cpu_to_be16(tag_flag); |
f5113effc jbd2: don't creat... |
659 |
jbd2_block_tag_csum_set(journal, tag, wbuf[bufs], |
c39008759 jbd2: checksum da... |
660 |
commit_transaction->t_tid); |
b517bea1c [PATCH] 64-bit jb... |
661 662 |
tagp += tag_bytes; space_left -= tag_bytes; |
f5113effc jbd2: don't creat... |
663 |
bufs++; |
470decc61 [PATCH] jbd2: ini... |
664 665 666 667 668 669 670 671 672 673 674 675 676 |
if (first_tag) { memcpy (tagp, journal->j_uuid, 16); tagp += 16; space_left -= 16; first_tag = 0; } /* If there's no more to do, or if the descriptor is full, let the IO rip! */ if (bufs == journal->j_wbufsize || commit_transaction->t_buffers == NULL || |
3caa487f5 jbd2: checksum de... |
677 |
space_left < tag_bytes + 16 + csum_size) { |
470decc61 [PATCH] jbd2: ini... |
678 |
|
f2a44523b jbd2: Unify log m... |
679 680 |
jbd_debug(4, "JBD2: Submit %d IOs ", bufs); |
470decc61 [PATCH] jbd2: ini... |
681 682 683 684 |
/* Write an end-of-descriptor marker before submitting the IOs. "tag" still points to the last tag we set up. */ |
8f888ef84 jbd2: change disk... |
685 |
tag->t_flags |= cpu_to_be16(JBD2_FLAG_LAST_TAG); |
470decc61 [PATCH] jbd2: ini... |
686 |
|
1101cd4d1 jbd2: unify revok... |
687 |
jbd2_descriptor_block_csum_set(journal, descriptor); |
470decc61 [PATCH] jbd2: ini... |
688 689 690 |
start_journal_io: for (i = 0; i < bufs; i++) { struct buffer_head *bh = wbuf[i]; |
818d276ce ext4: Add the jou... |
691 692 693 |
/* * Compute checksum. */ |
56316a0d2 jbd2: clean up fe... |
694 |
if (jbd2_has_feature_checksum(journal)) { |
818d276ce ext4: Add the jou... |
695 696 697 |
crc32_sum = jbd2_checksum_data(crc32_sum, bh); } |
470decc61 [PATCH] jbd2: ini... |
698 699 700 701 |
lock_buffer(bh); clear_buffer_dirty(bh); set_buffer_uptodate(bh); bh->b_end_io = journal_end_buffer_io_sync; |
82f04ab47 jbd2: finish conv... |
702 |
submit_bh(WRITE_SYNC, bh); |
470decc61 [PATCH] jbd2: ini... |
703 704 |
} cond_resched(); |
bf6993276 jbd2: Use tracepo... |
705 |
stats.run.rs_blocks_logged += bufs; |
470decc61 [PATCH] jbd2: ini... |
706 707 708 709 710 711 712 |
/* Force a new descriptor to be generated next time round the loop. */ descriptor = NULL; bufs = 0; } } |
f73bee498 jbd2: Modify ASYN... |
713 714 715 716 717 718 719 720 721 722 |
err = journal_finish_inode_data_buffers(journal, commit_transaction); if (err) { printk(KERN_WARNING "JBD2: Detected IO errors while flushing file data " "on %s ", journal->j_devname); if (journal->j_flags & JBD2_ABORT_ON_SYNCDATA_ERR) jbd2_journal_abort(journal, err); err = 0; } |
3339578f0 jbd2: cleanup jou... |
723 724 725 726 727 728 729 730 731 |
/* * Get current oldest transaction in the log before we issue flush * to the filesystem device. After the flush we can be sure that * blocks of all older transactions are checkpointed to persistent * storage and we will be safe to update journal start in the * superblock with the numbers we get here. */ update_tail = jbd2_journal_get_log_tail(journal, &first_tid, &first_block); |
bbd2be369 jbd2: Add functio... |
732 |
write_lock(&journal->j_state_lock); |
3339578f0 jbd2: cleanup jou... |
733 734 735 736 737 738 739 740 741 |
if (update_tail) { long freed = first_block - journal->j_tail; if (first_block < journal->j_tail) freed += journal->j_last - journal->j_first; /* Update tail only if we free significant amount of space */ if (freed < journal->j_maxlen / 4) update_tail = 0; } |
bbd2be369 jbd2: Add functio... |
742 743 744 |
J_ASSERT(commit_transaction->t_state == T_COMMIT); commit_transaction->t_state = T_COMMIT_DFLUSH; write_unlock(&journal->j_state_lock); |
3339578f0 jbd2: cleanup jou... |
745 |
|
cc3e1bea5 ext4, jbd2: Add b... |
746 747 748 749 750 |
/* * If the journal is not located on the file system device, * then we must flush the file system device before we issue * the commit record */ |
81be12c81 jbd2: fix sending... |
751 |
if (commit_transaction->t_need_data_flush && |
cc3e1bea5 ext4, jbd2: Add b... |
752 753 |
(journal->j_fs_dev != journal->j_dev) && (journal->j_flags & JBD2_BARRIER)) |
99aa78466 jbd2: use GFP_NOF... |
754 |
blkdev_issue_flush(journal->j_fs_dev, GFP_NOFS, NULL); |
818d276ce ext4: Add the jou... |
755 |
|
cc3e1bea5 ext4, jbd2: Add b... |
756 |
/* Done it all: now write the commit record asynchronously. */ |
56316a0d2 jbd2: clean up fe... |
757 |
if (jbd2_has_feature_async_commit(journal)) { |
818d276ce ext4: Add the jou... |
758 759 760 761 |
err = journal_submit_commit_record(journal, commit_transaction, &cbh, crc32_sum); if (err) __jbd2_journal_abort_hard(journal); |
e9e34f4e8 jbd2: don't abort... |
762 |
} |
c851ed540 jbd2: Implement d... |
763 |
|
82f04ab47 jbd2: finish conv... |
764 |
blk_finish_plug(&plug); |
470decc61 [PATCH] jbd2: ini... |
765 766 767 768 |
/* Lo and behold: we have just managed to send a transaction to the log. Before we can commit it, wait for the IO so far to complete. Control buffers being written are on the transaction's t_log_list queue, and metadata buffers are on |
f5113effc jbd2: don't creat... |
769 |
the io_bufs list. |
470decc61 [PATCH] jbd2: ini... |
770 771 772 773 774 |
Wait for the buffers in reverse order. That way we are less likely to be woken up until all IOs have completed, and so we incur less scheduling load. */ |
f2a44523b jbd2: Unify log m... |
775 776 |
jbd_debug(3, "JBD2: commit phase 3 "); |
470decc61 [PATCH] jbd2: ini... |
777 |
|
f5113effc jbd2: don't creat... |
778 779 780 781 |
while (!list_empty(&io_bufs)) { struct buffer_head *bh = list_entry(io_bufs.prev, struct buffer_head, b_assoc_buffers); |
470decc61 [PATCH] jbd2: ini... |
782 |
|
f5113effc jbd2: don't creat... |
783 784 |
wait_on_buffer(bh); cond_resched(); |
470decc61 [PATCH] jbd2: ini... |
785 786 787 |
if (unlikely(!buffer_uptodate(bh))) err = -EIO; |
f5113effc jbd2: don't creat... |
788 |
jbd2_unfile_log_bh(bh); |
470decc61 [PATCH] jbd2: ini... |
789 790 |
/* |
f5113effc jbd2: don't creat... |
791 792 |
* The list contains temporary buffer heads created by * jbd2_journal_write_metadata_buffer(). |
470decc61 [PATCH] jbd2: ini... |
793 794 |
*/ BUFFER_TRACE(bh, "dumping temporary bh"); |
470decc61 [PATCH] jbd2: ini... |
795 796 797 |
__brelse(bh); J_ASSERT_BH(bh, atomic_read(&bh->b_count) == 0); free_buffer_head(bh); |
f5113effc jbd2: don't creat... |
798 |
/* We also have to refile the corresponding shadowed buffer */ |
470decc61 [PATCH] jbd2: ini... |
799 800 |
jh = commit_transaction->t_shadow_list->b_tprev; bh = jh2bh(jh); |
f5113effc jbd2: don't creat... |
801 |
clear_buffer_jwrite(bh); |
470decc61 [PATCH] jbd2: ini... |
802 |
J_ASSERT_BH(bh, buffer_jbddirty(bh)); |
b34090e5e jbd2: refine wait... |
803 |
J_ASSERT_BH(bh, !buffer_shadow(bh)); |
470decc61 [PATCH] jbd2: ini... |
804 805 806 807 808 809 |
/* The metadata is now released for reuse, but we need to remember it against this transaction so that when we finally commit, we can do any checkpointing required. */ JBUFFER_TRACE(jh, "file as BJ_Forget"); |
f7f4bccb7 [PATCH] jbd2: ren... |
810 |
jbd2_journal_file_buffer(jh, commit_transaction, BJ_Forget); |
470decc61 [PATCH] jbd2: ini... |
811 812 813 814 815 |
JBUFFER_TRACE(jh, "brelse shadowed buffer"); __brelse(bh); } J_ASSERT (commit_transaction->t_shadow_list == NULL); |
f2a44523b jbd2: Unify log m... |
816 817 |
jbd_debug(3, "JBD2: commit phase 4 "); |
470decc61 [PATCH] jbd2: ini... |
818 819 |
/* Here we wait for the revoke record and descriptor record buffers */ |
e5a120aeb jbd2: remove jour... |
820 |
while (!list_empty(&log_bufs)) { |
470decc61 [PATCH] jbd2: ini... |
821 |
struct buffer_head *bh; |
e5a120aeb jbd2: remove jour... |
822 823 824 |
bh = list_entry(log_bufs.prev, struct buffer_head, b_assoc_buffers); wait_on_buffer(bh); cond_resched(); |
470decc61 [PATCH] jbd2: ini... |
825 826 827 828 829 830 |
if (unlikely(!buffer_uptodate(bh))) err = -EIO; BUFFER_TRACE(bh, "ph5: control buffer writeout done: unfile"); clear_buffer_jwrite(bh); |
e5a120aeb jbd2: remove jour... |
831 |
jbd2_unfile_log_bh(bh); |
470decc61 [PATCH] jbd2: ini... |
832 833 834 |
__brelse(bh); /* One for getblk */ /* AKPM: bforget here */ } |
77e841de8 jbd2: abort when ... |
835 836 |
if (err) jbd2_journal_abort(journal, err); |
f2a44523b jbd2: Unify log m... |
837 838 |
jbd_debug(3, "JBD2: commit phase 5 "); |
bbd2be369 jbd2: Add functio... |
839 840 841 842 |
write_lock(&journal->j_state_lock); J_ASSERT(commit_transaction->t_state == T_COMMIT_DFLUSH); commit_transaction->t_state = T_COMMIT_JFLUSH; write_unlock(&journal->j_state_lock); |
470decc61 [PATCH] jbd2: ini... |
843 |
|
56316a0d2 jbd2: clean up fe... |
844 |
if (!jbd2_has_feature_async_commit(journal)) { |
818d276ce ext4: Add the jou... |
845 846 847 848 849 |
err = journal_submit_commit_record(journal, commit_transaction, &cbh, crc32_sum); if (err) __jbd2_journal_abort_hard(journal); } |
6cba611e6 jbd2: fix potenti... |
850 |
if (cbh) |
fd98496f4 jbd2: Add barrier... |
851 |
err = journal_wait_on_commit_record(journal, cbh); |
56316a0d2 jbd2: clean up fe... |
852 |
if (jbd2_has_feature_async_commit(journal) && |
f73bee498 jbd2: Modify ASYN... |
853 |
journal->j_flags & JBD2_BARRIER) { |
99aa78466 jbd2: use GFP_NOF... |
854 |
blkdev_issue_flush(journal->j_dev, GFP_NOFS, NULL); |
f73bee498 jbd2: Modify ASYN... |
855 |
} |
470decc61 [PATCH] jbd2: ini... |
856 857 |
if (err) |
a7fa2baf8 jbd2: fix commit ... |
858 |
jbd2_journal_abort(journal, err); |
470decc61 [PATCH] jbd2: ini... |
859 |
|
3339578f0 jbd2: cleanup jou... |
860 861 862 863 864 865 866 |
/* * Now disk caches for filesystem device are flushed so we are safe to * erase checkpointed transactions from the log by updating journal * superblock. */ if (update_tail) jbd2_update_log_tail(journal, first_tid, first_block); |
470decc61 [PATCH] jbd2: ini... |
867 868 869 870 |
/* End of a transaction! Finally, we can do checkpoint processing: any buffers committed as a result of this transaction can be removed from any checkpoint list it was on before. */ |
f2a44523b jbd2: Unify log m... |
871 872 |
jbd_debug(3, "JBD2: commit phase 6 "); |
470decc61 [PATCH] jbd2: ini... |
873 |
|
c851ed540 jbd2: Implement d... |
874 |
J_ASSERT(list_empty(&commit_transaction->t_inode_list)); |
470decc61 [PATCH] jbd2: ini... |
875 876 |
J_ASSERT(commit_transaction->t_buffers == NULL); J_ASSERT(commit_transaction->t_checkpoint_list == NULL); |
470decc61 [PATCH] jbd2: ini... |
877 |
J_ASSERT(commit_transaction->t_shadow_list == NULL); |
470decc61 [PATCH] jbd2: ini... |
878 879 880 881 882 883 884 885 886 887 |
restart_loop: /* * As there are other places (journal_unmap_buffer()) adding buffers * to this list we have to be careful and hold the j_list_lock. */ spin_lock(&journal->j_list_lock); while (commit_transaction->t_forget) { transaction_t *cp_transaction; struct buffer_head *bh; |
de1b79413 jbd2: Fix oops in... |
888 |
int try_to_free = 0; |
470decc61 [PATCH] jbd2: ini... |
889 890 891 892 |
jh = commit_transaction->t_forget; spin_unlock(&journal->j_list_lock); bh = jh2bh(jh); |
de1b79413 jbd2: Fix oops in... |
893 894 895 896 897 |
/* * Get a reference so that bh cannot be freed before we are * done with it. */ get_bh(bh); |
470decc61 [PATCH] jbd2: ini... |
898 |
jbd_lock_bh_state(bh); |
23e2af351 jbd2: clean up an... |
899 |
J_ASSERT_JH(jh, jh->b_transaction == commit_transaction); |
470decc61 [PATCH] jbd2: ini... |
900 901 902 903 904 905 906 907 908 909 |
/* * If there is undo-protected committed data against * this buffer, then we can remove it now. If it is a * buffer needing such protection, the old frozen_data * field now points to a committed version of the * buffer, so rotate that field to the new committed * data. * * Otherwise, we can just throw away the frozen data now. |
e06c8227f jbd2: Add buffer ... |
910 911 912 |
* * We also know that the frozen data has already fired * its triggers if they exist, so we can clear that too. |
470decc61 [PATCH] jbd2: ini... |
913 914 |
*/ if (jh->b_committed_data) { |
af1e76d6b JBD2: jbd2 slab a... |
915 |
jbd2_free(jh->b_committed_data, bh->b_size); |
470decc61 [PATCH] jbd2: ini... |
916 917 918 919 |
jh->b_committed_data = NULL; if (jh->b_frozen_data) { jh->b_committed_data = jh->b_frozen_data; jh->b_frozen_data = NULL; |
e06c8227f jbd2: Add buffer ... |
920 |
jh->b_frozen_triggers = NULL; |
470decc61 [PATCH] jbd2: ini... |
921 922 |
} } else if (jh->b_frozen_data) { |
af1e76d6b JBD2: jbd2 slab a... |
923 |
jbd2_free(jh->b_frozen_data, bh->b_size); |
470decc61 [PATCH] jbd2: ini... |
924 |
jh->b_frozen_data = NULL; |
e06c8227f jbd2: Add buffer ... |
925 |
jh->b_frozen_triggers = NULL; |
470decc61 [PATCH] jbd2: ini... |
926 927 928 929 930 931 |
} spin_lock(&journal->j_list_lock); cp_transaction = jh->b_cp_transaction; if (cp_transaction) { JBUFFER_TRACE(jh, "remove from old cp transaction"); |
8e85fb3f3 jbd2: jbd2 stats ... |
932 |
cp_transaction->t_chp_stats.cs_dropped++; |
f7f4bccb7 [PATCH] jbd2: ren... |
933 |
__jbd2_journal_remove_checkpoint(jh); |
470decc61 [PATCH] jbd2: ini... |
934 935 936 937 |
} /* Only re-checkpoint the buffer_head if it is marked * dirty. If the buffer was added to the BJ_Forget list |
f7f4bccb7 [PATCH] jbd2: ren... |
938 |
* by jbd2_journal_forget, it may no longer be dirty and |
470decc61 [PATCH] jbd2: ini... |
939 940 |
* there's no point in keeping a checkpoint record for * it. */ |
b794e7a6e jbd2: fix asserti... |
941 942 943 944 945 946 947 948 949 950 951 952 953 954 955 956 957 958 959 960 961 962 963 964 965 966 967 968 969 |
/* * A buffer which has been freed while still being journaled by * a previous transaction. */ if (buffer_freed(bh)) { /* * If the running transaction is the one containing * "add to orphan" operation (b_next_transaction != * NULL), we have to wait for that transaction to * commit before we can really get rid of the buffer. * So just clear b_modified to not confuse transaction * credit accounting and refile the buffer to * BJ_Forget of the running transaction. If the just * committed transaction contains "add to orphan" * operation, we can completely invalidate the buffer * now. We are rather through in that since the * buffer may be still accessible when blocksize < * pagesize and it is attached to the last partial * page. */ jh->b_modified = 0; if (!jh->b_next_transaction) { clear_buffer_freed(bh); clear_buffer_jbddirty(bh); clear_buffer_mapped(bh); clear_buffer_new(bh); clear_buffer_req(bh); bh->b_bdev = NULL; } |
470decc61 [PATCH] jbd2: ini... |
970 971 972 973 |
} if (buffer_jbddirty(bh)) { JBUFFER_TRACE(jh, "add to new checkpointing trans"); |
f7f4bccb7 [PATCH] jbd2: ren... |
974 |
__jbd2_journal_insert_checkpoint(jh, commit_transaction); |
7ad7445f6 jbd2: don't dirty... |
975 976 |
if (is_journal_aborted(journal)) clear_buffer_jbddirty(bh); |
470decc61 [PATCH] jbd2: ini... |
977 978 |
} else { J_ASSERT_BH(bh, !buffer_dirty(bh)); |
de1b79413 jbd2: Fix oops in... |
979 980 |
/* * The buffer on BJ_Forget list and not jbddirty means |
470decc61 [PATCH] jbd2: ini... |
981 982 983 984 985 |
* it has been freed by this transaction and hence it * could not have been reallocated until this * transaction has committed. *BUT* it could be * reallocated once we have written all the data to * disk and before we process the buffer on BJ_Forget |
de1b79413 jbd2: Fix oops in... |
986 987 988 989 |
* list. */ if (!jh->b_next_transaction) try_to_free = 1; |
470decc61 [PATCH] jbd2: ini... |
990 |
} |
de1b79413 jbd2: Fix oops in... |
991 992 993 994 995 996 997 |
JBUFFER_TRACE(jh, "refile or unfile buffer"); __jbd2_journal_refile_buffer(jh); jbd_unlock_bh_state(bh); if (try_to_free) release_buffer_page(bh); /* Drops bh reference */ else __brelse(bh); |
470decc61 [PATCH] jbd2: ini... |
998 999 1000 1001 |
cond_resched_lock(&journal->j_list_lock); } spin_unlock(&journal->j_list_lock); /* |
f5a7a6b0d jbd2: Fix asserti... |
1002 1003 1004 1005 |
* This is a bit sleazy. We use j_list_lock to protect transition * of a transaction into T_FINISHED state and calling * __jbd2_journal_drop_transaction(). Otherwise we could race with * other checkpointing code processing the transaction... |
470decc61 [PATCH] jbd2: ini... |
1006 |
*/ |
a931da6ac jbd2: Change j_st... |
1007 |
write_lock(&journal->j_state_lock); |
470decc61 [PATCH] jbd2: ini... |
1008 1009 1010 1011 1012 1013 1014 |
spin_lock(&journal->j_list_lock); /* * Now recheck if some buffers did not get attached to the transaction * while the lock was dropped... */ if (commit_transaction->t_forget) { spin_unlock(&journal->j_list_lock); |
a931da6ac jbd2: Change j_st... |
1015 |
write_unlock(&journal->j_state_lock); |
470decc61 [PATCH] jbd2: ini... |
1016 1017 |
goto restart_loop; } |
d4e839d4a jbd2: add transac... |
1018 1019 1020 1021 1022 1023 1024 1025 1026 1027 1028 1029 1030 1031 1032 1033 1034 1035 |
/* Add the transaction to the checkpoint list * __journal_remove_checkpoint() can not destroy transaction * under us because it is not marked as T_FINISHED yet */ if (journal->j_checkpoint_transactions == NULL) { journal->j_checkpoint_transactions = commit_transaction; commit_transaction->t_cpnext = commit_transaction; commit_transaction->t_cpprev = commit_transaction; } else { commit_transaction->t_cpnext = journal->j_checkpoint_transactions; commit_transaction->t_cpprev = commit_transaction->t_cpnext->t_cpprev; commit_transaction->t_cpnext->t_cpprev = commit_transaction; commit_transaction->t_cpprev->t_cpnext = commit_transaction; } spin_unlock(&journal->j_list_lock); |
470decc61 [PATCH] jbd2: ini... |
1036 |
/* Done with this transaction! */ |
f2a44523b jbd2: Unify log m... |
1037 1038 |
jbd_debug(3, "JBD2: commit phase 7 "); |
470decc61 [PATCH] jbd2: ini... |
1039 |
|
bbd2be369 jbd2: Add functio... |
1040 |
J_ASSERT(commit_transaction->t_state == T_COMMIT_JFLUSH); |
470decc61 [PATCH] jbd2: ini... |
1041 |
|
8e85fb3f3 jbd2: jbd2 stats ... |
1042 |
commit_transaction->t_start = jiffies; |
bf6993276 jbd2: Use tracepo... |
1043 1044 |
stats.run.rs_logging = jbd2_time_diff(stats.run.rs_logging, commit_transaction->t_start); |
8e85fb3f3 jbd2: jbd2 stats ... |
1045 1046 |
/* |
bf6993276 jbd2: Use tracepo... |
1047 |
* File the transaction statistics |
8e85fb3f3 jbd2: jbd2 stats ... |
1048 |
*/ |
8e85fb3f3 jbd2: jbd2 stats ... |
1049 |
stats.ts_tid = commit_transaction->t_tid; |
8dd420466 jbd2: Remove t_ha... |
1050 1051 |
stats.run.rs_handle_count = atomic_read(&commit_transaction->t_handle_count); |
bf6993276 jbd2: Use tracepo... |
1052 1053 |
trace_jbd2_run_stats(journal->j_fs_dev->bd_dev, commit_transaction->t_tid, &stats.run); |
42cf3452d jbd2: calculate s... |
1054 |
stats.ts_requested = (commit_transaction->t_requested) ? 1 : 0; |
8e85fb3f3 jbd2: jbd2 stats ... |
1055 |
|
794446c69 jbd2: fix race be... |
1056 |
commit_transaction->t_state = T_COMMIT_CALLBACK; |
470decc61 [PATCH] jbd2: ini... |
1057 1058 1059 |
J_ASSERT(commit_transaction == journal->j_committing_transaction); journal->j_commit_sequence = commit_transaction->t_tid; journal->j_committing_transaction = NULL; |
e07f7183a jbd2: improve jbd... |
1060 |
commit_time = ktime_to_ns(ktime_sub(ktime_get(), start_time)); |
470decc61 [PATCH] jbd2: ini... |
1061 |
|
e07f7183a jbd2: improve jbd... |
1062 1063 1064 1065 1066 1067 1068 1069 1070 |
/* * weight the commit time higher than the average time so we don't * react too strongly to vast changes in the commit time */ if (likely(journal->j_average_commit_time)) journal->j_average_commit_time = (commit_time + journal->j_average_commit_time*3) / 4; else journal->j_average_commit_time = commit_time; |
794446c69 jbd2: fix race be... |
1071 |
|
a931da6ac jbd2: Change j_st... |
1072 |
write_unlock(&journal->j_state_lock); |
6c20ec850 jbd2: Call the co... |
1073 |
|
fb68407b0 jbd2: Call journa... |
1074 1075 |
if (journal->j_commit_callback) journal->j_commit_callback(journal, commit_transaction); |
879c5e6b7 jbd2: convert ins... |
1076 |
trace_jbd2_end_commit(journal, commit_transaction); |
f2a44523b jbd2: Unify log m... |
1077 1078 |
jbd_debug(1, "JBD2: commit %d complete, head %d ", |
470decc61 [PATCH] jbd2: ini... |
1079 |
journal->j_commit_sequence, journal->j_tail_sequence); |
794446c69 jbd2: fix race be... |
1080 1081 1082 |
write_lock(&journal->j_state_lock); spin_lock(&journal->j_list_lock); commit_transaction->t_state = T_FINISHED; |
d4e839d4a jbd2: add transac... |
1083 |
/* Check if the transaction can be dropped now that we are finished */ |
794446c69 jbd2: fix race be... |
1084 1085 1086 1087 1088 1089 1090 |
if (commit_transaction->t_checkpoint_list == NULL && commit_transaction->t_checkpoint_io_list == NULL) { __jbd2_journal_drop_transaction(journal, commit_transaction); jbd2_journal_free_transaction(commit_transaction); } spin_unlock(&journal->j_list_lock); write_unlock(&journal->j_state_lock); |
470decc61 [PATCH] jbd2: ini... |
1091 |
wake_up(&journal->j_wait_done_commit); |
42cf3452d jbd2: calculate s... |
1092 1093 1094 1095 1096 1097 1098 1099 1100 1101 1102 1103 1104 1105 1106 1107 1108 |
/* * Calculate overall stats */ spin_lock(&journal->j_history_lock); journal->j_stats.ts_tid++; journal->j_stats.ts_requested += stats.ts_requested; journal->j_stats.run.rs_wait += stats.run.rs_wait; journal->j_stats.run.rs_request_delay += stats.run.rs_request_delay; journal->j_stats.run.rs_running += stats.run.rs_running; journal->j_stats.run.rs_locked += stats.run.rs_locked; journal->j_stats.run.rs_flushing += stats.run.rs_flushing; journal->j_stats.run.rs_logging += stats.run.rs_logging; journal->j_stats.run.rs_handle_count += stats.run.rs_handle_count; journal->j_stats.run.rs_blocks += stats.run.rs_blocks; journal->j_stats.run.rs_blocks_logged += stats.run.rs_blocks_logged; spin_unlock(&journal->j_history_lock); |
470decc61 [PATCH] jbd2: ini... |
1109 |
} |