| Start/ | End/ | |||
| True | False | - | Line | Source |
| 1 | /* | |||
| 2 | * linux/fs/commit.c | |||
| 3 | * | |||
| 4 | * Written by Stephen C. Tweedie <sct@redhat.com>, 1998 | |||
| 5 | * | |||
| 6 | * Copyright 1998 Red Hat corp --- All Rights Reserved | |||
| 7 | * | |||
| 8 | * This file is part of the Linux kernel and is made available under | |||
| 9 | * the terms of the GNU General Public License, version 2, or at your | |||
| 10 | * option, any later version, incorporated herein by reference. | |||
| 11 | * | |||
| 12 | * Journal commit routines for the generic filesystem journaling code; | |||
| 13 | * part of the ext2fs journaling system. | |||
| 14 | */ | |||
| 15 | ||||
| 16 | #include <linux/time.h> | |||
| 17 | #include <linux/fs.h> | |||
| 18 | #include <linux/jbd.h> | |||
| 19 | #include <linux/errno.h> | |||
| 20 | #include <linux/slab.h> | |||
| 21 | #include <linux/mm.h> | |||
| 22 | #include <linux/pagemap.h> | |||
| 23 | #include <linux/smp_lock.h> | |||
| 24 | ||||
| 25 | /* | |||
| 26 | * Default IO end handler for temporary BJ_IO buffer_heads. | |||
| 27 | */ | |||
| 204070 | 204070 | 28 | static void journal_end_buffer_io_sync(struct buffer_head *bh, int uptodate) | |
| 29 | { | |||
| 30 | BUFFER_TRACE(bh, ""); | |||
| 0 | 204070 | - | 30 | do-while (0) |
| 204070 | 0 | - | 31 | if (uptodate) |
| 32 | set_buffer_uptodate(bh); | |||
| 33 | else | |||
| 34 | clear_buffer_uptodate(bh); | |||
| 35 | unlock_buffer(bh); | |||
| 36 | } | |||
| 37 | ||||
| 38 | /* | |||
| 39 | * When an ext3-ordered file is truncated, it is possible that many pages are | |||
| 40 | * not sucessfully freed, because they are attached to a committing transaction. | |||
| 41 | * After the transaction commits, these pages are left on the LRU, with no | |||
| 42 | * ->mapping, and with attached buffers. These pages are trivially reclaimable | |||
| 43 | * by the VM, but their apparent absence upsets the VM accounting, and it makes | |||
| 44 | * the numbers in /proc/meminfo look odd. | |||
| 45 | * | |||
| 46 | * So here, we have a buffer which has just come off the forget list. Look to | |||
| 47 | * see if we can strip all buffers from the backing page. | |||
| 48 | * | |||
| 49 | * Called under lock_journal(), and possibly under journal_datalist_lock. The | |||
| 50 | * caller provided us with a ref against the buffer, and we drop that here. | |||
| 51 | */ | |||
| 3008 | 3008 | 52 | static void release_buffer_page(struct buffer_head *bh) | |
| 53 | { | |||
| 54 | struct page *page; | |||
| 55 | ||||
| 0 | 3008 | - | 56 | if (buffer_dirty(bh)) |
| 0 | - | 57 | goto nope; | |
| 21 | 2987 | 58 | if (atomic_read(&bh->b_count) != 1) | |
| 21 | 59 | goto nope; | ||
| 60 | page = bh->b_page; | |||
| 0 | 2987 | - | 61 | if (!page) |
| 0 | - | 62 | goto nope; | |
| 2987 | 0 | - | 63 | if (page->mapping) |
| 2987 | 64 | goto nope; | ||
| 65 | ||||
| 66 | /* OK, it's a truncated page */ | |||
| 0 | 0 | - | 67 | if (TestSetPageLocked(page)) |
| 0 | - | 68 | goto nope; | |
| 69 | ||||
| 70 | page_cache_get(page); | |||
| 71 | __brelse(bh); | |||
| 72 | try_to_free_buffers(page); | |||
| 73 | unlock_page(page); | |||
| 74 | page_cache_release(page); | |||
| 0 | - | 75 | return; | |
| 76 | ||||
| 77 | nope: | |||
| 78 | __brelse(bh); | |||
| 79 | } | |||
| 80 | ||||
| 81 | /* | |||
| 82 | * Try to acquire jbd_lock_bh_state() against the buffer, when j_list_lock is | |||
| 83 | * held. For ranking reasons we must trylock. If we lose, schedule away and | |||
| 84 | * return 0. j_list_lock is dropped in this case. | |||
| 85 | */ | |||
| 3107E3 | 0 | 86 | static int inverted_lock(journal_t *journal, struct buffer_head *bh) | |
| 87 | { | |||
| 0 | 3107E3 | - | 88 | if (!jbd_trylock_bh_state(bh)) { |
| 89 | spin_unlock(&journal->j_list_lock); | |||
| 89 | do | |||
| 0 | 0 | - | 89 | do-while (0) |
| 0 | 0 | - | 89 | do-while (0) |
| 90 | schedule(); | |||
| 0 | - | 91 | return 0; | |
| 92 | } | |||
| 3107E3 | 93 | return 1; | ||
| 94 | } | |||
| 95 | ||||
| 96 | /* Done it all: now write the commit record. We should have | |||
| 97 | * cleaned up our previous buffers by now, so if we are in abort | |||
| 98 | * mode we can now just skip the rest of the journal write | |||
| 99 | * entirely. | |||
| 100 | * | |||
| 101 | * Returns 1 if the journal needs to be aborted or 0 on success | |||
| 102 | */ | |||
| 14905 | 0 | 103 | static int journal_write_commit_record(journal_t *journal, | |
| 104 | transaction_t *commit_transaction) | |||
| 105 | { | |||
| 106 | struct journal_head *descriptor; | |||
| 107 | struct buffer_head *bh; | |||
| 108 | int i, ret; | |||
| 109 | int barrier_done = 0; | |||
| 110 | ||||
| 0 | 14905 | - | 111 | if (is_journal_aborted(journal)) |
| 0 | - | 112 | return 0; | |
| 113 | ||||
| 114 | descriptor = journal_get_descriptor_buffer(journal); | |||
| 0 | 14905 | - | 115 | if (!descriptor) |
| 0 | - | 116 | return 1; | |
| 117 | ||||
| 118 | bh = jh2bh(descriptor); | |||
| 119 | ||||
| 120 | /* AKPM: buglet - add `i' to tmp! */ | |||
| 119240 | 14905 | 121 | for (i = 0; i < bh->b_size; i += 512) { | |
| 122 | journal_header_t *tmp = (journal_header_t*)bh->b_data; | |||
| 123 | tmp->h_magic = cpu_to_be32(JFS_MAGIC_NUMBER); | |||
| 119240 | 0 | - | 123 | ternary-?: __builtin_constant_p ( ( __u32 ) .. |
| 124 | tmp->h_blocktype = cpu_to_be32(JFS_COMMIT_BLOCK); | |||
| 119240 | 0 | - | 124 | ternary-?: __builtin_constant_p ( ( __u32 ) .. |
| 125 | tmp->h_sequence = cpu_to_be32(commit_transaction->t_tid); | |||
| 0 | 119240 | - | 125 | ternary-?: __builtin_constant_p ( ( __u32 ) .. |
| 126 | } | |||
| 127 | ||||
| 128 | JBUFFER_TRACE(descriptor, "write commit block"); | |||
| 0 | 14905 | - | 128 | do-while (0) |
| 129 | set_buffer_dirty(bh); | |||
| 0 | 14905 | - | 130 | if (journal->j_flags & JFS_BARRIER) { |
| 131 | set_buffer_ordered(bh); | |||
| 132 | barrier_done = 1; | |||
| 133 | } | |||
| 134 | ret = sync_dirty_buffer(bh); | |||
| 135 | /* is it possible for another commit to fail at roughly | |||
| 136 | * the same time as this one? If so, we don't want to | |||
| 137 | * trust the barrier flag in the super, but instead want | |||
| 138 | * to remember if we sent a barrier request | |||
| 139 | */ | |||
| 0 | 14905 | - | 140 | if (ret == -EOPNOTSUPP && barrier_done) { |
| 0 | - | 140 | T && T | |
| 0 | - | 140 | T && F | |
| 14905 | 140 | F && _ | ||
| 141 | char b[BDEVNAME_SIZE]; | |||
| 142 | ||||
| 143 | printk(KERN_WARNING | |||
| 144 | "JBD: barrier-based sync failed on %s - " | |||
| 145 | "disabling barriers\n", | |||
| 146 | bdevname(journal->j_dev, b)); | |||
| 147 | spin_lock(&journal->j_state_lock); | |||
| 147 | do | |||
| 0 | 0 | - | 147 | do-while (0) |
| 0 | 0 | - | 147 | do-while (0) |
| 148 | journal->j_flags &= ~JFS_BARRIER; | |||
| 149 | spin_unlock(&journal->j_state_lock); | |||
| 149 | do | |||
| 0 | 0 | - | 149 | do-while (0) |
| 0 | 0 | - | 149 | do-while (0) |
| 150 | ||||
| 151 | /* And try again, without the barrier */ | |||
| 152 | clear_buffer_ordered(bh); | |||
| 153 | set_buffer_uptodate(bh); | |||
| 154 | set_buffer_dirty(bh); | |||
| 155 | ret = sync_dirty_buffer(bh); | |||
| 156 | } | |||
| 157 | put_bh(bh); /* One for getblk() */ | |||
| 158 | journal_put_journal_head(descriptor); | |||
| 159 | ||||
| 14905 | 160 | return (ret == -EIO); | ||
| 161 | } | |||
| 162 | ||||
| 163 | /* | |||
| 164 | * journal_commit_transaction | |||
| 165 | * | |||
| 166 | * The primary function for committing a transaction to the log. This | |||
| 167 | * function is called by the journal thread to begin a complete commit. | |||
| 168 | */ | |||
| 14905 | 14905 | 169 | void journal_commit_transaction(journal_t *journal) | |
| 170 | { | |||
| 171 | transaction_t *commit_transaction; | |||
| 172 | struct journal_head *jh, *new_jh, *descriptor; | |||
| 173 | struct buffer_head **wbuf = journal->j_wbuf; | |||
| 174 | int bufs; | |||
| 175 | int flags; | |||
| 176 | int err; | |||
| 177 | unsigned long blocknr; | |||
| 178 | char *tagp = NULL; | |||
| 179 | journal_header_t *header; | |||
| 180 | journal_block_tag_t *tag = NULL; | |||
| 181 | int space_left = 0; | |||
| 182 | int first_tag = 0; | |||
| 183 | int tag_flag; | |||
| 184 | int i; | |||
| 185 | ||||
| 186 | /* | |||
| 187 | * First job: lock down the current transaction and wait for | |||
| 188 | * all outstanding updates to complete. | |||
| 189 | */ | |||
| 190 | ||||
| 191 | #ifdef COMMIT_STATS | |||
| 192 | spin_lock(&journal->j_list_lock); | |||
| 193 | summarise_journal_usage(journal); | |||
| 194 | spin_unlock(&journal->j_list_lock); | |||
| 195 | #endif | |||
| 196 | ||||
| 197 | /* Do we need to erase the effects of a prior journal_flush? */ | |||
| 6 | 14899 | 198 | if (journal->j_flags & JFS_FLUSHED) { | |
| 199 | jbd_debug(3, "super block updated\n"); | |||
| 200 | journal_update_superblock(journal, 1); | |||
| 201 | } else { | |||
| 202 | jbd_debug(3, "superblock not updated\n"); | |||
| 203 | } | |||
| 204 | ||||
| 205 | J_ASSERT(journal->j_running_transaction != NULL); | |||
| 0 | 14905 | - | 205 | if (! ( journal -> j_running_transaction != .. |
| 0 | 14905 | - | 205 | do-while (0) |
| 206 | J_ASSERT(journal->j_committing_transaction == NULL); | |||
| 0 | 14905 | - | 206 | if (! ( journal -> j_committing_transaction .. |
| 0 | 14905 | - | 206 | do-while (0) |
| 207 | ||||
| 208 | commit_transaction = journal->j_running_transaction; | |||
| 209 | J_ASSERT(commit_transaction->t_state == T_RUNNING); | |||
| 0 | 14905 | - | 209 | if (! ( commit_transaction -> t_state == T_R.. |
| 0 | 14905 | - | 209 | do-while (0) |
| 210 | ||||
| 211 | jbd_debug(1, "JBD: starting commit of transaction %d\n", | |||
| 212 | commit_transaction->t_tid); | |||
| 213 | ||||
| 214 | spin_lock(&journal->j_state_lock); | |||
| 214 | do | |||
| 0 | 14905 | - | 214 | do-while (0) |
| 0 | 14905 | - | 214 | do-while (0) |
| 215 | commit_transaction->t_state = T_LOCKED; | |||
| 216 | ||||
| 217 | spin_lock(&commit_transaction->t_handle_lock); | |||
| 217 | do | |||
| 0 | 14905 | - | 217 | do-while (0) |
| 0 | 14905 | - | 217 | do-while (0) |
| 1510 | 14905 | 218 | while (commit_transaction->t_updates) { | |
| 219 | DEFINE_WAIT(wait); | |||
| 220 | ||||
| 221 | prepare_to_wait(&journal->j_wait_updates, &wait, | |||
| 222 | TASK_UNINTERRUPTIBLE); | |||
| 1510 | 0 | - | 223 | if (commit_transaction->t_updates) { |
| 224 | spin_unlock(&commit_transaction->t_handle_lock); | |||
| 224 | do | |||
| 0 | 1510 | - | 224 | do-while (0) |
| 0 | 1510 | - | 224 | do-while (0) |
| 225 | spin_unlock(&journal->j_state_lock); | |||
| 225 | do | |||
| 0 | 1510 | - | 225 | do-while (0) |
| 0 | 1510 | - | 225 | do-while (0) |
| 226 | schedule(); | |||
| 227 | spin_lock(&journal->j_state_lock); | |||
| 227 | do | |||
| 0 | 1510 | - | 227 | do-while (0) |
| 0 | 1510 | - | 227 | do-while (0) |
| 228 | spin_lock(&commit_transaction->t_handle_lock); | |||
| 228 | do | |||
| 0 | 1510 | - | 228 | do-while (0) |
| 0 | 1510 | - | 228 | do-while (0) |
| 229 | } | |||
| 230 | finish_wait(&journal->j_wait_updates, &wait); | |||
| 231 | } | |||
| 232 | spin_unlock(&commit_transaction->t_handle_lock); | |||
| 232 | do | |||
| 0 | 14905 | - | 232 | do-while (0) |
| 0 | 14905 | - | 232 | do-while (0) |
| 233 | ||||
| 234 | J_ASSERT (commit_transaction->t_outstanding_credits <= | |||
| 0 | 14905 | - | 234 | if (! ( commit_transaction -> t_outstanding_.. |
| 0 | 14905 | - | 234 | do-while (0) |
| 235 | journal->j_max_transaction_buffers); | |||
| 236 | ||||
| 237 | /* | |||
| 238 | * First thing we are allowed to do is to discard any remaining | |||
| 239 | * BJ_Reserved buffers. Note, it is _not_ permissible to assume | |||
| 240 | * that there are no such buffers: if a large filesystem | |||
| 241 | * operation like a truncate needs to split itself over multiple | |||
| 242 | * transactions, then it may try to do a journal_restart() while | |||
| 243 | * there are still BJ_Reserved buffers outstanding. These must | |||
| 244 | * be released cleanly from the current transaction. | |||
| 245 | * | |||
| 246 | * In this case, the filesystem must still reserve write access | |||
| 247 | * again before modifying the buffer in the new transaction, but | |||
| 248 | * we do not require it to remember exactly which old buffers it | |||
| 249 | * has reserved. This is consistent with the existing behaviour | |||
| 250 | * that multiple journal_get_write_access() calls to the same | |||
| 251 | * buffer are perfectly permissable. | |||
| 252 | */ | |||
| 3443 | 14905 | 253 | while (commit_transaction->t_reserved_list) { | |
| 254 | jh = commit_transaction->t_reserved_list; | |||
| 255 | JBUFFER_TRACE(jh, "reserved, unused: refile"); | |||
| 0 | 3443 | - | 255 | do-while (0) |
| 256 | /* | |||
| 257 | * A journal_get_undo_access()+journal_release_buffer() may | |||
| 258 | * leave undo-committed data. | |||
| 259 | */ | |||
| 3443 | 0 | - | 260 | if (jh->b_committed_data) { |
| 261 | struct buffer_head *bh = jh2bh(jh); | |||
| 262 | ||||
| 263 | jbd_lock_bh_state(bh); | |||
| 264 | kfree(jh->b_committed_data); | |||
| 265 | jh->b_committed_data = NULL; | |||
| 266 | jbd_unlock_bh_state(bh); | |||
| 267 | } | |||
| 268 | journal_refile_buffer(journal, jh); | |||
| 269 | } | |||
| 270 | ||||
| 271 | /* | |||
| 272 | * Now try to drop any written-back buffers from the journal's | |||
| 273 | * checkpoint lists. We do this *before* commit because it potentially | |||
| 274 | * frees some memory | |||
| 275 | */ | |||
| 276 | spin_lock(&journal->j_list_lock); | |||
| 276 | do | |||
| 0 | 14905 | - | 276 | do-while (0) |
| 0 | 14905 | - | 276 | do-while (0) |
| 277 | __journal_clean_checkpoint_list(journal); | |||
| 278 | spin_unlock(&journal->j_list_lock); | |||
| 278 | do | |||
| 0 | 14905 | - | 278 | do-while (0) |
| 0 | 14905 | - | 278 | do-while (0) |
| 279 | ||||
| 280 | jbd_debug (3, "JBD: commit phase 1\n"); | |||
| 281 | ||||
| 282 | /* | |||
| 283 | * Switch to a new revoke table. | |||
| 284 | */ | |||
| 285 | journal_switch_revoke_table(journal); | |||
| 286 | ||||
| 287 | commit_transaction->t_state = T_FLUSH; | |||
| 288 | journal->j_committing_transaction = commit_transaction; | |||
| 289 | journal->j_running_transaction = NULL; | |||
| 290 | commit_transaction->t_log_start = journal->j_head; | |||
| 291 | wake_up(&journal->j_wait_transaction_locked); | |||
| 292 | spin_unlock(&journal->j_state_lock); | |||
| 292 | do | |||
| 0 | 14905 | - | 292 | do-while (0) |
| 0 | 14905 | - | 292 | do-while (0) |
| 293 | ||||
| 294 | jbd_debug (3, "JBD: commit phase 2\n"); | |||
| 295 | ||||
| 296 | /* | |||
| 297 | * First, drop modified flag: all accesses to the buffers | |||
| 298 | * will be tracked for a new trasaction only -bzzz | |||
| 299 | */ | |||
| 300 | spin_lock(&journal->j_list_lock); | |||
| 300 | do | |||
| 0 | 14905 | - | 300 | do-while (0) |
| 0 | 14905 | - | 300 | do-while (0) |
| 12510 | 2395 | 301 | if (commit_transaction->t_buffers) { | |
| 302 | new_jh = jh = commit_transaction->t_buffers->b_tnext; | |||
| 303 | do { | |||
| 304 | J_ASSERT_JH(new_jh, new_jh->b_modified == 1 || | |||
| 0 | 191527 | - | 304 | if (! ( new_jh -> b_modified == 1 || new.. |
| 0 | - | 304 | !(F || F) | |
| 191065 | 304 | !(T || _) | ||
| 462 | 304 | !(F || T) | ||
| 0 | 191527 | - | 304 | do-while (0) |
| 305 | new_jh->b_modified == 0); | |||
| 306 | new_jh->b_modified = 0; | |||
| 307 | new_jh = new_jh->b_tnext; | |||
| 179017 | 12510 | 308 | } while (new_jh != jh); | |
| 309 | } | |||
| 310 | spin_unlock(&journal->j_list_lock); | |||
| 310 | do | |||
| 0 | 14905 | - | 310 | do-while (0) |
| 0 | 14905 | - | 310 | do-while (0) |
| 311 | ||||
| 312 | /* | |||
| 313 | * Now start flushing things to disk, in the order they appear | |||
| 314 | * on the transaction lists. Data blocks go first. | |||
| 315 | */ | |||
| 316 | ||||
| 317 | err = 0; | |||
| 318 | /* | |||
| 319 | * Whenever we unlock the journal and sleep, things can get added | |||
| 320 | * onto ->t_sync_datalist, so we have to keep looping back to | |||
| 321 | * write_out_data until we *know* that the list is empty. | |||
| 322 | */ | |||
| 323 | bufs = 0; | |||
| 324 | /* | |||
| 325 | * Cleanup any flushed data buffers from the data list. Even in | |||
| 326 | * abort mode, we want to flush this out as soon as possible. | |||
| 327 | */ | |||
| 328 | write_out_data: | |||
| 329 | cond_resched(); | |||
| 330 | spin_lock(&journal->j_list_lock); | |||
| 330 | do | |||
| 0 | 26370 | - | 330 | do-while (0) |
| 0 | 26370 | - | 330 | do-while (0) |
| 331 | ||||
| 8431E3 | 14905 | 332 | while (commit_transaction->t_sync_datalist) { | |
| 333 | struct buffer_head *bh; | |||
| 334 | ||||
| 335 | jh = commit_transaction->t_sync_datalist; | |||
| 336 | commit_transaction->t_sync_datalist = jh->b_tnext; | |||
| 337 | bh = jh2bh(jh); | |||
| 477455 | 7954E3 | 338 | if (buffer_locked(bh)) { | |
| 339 | BUFFER_TRACE(bh, "locked"); | |||
| 0 | 477455 | - | 339 | do-while (0) |
| 0 | 477455 | - | 340 | if (!inverted_lock(journal, bh)) |
| 0 | - | 341 | goto write_out_data; | |
| 342 | __journal_temp_unlink_buffer(jh); | |||
| 343 | __journal_file_buffer(jh, commit_transaction, | |||
| 344 | BJ_Locked); | |||
| 345 | jbd_unlock_bh_state(bh); | |||
| 33 | 477422 | 346 | if (lock_need_resched(&journal->j_list_lock)) { | |
| 347 | spin_unlock(&journal->j_list_lock); | |||
| 347 | do | |||
| 0 | 33 | - | 347 | do-while (0) |
| 0 | 33 | - | 347 | do-while (0) |
| 33 | 348 | goto write_out_data; | ||
| 349 | } | |||
| 350 | } else { | |||
| 5760E3 | 2193E3 | 351 | if (buffer_dirty(bh)) { | |
| 352 | BUFFER_TRACE(bh, "start journal writeout"); | |||
| 0 | 5760E3 | - | 352 | do-while (0) |
| 353 | get_bh(bh); | |||
| 354 | wbuf[bufs++] = bh; | |||
| 11251 | 5749E3 | 355 | if (bufs == journal->j_wbufsize) { | |
| 356 | jbd_debug(2, "submit %d writes\n", | |||
| 357 | bufs); | |||
| 358 | spin_unlock(&journal->j_list_lock); | |||
| 358 | do | |||
| 0 | 11251 | - | 358 | do-while (0) |
| 0 | 11251 | - | 358 | do-while (0) |
| 359 | ll_rw_block(SWRITE, bufs, wbuf); | |||
| 360 | journal_brelse_array(wbuf, bufs); | |||
| 361 | bufs = 0; | |||
| 11251 | 362 | goto write_out_data; | ||
| 363 | } | |||
| 364 | } else { | |||
| 365 | BUFFER_TRACE(bh, "writeout complete: unfile"); | |||
| 0 | 2193E3 | - | 365 | do-while (0) |
| 0 | 2193E3 | - | 366 | if (!inverted_lock(journal, bh)) |
| 0 | - | 367 | goto write_out_data; | |
| 368 | __journal_unfile_buffer(jh); | |||
| 369 | jbd_unlock_bh_state(bh); | |||
| 370 | journal_remove_journal_head(bh); | |||
| 371 | put_bh(bh); | |||
| 181 | 2193E3 | 372 | if (lock_need_resched(&journal->j_list_lock)) { | |
| 373 | spin_unlock(&journal->j_list_lock); | |||
| 373 | do | |||
| 0 | 181 | - | 373 | do-while (0) |
| 0 | 181 | - | 373 | do-while (0) |
| 181 | 374 | goto write_out_data; | ||
| 375 | } | |||
| 376 | } | |||
| 377 | } | |||
| 378 | } | |||
| 379 | ||||
| 0 | 14905 | - | 380 | if (bufs) { |
| 381 | spin_unlock(&journal->j_list_lock); | |||
| 381 | do | |||
| 0 | 0 | - | 381 | do-while (0) |
| 0 | 0 | - | 381 | do-while (0) |
| 382 | ll_rw_block(SWRITE, bufs, wbuf); | |||
| 383 | journal_brelse_array(wbuf, bufs); | |||
| 384 | spin_lock(&journal->j_list_lock); | |||
| 384 | do | |||
| 0 | 0 | - | 384 | do-while (0) |
| 0 | 0 | - | 384 | do-while (0) |
| 385 | } | |||
| 386 | ||||
| 387 | /* | |||
| 388 | * Wait for all previously submitted IO to complete. | |||
| 389 | */ | |||
| 436309 | 14905 | 390 | while (commit_transaction->t_locked_list) { | |
| 391 | struct buffer_head *bh; | |||
| 392 | ||||
| 393 | jh = commit_transaction->t_locked_list->b_tprev; | |||
| 394 | bh = jh2bh(jh); | |||
| 395 | get_bh(bh); | |||
| 7156 | 429153 | 396 | if (buffer_locked(bh)) { | |
| 397 | spin_unlock(&journal->j_list_lock); | |||
| 397 | do | |||
| 0 | 7156 | - | 397 | do-while (0) |
| 0 | 7156 | - | 397 | do-while (0) |
| 398 | wait_on_buffer(bh); | |||
| 0 | 7156 | - | 399 | if (unlikely(!buffer_uptodate(bh))) |
| 400 | err = -EIO; | |||
| 401 | spin_lock(&journal->j_list_lock); | |||
| 401 | do | |||
| 0 | 7156 | - | 401 | do-while (0) |
| 0 | 7156 | - | 401 | do-while (0) |
| 402 | } | |||
| 0 | 436309 | - | 403 | if (!inverted_lock(journal, bh)) { |
| 404 | put_bh(bh); | |||
| 405 | spin_lock(&journal->j_list_lock); | |||
| 405 | do | |||
| 0 | 0 | - | 405 | do-while (0) |
| 0 | 0 | - | 405 | |