diff options
-rw-r--r-- | drivers/firmware/dmi_scan.c | 6 | ||||
-rw-r--r-- | drivers/message/fusion/mptlan.c | 108 | ||||
-rw-r--r-- | fs/ext4/ialloc.c | 2 | ||||
-rw-r--r-- | fs/ext4/inode.c | 7 | ||||
-rw-r--r-- | fs/ext4/mballoc.c | 1 | ||||
-rw-r--r-- | fs/ext4/super.c | 24 | ||||
-rw-r--r-- | fs/jbd/checkpoint.c | 31 | ||||
-rw-r--r-- | fs/jbd2/checkpoint.c | 32 | ||||
-rw-r--r-- | fs/jbd2/journal.c | 2 |
9 files changed, 72 insertions, 141 deletions
diff --git a/drivers/firmware/dmi_scan.c b/drivers/firmware/dmi_scan.c index 3e526b6d00c..8daf4793ac3 100644 --- a/drivers/firmware/dmi_scan.c +++ b/drivers/firmware/dmi_scan.c @@ -81,9 +81,9 @@ static void dmi_table(u8 *buf, int len, int num, const struct dmi_header *dm = (const struct dmi_header *)data; /* - * We want to know the total length (formated area and strings) - * before decoding to make sure we won't run off the table in - * dmi_decode or dmi_string + * We want to know the total length (formatted area and + * strings) before decoding to make sure we won't run off the + * table in dmi_decode or dmi_string */ data += dm->length; while ((data - buf < len - 1) && (data[0] || data[1])) diff --git a/drivers/message/fusion/mptlan.c b/drivers/message/fusion/mptlan.c index a1abf95cf75..603ffd008c7 100644 --- a/drivers/message/fusion/mptlan.c +++ b/drivers/message/fusion/mptlan.c @@ -77,12 +77,6 @@ MODULE_VERSION(my_VERSION); * Fusion MPT LAN private structures */ -struct NAA_Hosed { - u16 NAA; - u8 ieee[FC_ALEN]; - struct NAA_Hosed *next; -}; - struct BufferControl { struct sk_buff *skb; dma_addr_t dma; @@ -159,11 +153,6 @@ static u8 LanCtx = MPT_MAX_PROTOCOL_DRIVERS; static u32 max_buckets_out = 127; static u32 tx_max_out_p = 127 - 16; -#ifdef QLOGIC_NAA_WORKAROUND -static struct NAA_Hosed *mpt_bad_naa = NULL; -DEFINE_RWLOCK(bad_naa_lock); -#endif - /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/ /** * lan_reply - Handle all data sent from the hardware. @@ -780,30 +769,6 @@ mpt_lan_sdu_send (struct sk_buff *skb, struct net_device *dev) // ctx, skb, skb->data)); mac = skb_mac_header(skb); -#ifdef QLOGIC_NAA_WORKAROUND -{ - struct NAA_Hosed *nh; - - /* Munge the NAA for Tx packets to QLogic boards, which don't follow - RFC 2625. The longer I look at this, the more my opinion of Qlogic - drops. */ - read_lock_irq(&bad_naa_lock); - for (nh = mpt_bad_naa; nh != NULL; nh=nh->next) { - if ((nh->ieee[0] == mac[0]) && - (nh->ieee[1] == mac[1]) && - (nh->ieee[2] == mac[2]) && - (nh->ieee[3] == mac[3]) && - (nh->ieee[4] == mac[4]) && - (nh->ieee[5] == mac[5])) { - cur_naa = nh->NAA; - dlprintk ((KERN_INFO "mptlan/sdu_send: using NAA value " - "= %04x.\n", cur_naa)); - break; - } - } - read_unlock_irq(&bad_naa_lock); -} -#endif pTrans->TransactionDetails[0] = cpu_to_le32((cur_naa << 16) | (mac[0] << 8) | @@ -1572,79 +1537,6 @@ mpt_lan_type_trans(struct sk_buff *skb, struct net_device *dev) fcllc = (struct fcllc *)skb->data; -#ifdef QLOGIC_NAA_WORKAROUND -{ - u16 source_naa = fch->stype, found = 0; - - /* Workaround for QLogic not following RFC 2625 in regards to the NAA - value. */ - - if ((source_naa & 0xF000) == 0) - source_naa = swab16(source_naa); - - if (fcllc->ethertype == htons(ETH_P_ARP)) - dlprintk ((KERN_INFO "mptlan/type_trans: got arp req/rep w/ naa of " - "%04x.\n", source_naa)); - - if ((fcllc->ethertype == htons(ETH_P_ARP)) && - ((source_naa >> 12) != MPT_LAN_NAA_RFC2625)){ - struct NAA_Hosed *nh, *prevnh; - int i; - - dlprintk ((KERN_INFO "mptlan/type_trans: ARP Req/Rep from " - "system with non-RFC 2625 NAA value (%04x).\n", - source_naa)); - - write_lock_irq(&bad_naa_lock); - for (prevnh = nh = mpt_bad_naa; nh != NULL; - prevnh=nh, nh=nh->next) { - if ((nh->ieee[0] == fch->saddr[0]) && - (nh->ieee[1] == fch->saddr[1]) && - (nh->ieee[2] == fch->saddr[2]) && - (nh->ieee[3] == fch->saddr[3]) && - (nh->ieee[4] == fch->saddr[4]) && - (nh->ieee[5] == fch->saddr[5])) { - found = 1; - dlprintk ((KERN_INFO "mptlan/type_trans: ARP Re" - "q/Rep w/ bad NAA from system already" - " in DB.\n")); - break; - } - } - - if ((!found) && (nh == NULL)) { - - nh = kmalloc(sizeof(struct NAA_Hosed), GFP_KERNEL); - dlprintk ((KERN_INFO "mptlan/type_trans: ARP Req/Rep w/" - " bad NAA from system not yet in DB.\n")); - - if (nh != NULL) { - nh->next = NULL; - if (!mpt_bad_naa) - mpt_bad_naa = nh; - if (prevnh) - prevnh->next = nh; - - nh->NAA = source_naa; /* Set the S_NAA value. */ - for (i = 0; i < FC_ALEN; i++) - nh->ieee[i] = fch->saddr[i]; - dlprintk ((KERN_INFO "Got ARP from %02x:%02x:%02x:%02x:" - "%02x:%02x with non-compliant S_NAA value.\n", - fch->saddr[0], fch->saddr[1], fch->saddr[2], - fch->saddr[3], fch->saddr[4],fch->saddr[5])); - } else { - printk (KERN_ERR "mptlan/type_trans: Unable to" - " kmalloc a NAA_Hosed struct.\n"); - } - } else if (!found) { - printk (KERN_ERR "mptlan/type_trans: found not" - " set, but nh isn't null. Evil " - "funkiness abounds.\n"); - } - write_unlock_irq(&bad_naa_lock); - } -} -#endif /* Strip the SNAP header from ARP packets since we don't * pass them through to the 802.2/SNAP layers. diff --git a/fs/ext4/ialloc.c b/fs/ext4/ialloc.c index fe34d74cfb1..2a117e286e5 100644 --- a/fs/ext4/ialloc.c +++ b/fs/ext4/ialloc.c @@ -718,6 +718,8 @@ got: gdp->bg_flags &= cpu_to_le16(~EXT4_BG_BLOCK_UNINIT); free = ext4_free_blocks_after_init(sb, group, gdp); gdp->bg_free_blocks_count = cpu_to_le16(free); + gdp->bg_checksum = ext4_group_desc_csum(sbi, group, + gdp); } spin_unlock(sb_bgl_lock(sbi, group)); diff --git a/fs/ext4/inode.c b/fs/ext4/inode.c index 8dbf6953845..be21a5ae33c 100644 --- a/fs/ext4/inode.c +++ b/fs/ext4/inode.c @@ -2329,6 +2329,8 @@ static int ext4_da_writepage(struct page *page, unlock_page(page); return 0; } + /* now mark the buffer_heads as dirty and uptodate */ + block_commit_write(page, 0, PAGE_CACHE_SIZE); } if (test_opt(inode->i_sb, NOBH) && ext4_should_writeback_data(inode)) @@ -4580,9 +4582,10 @@ static int ext4_indirect_trans_blocks(struct inode *inode, int nrblocks, static int ext4_index_trans_blocks(struct inode *inode, int nrblocks, int chunk) { if (!(EXT4_I(inode)->i_flags & EXT4_EXTENTS_FL)) - return ext4_indirect_trans_blocks(inode, nrblocks, 0); - return ext4_ext_index_trans_blocks(inode, nrblocks, 0); + return ext4_indirect_trans_blocks(inode, nrblocks, chunk); + return ext4_ext_index_trans_blocks(inode, nrblocks, chunk); } + /* * Account for index blocks, block groups bitmaps and block group * descriptor blocks if modify datablocks and index blocks diff --git a/fs/ext4/mballoc.c b/fs/ext4/mballoc.c index dfe17a13405..444ad998f72 100644 --- a/fs/ext4/mballoc.c +++ b/fs/ext4/mballoc.c @@ -4441,6 +4441,7 @@ ext4_mb_free_metadata(handle_t *handle, struct ext4_buddy *e4b, else if (block >= (entry->start_blk + entry->count)) n = &(*n)->rb_right; else { + ext4_unlock_group(sb, group); ext4_error(sb, __func__, "Double free of blocks %d (%d %d)\n", block, entry->start_blk, entry->count); diff --git a/fs/ext4/super.c b/fs/ext4/super.c index 994859df010..e4a241c65db 100644 --- a/fs/ext4/super.c +++ b/fs/ext4/super.c @@ -1458,9 +1458,8 @@ static int ext4_fill_flex_info(struct super_block *sb) /* We allocate both existing and potentially added groups */ flex_group_count = ((sbi->s_groups_count + groups_per_flex - 1) + - ((sbi->s_es->s_reserved_gdt_blocks +1 ) << - EXT4_DESC_PER_BLOCK_BITS(sb))) / - groups_per_flex; + ((le16_to_cpu(sbi->s_es->s_reserved_gdt_blocks) + 1) << + EXT4_DESC_PER_BLOCK_BITS(sb))) / groups_per_flex; sbi->s_flex_groups = kzalloc(flex_group_count * sizeof(struct flex_groups), GFP_KERNEL); if (sbi->s_flex_groups == NULL) { @@ -2885,12 +2884,9 @@ int ext4_force_commit(struct super_block *sb) /* * Ext4 always journals updates to the superblock itself, so we don't * have to propagate any other updates to the superblock on disk at this - * point. Just start an async writeback to get the buffers on their way - * to the disk. - * - * This implicitly triggers the writebehind on sync(). + * point. (We can probably nuke this function altogether, and remove + * any mention to sb->s_dirt in all of fs/ext4; eventual cleanup...) */ - static void ext4_write_super(struct super_block *sb) { if (mutex_trylock(&sb->s_lock) != 0) @@ -2900,15 +2896,15 @@ static void ext4_write_super(struct super_block *sb) static int ext4_sync_fs(struct super_block *sb, int wait) { - tid_t target; + int ret = 0; trace_mark(ext4_sync_fs, "dev %s wait %d", sb->s_id, wait); sb->s_dirt = 0; - if (jbd2_journal_start_commit(EXT4_SB(sb)->s_journal, &target)) { - if (wait) - jbd2_log_wait_commit(EXT4_SB(sb)->s_journal, target); - } - return 0; + if (wait) + ret = ext4_force_commit(sb); + else + jbd2_journal_start_commit(EXT4_SB(sb)->s_journal, NULL); + return ret; } /* diff --git a/fs/jbd/checkpoint.c b/fs/jbd/checkpoint.c index 1bd8d4acc6f..61f32f3868c 100644 --- a/fs/jbd/checkpoint.c +++ b/fs/jbd/checkpoint.c @@ -115,7 +115,7 @@ static int __try_to_free_cp_buf(struct journal_head *jh) */ void __log_wait_for_space(journal_t *journal) { - int nblocks; + int nblocks, space_left; assert_spin_locked(&journal->j_state_lock); nblocks = jbd_space_needed(journal); @@ -128,25 +128,42 @@ void __log_wait_for_space(journal_t *journal) /* * Test again, another process may have checkpointed while we * were waiting for the checkpoint lock. If there are no - * outstanding transactions there is nothing to checkpoint and - * we can't make progress. Abort the journal in this case. + * transactions ready to be checkpointed, try to recover + * journal space by calling cleanup_journal_tail(), and if + * that doesn't work, by waiting for the currently committing + * transaction to complete. If there is absolutely no way + * to make progress, this is either a BUG or corrupted + * filesystem, so abort the journal and leave a stack + * trace for forensic evidence. */ spin_lock(&journal->j_state_lock); spin_lock(&journal->j_list_lock); nblocks = jbd_space_needed(journal); - if (__log_space_left(journal) < nblocks) { + space_left = __log_space_left(journal); + if (space_left < nblocks) { int chkpt = journal->j_checkpoint_transactions != NULL; + tid_t tid = 0; + if (journal->j_committing_transaction) + tid = journal->j_committing_transaction->t_tid; spin_unlock(&journal->j_list_lock); spin_unlock(&journal->j_state_lock); if (chkpt) { log_do_checkpoint(journal); + } else if (cleanup_journal_tail(journal) == 0) { + /* We were able to recover space; yay! */ + ; + } else if (tid) { + log_wait_commit(journal, tid); } else { - printk(KERN_ERR "%s: no transactions\n", - __func__); + printk(KERN_ERR "%s: needed %d blocks and " + "only had %d space available\n", + __func__, nblocks, space_left); + printk(KERN_ERR "%s: no way to get more " + "journal space\n", __func__); + WARN_ON(1); journal_abort(journal, 0); } - spin_lock(&journal->j_state_lock); } else { spin_unlock(&journal->j_list_lock); diff --git a/fs/jbd2/checkpoint.c b/fs/jbd2/checkpoint.c index 9203c3332f1..9497718fe92 100644 --- a/fs/jbd2/checkpoint.c +++ b/fs/jbd2/checkpoint.c @@ -116,7 +116,7 @@ static int __try_to_free_cp_buf(struct journal_head *jh) */ void __jbd2_log_wait_for_space(journal_t *journal) { - int nblocks; + int nblocks, space_left; assert_spin_locked(&journal->j_state_lock); nblocks = jbd_space_needed(journal); @@ -129,25 +129,43 @@ void __jbd2_log_wait_for_space(journal_t *journal) /* * Test again, another process may have checkpointed while we * were waiting for the checkpoint lock. If there are no - * outstanding transactions there is nothing to checkpoint and - * we can't make progress. Abort the journal in this case. + * transactions ready to be checkpointed, try to recover + * journal space by calling cleanup_journal_tail(), and if + * that doesn't work, by waiting for the currently committing + * transaction to complete. If there is absolutely no way + * to make progress, this is either a BUG or corrupted + * filesystem, so abort the journal and leave a stack + * trace for forensic evidence. */ spin_lock(&journal->j_state_lock); spin_lock(&journal->j_list_lock); nblocks = jbd_space_needed(journal); - if (__jbd2_log_space_left(journal) < nblocks) { + space_left = __jbd2_log_space_left(journal); + if (space_left < nblocks) { int chkpt = journal->j_checkpoint_transactions != NULL; + tid_t tid = 0; + if (journal->j_committing_transaction) + tid = journal->j_committing_transaction->t_tid; spin_unlock(&journal->j_list_lock); spin_unlock(&journal->j_state_lock); if (chkpt) { jbd2_log_do_checkpoint(journal); + } else if (jbd2_cleanup_journal_tail(journal) == 0) { + /* We were able to recover space; yay! */ + ; + } else if (tid) { + jbd2_log_wait_commit(journal, tid); } else { - printk(KERN_ERR "%s: no transactions\n", - __func__); + printk(KERN_ERR "%s: needed %d blocks and " + "only had %d space available\n", + __func__, nblocks, space_left); + printk(KERN_ERR "%s: no way to get more " + "journal space in %s\n", __func__, + journal->j_devname); + WARN_ON(1); jbd2_journal_abort(journal, 0); } - spin_lock(&journal->j_state_lock); } else { spin_unlock(&journal->j_list_lock); diff --git a/fs/jbd2/journal.c b/fs/jbd2/journal.c index 783de118de9..e70d657a19f 100644 --- a/fs/jbd2/journal.c +++ b/fs/jbd2/journal.c @@ -1089,6 +1089,7 @@ journal_t * jbd2_journal_init_inode (struct inode *inode) if (!journal->j_wbuf) { printk(KERN_ERR "%s: Cant allocate bhs for commit thread\n", __func__); + jbd2_stats_proc_exit(journal); kfree(journal); return NULL; } @@ -1098,6 +1099,7 @@ journal_t * jbd2_journal_init_inode (struct inode *inode) if (err) { printk(KERN_ERR "%s: Cannnot locate journal superblock\n", __func__); + jbd2_stats_proc_exit(journal); kfree(journal); return NULL; } |