return jbd2_journal_start_thread(journal);
 }
 
+/*
+ * This function expects that the caller will have locked the journal
+ * buffer head, and will return with it unlocked
+ */
 static int jbd2_write_superblock(journal_t *journal, int write_flags)
 {
        struct buffer_head *bh = journal->j_sb_buffer;
        trace_jbd2_write_superblock(journal, write_flags);
        if (!(journal->j_flags & JBD2_BARRIER))
                write_flags &= ~(REQ_FUA | REQ_PREFLUSH);
-       lock_buffer(bh);
        if (buffer_write_io_error(bh)) {
                /*
                 * Oh, dear.  A previous attempt to write the journal
        jbd_debug(1, "JBD2: updating superblock (start %lu, seq %u)\n",
                  tail_block, tail_tid);
 
+       lock_buffer(journal->j_sb_buffer);
        sb->s_sequence = cpu_to_be32(tail_tid);
        sb->s_start    = cpu_to_be32(tail_block);
 
        journal_superblock_t *sb = journal->j_superblock;
 
        BUG_ON(!mutex_is_locked(&journal->j_checkpoint_mutex));
-       read_lock(&journal->j_state_lock);
-       /* Is it already empty? */
-       if (sb->s_start == 0) {
-               read_unlock(&journal->j_state_lock);
+       lock_buffer(journal->j_sb_buffer);
+       if (sb->s_start == 0) {         /* Is it already empty? */
+               unlock_buffer(journal->j_sb_buffer);
                return;
        }
+
        jbd_debug(1, "JBD2: Marking journal as empty (seq %d)\n",
                  journal->j_tail_sequence);
 
        sb->s_sequence = cpu_to_be32(journal->j_tail_sequence);
        sb->s_start    = cpu_to_be32(0);
-       read_unlock(&journal->j_state_lock);
 
        jbd2_write_superblock(journal, write_op);
 
        journal_superblock_t *sb = journal->j_superblock;
        int errcode;
 
-       read_lock(&journal->j_state_lock);
+       lock_buffer(journal->j_sb_buffer);
        errcode = journal->j_errno;
-       read_unlock(&journal->j_state_lock);
        if (errcode == -ESHUTDOWN)
                errcode = 0;
        jbd_debug(1, "JBD2: updating superblock error (errno %d)\n", errcode);
 
        sb = journal->j_superblock;
 
+       /* Load the checksum driver if necessary */
+       if ((journal->j_chksum_driver == NULL) &&
+           INCOMPAT_FEATURE_ON(JBD2_FEATURE_INCOMPAT_CSUM_V3)) {
+               journal->j_chksum_driver = crypto_alloc_shash("crc32c", 0, 0);
+               if (IS_ERR(journal->j_chksum_driver)) {
+                       printk(KERN_ERR "JBD2: Cannot load crc32c driver.\n");
+                       journal->j_chksum_driver = NULL;
+                       return 0;
+               }
+               /* Precompute checksum seed for all metadata */
+               journal->j_csum_seed = jbd2_chksum(journal, ~0, sb->s_uuid,
+                                                  sizeof(sb->s_uuid));
+       }
+
+       lock_buffer(journal->j_sb_buffer);
+
        /* If enabling v3 checksums, update superblock */
        if (INCOMPAT_FEATURE_ON(JBD2_FEATURE_INCOMPAT_CSUM_V3)) {
                sb->s_checksum_type = JBD2_CRC32C_CHKSUM;
                sb->s_feature_compat &=
                        ~cpu_to_be32(JBD2_FEATURE_COMPAT_CHECKSUM);
-
-               /* Load the checksum driver */
-               if (journal->j_chksum_driver == NULL) {
-                       journal->j_chksum_driver = crypto_alloc_shash("crc32c",
-                                                                     0, 0);
-                       if (IS_ERR(journal->j_chksum_driver)) {
-                               printk(KERN_ERR "JBD2: Cannot load crc32c "
-                                      "driver.\n");
-                               journal->j_chksum_driver = NULL;
-                               return 0;
-                       }
-
-                       /* Precompute checksum seed for all metadata */
-                       journal->j_csum_seed = jbd2_chksum(journal, ~0,
-                                                          sb->s_uuid,
-                                                          sizeof(sb->s_uuid));
-               }
        }
 
        /* If enabling v1 checksums, downgrade superblock */
        sb->s_feature_compat    |= cpu_to_be32(compat);
        sb->s_feature_ro_compat |= cpu_to_be32(ro);
        sb->s_feature_incompat  |= cpu_to_be32(incompat);
+       unlock_buffer(journal->j_sb_buffer);
 
        return 1;
 #undef COMPAT_FEATURE_ON