block: make blkdev_get/put() handle exclusive access
[linux-2.6.git] / fs / jfs / jfs_logmgr.c
index cfcdad3..5a290f2 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/fs.h>
 #include <linux/blkdev.h>
 #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 <linux/seq_file.h>
+#include <linux/slab.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"
 
  */
 static struct lbuf *log_redrive_list;
 static DEFINE_SPINLOCK(log_redrive_lock);
-DECLARE_WAIT_QUEUE_HEAD(jfs_IO_thread_wait);
 
 
 /*
  *     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))
 
 
 /*
@@ -164,15 +167,7 @@ do {                                               \
  */
 static LIST_HEAD(jfs_external_logs);
 static struct jfs_log *dummy_log = NULL;
-static 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 DEFINE_MUTEX(jfs_log_mutex);
 
 /*
  * forward references
@@ -198,7 +193,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);
 
 
 
@@ -215,6 +210,17 @@ static struct lmStat {
 } lmStat;
 #endif
 
+static void write_special_inodes(struct jfs_log *log,
+                                int (*writer)(struct address_space *))
+{
+       struct jfs_sb_info *sbi;
+
+       list_for_each_entry(sbi, &log->sb_list, log_list) {
+               writer(sbi->ipbmap->i_mapping);
+               writer(sbi->ipimap->i_mapping);
+               writer(sbi->direct_inode->i_mapping);
+       }
+}
 
 /*
  * NAME:       lmLog()
@@ -251,7 +257,7 @@ int lmLog(struct jfs_log * log, struct tblock * tblk, struct lrd * lrd,
                goto writeRecord;
 
        /*
-        *      initialize/update page/transaction recovery lsn
+        *      initialize/update page/transaction recovery lsn
         */
        lsn = log->lsn;
 
@@ -270,7 +276,7 @@ int lmLog(struct jfs_log * log, struct tblock * tblk, struct lrd * lrd,
        }
 
        /*
-        *      initialize/update lsn of tblock of the page
+        *      initialize/update lsn of tblock of the page
         *
         * transaction inherits oldest lsn of pages associated
         * with allocation/deallocation of resources (their
@@ -314,7 +320,7 @@ int lmLog(struct jfs_log * log, struct tblock * tblk, struct lrd * lrd,
        LOGSYNC_UNLOCK(log, flags);
 
        /*
-        *      write the log record
+        *      write the log record
         */
       writeRecord:
        lsn = lmWriteRecord(log, tblk, lrd, tlck);
@@ -343,7 +349,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
@@ -379,7 +385,7 @@ lmWriteRecord(struct jfs_log * log, struct tblock * tblk, struct lrd * lrd,
                goto moveLrd;
 
        /*
-        *      move log record data
+        *      move log record data
         */
        /* retrieve source meta-data page to log */
        if (tlck->flag & tlckPAGELOCK) {
@@ -472,7 +478,7 @@ lmWriteRecord(struct jfs_log * log, struct tblock * tblk, struct lrd * lrd,
        }
 
        /*
-        *      move log record descriptor
+        *      move log record descriptor
         */
       moveLrd:
        lrd->length = cpu_to_le16(len);
@@ -560,7 +566,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)
@@ -581,7 +587,7 @@ static int lmNextPage(struct jfs_log * log)
        LOGGC_LOCK(log);
 
        /*
-        *      write or queue the full page at the tail of write queue
+        *      write or queue the full page at the tail of write queue
         */
        /* get the tail tblk on commit queue */
        if (list_empty(&log->cqueue))
@@ -632,7 +638,7 @@ static int lmNextPage(struct jfs_log * log)
        LOGGC_UNLOCK(log);
 
        /*
-        *      allocate/initialize next page
+        *      allocate/initialize next page
         */
        /* if log wraps, the first data page of log is 2
         * (0 never used, 1 is superblock).
@@ -662,7 +668,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
@@ -922,20 +928,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 */
@@ -945,18 +948,16 @@ 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 */
-       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);
-       }
+       if (hard_sync)
+               write_special_inodes(log, filemap_fdatawrite);
+       else
+               write_special_inodes(log, filemap_flush);
 
        /*
-        *      forward syncpt
+        *      forward syncpt
         */
        /* if last sync is same as last syncpt,
         * invoke sync point forward processing to update sync.
@@ -992,7 +993,7 @@ static int lmLogSync(struct jfs_log * log, int nosyncwait)
                lsn = log->lsn;
 
        /*
-        *      setup next syncpt trigger (SWAG)
+        *      setup next syncpt trigger (SWAG)
         */
        logsize = log->logsize;
 
@@ -1003,21 +1004,19 @@ static int lmLogSync(struct jfs_log * log, int nosyncwait)
        if (more < 2 * LOGPSIZE) {
                jfs_warn("\n ... Log Wrap ... Log Wrap ... Log Wrap ...\n");
                /*
-                *      log wrapping
+                *      log wrapping
                 *
                 * option 1 - panic ? No.!
                 * option 2 - shutdown file systems
-                *            associated with log ?
+                *            associated with log ?
                 * option 3 - extend log ?
-                */
-               /*
                 * option 4 - second chance
                 *
                 * mark log wrapped, and continue.
                 * when all active transactions are completed,
-                * mark log vaild for recovery.
+                * mark log valid for recovery.
                 * if crashed during invalid state, log state
-                * implies invald log, forcing fsck().
+                * implies invalid log, forcing fsck().
                 */
                /* mark log state log wrap in log superblock */
                /* log->state = LOGWRAP; */
@@ -1029,16 +1028,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);
@@ -1051,15 +1047,28 @@ 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()
  *
- * FUNCTION:    open the log on first open;
+ * FUNCTION:   open the log on first open;
  *     insert filesystem in the active list of the log.
  *
  * PARAMETER:  ipmnt   - file system mount inode
- *             iplog   - log inode (out)
+ *             iplog   - log inode (out)
  *
  * RETURN:
  *
@@ -1074,62 +1083,58 @@ 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
+        *      external log as separate logical volume
         *
         * file systems to log may have n-to-1 relationship;
         */
 
-       bdev = open_by_devnum(sbi->logdev, FMODE_READ|FMODE_WRITE);
+       bdev = open_by_devnum(sbi->logdev, FMODE_READ|FMODE_WRITE|FMODE_EXCL,
+                             log);
        if (IS_ERR(bdev)) {
                rc = -PTR_ERR(bdev);
                goto free;
        }
 
-       if ((rc = bd_claim(bdev, log))) {
-               goto close;
-       }
-
        log->bdev = bdev;
        memcpy(log->uuid, sbi->loguuid, sizeof(log->uuid));
-       
+
        /*
         * initialize log:
         */
        if ((rc = lmLogInit(log)))
-               goto unclaim;
+               goto close;
 
        list_add(&log->journal_list, &jfs_external_logs);
 
@@ -1145,24 +1150,21 @@ journal_found:
        sbi->log = log;
        LOG_UNLOCK(log);
 
-       up(&jfs_log_sem);
+       mutex_unlock(&jfs_log_mutex);
        return 0;
 
        /*
-        *      unwind on error
+        *      unwind on error
         */
       shutdown:                /* unwind lbmLogInit() */
        list_del(&log->journal_list);
        lbmLogShutdown(log);
 
-      unclaim:
-       bd_release(bdev);
-
       close:           /* close external log device */
-       blkdev_put(bdev);
+       blkdev_put(bdev, FMODE_READ|FMODE_WRITE|FMODE_EXCL);
 
       free:            /* free log descriptor */
-       up(&jfs_log_sem);
+       mutex_unlock(&jfs_log_mutex);
        kfree(log);
 
        jfs_warn("lmLogOpen: exit(%d)", rc);
@@ -1174,9 +1176,8 @@ 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);
 
@@ -1207,14 +1208,13 @@ 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;
@@ -1225,7 +1225,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;
                }
        }
@@ -1234,7 +1234,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;
 }
@@ -1248,13 +1248,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)
@@ -1292,7 +1292,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) {
                /*
@@ -1423,7 +1423,7 @@ int lmLogInit(struct jfs_log * log)
        return 0;
 
        /*
-        *      unwind on error
+        *      unwind on error
         */
       errout30:                /* release log page */
        log->wqueue = NULL;
@@ -1462,7 +1462,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);
@@ -1476,7 +1476,7 @@ int lmLogClose(struct super_block *sb)
 
        if (test_bit(log_INLINELOG, &log->flag)) {
                /*
-                *      in-line log in host file system
+                *      in-line log in host file system
                 */
                rc = lmLogShutdown(log);
                kfree(log);
@@ -1500,19 +1500,18 @@ int lmLogClose(struct super_block *sb)
                goto out;
 
        /*
-        *      external log as separate logical volume
+        *      external log as separate logical volume
         */
        list_del(&log->journal_list);
        bdev = log->bdev;
        rc = lmLogShutdown(log);
 
-       bd_release(bdev);
-       blkdev_put(bdev);
+       blkdev_put(bdev, FMODE_READ|FMODE_WRITE|FMODE_EXCL);
 
        kfree(log);
 
       out:
-       up(&jfs_log_sem);
+       mutex_unlock(&jfs_log_mutex);
        jfs_info("lmLogClose: exit(%d)", rc);
        return rc;
 }
@@ -1532,7 +1531,6 @@ 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)
@@ -1585,7 +1583,7 @@ void jfs_flush_journal(struct jfs_log *log, int wait)
                set_current_state(TASK_UNINTERRUPTIBLE);
                LOGGC_UNLOCK(log);
                schedule();
-               current->state = TASK_RUNNING;
+               __set_current_state(TASK_RUNNING);
                LOGGC_LOCK(log);
                remove_wait_queue(&target->gcwait, &__wait);
        }
@@ -1594,11 +1592,7 @@ 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);
-       }
+       write_special_inodes(log, filemap_fdatawrite);
 
        /*
         * If there was recent activity, we may need to wait
@@ -1607,30 +1601,38 @@ void jfs_flush_journal(struct jfs_log *log, int wait)
        if ((!list_empty(&log->cqueue)) || !list_empty(&log->synclist)) {
                for (i = 0; i < 200; i++) {     /* Too much? */
                        msleep(250);
+                       write_special_inodes(log, filemap_fdatawrite);
                        if (list_empty(&log->cqueue) &&
                            list_empty(&log->synclist))
                                break;
                }
        }
        assert(list_empty(&log->cqueue));
+
+#ifdef CONFIG_JFS_DEBUG
        if (!list_empty(&log->synclist)) {
                struct logsyncblk *lp;
 
+               printk(KERN_ERR "jfs_flush_journal: synclist not empty\n");
                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));
+                               print_hex_dump(KERN_ERR, "metapage: ",
+                                              DUMP_PREFIX_ADDRESS, 16, 4,
+                                              mp, sizeof(struct metapage), 0);
+                               print_hex_dump(KERN_ERR, "page: ",
+                                              DUMP_PREFIX_ADDRESS, 16,
+                                              sizeof(long), mp->page,
+                                              sizeof(struct page), 0);
+                       } else
+                               print_hex_dump(KERN_ERR, "tblock:",
+                                              DUMP_PREFIX_ADDRESS, 16, 4,
+                                              lp, sizeof(struct tblock), 0);
                }
-//             current->state = TASK_INTERRUPTIBLE;
-//             schedule();
        }
-       //assert(list_empty(&log->synclist));
+#else
+       WARN_ON(!list_empty(&log->synclist));
+#endif
        clear_bit(log_FLUSH, &log->flag);
 }
 
@@ -1645,7 +1647,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)
@@ -1671,7 +1673,7 @@ 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;
@@ -1697,7 +1699,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
         */
@@ -1718,7 +1720,7 @@ int lmLogShutdown(struct jfs_log * log)
  *
  * PARAMETE:   log     - pointer to logs inode.
  *             fsdev   - kdev_t of filesystem.
- *             serial  - pointer to returned log serial number
+ *             serial  - pointer to returned log serial number
  *             activate - insert/remove device from active list.
  *
  * RETURN:     0       - success
@@ -1763,7 +1765,7 @@ static int lmLogFileSystem(struct jfs_log * log, struct jfs_sb_info *sbi,
                        lbmFree(bpsuper);
                        return -EIO;
                }
-               
+
        }
 
        /*
@@ -1955,10 +1957,10 @@ static void lbmfree(struct lbuf * bp)
 /*
  * NAME:       lbmRedrive
  *
- * FUNCTION:   add a log buffer to the the log redrive list
+ * FUNCTION:   add a log buffer to the log redrive list
  *
  * PARAMETER:
- *     bp      - log buffer
+ *     bp      - log buffer
  *
  * NOTES:
  *     Takes log_redrive_lock.
@@ -1972,7 +1974,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);
 }
 
 
@@ -2049,7 +2051,7 @@ static void lbmWrite(struct jfs_log * log, struct lbuf * bp, int flag,
        bp->l_flag = flag;
 
        /*
-        *      insert bp at tail of write queue associated with log
+        *      insert bp at tail of write queue associated with log
         *
         * (request is either for bp already/currently at head of queue
         * or new bp to be inserted at tail)
@@ -2112,7 +2114,7 @@ static void lbmDirectWrite(struct jfs_log * log, struct lbuf * bp, int flag)
            log->base + (bp->l_pn << (L2LOGPSIZE - log->l2bsize));
 
        /*
-        *      initiate pageout of the page
+        *      initiate pageout of the page
         */
        lbmStartIO(bp);
 }
@@ -2123,7 +2125,7 @@ static void lbmDirectWrite(struct jfs_log * log, struct lbuf * bp, int flag)
  *
  * FUNCTION:   Interface to DD strategy routine
  *
- * RETURN:      none
+ * RETURN:     none
  *
  * serialization: LCACHE_LOCK() is NOT held during log i/o;
  */
@@ -2151,7 +2153,7 @@ static void lbmStartIO(struct lbuf * bp)
        /* check if journaling to disk has been disabled */
        if (log->no_integrity) {
                bio->bi_size = 0;
-               lbmIODone(bio, 0, 0);
+               lbmIODone(bio, 0);
        } else {
                submit_bio(WRITE_SYNC, bio);
                INCREMENT(lmStat.submitted);
@@ -2189,16 +2191,13 @@ static int lbmIOWait(struct lbuf * bp, int flag)
  *
  * executed at INTIODONE level
  */
-static int lbmIODone(struct bio *bio, unsigned int bytes_done, int error)
+static void lbmIODone(struct bio *bio, int error)
 {
        struct lbuf *bp = bio->bi_private;
        struct lbuf *nextbp, *tail;
        struct jfs_log *log;
        unsigned long flags;
 
-       if (bio->bi_size)
-               return 1;
-
        /*
         * get back jfs buffer bound to the i/o buffer
         */
@@ -2217,7 +2216,7 @@ static int lbmIODone(struct bio *bio, unsigned int bytes_done, int error)
        bio_put(bio);
 
        /*
-        *      pagein completion
+        *      pagein completion
         */
        if (bp->l_flag & lbmREAD) {
                bp->l_flag &= ~lbmREAD;
@@ -2227,11 +2226,11 @@ static int lbmIODone(struct bio *bio, unsigned int bytes_done, int error)
                /* wakeup I/O initiator */
                LCACHE_WAKEUP(&bp->l_ioevent);
 
-               return 0;
+               return;
        }
 
        /*
-        *      pageout completion
+        *      pageout completion
         *
         * the bp at the head of write queue has completed pageout.
         *
@@ -2252,7 +2251,7 @@ static int lbmIODone(struct bio *bio, unsigned int bytes_done, int error)
        if (bp->l_flag & lbmDIRECT) {
                LCACHE_WAKEUP(&bp->l_ioevent);
                LCACHE_UNLOCK(flags);
-               return 0;
+               return;
        }
 
        tail = log->wqueue;
@@ -2297,7 +2296,7 @@ static int lbmIODone(struct bio *bio, unsigned int bytes_done, int error)
        }
 
        /*
-        *      synchronous pageout:
+        *      synchronous pageout:
         *
         * buffer has not necessarily been removed from write queue
         * (e.g., synchronous write of partial-page with COMMIT):
@@ -2311,7 +2310,7 @@ static int lbmIODone(struct bio *bio, unsigned int bytes_done, int error)
        }
 
        /*
-        *      Group Commit pageout:
+        *      Group Commit pageout:
         */
        else if (bp->l_flag & lbmGC) {
                LCACHE_UNLOCK(flags);
@@ -2319,7 +2318,7 @@ static int lbmIODone(struct bio *bio, unsigned int bytes_done, int error)
        }
 
        /*
-        *      asynchronous pageout:
+        *      asynchronous pageout:
         *
         * buffer must have been removed from write queue:
         * insert buffer at head of freelist where it can be recycled
@@ -2331,44 +2330,35 @@ static int lbmIODone(struct bio *bio, unsigned int bytes_done, int error)
 
                LCACHE_UNLOCK(flags);   /* unlock+enable */
        }
-
-       return 0;
 }
 
 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) != 0) {
+               while ((bp = log_redrive_list)) {
                        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) {
+
+               if (freezing(current)) {
                        spin_unlock_irq(&log_redrive_lock);
-                       refrigerator(PF_FREEZE);
+                       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);
+                       __set_current_state(TASK_RUNNING);
                }
-       } while (!jfs_stop_threads);
+       } while (!kthread_should_stop());
 
        jfs_info("jfsIOWait being killed!");
-       complete_and_exit(&jfsIOwait, 0);
+       return 0;
 }
 
 /*
@@ -2377,7 +2367,7 @@ int jfsIOWait(void *arg)
  * FUNCTION:   format file system log
  *
  * PARAMETERS:
- *      log    - volume log
+ *     log     - volume log
  *     logAddress - start address of log space in FS block
  *     logSize - length of log space in FS block;
  *
@@ -2409,16 +2399,16 @@ int lmLogFormat(struct jfs_log *log, s64 logAddress, int logSize)
        npages = logSize >> sbi->l2nbperpage;
 
        /*
-        *      log space:
+        *      log space:
         *
         * page 0 - reserved;
         * page 1 - log superblock;
         * page 2 - log data page: A SYNC log record is written
-        *          into this page at logform time;
+        *          into this page at logform time;
         * pages 3-N - log data page: set to empty log data pages;
         */
        /*
-        *      init log superblock: log page 1
+        *      init log superblock: log page 1
         */
        logsuper = (struct logsuper *) bp->l_ldata;
 
@@ -2438,7 +2428,7 @@ int lmLogFormat(struct jfs_log *log, s64 logAddress, int logSize)
                goto exit;
 
        /*
-        *      init pages 2 to npages-1 as log data pages:
+        *      init pages 2 to npages-1 as log data pages:
         *
         * log page sequence number (lpsn) initialization:
         *
@@ -2481,7 +2471,7 @@ int lmLogFormat(struct jfs_log *log, s64 logAddress, int logSize)
                goto exit;
 
        /*
-        *      initialize succeeding log pages: lpsn = 0, 1, ..., (N-2)
+        *      initialize succeeding log pages: lpsn = 0, 1, ..., (N-2)
         */
        for (lspn = 0; lspn < npages - 3; lspn++) {
                lp->h.page = lp->t.page = cpu_to_le32(lspn);
@@ -2497,7 +2487,7 @@ int lmLogFormat(struct jfs_log *log, s64 logAddress, int logSize)
        rc = 0;
 exit:
        /*
-        *      finalize log
+        *      finalize log
         */
        /* release the buffer */
        lbmFree(bp);
@@ -2506,13 +2496,9 @@ exit:
 }
 
 #ifdef CONFIG_JFS_STATISTICS
-int jfs_lmstats_read(char *buffer, char **start, off_t offset, int length,
-                     int *eof, void *data)
+static int jfs_lmstats_proc_show(struct seq_file *m, void *v)
 {
-       int len = 0;
-       off_t begin;
-
-       len += sprintf(buffer,
+       seq_printf(m,
                       "JFS Logmgr stats\n"
                       "================\n"
                       "commits = %d\n"
@@ -2525,19 +2511,19 @@ int jfs_lmstats_read(char *buffer, char **start, off_t offset, int length,
                       lmStat.pagedone,
                       lmStat.full_page,
                       lmStat.partial_page);
+       return 0;
+}
 
-       begin = offset;
-       *start = buffer + begin;
-       len -= begin;
-
-       if (len > length)
-               len = length;
-       else
-               *eof = 1;
-
-       if (len < 0)
-               len = 0;
-
-       return len;
+static int jfs_lmstats_proc_open(struct inode *inode, struct file *file)
+{
+       return single_open(file, jfs_lmstats_proc_show, NULL);
 }
+
+const struct file_operations jfs_lmstats_proc_fops = {
+       .owner          = THIS_MODULE,
+       .open           = jfs_lmstats_proc_open,
+       .read           = seq_read,
+       .llseek         = seq_lseek,
+       .release        = single_release,
+};
 #endif /* CONFIG_JFS_STATISTICS */