cregit-Linux how code gets into the kernel

Release 4.10 fs/jbd2/journal.c

Directory: fs/jbd2
/*
 * linux/fs/jbd2/journal.c
 *
 * 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.
 *
 * Generic filesystem journal-writing code; part of the ext2fs
 * journaling system.
 *
 * This file manages journals: areas of disk reserved for logging
 * transactional updates.  This includes the kernel journaling thread
 * which is responsible for scheduling updates to the log.
 *
 * We do not actually manage the physical storage of the journal in this
 * file: that is left to a per-journal policy function, which allows us
 * to store the journal within a filesystem-specified area for ext2
 * journaling (ext2 can use a reserved inode for storing the log).
 */

#include <linux/module.h>
#include <linux/time.h>
#include <linux/fs.h>
#include <linux/jbd2.h>
#include <linux/errno.h>
#include <linux/slab.h>
#include <linux/init.h>
#include <linux/mm.h>
#include <linux/freezer.h>
#include <linux/pagemap.h>
#include <linux/kthread.h>
#include <linux/poison.h>
#include <linux/proc_fs.h>
#include <linux/seq_file.h>
#include <linux/math64.h>
#include <linux/hash.h>
#include <linux/log2.h>
#include <linux/vmalloc.h>
#include <linux/backing-dev.h>
#include <linux/bitops.h>
#include <linux/ratelimit.h>


#define CREATE_TRACE_POINTS
#include <trace/events/jbd2.h>

#include <linux/uaccess.h>
#include <asm/page.h>

#ifdef CONFIG_JBD2_DEBUG

ushort jbd2_journal_enable_debug __read_mostly;

EXPORT_SYMBOL(jbd2_journal_enable_debug);

module_param_named(jbd2_debug, jbd2_journal_enable_debug, ushort, 0644);
MODULE_PARM_DESC(jbd2_debug, "Debugging level for jbd2");
#endif


EXPORT_SYMBOL(jbd2_journal_extend);

EXPORT_SYMBOL(jbd2_journal_stop);

EXPORT_SYMBOL(jbd2_journal_lock_updates);

EXPORT_SYMBOL(jbd2_journal_unlock_updates);

EXPORT_SYMBOL(jbd2_journal_get_write_access);

EXPORT_SYMBOL(jbd2_journal_get_create_access);

EXPORT_SYMBOL(jbd2_journal_get_undo_access);

EXPORT_SYMBOL(jbd2_journal_set_triggers);

EXPORT_SYMBOL(jbd2_journal_dirty_metadata);

EXPORT_SYMBOL(jbd2_journal_forget);
#if 0
EXPORT_SYMBOL(journal_sync_buffer);
#endif

EXPORT_SYMBOL(jbd2_journal_flush);

EXPORT_SYMBOL(jbd2_journal_revoke);


EXPORT_SYMBOL(jbd2_journal_init_dev);

EXPORT_SYMBOL(jbd2_journal_init_inode);

EXPORT_SYMBOL(jbd2_journal_check_used_features);

EXPORT_SYMBOL(jbd2_journal_check_available_features);

EXPORT_SYMBOL(jbd2_journal_set_features);

EXPORT_SYMBOL(jbd2_journal_load);

EXPORT_SYMBOL(jbd2_journal_destroy);

EXPORT_SYMBOL(jbd2_journal_abort);

EXPORT_SYMBOL(jbd2_journal_errno);

EXPORT_SYMBOL(jbd2_journal_ack_err);

EXPORT_SYMBOL(jbd2_journal_clear_err);

EXPORT_SYMBOL(jbd2_log_wait_commit);

EXPORT_SYMBOL(jbd2_log_start_commit);

EXPORT_SYMBOL(jbd2_journal_start_commit);

EXPORT_SYMBOL(jbd2_journal_force_commit_nested);

EXPORT_SYMBOL(jbd2_journal_wipe);

EXPORT_SYMBOL(jbd2_journal_blocks_per_page);

EXPORT_SYMBOL(jbd2_journal_invalidatepage);

EXPORT_SYMBOL(jbd2_journal_try_to_free_buffers);

EXPORT_SYMBOL(jbd2_journal_force_commit);

EXPORT_SYMBOL(jbd2_journal_inode_add_write);

EXPORT_SYMBOL(jbd2_journal_inode_add_wait);

EXPORT_SYMBOL(jbd2_journal_init_jbd_inode);

EXPORT_SYMBOL(jbd2_journal_release_jbd_inode);

EXPORT_SYMBOL(jbd2_journal_begin_ordered_truncate);

EXPORT_SYMBOL(jbd2_inode_cache);

static void __journal_abort_soft (journal_t *journal, int errno);
static int jbd2_journal_create_slab(size_t slab_size);

#ifdef CONFIG_JBD2_DEBUG

void __jbd2_debug(int level, const char *file, const char *func, unsigned int line, const char *fmt, ...) { struct va_format vaf; va_list args; if (level > jbd2_journal_enable_debug) return; va_start(args, fmt); vaf.fmt = fmt; vaf.va = &args; printk(KERN_DEBUG "%s: (%s, %u): %pV\n", file, func, line, &vaf); va_end(args); }

Contributors

PersonTokensPropCommitsCommitProp
paul gortmakerpaul gortmaker83100.00%1100.00%
Total83100.00%1100.00%

EXPORT_SYMBOL(__jbd2_debug); #endif /* Checksumming functions */
static int jbd2_verify_csum_type(journal_t *j, journal_superblock_t *sb) { if (!jbd2_journal_has_csum_v2or3_feature(j)) return 1; return sb->s_checksum_type == JBD2_CRC32C_CHKSUM; }

Contributors

PersonTokensPropCommitsCommitProp
darrick j. wongdarrick j. wong3196.88%266.67%
rashika kheriarashika kheria13.12%133.33%
Total32100.00%3100.00%


static __be32 jbd2_superblock_csum(journal_t *j, journal_superblock_t *sb) { __u32 csum; __be32 old_csum; old_csum = sb->s_checksum; sb->s_checksum = 0; csum = jbd2_chksum(j, ~0, (char *)sb, sizeof(journal_superblock_t)); sb->s_checksum = old_csum; return cpu_to_be32(csum); }

Contributors

PersonTokensPropCommitsCommitProp
darrick j. wongdarrick j. wong65100.00%2100.00%
Total65100.00%2100.00%


static int jbd2_superblock_csum_verify(journal_t *j, journal_superblock_t *sb) { if (!jbd2_journal_has_csum_v2or3(j)) return 1; return sb->s_checksum == jbd2_superblock_csum(j, sb); }

Contributors

PersonTokensPropCommitsCommitProp
darrick j. wongdarrick j. wong3697.30%266.67%
rashika kheriarashika kheria12.70%133.33%
Total37100.00%3100.00%


static void jbd2_superblock_csum_set(journal_t *j, journal_superblock_t *sb) { if (!jbd2_journal_has_csum_v2or3(j)) return; sb->s_checksum = jbd2_superblock_csum(j, sb); }

Contributors

PersonTokensPropCommitsCommitProp
darrick j. wongdarrick j. wong3397.06%266.67%
rashika kheriarashika kheria12.94%133.33%
Total34100.00%3100.00%

/* * Helper function used to manage commit timeouts */
static void commit_timeout(unsigned long __data) { struct task_struct * p = (struct task_struct *) __data; wake_up_process(p); }

Contributors

PersonTokensPropCommitsCommitProp
dave kleikampdave kleikamp27100.00%1100.00%
Total27100.00%1100.00%

/* * kjournald2: The main thread function used to manage a logging device * journal. * * This kernel thread is responsible for two things: * * 1) COMMIT: Every so often we need to commit the current state of the * filesystem to disk. The journal thread is responsible for writing * all of the metadata buffers to disk. * * 2) CHECKPOINT: We cannot reuse a used section of the log file until all * of the data in that part of the log has been rewritten elsewhere on * the disk. Flushing these old buffers to reclaim space in the log is * known as checkpointing, and this thread is responsible for that job. */
static int kjournald2(void *arg) { journal_t *journal = arg; transaction_t *transaction; /* * Set up an interval timer which can be used to trigger a commit wakeup * after the commit interval expires */ setup_timer(&journal->j_commit_timer, commit_timeout, (unsigned long)current); set_freezable(); /* Record that the journal thread is running */ journal->j_task = current; wake_up(&journal->j_wait_done_commit); /* * And now, wait forever for commit wakeup events. */ write_lock(&journal->j_state_lock); loop: if (journal->j_flags & JBD2_UNMOUNT) goto end_loop; jbd_debug(1, "commit_sequence=%d, commit_request=%d\n", journal->j_commit_sequence, journal->j_commit_request); if (journal->j_commit_sequence != journal->j_commit_request) { jbd_debug(1, "OK, requests differ\n"); write_unlock(&journal->j_state_lock); del_timer_sync(&journal->j_commit_timer); jbd2_journal_commit_transaction(journal); write_lock(&journal->j_state_lock); goto loop; } wake_up(&journal->j_wait_done_commit); if (freezing(current)) { /* * The simpler the better. Flushing journal isn't a * good idea, because that depends on threads that may * be already stopped. */ jbd_debug(1, "Now suspending kjournald2\n"); write_unlock(&journal->j_state_lock); try_to_freeze(); write_lock(&journal->j_state_lock); } else { /* * We assume on resume that commits are already there, * so we don't sleep */ DEFINE_WAIT(wait); int should_sleep = 1; prepare_to_wait(&journal->j_wait_commit, &wait, TASK_INTERRUPTIBLE); if (journal->j_commit_sequence != journal->j_commit_request) should_sleep = 0; transaction = journal->j_running_transaction; if (transaction && time_after_eq(jiffies, transaction->t_expires)) should_sleep = 0; if (journal->j_flags & JBD2_UNMOUNT) should_sleep = 0; if (should_sleep) { write_unlock(&journal->j_state_lock); schedule(); write_lock(&journal->j_state_lock); } finish_wait(&journal->j_wait_commit, &wait); } jbd_debug(1, "kjournald2 wakes\n"); /* * Were we woken up by a commit wakeup event? */ transaction = journal->j_running_transaction; if (transaction && time_after_eq(jiffies, transaction->t_expires)) { journal->j_commit_request = transaction->t_tid; jbd_debug(1, "woke because of timeout\n"); } goto loop; end_loop: write_unlock(&journal->j_state_lock); del_timer_sync(&journal->j_commit_timer); journal->j_task = NULL; wake_up(&journal->j_wait_done_commit); jbd_debug(1, "Journal thread exiting.\n"); return 0; }

Contributors

PersonTokensPropCommitsCommitProp
dave kleikampdave kleikamp37095.36%120.00%
theodore tsotheodore tso82.06%120.00%
mingming caomingming cao61.55%120.00%
nigel cunninghamnigel cunningham30.77%120.00%
tejun heotejun heo10.26%120.00%
Total388100.00%5100.00%


static int jbd2_journal_start_thread(journal_t *journal) { struct task_struct *t; t = kthread_run(kjournald2, journal, "jbd2/%s", journal->j_devname); if (IS_ERR(t)) return PTR_ERR(t); wait_event(journal->j_wait_done_commit, journal->j_task != NULL); return 0; }

Contributors

PersonTokensPropCommitsCommitProp
dave kleikampdave kleikamp2745.76%120.00%
pavel emelianovpavel emelianov2440.68%120.00%
theodore tsotheodore tso58.47%120.00%
mingming caomingming cao23.39%120.00%
al viroal viro11.69%120.00%
Total59100.00%5100.00%


static void journal_kill_thread(journal_t *journal) { write_lock(&journal->j_state_lock); journal->j_flags |= JBD2_UNMOUNT; while (journal->j_task) { write_unlock(&journal->j_state_lock); wake_up(&journal->j_wait_commit); wait_event(journal->j_wait_done_commit, journal->j_task == NULL); write_lock(&journal->j_state_lock); } write_unlock(&journal->j_state_lock); }

Contributors

PersonTokensPropCommitsCommitProp
dave kleikampdave kleikamp6888.31%120.00%
theodore tsotheodore tso79.09%240.00%
mingming caomingming cao11.30%120.00%
al viroal viro11.30%120.00%
Total77100.00%5100.00%

/* * jbd2_journal_write_metadata_buffer: write a metadata buffer to the journal. * * Writes a metadata buffer to a given disk block. The actual IO is not * performed but a new buffer_head is constructed which labels the data * to be written with the correct destination disk block. * * Any magic-number escaping which needs to be done will cause a * copy-out here. If the buffer happens to start with the * JBD2_MAGIC_NUMBER, then we can't write it to the log directly: the * magic number is only written to the log for descripter blocks. In * this case, we copy the data and replace the first word with 0, and we * return a result code which indicates that this buffer needs to be * marked as an escaped buffer in the corresponding log descriptor * block. The missing word can then be restored when the block is read * during recovery. * * If the source buffer has already been modified by a new transaction * since we took the last commit snapshot, we use the frozen copy of * that data for IO. If we end up using the existing buffer_head's data * for the write, then we have to make sure nobody modifies it while the * IO is in progress. do_get_write_access() handles this. * * The function returns a pointer to the buffer_head to be used for IO. * * * Return value: * <0: Error * >=0: Finished OK * * On success: * Bit 0 set == escape performed on the data * Bit 1 set == buffer copy-out performed (kfree the data after IO) */
int jbd2_journal_write_metadata_buffer(transaction_t *transaction, struct journal_head *jh_in, struct buffer_head **bh_out, sector_t blocknr) { int need_copy_out = 0; int done_copy_out = 0; int do_escape = 0; char *mapped_data; struct buffer_head *new_bh; struct page *new_page; unsigned int new_offset; struct buffer_head *bh_in = jh2bh(jh_in); journal_t *journal = transaction->t_journal; /* * The buffer really shouldn't be locked: only the current committing * transaction is allowed to write it, so nobody else is allowed * to do any IO. * * akpm: except if we're journalling data, and write() output is * also part of a shared mapping, and another thread has * decided to launch a writepage() against this buffer. */ J_ASSERT_BH(bh_in, buffer_jbddirty(bh_in)); new_bh = alloc_buffer_head(GFP_NOFS|__GFP_NOFAIL); /* keep subsequent assertions sane */ atomic_set(&new_bh->b_count, 1); jbd_lock_bh_state(bh_in); repeat: /* * If a new transaction has already done a buffer copy-out, then * we use that version of the data for the commit. */ if (jh_in->b_frozen_data) { done_copy_out = 1; new_page = virt_to_page(jh_in->b_frozen_data); new_offset = offset_in_page(jh_in->b_frozen_data); } else { new_page = jh2bh(jh_in)->b_page; new_offset = offset_in_page(jh2bh(jh_in)->b_data); } mapped_data = kmap_atomic(new_page); /* * Fire data frozen trigger if data already wasn't frozen. Do this * before checking for escaping, as the trigger may modify the magic * offset. If a copy-out happens afterwards, it will have the correct * data in the buffer. */ if (!done_copy_out) jbd2_buffer_frozen_trigger(jh_in, mapped_data + new_offset, jh_in->b_triggers); /* * Check for escaping */ if (*((__be32 *)(mapped_data + new_offset)) == cpu_to_be32(JBD2_MAGIC_NUMBER)) { need_copy_out = 1; do_escape = 1; } kunmap_atomic(mapped_data); /* * Do we need to do a data copy? */ if (need_copy_out && !done_copy_out) { char *tmp; jbd_unlock_bh_state(bh_in); tmp = jbd2_alloc(bh_in->b_size, GFP_NOFS); if (!tmp) { brelse(new_bh); return -ENOMEM; } jbd_lock_bh_state(bh_in); if (jh_in->b_frozen_data) { jbd2_free(tmp, bh_in->b_size); goto repeat; } jh_in->b_frozen_data = tmp; mapped_data = kmap_atomic(new_page); memcpy(tmp, mapped_data + new_offset, bh_in->b_size); kunmap_atomic(mapped_data); new_page = virt_to_page(tmp); new_offset = offset_in_page(tmp); done_copy_out = 1; /* * This isn't strictly necessary, as we're using frozen * data for the escaping, but it keeps consistency with * b_frozen_data usage. */ jh_in->b_frozen_triggers = jh_in->b_triggers; } /* * Did we need to do an escaping? Now we've done all the * copying, we can finally do so. */ if (do_escape) { mapped_data = kmap_atomic(new_page); *((unsigned int *)(mapped_data + new_offset)) = 0; kunmap_atomic(mapped_data); } set_bh_page(new_bh, new_page, new_offset); new_bh->b_size = bh_in->b_size; new_bh->b_bdev = journal->j_dev; new_bh->b_blocknr = blocknr; new_bh->b_private = bh_in; set_buffer_mapped(new_bh); set_buffer_dirty(new_bh); *bh_out = new_bh; /* * The to-be-written buffer needs to get moved to the io queue, * and the original buffer whose contents we are shadowing or * copying is moved to the transaction's shadow queue. */ JBUFFER_TRACE(jh_in, "file as BJ_Shadow"); spin_lock(&journal->j_list_lock); __jbd2_journal_file_buffer(jh_in, transaction, BJ_Shadow); spin_unlock(&journal->j_list_lock); set_buffer_shadow(bh_in); jbd_unlock_bh_state(bh_in); return do_escape | (done_copy_out << 1); }

Contributors

PersonTokensPropCommitsCommitProp
dave kleikampdave kleikamp38677.67%110.00%
ding dinghuading dinghua418.25%110.00%
jan karajan kara326.44%330.00%
joel beckerjoel becker183.62%110.00%
theodore tsotheodore tso142.82%110.00%
mingming caomingming cao40.80%220.00%
michal hockomichal hocko20.40%110.00%
Total497100.00%10100.00%

/* * Allocation code for the journal file. Manage the space left in the * journal, so that we can begin checkpointing when appropriate. */ /* * Called with j_state_lock locked for writing. * Returns true if a transaction commit was started. */
int __jbd2_log_start_commit(journal_t *journal, tid_t target) { /* Return if the txn has already requested to be committed */ if (journal->j_commit_request == target) return 0; /* * The only transaction we can possibly wait upon is the * currently running transaction (if it exists). Otherwise, * the target tid must be an old one. */ if (journal->j_running_transaction && journal->j_running_transaction->t_tid == target) { /* * We want a new commit: OK, mark the request and wakeup the * commit thread. We do _not_ do the commit ourselves. */ journal->j_commit_request = target; jbd_debug(1, "JBD2: requesting commit %d/%d\n", journal->j_commit_request, journal->j_commit_sequence); journal->j_running_transaction->t_requested = jiffies; wake_up(&journal->j_wait_commit); return 1; } else if (!tid_geq(journal->j_commit_request, target)) /* This should never happen, but if it does, preserve the evidence before kjournald goes into a loop and increments j_commit_sequence beyond all recognition. */ WARN_ONCE(1, "JBD2: bad log_start_commit: %u %u %u %u\n", journal->j_commit_request, journal->j_commit_sequence, target, journal->j_running_transaction ? journal->j_running_transaction->t_tid : 0); return 0; }

Contributors

PersonTokensPropCommitsCommitProp
theodore tsotheodore tso5946.09%337.50%
dave kleikampdave kleikamp5341.41%112.50%
eric sandeeneric sandeen129.38%112.50%
eryu guaneryu guan21.56%112.50%
andrea gelminiandrea gelmini10.78%112.50%
mingming caomingming cao10.78%112.50%
Total128100.00%8100.00%


int jbd2_log_start_commit(journal_t *journal, tid_t tid) { int ret; write_lock(&journal->j_state_lock); ret = __jbd2_log_start_commit(journal, tid); write_unlock(&journal->j_state_lock); return ret; }

Contributors

PersonTokensPropCommitsCommitProp
dave kleikampdave kleikamp3990.70%133.33%
theodore tsotheodore tso24.65%133.33%
mingming caomingming cao24.65%133.33%
Total43100.00%3100.00%

/* * Force and wait any uncommitted transactions. We can only force the running * transaction if we don't have an active handle, otherwise, we will deadlock. * Returns: <0 in case of error, * 0 if nothing to commit, * 1 if transaction was successfully committed. */
static int __jbd2_journal_force_commit(journal_t *journal) { transaction_t *transaction = NULL; tid_t tid; int need_to_start = 0, ret = 0; read_lock(&journal->j_state_lock); if (journal->j_running_transaction && !current->journal_info) { transaction = journal->j_running_transaction; if (!tid_geq(journal->j_commit_request, transaction->t_tid)) need_to_start = 1; } else if (journal->j_committing_transaction) transaction = journal->j_committing_transaction; if (!transaction) { /* Nothing to commit */ read_unlock(&journal->j_state_lock); return 0; } tid = transaction->t_tid; read_unlock(&journal->j_state_lock); if (need_to_start) jbd2_log_start_commit(journal, tid); ret = jbd2_log_wait_commit(journal, tid); if (!ret) ret = 1; return ret; }

Contributors

PersonTokensPropCommitsCommitProp
dave kleikampdave kleikamp10066.23%120.00%
theodore tsotheodore tso2919.21%240.00%
dmitriy monakhovdmitriy monakhov2113.91%120.00%
mingming caomingming cao10.66%120.00%
Total151100.00%5100.00%

/** * Force and wait upon a commit if the calling process is not within * transaction. This is used for forcing out undo-protected data which contains * bitmaps, when the fs is running out of space. * * @journal: journal to force * Returns true if progress was made. */
int jbd2_journal_force_commit_nested(journal_t *journal) { int ret; ret = __jbd2_journal_force_commit(journal); return ret > 0; }

Contributors

PersonTokensPropCommitsCommitProp
dmitriy monakhovdmitriy monakhov24100.00%1100.00%
Total24100.00%1100.00%

/** * int journal_force_commit() - force any uncommitted transactions * @journal: journal to force * * Caller want unconditional commit. We can only force the running transaction * if we don't have an active handle, otherwise, we will deadlock. */
int jbd2_journal_force_commit(journal_t *journal) { int ret; J_ASSERT(!current->journal_info); ret = __jbd2_journal_force_commit(journal); if (ret > 0) ret = 0; return ret; }

Contributors

PersonTokensPropCommitsCommitProp
dmitriy monakhovdmitriy monakhov3895.00%150.00%
dave kleikampdave kleikamp25.00%150.00%
Total40100.00%2100.00%

/* * Start a commit of the current running transaction (if any). Returns true * if a transaction is going to be committed (or is currently already * committing), and fills its tid in at *ptid */
int jbd2_journal_start_commit(journal_t *journal, tid_t *ptid) { int ret = 0; write_lock(&journal->j_state_lock); if (journal->j_running_transaction) { tid_t tid = journal->j_running_transaction->t_tid; __jbd2_log_start_commit(journal, tid); /* There's a running transaction and we've just made sure * it's commit has been scheduled. */ if (ptid) *ptid = tid; ret = 1; } else if (journal->j_committing_transaction) { /* * If commit has been started, then we have to wait for * completion of that transaction. */ if (ptid) *ptid = journal->j_committing_transaction->t_tid; ret = 1; } write_unlock(&journal->j_state_lock); return ret; }

Contributors

PersonTokensPropCommitsCommitProp
dave kleikampdave kleikamp8886.27%120.00%
jan karajan kara98.82%120.00%
mingming caomingming cao21.96%120.00%
theodore tsotheodore tso21.96%120.00%
artem bityutskiyartem bityutskiy10.98%120.00%
Total102100.00%5100.00%

/* * Return 1 if a given transaction has not yet sent barrier request * connected with a transaction commit. If 0 is returned, transaction * may or may not have sent the barrier. Used to avoid sending barrier * twice in common cases. */
int jbd2_trans_will_send_data_barrier(journal_t *journal, tid_t tid) { int ret = 0; transaction_t *commit_trans; if (!(journal->j_flags & JBD2_BARRIER)) return 0; read_lock(&journal->j_state_lock); /* Transaction already committed? */ if (tid_geq(journal->j_commit_sequence, tid)) goto out; commit_trans = journal->j_committing_transaction; if (!commit_trans || commit_trans->t_tid != tid) { ret = 1; goto out; } /* * Transaction is being committed and we already proceeded to * submitting a flush to fs partition? */ if (journal->j_fs_dev != journal->j_dev) { if (!commit_trans->t_need_data_flush || commit_trans->t_state >= T_COMMIT_DFLUSH) goto out; } else { if (commit_trans->t_state >= T_COMMIT_JFLUSH) goto out; } ret = 1; out: read_unlock(&journal->j_state_lock); return ret; }

Contributors

PersonTokensPropCommitsCommitProp
jan karajan kara144100.00%1100.00%
Total144100.00%1100.00%

EXPORT_SYMBOL(jbd2_trans_will_send_data_barrier); /* * Wait for a specified commit to complete. * The caller may not hold the journal lock. */
int jbd2_log_wait_commit(journal_t *journal, tid_t tid) { int err = 0; jbd2_might_wait_for_commit(journal); read_lock(&journal->j_state_lock); #ifdef CONFIG_JBD2_DEBUG if (!tid_geq(journal->j_commit_request, tid)) { printk(KERN_ERR "%s: error: j_commit_request=%d, tid=%d\n", __func__, journal->j_commit_request, tid); } #endif while (tid_gt(tid, journal->j_commit_sequence)) { jbd_debug(1, "JBD2: want %d, j_commit_sequence=%d\n", tid, journal->j_commit_sequence); read_unlock(&journal->j_state_lock); wake_up(&journal->j_wait_commit); wait_event(journal->j_wait_done_commit, !tid_gt(tid, journal->j_commit_sequence)); read_lock(&journal->j_state_lock); } read_unlock(&journal->j_state_lock); if (unlikely(is_journal_aborted(journal))) err = -EIO; return err; }

Contributors

PersonTokensPropCommitsCommitProp
dave kleikampdave kleikamp13787.82%112.50%
theodore tsotheodore tso106.41%225.00%
jan karajan kara63.85%225.00%
harvey harrisonharvey harrison10.64%112.50%
eryu guaneryu guan10.64%112.50%
mingming caomingming cao10.64%112.50%
Total156100.00%8100.00%

/* * When this function returns the transaction corresponding to tid * will be completed. If the transaction has currently running, start * committing that transaction before waiting for it to complete. If * the transaction id is stale, it is by definition already completed, * so just return SUCCESS. */
int jbd2_complete_transaction(journal_t *journal, tid_t tid) { int need_to_wait = 1; read_lock(&journal->j_state_lock); if (journal->j_running_transaction && journal->j_running_transaction->t_tid == tid) { if (journal->j_commit_request != tid) { /* transaction not yet started, so request it */ read_unlock(&journal->j_state_lock); jbd2_log_start_commit(journal, tid); goto wait_commit; } } else if (!(journal->j_committing_transaction && journal->j_committing_transaction->t_tid == tid)) need_to_wait = 0; read_unlock(&journal->j_state_lock); if (!need_to_wait) return 0; wait_commit: return jbd2_log_wait_commit(journal, tid); }

Contributors

PersonTokensPropCommitsCommitProp
theodore tsotheodore tso118100.00%1100.00%
Total118100.00%1100.00%

EXPORT_SYMBOL(jbd2_complete_transaction); /* * Log buffer allocation routines: */
int jbd2_journal_next_log_block(journal_t *journal, unsigned long long *retp) { unsigned long blocknr; write_lock(&journal->j_state_lock); J_ASSERT(journal->j_free > 1); blocknr = journal->j_head; journal->j_head++; journal->j_free--; if (journal->j_head == journal->j_last) journal->j_head = journal->j_first; write_unlock(&journal->j_state_lock); return jbd2_journal_bmap(journal, blocknr, retp); }

Contributors

PersonTokensPropCommitsCommitProp
dave kleikampdave kleikamp8192.05%125.00%
mingming caomingming cao55.68%250.00%
theodore tsotheodore tso22.27%125.00%
Total88100.00%4100.00%

/* * Conversion of logical to physical block numbers for the journal * * On external journals the journal blocks are identity-mapped, so * this is a no-op. If needed, we can use j_blk_offset - everything is * ready. */
int jbd2_journal_bmap(journal_t *journal, unsigned long blocknr, unsigned long long *retp) { int err = 0; unsigned long long ret; if (journal->j_inode) { ret = bmap(journal->j_inode, blocknr); if (ret) *retp = ret; else { printk(KERN_ALERT "%s: journal block not found " "at offset %lu on %s\n", __func__, blocknr, journal->j_devname); err = -EIO; __journal_abort_soft(journal, err); } } else { *retp = blocknr; /* +journal->j_blk_offset */ } return err; }

Contributors

PersonTokensPropCommitsCommitProp
johann lombardijohann lombardi4747.47%116.67%
dave kleikampdave kleikamp4343.43%116.67%
mingming caomingming cao77.07%233.33%
theodore tsotheodore tso11.01%116.67%
harvey harrisonharvey harrison11.01%116.67%
Total99100.00%6100.00%

/* * We play buffer_head aliasing tricks to write data/metadata blocks to * the journal without copying their contents, but for journal * descriptor blocks we do need to generate bona fide buffers. * * After the caller of jbd2_journal_get_descriptor_buffer() has finished modifying * the buffer's contents they really should run flush_dcache_page(bh->b_page). * But we don't bother doing that, so there will be coherency problems with * mmaps of blockdevs which hold live JBD-controlled filesystems. */
struct buffer_head * jbd2_journal_get_descriptor_buffer(transaction_t *transaction, int type) { journal_t *journal = transaction->t_journal; struct buffer_head *bh; unsigned long long blocknr; journal_header_t *header; int err; err = jbd2_journal_next_log_block(journal, &blocknr); if (err) return NULL; bh = __getblk(journal->j_dev, blocknr, journal->j_blocksize); if (!bh) return NULL; lock_buffer(bh); memset(bh->b_data, 0, journal->j_blocksize); header =