| Start/ | End/ | |||
| True | False | - | Line | Source |
| 1 | /* | |||
| 2 | * linux/fs/journal.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 | * Generic filesystem journal-writing code; part of the ext2fs | |||
| 13 | * journaling system. | |||
| 14 | * | |||
| 15 | * This file manages journals: areas of disk reserved for logging | |||
| 16 | * transactional updates. This includes the kernel journaling thread | |||
| 17 | * which is responsible for scheduling updates to the log. | |||
| 18 | * | |||
| 19 | * We do not actually manage the physical storage of the journal in this | |||
| 20 | * file: that is left to a per-journal policy function, which allows us | |||
| 21 | * to store the journal within a filesystem-specified area for ext2 | |||
| 22 | * journaling (ext2 can use a reserved inode for storing the log). | |||
| 23 | */ | |||
| 24 | ||||
| 25 | #include <linux/module.h> | |||
| 26 | #include <linux/time.h> | |||
| 27 | #include <linux/fs.h> | |||
| 28 | #include <linux/jbd.h> | |||
| 29 | #include <linux/errno.h> | |||
| 30 | #include <linux/slab.h> | |||
| 31 | #include <linux/smp_lock.h> | |||
| 32 | #include <linux/init.h> | |||
| 33 | #include <linux/mm.h> | |||
| 34 | #include <linux/suspend.h> | |||
| 35 | #include <linux/pagemap.h> | |||
| 36 | #include <asm/uaccess.h> | |||
| 37 | #include <asm/page.h> | |||
| 38 | #include <linux/proc_fs.h> | |||
| 39 | ||||
| 40 | EXPORT_SYMBOL(journal_start); | |||
| 41 | EXPORT_SYMBOL(journal_restart); | |||
| 42 | EXPORT_SYMBOL(journal_extend); | |||
| 43 | EXPORT_SYMBOL(journal_stop); | |||
| 44 | EXPORT_SYMBOL(journal_lock_updates); | |||
| 45 | EXPORT_SYMBOL(journal_unlock_updates); | |||
| 46 | EXPORT_SYMBOL(journal_get_write_access); | |||
| 47 | EXPORT_SYMBOL(journal_get_create_access); | |||
| 48 | EXPORT_SYMBOL(journal_get_undo_access); | |||
| 49 | EXPORT_SYMBOL(journal_dirty_data); | |||
| 50 | EXPORT_SYMBOL(journal_dirty_metadata); | |||
| 51 | EXPORT_SYMBOL(journal_release_buffer); | |||
| 52 | EXPORT_SYMBOL(journal_forget); | |||
| 53 | #if 0 | |||
| 54 | EXPORT_SYMBOL(journal_sync_buffer); | |||
| 55 | #endif | |||
| 56 | EXPORT_SYMBOL(journal_flush); | |||
| 57 | EXPORT_SYMBOL(journal_revoke); | |||
| 58 | ||||
| 59 | EXPORT_SYMBOL(journal_init_dev); | |||
| 60 | EXPORT_SYMBOL(journal_init_inode); | |||
| 61 | EXPORT_SYMBOL(journal_update_format); | |||
| 62 | EXPORT_SYMBOL(journal_check_used_features); | |||
| 63 | EXPORT_SYMBOL(journal_check_available_features); | |||
| 64 | EXPORT_SYMBOL(journal_set_features); | |||
| 65 | EXPORT_SYMBOL(journal_create); | |||
| 66 | EXPORT_SYMBOL(journal_load); | |||
| 67 | EXPORT_SYMBOL(journal_destroy); | |||
| 68 | EXPORT_SYMBOL(journal_update_superblock); | |||
| 69 | EXPORT_SYMBOL(journal_abort); | |||
| 70 | EXPORT_SYMBOL(journal_errno); | |||
| 71 | EXPORT_SYMBOL(journal_ack_err); | |||
| 72 | EXPORT_SYMBOL(journal_clear_err); | |||
| 73 | EXPORT_SYMBOL(log_wait_commit); | |||
| 74 | EXPORT_SYMBOL(journal_start_commit); | |||
| 75 | EXPORT_SYMBOL(journal_force_commit_nested); | |||
| 76 | EXPORT_SYMBOL(journal_wipe); | |||
| 77 | EXPORT_SYMBOL(journal_blocks_per_page); | |||
| 78 | EXPORT_SYMBOL(journal_invalidatepage); | |||
| 79 | EXPORT_SYMBOL(journal_try_to_free_buffers); | |||
| 80 | EXPORT_SYMBOL(journal_force_commit); | |||
| 81 | ||||
| 82 | static int journal_convert_superblock_v1(journal_t *, journal_superblock_t *); | |||
| 83 | static void __journal_abort_soft (journal_t *journal, int errno); | |||
| 84 | ||||
| 85 | /* | |||
| 86 | * Helper function used to manage commit timeouts | |||
| 87 | */ | |||
| 88 | ||||
| 9594 | 9594 | 89 | static void commit_timeout(unsigned long __data) | |
| 90 | { | |||
| 91 | struct task_struct * p = (struct task_struct *) __data; | |||
| 92 | ||||
| 93 | wake_up_process(p); | |||
| 94 | } | |||
| 95 | ||||
| 96 | /* | |||
| 97 | * kjournald: The main thread function used to manage a logging device | |||
| 98 | * journal. | |||
| 99 | * | |||
| 100 | * This kernel thread is responsible for two things: | |||
| 101 | * | |||
| 102 | * 1) COMMIT: Every so often we need to commit the current state of the | |||
| 103 | * filesystem to disk. The journal thread is responsible for writing | |||
| 104 | * all of the metadata buffers to disk. | |||
| 105 | * | |||
| 106 | * 2) CHECKPOINT: We cannot reuse a used section of the log file until all | |||
| 107 | * of the data in that part of the log has been rewritten elsewhere on | |||
| 108 | * the disk. Flushing these old buffers to reclaim space in the log is | |||
| 109 | * known as checkpointing, and this thread is responsible for that job. | |||
| 110 | */ | |||
| 111 | ||||
| 6 | 0 | 112 | static int kjournald(void *arg) | |
| 113 | { | |||
| 114 | journal_t *journal = (journal_t *) arg; | |||
| 115 | transaction_t *transaction; | |||
| 116 | struct timer_list timer; | |||
| 117 | ||||
| 118 | daemonize("kjournald"); | |||
| 119 | ||||
| 120 | /* Set up an interval timer which can be used to trigger a | |||
| 121 | commit wakeup after the commit interval expires */ | |||
| 122 | init_timer(&timer); | |||
| 123 | timer.data = (unsigned long) current; | |||
| 124 | timer.function = commit_timeout; | |||
| 125 | journal->j_commit_timer = &timer; | |||
| 126 | ||||
| 127 | /* Record that the journal thread is running */ | |||
| 128 | journal->j_task = current; | |||
| 129 | wake_up(&journal->j_wait_done_commit); | |||
| 130 | ||||
| 131 | printk(KERN_INFO "kjournald starting. Commit interval %ld seconds\n", | |||
| 132 | journal->j_commit_interval / HZ); | |||
| 133 | ||||
| 134 | /* | |||
| 135 | * And now, wait forever for commit wakeup events. | |||
| 136 | */ | |||
| 137 | spin_lock(&journal->j_state_lock); | |||
| 137 | do | |||
| 0 | 6 | - | 137 | do-while (0) |
| 0 | 6 | - | 137 | do-while (0) |
| 138 | ||||
| 139 | loop: | |||
| 0 | 28460 | - | 140 | if (journal->j_flags & JFS_UNMOUNT) |
| 0 | - | 141 | goto end_loop; | |
| 142 | ||||
| 143 | jbd_debug(1, "commit_sequence=%d, commit_request=%d\n", | |||
| 144 | journal->j_commit_sequence, journal->j_commit_request); | |||
| 145 | ||||
| 14906 | 13554 | 146 | if (journal->j_commit_sequence != journal->j_commit_request) { | |
| 147 | jbd_debug(1, "OK, requests differ\n"); | |||
| 148 | spin_unlock(&journal->j_state_lock); | |||
| 148 | do | |||
| 0 | 14906 | - | 148 | do-while (0) |
| 0 | 14906 | - | 148 | do-while (0) |
| 149 | del_timer_sync(journal->j_commit_timer); | |||
| 150 | journal_commit_transaction(journal); | |||
| 151 | spin_lock(&journal->j_state_lock); | |||
| 151 | do | |||
| 0 | 14906 | - | 151 | do-while (0) |
| 0 | 14906 | - | 151 | do-while (0) |
| 14906 | 152 | goto loop; | ||
| 153 | } | |||
| 154 | ||||
| 155 | wake_up(&journal->j_wait_done_commit); | |||
| 0 | 13554 | - | 156 | if (freezing(current)) { |
| 157 | /* | |||
| 158 | * The simpler the better. Flushing journal isn't a | |||
| 159 | * good idea, because that depends on threads that may | |||
| 160 | * be already stopped. | |||
| 161 | */ | |||
| 162 | jbd_debug(1, "Now suspending kjournald\n"); | |||
| 163 | spin_unlock(&journal->j_state_lock); | |||
| 163 | do | |||
| 0 | 0 | - | 163 | do-while (0) |
| 0 | 0 | - | 163 | do-while (0) |
| 164 | refrigerator(); | |||
| 165 | spin_lock(&journal->j_state_lock); | |||
| 165 | do | |||
| 0 | 0 | - | 165 | do-while (0) |
| 0 | 0 | - | 165 | do-while (0) |
| 166 | } else { | |||
| 167 | /* | |||
| 168 | * We assume on resume that commits are already there, | |||
| 169 | * so we don't sleep | |||
| 170 | */ | |||
| 171 | DEFINE_WAIT(wait); | |||
| 172 | int should_sleep = 1; | |||
| 173 | ||||
| 174 | prepare_to_wait(&journal->j_wait_commit, &wait, | |||
| 175 | TASK_INTERRUPTIBLE); | |||
| 0 | 13554 | - | 176 | if (journal->j_commit_sequence != journal->j_commit_request) |
| 177 | should_sleep = 0; | |||
| 178 | transaction = journal->j_running_transaction; | |||
| 1 | 13553 | 179 | if (transaction && time_after_eq(jiffies, | |
| 1 | 179 | T && ((T) && (T) && (T)) | ||
| 3933 | 179 | T && ((T) && (T) && (F)) | ||
| 0 | - | 179 | T && ((T) && (F) && (_)) | |
| 0 | - | 179 | T && ((F) && (_) && (_)) | |
| 9620 | 179 | F && ((_) && (_) && (_)) | ||
| 180 | transaction->t_expires)) | |||
| 181 | should_sleep = 0; | |||
| 0 | 13554 | - | 182 | if (journal->j_flags & JFS_UNMOUNT) |
| 183 | should_sleep = 0; | |||
| 13553 | 1 | 184 | if (should_sleep) { | |
| 185 | spin_unlock(&journal->j_state_lock); | |||
| 185 | do | |||
| 0 | 13553 | - | 185 | do-while (0) |
| 0 | 13553 | - | 185 | do-while (0) |
| 186 | schedule(); | |||
| 187 | spin_lock(&journal->j_state_lock); | |||
| 187 | do | |||
| 0 | 13547 | - | 187 | do-while (0) |
| 0 | 13547 | - | 187 | do-while (0) |
| 188 | } | |||
| 189 | finish_wait(&journal->j_wait_commit, &wait); | |||
| 190 | } | |||
| 191 | ||||
| 192 | jbd_debug(1, "kjournald wakes\n"); | |||
| 193 | ||||
| 194 | /* | |||
| 195 | * Were we woken up by a commit wakeup event? | |||
| 196 | */ | |||
| 197 | transaction = journal->j_running_transaction; | |||
| 9562 | 3986 | 198 | if (transaction && time_after_eq(jiffies, transaction->t_expires)) { | |
| 9562 | 198 | T && ((T) && (T) && (T)) | ||
| 3986 | 198 | T && ((T) && (T) && (F)) | ||
| 0 | - | 198 | T && ((T) && (F) && (_)) | |
| 0 | - | 198 | T && ((F) && (_) && (_)) | |
| 0 | - | 198 | F && ((_) && (_) && (_)) | |
| 199 | journal->j_commit_request = transaction->t_tid; | |||
| 200 | jbd_debug(1, "woke because of timeout\n"); | |||
| 201 | } | |||
| 13548 | 202 | goto loop; | ||
| 203 | ||||
| 204 | end_loop: | |||
| 205 | spin_unlock(&journal->j_state_lock); | |||
| 205 | do | |||
| 0 | 0 | - | 205 | do-while (0) |
| 0 | 0 | - | 205 | do-while (0) |
| 206 | del_timer_sync(journal->j_commit_timer); | |||
| 207 | journal->j_task = NULL; | |||
| 208 | wake_up(&journal->j_wait_done_commit); | |||
| 209 | jbd_debug(1, "Journal thread exiting.\n"); | |||
| 0 | - | 210 | return 0; | |
| 211 | } | |||
| 212 | ||||
| 6 | 6 | 213 | static void journal_start_thread(journal_t *journal) | |
| 214 | { | |||
| 215 | kernel_thread(kjournald, journal, CLONE_VM|CLONE_FS|CLONE_FILES); | |||
| 216 | wait_event(journal->j_wait_done_commit, journal->j_task != 0); | |||
| 0 | 6 | - | 216 | if (journal -> j_task != 0) |
| 0 | - | 216 | break | |
| 216 | do | |||
| 12 | 0 | - | 216 | for (;1;) |
| 6 | 6 | 216 | if (journal -> j_task != 0) | |
| 6 | 216 | break | ||
| 0 | 6 | - | 216 | do-while (0) |
| 0 | 6 | - | 216 | do-while (0) |
| 217 | } | |||
| 218 | ||||
| 0 | 0 | - | 219 | static void journal_kill_thread(journal_t *journal) |
| 220 | { | |||
| 221 | spin_lock(&journal->j_state_lock); | |||
| 221 | do | |||
| 0 | 0 | - | 221 | do-while (0) |
| 0 | 0 | - | 221 | do-while (0) |
| 222 | journal->j_flags |= JFS_UNMOUNT; | |||
| 223 | ||||
| 0 | 0 | - | 224 | while (journal->j_task) { |
| 225 | wake_up(&journal->j_wait_commit); | |||
| 226 | spin_unlock(&journal->j_state_lock); | |||
| 226 | do | |||
| 0 | 0 | - | 226 | do-while (0) |
| 0 | 0 | - | 226 | do-while (0) |
| 227 | wait_event(journal->j_wait_done_commit, journal->j_task == 0); | |||
| 0 | 0 | - | 227 | if (journal -> j_task == 0) |
| 0 | - | 227 | break | |
| 227 | do | |||
| 0 | 0 | - | 227 | for (;1;) |
| 0 | 0 | - | 227 | if (journal -> j_task == 0) |
| 0 | - | 227 | break | |
| 0 | 0 | - | 227 | do-while (0) |
| 0 | 0 | - | 227 | do-while (0) |
| 228 | spin_lock(&journal->j_state_lock); | |||
| 228 | do | |||
| 0 | 0 | - | 228 | do-while (0) |
| 0 | 0 | - | 228 | do-while (0) |
| 229 | } | |||
| 230 | spin_unlock(&journal->j_state_lock); | |||
| 230 | do | |||
| 0 | 0 | - | 230 | do-while (0) |
| 0 | 0 | - | 230 | do-while (0) |
| 231 | } | |||
| 232 | ||||
| 233 | /* | |||
| 234 | * journal_write_metadata_buffer: write a metadata buffer to the journal. | |||
| 235 | * | |||
| 236 | * Writes a metadata buffer to a given disk block. The actual IO is not | |||
| 237 | * performed but a new buffer_head is constructed which labels the data | |||
| 238 | * to be written with the correct destination disk block. | |||
| 239 | * | |||
| 240 | * Any magic-number escaping which needs to be done will cause a | |||
| 241 | * copy-out here. If the buffer happens to start with the | |||
| 242 | * JFS_MAGIC_NUMBER, then we can't write it to the log directly: the | |||
| 243 | * magic number is only written to the log for descripter blocks. In | |||
| 244 | * this case, we copy the data and replace the first word with 0, and we | |||
| 245 | * return a result code which indicates that this buffer needs to be | |||
| 246 | * marked as an escaped buffer in the corresponding log descriptor | |||
| 247 | * block. The missing word can then be restored when the block is read | |||
| 248 | * during recovery. | |||
| 249 | * | |||
| 250 | * If the source buffer has already been modified by a new transaction | |||
| 251 | * since we took the last commit snapshot, we use the frozen copy of | |||
| 252 | * that data for IO. If we end up using the existing buffer_head's data | |||
| 253 | * for the write, then we *have* to lock the buffer to prevent anyone | |||
| 254 | * else from using and possibly modifying it while the IO is in | |||
| 255 | * progress. | |||
| 256 | * | |||
| 257 | * The function returns a pointer to the buffer_heads to be used for IO. | |||
| 258 | * | |||
| 259 | * We assume that the journal has already been locked in this function. | |||
| 260 | * | |||
| 261 | * Return value: | |||
| 262 | * <0: Error | |||
| 263 | * >=0: Finished OK | |||
| 264 | * | |||
| 265 | * On success: | |||
| 266 | * Bit 0 set == escape performed on the data | |||
| 267 | * Bit 1 set == buffer copy-out performed (kfree the data after IO) | |||
| 268 | */ | |||
| 269 | ||||
| 191536 | 0 | 270 | int journal_write_metadata_buffer(transaction_t *transaction, | |
| 271 | struct journal_head *jh_in, | |||
| 272 | struct journal_head **jh_out, | |||
| 273 | int blocknr) | |||
| 274 | { | |||
| 275 | int need_copy_out = 0; | |||
| 276 | int done_copy_out = 0; | |||
| 277 | int do_escape = 0; | |||
| 278 | char *mapped_data; | |||
| 279 | struct buffer_head *new_bh; | |||
| 280 | struct journal_head *new_jh; | |||
| 281 | struct page *new_page; | |||
| 282 | unsigned int new_offset; | |||
| 283 | struct buffer_head *bh_in = jh2bh(jh_in); | |||
| 284 | ||||
| 285 | /* | |||
| 286 | * The buffer really shouldn't be locked: only the current committing | |||
| 287 | * transaction is allowed to write it, so nobody else is allowed | |||
| 288 | * to do any IO. | |||
| 289 | * | |||
| 290 | * akpm: except if we're journalling data, and write() output is | |||
| 291 | * also part of a shared mapping, and another thread has | |||
| 292 | * decided to launch a writepage() against this buffer. | |||
| 293 | */ | |||
| 294 | J_ASSERT_BH(bh_in, buffer_jbddirty(bh_in)); | |||
| 0 | 191536 | - | 294 | if (! ( buffer_jbddirty ( bh_in ) )) |
| 0 | 191536 | - | 294 | do-while (0) |
| 295 | ||||
| 296 | new_bh = alloc_buffer_head(GFP_NOFS|__GFP_NOFAIL); | |||
| 297 | ||||
| 298 | /* | |||
| 299 | * If a new transaction has already done a buffer copy-out, then | |||
| 300 | * we use that version of the data for the commit. | |||
| 301 | */ | |||
| 302 | jbd_lock_bh_state(bh_in); | |||
| 303 | repeat: | |||
| 12987 | 178549 | 304 | if (jh_in->b_frozen_data) { | |
| 305 | done_copy_out = 1; | |||
| 306 | new_page = virt_to_page(jh_in->b_frozen_data); | |||
| 0 | 12987 | - | 306 | ternary-?: ( ( unsigned long ) ( jh_in -> b_.. |
| 307 | new_offset = offset_in_page(jh_in->b_frozen_data); | |||
| 308 | } else { | |||
| 309 | new_page = jh2bh(jh_in)->b_page; | |||
| 310 | new_offset = offset_in_page(jh2bh(jh_in)->b_data); | |||
| 311 | } | |||
| 312 | ||||
| 313 | mapped_data = kmap_atomic(new_page, KM_USER0); | |||
| 314 | /* | |||
| 315 | * Check for escaping | |||
| 316 | */ | |||
| 317 | if (*((__be32 *)(mapped_data + new_offset)) == | |||
| 0 | 191536 | - | 318 | cpu_to_be32(JFS_MAGIC_NUMBER)) { |
| 191536 | 0 | - | 318 | ternary-?: __builtin_constant_p ( ( __u32 ) ( .. |
| 319 | need_copy_out = 1; | |||
| 320 | do_escape = 1; | |||
| 321 | } | |||
| 322 | kunmap_atomic(mapped_data, KM_USER0); | |||
| 0 | 191536 | - | 322 | do-while (0) |
| 323 | ||||
| 324 | /* | |||
| 325 | * Do we need to do a data copy? | |||
| 326 | */ | |||
| 0 | 191536 | - | 327 | if (need_copy_out && !done_copy_out) { |
| 0 | - | 327 | T && T | |
| 0 | - | 327 | T && F | |
| 191536 | 327 | F && _ | ||
| 328 | char *tmp; | |||
| 329 | ||||
| 330 | jbd_unlock_bh_state(bh_in); | |||
| 331 | tmp = jbd_rep_kmalloc(bh_in->b_size, GFP_NOFS); | |||
| 332 | jbd_lock_bh_state(bh_in); | |||
| 0 | 0 | - | 333 | if (jh_in->b_frozen_data) { |
| 334 | kfree(tmp); | |||
| 0 | - | 335 | goto repeat; | |
| 336 | } | |||
| 337 | ||||
| 338 | jh_in->b_frozen_data = tmp; | |||
| 339 | mapped_data = kmap_atomic(new_page, KM_USER0); | |||
| 340 | memcpy(tmp, mapped_data + new_offset, jh2bh(jh_in)->b_size); | |||
| 341 | kunmap_atomic(mapped_data, KM_USER0); | |||
| 0 | 0 | - | 341 | do-while (0) |
| 342 | ||||
| 343 | new_page = virt_to_page(tmp); | |||
| 0 | 0 | - | 343 | ternary-?: ( ( unsigned long ) ( tmp ) >= 0x.. |
| 344 | new_offset = offset_in_page(tmp); | |||
| 345 | done_copy_out = 1; | |||
| 346 | } | |||
| 347 | ||||
| 348 | /* | |||
| 349 | * Did we need to do an escaping? Now we've done all the | |||
| 350 | * copying, we can finally do so. | |||
| 351 | */ | |||
| 0 | 191536 | - | 352 | if (do_escape) { |
| 353 | mapped_data = kmap_atomic(new_page, KM_USER0); | |||
| 354 | *((unsigned int *)(mapped_data + new_offset)) = 0; | |||
| 355 | kunmap_atomic(mapped_data, KM_USER0); | |||
| 0 | 0 | - | 355 | do-while (0) |
| 356 | } | |||
| 357 | ||||
| 358 | /* keep subsequent assertions sane */ | |||
| 359 | new_bh->b_state = 0; | |||
| 360 | init_buffer(new_bh, NULL, NULL); | |||
| 361 | atomic_set(&new_bh->b_count, 1); | |||
| 362 | jbd_unlock_bh_state(bh_in); | |||
| 363 | ||||
| 364 | new_jh = journal_add_journal_head(new_bh); /* This sleeps */ | |||
| 365 | ||||
| 366 | set_bh_page(new_bh, new_page, new_offset); | |||
| 367 | new_jh->b_transaction = NULL; | |||
| 368 | new_bh->b_size = jh2bh(jh_in)->b_size; | |||
| 369 | new_bh->b_bdev = transaction->t_journal->j_dev; | |||
| 370 | new_bh->b_blocknr = blocknr; | |||
| 371 | set_buffer_mapped(new_bh); | |||
| 372 | set_buffer_dirty(new_bh); | |||
| 373 | ||||
| 374 | *jh_out = new_jh; | |||
| 375 | ||||
| 376 | /* | |||
| 377 | * The to-be-written buffer needs to get moved to the io queue, | |||
| 378 | * and the original buffer whose contents we are shadowing or | |||
| 379 | * copying is moved to the transaction's shadow queue. | |||
| 380 | */ | |||
| 381 | JBUFFER_TRACE(jh_in, "file as BJ_Shadow"); | |||
| 0 | 191536 | - | 381 | do-while (0) |
| 382 | journal_file_buffer(jh_in, transaction, BJ_Shadow); | |||
| 383 | JBUFFER_TRACE(new_jh, "file as BJ_IO"); | |||
| 0 | 191536 | - | 383 | do-while (0) |
| 384 | journal_file_buffer(new_jh, transaction, BJ_IO); | |||
| 385 | ||||
| 191536 | 386 | return do_escape | (done_copy_out << 1); | ||
| 387 | } | |||
| 388 | ||||
| 389 | /* | |||
| 390 | * Allocation code for the journal file. Manage the space left in the | |||
| 391 | * journal, so that we can begin checkpointing when appropriate. | |||
| 392 | */ | |||
| 393 | ||||
| 394 | /* | |||
| 395 | * __log_space_left: Return the number of free blocks left in the journal. | |||
| 396 | * | |||
| 397 | * Called with the journal already locked. | |||
| 398 | * | |||
| 399 | * Called under j_state_lock | |||
| 400 | */ | |||
| 401 | ||||
| 1517E4 | 0 | 402 | int __log_space_left(journal_t *journal) | |
| 403 | { | |||
| 404 | int left = journal->j_free; | |||
| 405 | ||||
| 406 | assert_spin_locked(&journal->j_state_lock); | |||
| 0 | 1517E4 | - | 406 | do-while (0) |
| 407 | ||||
| 408 | /* | |||
| 409 | * Be pessimistic here about the number of those free blocks which | |||
| 410 | * might be required for log descriptor control blocks. | |||
| 411 | */ | |||
| 412 | ||||
| 413 | #define MIN_LOG_RESERVED_BLOCKS 32 /* Allow for rounding errors */ | |||
| 414 | ||||
| 415 | left -= MIN_LOG_RESERVED_BLOCKS; | |||
| 416 | ||||
| 0 | 1517E4 | - | 417 | if (left <= 0) |
| 0 | - | 418 | return 0; | |
| 419 | left -= (left >> 3); | |||
| 1517E4 | 420 | return left; | ||
| 421 | } | |||
| 422 | ||||
| 423 | /* | |||
| 424 | * Called under j_state_lock. Returns true if a transaction was started. | |||
| 425 | */ | |||
| 660696 | 0 | 426 | int __log_start_commit(journal_t *journal, tid_t target) | |
| 427 | { | |||
| 428 | /* | |||
| 429 | * Are we already doing a recent enough commit? | |||
| 430 | */ | |||
| 5415 | 655281 | 431 | if (!tid_geq(journal->j_commit_request, target)) { | |
| 432 | /* | |||
| 433 | * We want a new commit: OK, mark the request and wakup the | |||
| 434 | * commit thread. We do _not_ do the commit ourselves. | |||
| 435 | */ | |||
| 436 | ||||
| 437 | journal->j_commit_request = target; | |||
| 438 | jbd_debug(1, "JBD: requesting commit %d/%d\n", | |||
| 439 | journal->j_commit_request, | |||
| 440 | journal->j_commit_sequence); | |||
| 441 | wake_up(&journal->j_wait_commit); | |||
| 5415 | 442 | return 1; | ||
| 443 | } | |||
| 655281 | 444 | return 0; | ||
| 445 | } | |||
| 446 | ||||
| 3 | 0 | 447 | int log_start_commit(journal_t *journal, tid_t tid) | |
| 448 | { | |||
| 449 | int ret; | |||
| 450 | ||||
| 451 | spin_lock(&journal->j_state_lock); | |||
| 451 | do | |||
| 0 | 3 | - | 451 | do-while (0) |
| 0 | 3 | - | 451 | do-while (0) |
| 452 | ret = __log_start_commit(journal, tid); | |||
| 453 | spin_unlock(&journal->j_state_lock); | |||
| 453 | do | |||
| 0 | 3 | - | 453 | do-while (0) |
| 0 | 3 | - | 453 | do-while (0) |
| 3 | 454 | return ret; | ||
| 455 | } | |||
| 456 | ||||
| 457 | /* | |||
| 458 | * Force and wait upon a commit if the calling process is not within | |||
| 459 | * transaction. This is used for forcing out undo-protected data which contains | |||
| 460 | * bitmaps, when the fs is running out of space. | |||
| 461 | * | |||
| 462 | ||||