fedora core 6 1.2949 + vserver 2.2.0
[linux-2.6.git] / fs / jfs / jfs_logmgr.c
index f4ce460..5065baa 100644 (file)
@@ -4,16 +4,16 @@
  *
  *   This program is free software;  you can redistribute it and/or modify
  *   it under the terms of the GNU General Public License as published by
- *   the Free Software Foundation; either version 2 of the License, or 
+ *   the Free Software Foundation; either version 2 of the License, or
  *   (at your option) any later version.
- * 
+ *
  *   This program is distributed in the hope that it will be useful,
  *   but WITHOUT ANY WARRANTY;  without even the implied warranty of
  *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See
  *   the GNU General Public License for more details.
  *
  *   You should have received a copy of the GNU General Public License
- *   along with this program;  if not, write to the Free Software 
+ *   along with this program;  if not, write to the Free Software
  *   Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
  */
 
 #include <linux/interrupt.h>
 #include <linux/smp_lock.h>
 #include <linux/completion.h>
+#include <linux/kthread.h>
 #include <linux/buffer_head.h>         /* for sync_blockdev() */
 #include <linux/bio.h>
-#include <linux/suspend.h>
+#include <linux/freezer.h>
+#include <linux/delay.h>
+#include <linux/mutex.h>
 #include "jfs_incore.h"
 #include "jfs_filsys.h"
 #include "jfs_metapage.h"
+#include "jfs_superblock.h"
 #include "jfs_txnmgr.h"
 #include "jfs_debug.h"
 
  * lbuf's ready to be redriven.  Protected by log_redrive_lock (jfsIO thread)
  */
 static struct lbuf *log_redrive_list;
-static spinlock_t log_redrive_lock = SPIN_LOCK_UNLOCKED;
-DECLARE_WAIT_QUEUE_HEAD(jfs_IO_thread_wait);
+static DEFINE_SPINLOCK(log_redrive_lock);
 
 
 /*
  *     log read/write serialization (per log)
  */
-#define LOG_LOCK_INIT(log)     init_MUTEX(&(log)->loglock)
-#define LOG_LOCK(log)          down(&((log)->loglock))
-#define LOG_UNLOCK(log)                up(&((log)->loglock))
+#define LOG_LOCK_INIT(log)     mutex_init(&(log)->loglock)
+#define LOG_LOCK(log)          mutex_lock(&((log)->loglock))
+#define LOG_UNLOCK(log)                mutex_unlock(&((log)->loglock))
 
 
 /*
@@ -113,7 +116,7 @@ DECLARE_WAIT_QUEUE_HEAD(jfs_IO_thread_wait);
 /*
  *     log buffer cache synchronization
  */
-static spinlock_t jfsLCacheLock = SPIN_LOCK_UNLOCKED;
+static DEFINE_SPINLOCK(jfsLCacheLock);
 
 #define        LCACHE_LOCK(flags)      spin_lock_irqsave(&jfsLCacheLock, flags)
 #define        LCACHE_UNLOCK(flags)    spin_unlock_irqrestore(&jfsLCacheLock, flags)
@@ -161,17 +164,9 @@ do {                                               \
 /*
  * Global list of active external journals
  */
-LIST_HEAD(jfs_external_logs);
-struct jfs_log *dummy_log = NULL;
-DECLARE_MUTEX(jfs_log_sem);
-
-/*
- * external references
- */
-extern void txLazyUnlock(struct tblock * tblk);
-extern int jfs_stop_threads;
-extern struct completion jfsIOwait;
-extern int jfs_tlocks_low;
+static LIST_HEAD(jfs_external_logs);
+static struct jfs_log *dummy_log = NULL;
+static DEFINE_MUTEX(jfs_log_mutex);
 
 /*
  * forward references
@@ -197,7 +192,7 @@ static int lbmIOWait(struct lbuf * bp, int flag);
 static bio_end_io_t lbmIODone;
 static void lbmStartIO(struct lbuf * bp);
 static void lmGCwrite(struct jfs_log * log, int cant_block);
-static int lmLogSync(struct jfs_log * log, int nosyncwait);
+static int lmLogSync(struct jfs_log * log, int hard_sync);
 
 
 
@@ -205,7 +200,7 @@ static int lmLogSync(struct jfs_log * log, int nosyncwait);
  *     statistics
  */
 #ifdef CONFIG_JFS_STATISTICS
-struct lmStat {
+static struct lmStat {
        uint commit;            /* # of commit */
        uint pagedone;          /* # of page written */
        uint submitted;         /* # of pages submitted */
@@ -233,6 +228,7 @@ int lmLog(struct jfs_log * log, struct tblock * tblk, struct lrd * lrd,
        int lsn;
        int diffp, difft;
        struct metapage *mp = NULL;
+       unsigned long flags;
 
        jfs_info("lmLog: log:0x%p tblk:0x%p, lrd:0x%p tlck:0x%p",
                 log, tblk, lrd, tlck);
@@ -253,7 +249,7 @@ int lmLog(struct jfs_log * log, struct tblock * tblk, struct lrd * lrd,
         */
        lsn = log->lsn;
 
-       LOGSYNC_LOCK(log);
+       LOGSYNC_LOCK(log, flags);
 
        /*
         * initialize page lsn if first log write of the page
@@ -309,7 +305,7 @@ int lmLog(struct jfs_log * log, struct tblock * tblk, struct lrd * lrd,
                }
        }
 
-       LOGSYNC_UNLOCK(log);
+       LOGSYNC_UNLOCK(log, flags);
 
        /*
         *      write the log record
@@ -333,7 +329,6 @@ int lmLog(struct jfs_log * log, struct tblock * tblk, struct lrd * lrd,
        return lsn;
 }
 
-
 /*
  * NAME:       lmWriteRecord()
  *
@@ -342,7 +337,7 @@ int lmLog(struct jfs_log * log, struct tblock * tblk, struct lrd * lrd,
  * PARAMETER:  cd      - commit descriptor
  *
  * RETURN:     end-of-log address
- *                     
+ *
  * serialization: LOG_LOCK() held on entry/exit
  */
 static int
@@ -559,7 +554,7 @@ lmWriteRecord(struct jfs_log * log, struct tblock * tblk, struct lrd * lrd,
  * PARAMETER:  log
  *
  * RETURN:     0
- *                     
+ *
  * serialization: LOG_LOCK() held on entry/exit
  */
 static int lmNextPage(struct jfs_log * log)
@@ -661,7 +656,7 @@ static int lmNextPage(struct jfs_log * log)
  *     page number - redrive pageout of the page at the head of
  *     pageout queue until full page has been written.
  *
- * RETURN:     
+ * RETURN:
  *
  * NOTE:
  *     LOGGC_LOCK serializes log group commit queue, and
@@ -921,20 +916,17 @@ static void lmPostGC(struct lbuf * bp)
  *     if new sync address is available
  *     (normally the case if sync() is executed by back-ground
  *     process).
- *     if not, explicitly run jfs_blogsync() to initiate
- *     getting of new sync address.
  *     calculate new value of i_nextsync which determines when
  *     this code is called again.
  *
- *     this is called only from lmLog().
- *
- * PARAMETER:  ip      - pointer to logs inode.
+ * PARAMETERS: log     - log structure
+ *             hard_sync - 1 to force all metadata to be written
  *
  * RETURN:     0
- *                     
+ *
  * serialization: LOG_LOCK() held on entry/exit
  */
-static int lmLogSync(struct jfs_log * log, int nosyncwait)
+static int lmLogSync(struct jfs_log * log, int hard_sync)
 {
        int logsize;
        int written;            /* written since last syncpt */
@@ -944,6 +936,22 @@ static int lmLogSync(struct jfs_log * log, int nosyncwait)
        struct lrd lrd;
        int lsn;
        struct logsyncblk *lp;
+       struct jfs_sb_info *sbi;
+       unsigned long flags;
+
+       /* push dirty metapages out to disk */
+       if (hard_sync)
+               list_for_each_entry(sbi, &log->sb_list, log_list) {
+                       filemap_fdatawrite(sbi->ipbmap->i_mapping);
+                       filemap_fdatawrite(sbi->ipimap->i_mapping);
+                       filemap_fdatawrite(sbi->direct_inode->i_mapping);
+               }
+       else
+               list_for_each_entry(sbi, &log->sb_list, log_list) {
+                       filemap_flush(sbi->ipbmap->i_mapping);
+                       filemap_flush(sbi->ipimap->i_mapping);
+                       filemap_flush(sbi->direct_inode->i_mapping);
+               }
 
        /*
         *      forward syncpt
@@ -953,10 +961,7 @@ static int lmLogSync(struct jfs_log * log, int nosyncwait)
         */
 
        if (log->sync == log->syncpt) {
-               LOGSYNC_LOCK(log);
-               /* ToDo: push dirty metapages out to disk */
-//              bmLogSync(log);
-
+               LOGSYNC_LOCK(log, flags);
                if (list_empty(&log->synclist))
                        log->sync = log->lsn;
                else {
@@ -964,7 +969,7 @@ static int lmLogSync(struct jfs_log * log, int nosyncwait)
                                        struct logsyncblk, synclist);
                        log->sync = lp->lsn;
                }
-               LOGSYNC_UNLOCK(log);
+               LOGSYNC_UNLOCK(log, flags);
 
        }
 
@@ -973,23 +978,6 @@ static int lmLogSync(struct jfs_log * log, int nosyncwait)
         * reset syncpt = sync
         */
        if (log->sync != log->syncpt) {
-               struct jfs_sb_info *sbi;
-
-               /*
-                * We need to make sure all of the "written" metapages
-                * actually make it to disk
-                */
-               list_for_each_entry(sbi, &log->sb_list, log_list) {
-                       filemap_fdatawrite(sbi->ipbmap->i_mapping);
-                       filemap_fdatawrite(sbi->ipimap->i_mapping);
-                       filemap_fdatawrite(sbi->sb->s_bdev->bd_inode->i_mapping);
-               }
-               list_for_each_entry(sbi, &log->sb_list, log_list) {
-                       filemap_fdatawait(sbi->ipbmap->i_mapping);
-                       filemap_fdatawait(sbi->ipimap->i_mapping);
-                       filemap_fdatawait(sbi->sb->s_bdev->bd_inode->i_mapping);
-               }
-
                lrd.logtid = 0;
                lrd.backchain = 0;
                lrd.type = cpu_to_le16(LOG_SYNCPT);
@@ -1039,16 +1027,13 @@ static int lmLogSync(struct jfs_log * log, int nosyncwait)
                /* next syncpt trigger = written + more */
                log->nextsync = written + more;
 
-       /* return if lmLogSync() from outside of transaction, e.g., sync() */
-       if (nosyncwait)
-               return lsn;
-
        /* if number of bytes written from last sync point is more
         * than 1/4 of the log size, stop new transactions from
         * starting until all current transactions are completed
         * by setting syncbarrier flag.
         */
-       if (written > LOGSYNC_BARRIER(logsize) && logsize > 32 * LOGPSIZE) {
+       if (!test_bit(log_SYNCBARRIER, &log->flag) &&
+           (written > LOGSYNC_BARRIER(logsize)) && log->active) {
                set_bit(log_SYNCBARRIER, &log->flag);
                jfs_info("log barrier on: lsn=0x%x syncpt=0x%x", lsn,
                         log->syncpt);
@@ -1061,6 +1046,19 @@ static int lmLogSync(struct jfs_log * log, int nosyncwait)
        return lsn;
 }
 
+/*
+ * NAME:       jfs_syncpt
+ *
+ * FUNCTION:   write log SYNCPT record for specified log
+ *
+ * PARAMETERS: log       - log structure
+ *             hard_sync - set to 1 to force metadata to be written
+ */
+void jfs_syncpt(struct jfs_log *log, int hard_sync)
+{      LOG_LOCK(log);
+       lmLogSync(log, hard_sync);
+       LOG_UNLOCK(log);
+}
 
 /*
  * NAME:       lmLogOpen()
@@ -1069,7 +1067,7 @@ static int lmLogSync(struct jfs_log * log, int nosyncwait)
  *     insert filesystem in the active list of the log.
  *
  * PARAMETER:  ipmnt   - file system mount inode
- *             iplog   - log inode (out)
+ *             iplog   - log inode (out)
  *
  * RETURN:
  *
@@ -1084,36 +1082,36 @@ int lmLogOpen(struct super_block *sb)
 
        if (sbi->flag & JFS_NOINTEGRITY)
                return open_dummy_log(sb);
-       
+
        if (sbi->mntflag & JFS_INLINELOG)
                return open_inline_log(sb);
 
-       down(&jfs_log_sem);
+       mutex_lock(&jfs_log_mutex);
        list_for_each_entry(log, &jfs_external_logs, journal_list) {
                if (log->bdev->bd_dev == sbi->logdev) {
                        if (memcmp(log->uuid, sbi->loguuid,
                                   sizeof(log->uuid))) {
                                jfs_warn("wrong uuid on JFS journal\n");
-                               up(&jfs_log_sem);
+                               mutex_unlock(&jfs_log_mutex);
                                return -EINVAL;
                        }
                        /*
                         * add file system to log active file system list
                         */
                        if ((rc = lmLogFileSystem(log, sbi, 1))) {
-                               up(&jfs_log_sem);
+                               mutex_unlock(&jfs_log_mutex);
                                return rc;
                        }
                        goto journal_found;
                }
        }
 
-       if (!(log = kmalloc(sizeof(struct jfs_log), GFP_KERNEL))) {
-               up(&jfs_log_sem);
+       if (!(log = kzalloc(sizeof(struct jfs_log), GFP_KERNEL))) {
+               mutex_unlock(&jfs_log_mutex);
                return -ENOMEM;
        }
-       memset(log, 0, sizeof(struct jfs_log));
        INIT_LIST_HEAD(&log->sb_list);
+       init_waitqueue_head(&log->syncwait);
 
        /*
         *      external log as separate logical volume
@@ -1133,7 +1131,7 @@ int lmLogOpen(struct super_block *sb)
 
        log->bdev = bdev;
        memcpy(log->uuid, sbi->loguuid, sizeof(log->uuid));
-       
+
        /*
         * initialize log:
         */
@@ -1154,7 +1152,7 @@ journal_found:
        sbi->log = log;
        LOG_UNLOCK(log);
 
-       up(&jfs_log_sem);
+       mutex_unlock(&jfs_log_mutex);
        return 0;
 
        /*
@@ -1171,7 +1169,7 @@ journal_found:
        blkdev_put(bdev);
 
       free:            /* free log descriptor */
-       up(&jfs_log_sem);
+       mutex_unlock(&jfs_log_mutex);
        kfree(log);
 
        jfs_warn("lmLogOpen: exit(%d)", rc);
@@ -1183,10 +1181,10 @@ static int open_inline_log(struct super_block *sb)
        struct jfs_log *log;
        int rc;
 
-       if (!(log = kmalloc(sizeof(struct jfs_log), GFP_KERNEL)))
+       if (!(log = kzalloc(sizeof(struct jfs_log), GFP_KERNEL)))
                return -ENOMEM;
-       memset(log, 0, sizeof(struct jfs_log));
        INIT_LIST_HEAD(&log->sb_list);
+       init_waitqueue_head(&log->syncwait);
 
        set_bit(log_INLINELOG, &log->flag);
        log->bdev = sb->s_bdev;
@@ -1215,15 +1213,15 @@ static int open_dummy_log(struct super_block *sb)
 {
        int rc;
 
-       down(&jfs_log_sem);
+       mutex_lock(&jfs_log_mutex);
        if (!dummy_log) {
-               dummy_log = kmalloc(sizeof(struct jfs_log), GFP_KERNEL);
+               dummy_log = kzalloc(sizeof(struct jfs_log), GFP_KERNEL);
                if (!dummy_log) {
-                       up(&jfs_log_sem);
+                       mutex_unlock(&jfs_log_mutex);
                        return -ENOMEM;
                }
-               memset(dummy_log, 0, sizeof(struct jfs_log));
                INIT_LIST_HEAD(&dummy_log->sb_list);
+               init_waitqueue_head(&dummy_log->syncwait);
                dummy_log->no_integrity = 1;
                /* Make up some stuff */
                dummy_log->base = 0;
@@ -1232,7 +1230,7 @@ static int open_dummy_log(struct super_block *sb)
                if (rc) {
                        kfree(dummy_log);
                        dummy_log = NULL;
-                       up(&jfs_log_sem);
+                       mutex_unlock(&jfs_log_mutex);
                        return rc;
                }
        }
@@ -1241,7 +1239,7 @@ static int open_dummy_log(struct super_block *sb)
        list_add(&JFS_SBI(sb)->log_list, &dummy_log->sb_list);
        JFS_SBI(sb)->log = dummy_log;
        LOG_UNLOCK(dummy_log);
-       up(&jfs_log_sem);
+       mutex_unlock(&jfs_log_mutex);
 
        return 0;
 }
@@ -1255,13 +1253,13 @@ static int open_dummy_log(struct super_block *sb)
  *     initialize the log from log superblock.
  *     set the log state in the superblock to LOGMOUNT and
  *     write SYNCPT log record.
- *             
+ *
  * PARAMETER:  log     - log structure
  *
  * RETURN:     0       - if ok
  *             -EINVAL - bad log magic number or superblock dirty
  *             error returned from logwait()
- *                     
+ *
  * serialization: single first open thread
  */
 int lmLogInit(struct jfs_log * log)
@@ -1286,8 +1284,6 @@ int lmLogInit(struct jfs_log * log)
 
        INIT_LIST_HEAD(&log->synclist);
 
-       init_waitqueue_head(&log->syncwait);
-
        INIT_LIST_HEAD(&log->cqueue);
        log->flush_tblk = NULL;
 
@@ -1301,7 +1297,7 @@ int lmLogInit(struct jfs_log * log)
 
        if (!test_bit(log_INLINELOG, &log->flag))
                log->l2bsize = L2LOGPSIZE;
-       
+
        /* check for disabled journaling to disk */
        if (log->no_integrity) {
                /*
@@ -1435,6 +1431,8 @@ int lmLogInit(struct jfs_log * log)
         *      unwind on error
         */
       errout30:                /* release log page */
+       log->wqueue = NULL;
+       bp->l_wqnext = NULL;
        lbmFree(bp);
 
       errout20:                /* release log superblock */
@@ -1469,7 +1467,7 @@ int lmLogClose(struct super_block *sb)
 
        jfs_info("lmLogClose: log:0x%p", log);
 
-       down(&jfs_log_sem);
+       mutex_lock(&jfs_log_mutex);
        LOG_LOCK(log);
        list_del(&sbi->log_list);
        LOG_UNLOCK(log);
@@ -1519,7 +1517,7 @@ int lmLogClose(struct super_block *sb)
        kfree(log);
 
       out:
-       up(&jfs_log_sem);
+       mutex_unlock(&jfs_log_mutex);
        jfs_info("lmLogClose: exit(%d)", rc);
        return rc;
 }
@@ -1539,6 +1537,7 @@ void jfs_flush_journal(struct jfs_log *log, int wait)
 {
        int i;
        struct tblock *target = NULL;
+       struct jfs_sb_info *sbi;
 
        /* jfs_write_inode may call us during read-only mount */
        if (!log)
@@ -1600,21 +1599,44 @@ void jfs_flush_journal(struct jfs_log *log, int wait)
        if (wait < 2)
                return;
 
+       list_for_each_entry(sbi, &log->sb_list, log_list) {
+               filemap_fdatawrite(sbi->ipbmap->i_mapping);
+               filemap_fdatawrite(sbi->ipimap->i_mapping);
+               filemap_fdatawrite(sbi->direct_inode->i_mapping);
+       }
+
        /*
         * If there was recent activity, we may need to wait
         * for the lazycommit thread to catch up
         */
        if ((!list_empty(&log->cqueue)) || !list_empty(&log->synclist)) {
-               for (i = 0; i < 800; i++) {     /* Too much? */
-                       current->state = TASK_INTERRUPTIBLE;
-                       schedule_timeout(HZ / 4);
+               for (i = 0; i < 200; i++) {     /* Too much? */
+                       msleep(250);
                        if (list_empty(&log->cqueue) &&
                            list_empty(&log->synclist))
                                break;
                }
        }
        assert(list_empty(&log->cqueue));
-       assert(list_empty(&log->synclist));
+
+#ifdef CONFIG_JFS_DEBUG
+       if (!list_empty(&log->synclist)) {
+               struct logsyncblk *lp;
+
+               list_for_each_entry(lp, &log->synclist, synclist) {
+                       if (lp->xflag & COMMIT_PAGE) {
+                               struct metapage *mp = (struct metapage *)lp;
+                               dump_mem("orphan metapage", lp,
+                                        sizeof(struct metapage));
+                               dump_mem("page", mp->page, sizeof(struct page));
+                       }
+                       else
+                               dump_mem("orphan tblock", lp,
+                                        sizeof(struct tblock));
+               }
+       }
+#endif
+       //assert(list_empty(&log->synclist));
        clear_bit(log_FLUSH, &log->flag);
 }
 
@@ -1629,7 +1651,7 @@ void jfs_flush_journal(struct jfs_log *log, int wait)
  * PARAMETER:  log     - log inode
  *
  * RETURN:     0       - success
- *                     
+ *
  * serialization: single last close thread
  */
 int lmLogShutdown(struct jfs_log * log)
@@ -1655,13 +1677,14 @@ int lmLogShutdown(struct jfs_log * log)
        lrd.type = cpu_to_le16(LOG_SYNCPT);
        lrd.length = 0;
        lrd.log.syncpt.sync = 0;
-       
+
        lsn = lmWriteRecord(log, NULL, &lrd, NULL);
        bp = log->bp;
        lp = (struct logpage *) bp->l_ldata;
        lp->h.eor = lp->t.eor = cpu_to_le16(bp->l_eor);
        lbmWrite(log, log->bp, lbmWRITE | lbmRELEASE | lbmSYNC, 0);
        lbmIOWait(log->bp, lbmFREE);
+       log->bp = NULL;
 
        /*
         * synchronous update log superblock
@@ -1680,7 +1703,7 @@ int lmLogShutdown(struct jfs_log * log)
        jfs_info("lmLogShutdown: lsn:0x%x page:%d eor:%d",
                 lsn, log->page, log->eor);
 
-      out:    
+      out:
        /*
         * shutdown per log i/o
         */
@@ -1746,7 +1769,7 @@ static int lmLogFileSystem(struct jfs_log * log, struct jfs_sb_info *sbi,
                        lbmFree(bpsuper);
                        return -EIO;
                }
-               
+
        }
 
        /*
@@ -1812,20 +1835,34 @@ static int lbmLogInit(struct jfs_log * log)
 
        log->lbuf_free = NULL;
 
-       for (i = 0; i < LOGPAGES; i++) {
-               lbuf = kmalloc(sizeof(struct lbuf), GFP_KERNEL);
-               if (lbuf == 0)
-                       goto error;
-               lbuf->l_ldata = (char *) get_zeroed_page(GFP_KERNEL);
-               if (lbuf->l_ldata == 0) {
-                       kfree(lbuf);
+       for (i = 0; i < LOGPAGES;) {
+               char *buffer;
+               uint offset;
+               struct page *page;
+
+               buffer = (char *) get_zeroed_page(GFP_KERNEL);
+               if (buffer == NULL)
                        goto error;
+               page = virt_to_page(buffer);
+               for (offset = 0; offset < PAGE_SIZE; offset += LOGPSIZE) {
+                       lbuf = kmalloc(sizeof(struct lbuf), GFP_KERNEL);
+                       if (lbuf == NULL) {
+                               if (offset == 0)
+                                       free_page((unsigned long) buffer);
+                               goto error;
+                       }
+                       if (offset) /* we already have one reference */
+                               get_page(page);
+                       lbuf->l_offset = offset;
+                       lbuf->l_ldata = buffer + offset;
+                       lbuf->l_page = page;
+                       lbuf->l_log = log;
+                       init_waitqueue_head(&lbuf->l_ioevent);
+
+                       lbuf->l_freelist = log->lbuf_free;
+                       log->lbuf_free = lbuf;
+                       i++;
                }
-               lbuf->l_log = log;
-               init_waitqueue_head(&lbuf->l_ioevent);
-
-               lbuf->l_freelist = log->lbuf_free;
-               log->lbuf_free = lbuf;
        }
 
        return (0);
@@ -1850,12 +1887,10 @@ static void lbmLogShutdown(struct jfs_log * log)
        lbuf = log->lbuf_free;
        while (lbuf) {
                struct lbuf *next = lbuf->l_freelist;
-               free_page((unsigned long) lbuf->l_ldata);
+               __free_page(lbuf->l_page);
                kfree(lbuf);
                lbuf = next;
        }
-
-       log->bp = NULL;
 }
 
 
@@ -1943,7 +1978,7 @@ static inline void lbmRedrive(struct lbuf *bp)
        log_redrive_list = bp;
        spin_unlock_irqrestore(&log_redrive_lock, flags);
 
-       wake_up(&jfs_IO_thread_wait);
+       wake_up_process(jfsIOthread);
 }
 
 
@@ -1967,9 +2002,9 @@ static int lbmRead(struct jfs_log * log, int pn, struct lbuf ** bpp)
 
        bio->bi_sector = bp->l_blkno << (log->l2bsize - 9);
        bio->bi_bdev = log->bdev;
-       bio->bi_io_vec[0].bv_page = virt_to_page(bp->l_ldata);
+       bio->bi_io_vec[0].bv_page = bp->l_page;
        bio->bi_io_vec[0].bv_len = LOGPSIZE;
-       bio->bi_io_vec[0].bv_offset = 0;
+       bio->bi_io_vec[0].bv_offset = bp->l_offset;
 
        bio->bi_vcnt = 1;
        bio->bi_idx = 0;
@@ -2108,9 +2143,9 @@ static void lbmStartIO(struct lbuf * bp)
        bio = bio_alloc(GFP_NOFS, 1);
        bio->bi_sector = bp->l_blkno << (log->l2bsize - 9);
        bio->bi_bdev = log->bdev;
-       bio->bi_io_vec[0].bv_page = virt_to_page(bp->l_ldata);
+       bio->bi_io_vec[0].bv_page = bp->l_page;
        bio->bi_io_vec[0].bv_len = LOGPSIZE;
-       bio->bi_io_vec[0].bv_offset = 0;
+       bio->bi_io_vec[0].bv_offset = bp->l_offset;
 
        bio->bi_vcnt = 1;
        bio->bi_idx = 0;
@@ -2120,16 +2155,13 @@ static void lbmStartIO(struct lbuf * bp)
        bio->bi_private = bp;
 
        /* check if journaling to disk has been disabled */
-       if (!log->no_integrity) {
+       if (log->no_integrity) {
+               bio->bi_size = 0;
+               lbmIODone(bio, 0, 0);
+       } else {
                submit_bio(WRITE_SYNC, bio);
                INCREMENT(lmStat.submitted);
        }
-       else {
-               bio->bi_size = 0;
-               lbmIODone(bio, 0, 0); /* 2nd argument appears to not be used => 0
-                                      *  3rd argument appears to not be used => 0
-                                      */
-       }
 }
 
 
@@ -2313,36 +2345,28 @@ int jfsIOWait(void *arg)
 {
        struct lbuf *bp;
 
-       daemonize("jfsIO");
-
-       complete(&jfsIOwait);
-
        do {
-               DECLARE_WAITQUEUE(wq, current);
-
                spin_lock_irq(&log_redrive_lock);
-               while ((bp = log_redrive_list)) {
+               while ((bp = log_redrive_list) != 0) {
                        log_redrive_list = bp->l_redrive_next;
                        bp->l_redrive_next = NULL;
                        spin_unlock_irq(&log_redrive_lock);
                        lbmStartIO(bp);
                        spin_lock_irq(&log_redrive_lock);
                }
-               if (current->flags & PF_FREEZE) {
-                       spin_unlock_irq(&log_redrive_lock);
-                       refrigerator(PF_FREEZE);
+               spin_unlock_irq(&log_redrive_lock);
+
+               if (freezing(current)) {
+                       refrigerator();
                } else {
-                       add_wait_queue(&jfs_IO_thread_wait, &wq);
                        set_current_state(TASK_INTERRUPTIBLE);
-                       spin_unlock_irq(&log_redrive_lock);
                        schedule();
                        current->state = TASK_RUNNING;
-                       remove_wait_queue(&jfs_IO_thread_wait, &wq);
                }
-       } while (!jfs_stop_threads);
+       } while (!kthread_should_stop());
 
        jfs_info("jfsIOWait being killed!");
-       complete_and_exit(&jfsIOwait, 0);
+       return 0;
 }
 
 /*