X-Git-Url: http://git.onelab.eu/?a=blobdiff_plain;f=fs%2Fjbd%2Fjournal.c;h=7f96b5cb67816109e38a51b79a6ee80364e48c5d;hb=43bc926fffd92024b46cafaf7350d669ba9ca884;hp=3c95df4bb817c9feaf5de75834ca7b39d4b2eec7;hpb=5273a3df6485dc2ad6aa7ddd441b9a21970f003b;p=linux-2.6.git diff --git a/fs/jbd/journal.c b/fs/jbd/journal.c index 3c95df4bb..7f96b5cb6 100644 --- a/fs/jbd/journal.c +++ b/fs/jbd/journal.c @@ -33,9 +33,12 @@ #include #include #include -#include +#include #include +#include +#include + EXPORT_SYMBOL(journal_start); EXPORT_SYMBOL(journal_restart); EXPORT_SYMBOL(journal_extend); @@ -54,7 +57,6 @@ EXPORT_SYMBOL(journal_sync_buffer); #endif EXPORT_SYMBOL(journal_flush); EXPORT_SYMBOL(journal_revoke); -EXPORT_SYMBOL(journal_callback_set); EXPORT_SYMBOL(journal_init_dev); EXPORT_SYMBOL(journal_init_inode); @@ -65,7 +67,6 @@ EXPORT_SYMBOL(journal_set_features); EXPORT_SYMBOL(journal_create); EXPORT_SYMBOL(journal_load); EXPORT_SYMBOL(journal_destroy); -EXPORT_SYMBOL(journal_recover); EXPORT_SYMBOL(journal_update_superblock); EXPORT_SYMBOL(journal_abort); EXPORT_SYMBOL(journal_errno); @@ -73,14 +74,15 @@ EXPORT_SYMBOL(journal_ack_err); EXPORT_SYMBOL(journal_clear_err); EXPORT_SYMBOL(log_wait_commit); EXPORT_SYMBOL(journal_start_commit); +EXPORT_SYMBOL(journal_force_commit_nested); EXPORT_SYMBOL(journal_wipe); EXPORT_SYMBOL(journal_blocks_per_page); EXPORT_SYMBOL(journal_invalidatepage); EXPORT_SYMBOL(journal_try_to_free_buffers); -EXPORT_SYMBOL(journal_bmap); EXPORT_SYMBOL(journal_force_commit); static int journal_convert_superblock_v1(journal_t *, journal_superblock_t *); +static void __journal_abort_soft (journal_t *journal, int errno); /* * Helper function used to manage commit timeouts @@ -93,16 +95,6 @@ static void commit_timeout(unsigned long __data) wake_up_process(p); } -/* Static check for data structure consistency. There's no code - * invoked --- we'll just get a linker failure if things aren't right. - */ -void __journal_internal_check(void) -{ - extern void journal_bad_superblock_size(void); - if (sizeof(struct journal_superblock_s) != 1024) - journal_bad_superblock_size(); -} - /* * kjournald: The main thread function used to manage a logging device * journal. @@ -119,24 +111,17 @@ void __journal_internal_check(void) * known as checkpointing, and this thread is responsible for that job. */ -journal_t *current_journal; // AKPM: debug - -int kjournald(void *arg) +static int kjournald(void *arg) { - journal_t *journal = (journal_t *) arg; + journal_t *journal = arg; transaction_t *transaction; - struct timer_list timer; - current_journal = journal; - - daemonize("kjournald"); - - /* Set up an interval timer which can be used to trigger a - commit wakeup after the commit interval expires */ - init_timer(&timer); - timer.data = (unsigned long) current; - timer.function = commit_timeout; - journal->j_commit_timer = &timer; + /* + * 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); /* Record that the journal thread is running */ journal->j_task = current; @@ -151,20 +136,23 @@ int kjournald(void *arg) spin_lock(&journal->j_state_lock); loop: + if (journal->j_flags & JFS_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"); spin_unlock(&journal->j_state_lock); - del_timer_sync(journal->j_commit_timer); + del_timer_sync(&journal->j_commit_timer); journal_commit_transaction(journal); spin_lock(&journal->j_state_lock); - goto end_loop; + goto loop; } wake_up(&journal->j_wait_done_commit); - if (current->flags & PF_FREEZE) { + if (freezing(current)) { /* * The simpler the better. Flushing journal isn't a * good idea, because that depends on threads that may @@ -172,7 +160,7 @@ loop: */ jbd_debug(1, "Now suspending kjournald\n"); spin_unlock(&journal->j_state_lock); - refrigerator(PF_FREEZE); + refrigerator(); spin_lock(&journal->j_state_lock); } else { /* @@ -190,6 +178,8 @@ loop: if (transaction && time_after_eq(jiffies, transaction->t_expires)) should_sleep = 0; + if (journal->j_flags & JFS_UNMOUNT) + should_sleep = 0; if (should_sleep) { spin_unlock(&journal->j_state_lock); schedule(); @@ -208,12 +198,11 @@ loop: journal->j_commit_request = transaction->t_tid; jbd_debug(1, "woke because of timeout\n"); } -end_loop: - if (!(journal->j_flags & JFS_UNMOUNT)) - goto loop; + goto loop; +end_loop: spin_unlock(&journal->j_state_lock); - del_timer_sync(journal->j_commit_timer); + 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"); @@ -222,7 +211,7 @@ end_loop: static void journal_start_thread(journal_t *journal) { - kernel_thread(kjournald, journal, CLONE_VM|CLONE_FS|CLONE_FILES); + kthread_run(kjournald, journal, "kjournald"); wait_event(journal->j_wait_done_commit, journal->j_task != 0); } @@ -324,8 +313,8 @@ repeat: /* * Check for escaping */ - if (*((unsigned int *)(mapped_data + new_offset)) == - htonl(JFS_MAGIC_NUMBER)) { + if (*((__be32 *)(mapped_data + new_offset)) == + cpu_to_be32(JFS_MAGIC_NUMBER)) { need_copy_out = 1; do_escape = 1; } @@ -464,6 +453,39 @@ int log_start_commit(journal_t *journal, tid_t tid) return ret; } +/* + * 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. + * + * We can only force the running transaction if we don't have an active handle; + * otherwise, we will deadlock. + * + * Returns true if a transaction was started. + */ +int journal_force_commit_nested(journal_t *journal) +{ + transaction_t *transaction = NULL; + tid_t tid; + + spin_lock(&journal->j_state_lock); + if (journal->j_running_transaction && !current->journal_info) { + transaction = journal->j_running_transaction; + __log_start_commit(journal, transaction->t_tid); + } else if (journal->j_committing_transaction) + transaction = journal->j_committing_transaction; + + if (!transaction) { + spin_unlock(&journal->j_state_lock); + return 0; /* Nothing to retry */ + } + + tid = transaction->t_tid; + spin_unlock(&journal->j_state_lock); + log_wait_commit(journal, tid); + return 1; +} + /* * Start a commit of the current running transaction (if any). Returns true * if a transaction was started, and fills its tid in at *ptid @@ -585,9 +607,13 @@ int journal_bmap(journal_t *journal, unsigned long blocknr, * 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 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 journal_head * journal_get_descriptor_buffer(journal_t *journal) +struct journal_head *journal_get_descriptor_buffer(journal_t *journal) { struct buffer_head *bh; unsigned long blocknr; @@ -599,8 +625,10 @@ struct journal_head * journal_get_descriptor_buffer(journal_t *journal) return NULL; bh = __getblk(journal->j_dev, blocknr, journal->j_blocksize); + lock_buffer(bh); memset(bh->b_data, 0, journal->j_blocksize); - bh->b_state |= (1 << BH_Dirty); + set_buffer_uptodate(bh); + unlock_buffer(bh); BUFFER_TRACE(bh, "return this buffer"); return journal_add_journal_head(bh); } @@ -630,8 +658,8 @@ static journal_t * journal_init_common (void) init_waitqueue_head(&journal->j_wait_checkpoint); init_waitqueue_head(&journal->j_wait_commit); init_waitqueue_head(&journal->j_wait_updates); - init_MUTEX(&journal->j_barrier); - init_MUTEX(&journal->j_checkpoint_sem); + mutex_init(&journal->j_barrier); + mutex_init(&journal->j_checkpoint_mutex); spin_lock_init(&journal->j_revoke_lock); spin_lock_init(&journal->j_list_lock); spin_lock_init(&journal->j_state_lock); @@ -680,6 +708,7 @@ journal_t * journal_init_dev(struct block_device *bdev, { journal_t *journal = journal_init_common(); struct buffer_head *bh; + int n; if (!journal) return NULL; @@ -695,6 +724,17 @@ journal_t * journal_init_dev(struct block_device *bdev, journal->j_sb_buffer = bh; journal->j_superblock = (journal_superblock_t *)bh->b_data; + /* journal descriptor can store up to n blocks -bzzz */ + n = journal->j_blocksize / sizeof(journal_block_tag_t); + journal->j_wbufsize = n; + journal->j_wbuf = kmalloc(n * sizeof(struct buffer_head*), GFP_KERNEL); + if (!journal->j_wbuf) { + printk(KERN_ERR "%s: Cant allocate bhs for commit thread\n", + __FUNCTION__); + kfree(journal); + journal = NULL; + } + return journal; } @@ -711,6 +751,7 @@ journal_t * journal_init_inode (struct inode *inode) struct buffer_head *bh; journal_t *journal = journal_init_common(); int err; + int n; unsigned long blocknr; if (!journal) @@ -727,6 +768,17 @@ journal_t * journal_init_inode (struct inode *inode) journal->j_maxlen = inode->i_size >> inode->i_sb->s_blocksize_bits; journal->j_blocksize = inode->i_sb->s_blocksize; + /* journal descriptor can store up to n blocks -bzzz */ + n = journal->j_blocksize / sizeof(journal_block_tag_t); + journal->j_wbufsize = n; + journal->j_wbuf = kmalloc(n * sizeof(struct buffer_head*), GFP_KERNEL); + if (!journal->j_wbuf) { + printk(KERN_ERR "%s: Cant allocate bhs for commit thread\n", + __FUNCTION__); + kfree(journal); + return NULL; + } + err = journal_bmap(journal, 0, &blocknr); /* If that failed, give up */ if (err) { @@ -768,8 +820,8 @@ static int journal_reset(journal_t *journal) journal_superblock_t *sb = journal->j_superblock; unsigned int first, last; - first = ntohl(sb->s_first); - last = ntohl(sb->s_maxlen); + first = be32_to_cpu(sb->s_first); + last = be32_to_cpu(sb->s_maxlen); journal->j_first = first; journal->j_last = last; @@ -846,12 +898,12 @@ int journal_create(journal_t *journal) /* OK, fill in the initial static fields in the new superblock */ sb = journal->j_superblock; - sb->s_header.h_magic = htonl(JFS_MAGIC_NUMBER); - sb->s_header.h_blocktype = htonl(JFS_SUPERBLOCK_V2); + sb->s_header.h_magic = cpu_to_be32(JFS_MAGIC_NUMBER); + sb->s_header.h_blocktype = cpu_to_be32(JFS_SUPERBLOCK_V2); - sb->s_blocksize = htonl(journal->j_blocksize); - sb->s_maxlen = htonl(journal->j_maxlen); - sb->s_first = htonl(1); + sb->s_blocksize = cpu_to_be32(journal->j_blocksize); + sb->s_maxlen = cpu_to_be32(journal->j_maxlen); + sb->s_first = cpu_to_be32(1); journal->j_transaction_sequence = 1; @@ -894,9 +946,9 @@ void journal_update_superblock(journal_t *journal, int wait) jbd_debug(1,"JBD: updating superblock (start %ld, seq %d, errno %d)\n", journal->j_tail, journal->j_tail_sequence, journal->j_errno); - sb->s_sequence = htonl(journal->j_tail_sequence); - sb->s_start = htonl(journal->j_tail); - sb->s_errno = htonl(journal->j_errno); + sb->s_sequence = cpu_to_be32(journal->j_tail_sequence); + sb->s_start = cpu_to_be32(journal->j_tail); + sb->s_errno = cpu_to_be32(journal->j_errno); spin_unlock(&journal->j_state_lock); BUFFER_TRACE(bh, "marking dirty"); @@ -904,7 +956,7 @@ void journal_update_superblock(journal_t *journal, int wait) if (wait) sync_dirty_buffer(bh); else - ll_rw_block(WRITE, 1, &bh); + ll_rw_block(SWRITE, 1, &bh); out: /* If we have just flushed the log (by marking s_start==0), then @@ -947,13 +999,13 @@ static int journal_get_superblock(journal_t *journal) err = -EINVAL; - if (sb->s_header.h_magic != htonl(JFS_MAGIC_NUMBER) || - sb->s_blocksize != htonl(journal->j_blocksize)) { + if (sb->s_header.h_magic != cpu_to_be32(JFS_MAGIC_NUMBER) || + sb->s_blocksize != cpu_to_be32(journal->j_blocksize)) { printk(KERN_WARNING "JBD: no valid journal superblock found\n"); goto out; } - switch(ntohl(sb->s_header.h_blocktype)) { + switch(be32_to_cpu(sb->s_header.h_blocktype)) { case JFS_SUPERBLOCK_V1: journal->j_format_version = 1; break; @@ -965,9 +1017,9 @@ static int journal_get_superblock(journal_t *journal) goto out; } - if (ntohl(sb->s_maxlen) < journal->j_maxlen) - journal->j_maxlen = ntohl(sb->s_maxlen); - else if (ntohl(sb->s_maxlen) > journal->j_maxlen) { + if (be32_to_cpu(sb->s_maxlen) < journal->j_maxlen) + journal->j_maxlen = be32_to_cpu(sb->s_maxlen); + else if (be32_to_cpu(sb->s_maxlen) > journal->j_maxlen) { printk (KERN_WARNING "JBD: journal file too short\n"); goto out; } @@ -995,11 +1047,11 @@ static int load_superblock(journal_t *journal) sb = journal->j_superblock; - journal->j_tail_sequence = ntohl(sb->s_sequence); - journal->j_tail = ntohl(sb->s_start); - journal->j_first = ntohl(sb->s_first); - journal->j_last = ntohl(sb->s_maxlen); - journal->j_errno = ntohl(sb->s_errno); + journal->j_tail_sequence = be32_to_cpu(sb->s_sequence); + journal->j_tail = be32_to_cpu(sb->s_start); + journal->j_first = be32_to_cpu(sb->s_first); + journal->j_last = be32_to_cpu(sb->s_maxlen); + journal->j_errno = be32_to_cpu(sb->s_errno); return 0; } @@ -1100,12 +1152,17 @@ void journal_destroy(journal_t *journal) iput(journal->j_inode); if (journal->j_revoke) journal_destroy_revoke(journal); + kfree(journal->j_wbuf); kfree(journal); } /** *int journal_check_used_features () - Check if features specified are used. + * @journal: Journal to check. + * @compat: bitmask of compatible features + * @ro: bitmask of features that force read-only mount + * @incompat: bitmask of incompatible features * * Check whether the journal uses all of a given set of * features. Return true (non-zero) if it does. @@ -1133,6 +1190,10 @@ int journal_check_used_features (journal_t *journal, unsigned long compat, /** * int journal_check_available_features() - Check feature set in journalling layer + * @journal: Journal to check. + * @compat: bitmask of compatible features + * @ro: bitmask of features that force read-only mount + * @incompat: bitmask of incompatible features * * Check whether the journaling code supports the use of * all of a given set of features on this journal. Return true @@ -1165,6 +1226,10 @@ int journal_check_available_features (journal_t *journal, unsigned long compat, /** * int journal_set_features () - Mark a given journal feature in the superblock + * @journal: Journal to act on. + * @compat: bitmask of compatible features + * @ro: bitmask of features that force read-only mount + * @incompat: bitmask of incompatible features * * Mark a given journal feature as present on the * superblock. Returns true if the requested features could be set. @@ -1197,6 +1262,7 @@ int journal_set_features (journal_t *journal, unsigned long compat, /** * int journal_update_format () - Update on-disk journal structure. + * @journal: Journal to act on. * * Given an initialised but unloaded journal struct, poke about in the * on-disk structure to update it to the most recent supported version. @@ -1212,7 +1278,7 @@ int journal_update_format (journal_t *journal) sb = journal->j_superblock; - switch (ntohl(sb->s_header.h_blocktype)) { + switch (be32_to_cpu(sb->s_header.h_blocktype)) { case JFS_SUPERBLOCK_V2: return 0; case JFS_SUPERBLOCK_V1: @@ -1234,7 +1300,7 @@ static int journal_convert_superblock_v1(journal_t *journal, /* Pre-initialise new fields to zero */ offset = ((char *) &(sb->s_feature_compat)) - ((char *) sb); - blocksize = ntohl(sb->s_blocksize); + blocksize = be32_to_cpu(sb->s_blocksize); memset(&sb->s_feature_compat, 0, blocksize-offset); sb->s_nr_users = cpu_to_be32(1); @@ -1360,7 +1426,7 @@ int journal_wipe(journal_t *journal, int write) * device this journal is present. */ -const char *journal_dev_name(journal_t *journal, char *buffer) +static const char *journal_dev_name(journal_t *journal, char *buffer) { struct block_device *bdev; @@ -1406,7 +1472,7 @@ void __journal_abort_hard(journal_t *journal) /* Soft abort: record the abort error status in the journal superblock, * but don't do any other IO. */ -void __journal_abort_soft (journal_t *journal, int errno) +static void __journal_abort_soft (journal_t *journal, int errno) { if (journal->j_flags & JFS_ABORT) return; @@ -1497,6 +1563,7 @@ int journal_errno(journal_t *journal) /** * int journal_clear_err () - clears the journal's error state + * @journal: journal to act on. * * An error must be cleared or Acked to take a FS out of readonly * mode. @@ -1516,6 +1583,7 @@ int journal_clear_err(journal_t *journal) /** * void journal_ack_err() - Ack journal err. + * @journal: journal to act on. * * An error must be cleared or Acked to take a FS out of readonly * mode. @@ -1534,14 +1602,10 @@ int journal_blocks_per_page(struct inode *inode) } /* - * Simple support for retying memory allocations. Introduced to help to - * debug different VM deadlock avoidance strategies. - */ -/* - * Simple support for retying memory allocations. Introduced to help to + * Simple support for retrying memory allocations. Introduced to help to * debug different VM deadlock avoidance strategies. */ -void * __jbd_kmalloc (const char *where, size_t size, int flags, int retry) +void * __jbd_kmalloc (const char *where, size_t size, gfp_t flags, int retry) { return kmalloc(size, flags | (retry ? __GFP_NOFAIL : 0)); } @@ -1577,7 +1641,7 @@ static void journal_destroy_journal_head_cache(void) { J_ASSERT(journal_head_cache != NULL); kmem_cache_destroy(journal_head_cache); - journal_head_cache = 0; + journal_head_cache = NULL; } /* @@ -1726,6 +1790,7 @@ static void __journal_remove_journal_head(struct buffer_head *bh) if (jh->b_transaction == NULL && jh->b_next_transaction == NULL && jh->b_cp_transaction == NULL) { + J_ASSERT_JH(jh, jh->b_jlist == BJ_None); J_ASSERT_BH(bh, buffer_jbd(bh)); J_ASSERT_BH(bh, jh2bh(jh) == bh); BUFFER_TRACE(bh, "remove journal_head"); @@ -1802,7 +1867,7 @@ EXPORT_SYMBOL(journal_enable_debug); static struct proc_dir_entry *proc_jbd_debug; -int read_jbd_debug(char *page, char **start, off_t off, +static int read_jbd_debug(char *page, char **start, off_t off, int count, int *eof, void *data) { int ret; @@ -1812,7 +1877,7 @@ int read_jbd_debug(char *page, char **start, off_t off, return ret; } -int write_jbd_debug(struct file *file, const char __user *buffer, +static int write_jbd_debug(struct file *file, const char __user *buffer, unsigned long count, void *data) { char buf[32]; @@ -1901,6 +1966,14 @@ static int __init journal_init(void) { int ret; +/* Static check for data structure consistency. There's no code + * invoked --- we'll just get a linker failure if things aren't right. + */ + extern void journal_bad_superblock_size(void); + if (sizeof(struct journal_superblock_s) != 1024) + journal_bad_superblock_size(); + + ret = journal_init_caches(); if (ret != 0) journal_destroy_caches();