vserver 2.0 rc7
[linux-2.6.git] / fs / jfs / jfs_logmgr.c
index dfa771c..dfa1200 100644 (file)
@@ -67,6 +67,7 @@
 #include <linux/buffer_head.h>         /* for sync_blockdev() */
 #include <linux/bio.h>
 #include <linux/suspend.h>
+#include <linux/delay.h>
 #include "jfs_incore.h"
 #include "jfs_filsys.h"
 #include "jfs_metapage.h"
@@ -233,6 +234,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 +255,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 +311,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 +335,6 @@ int lmLog(struct jfs_log * log, struct tblock * tblk, struct lrd * lrd,
        return lsn;
 }
 
-
 /*
  * NAME:       lmWriteRecord()
  *
@@ -926,9 +927,8 @@ static void lmPostGC(struct lbuf * bp)
  *     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
+ *             nosyncwait - 1 if called asynchronously
  *
  * RETURN:     0
  *                     
@@ -944,6 +944,15 @@ 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);
+       }
 
        /*
         *      forward syncpt
@@ -953,10 +962,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 +970,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,27 +979,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) {
-                       if (sbi->flag & JFS_NOINTEGRITY)
-                               continue;
-                       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) {
-                       if (sbi->flag & JFS_NOINTEGRITY)
-                               continue;
-                       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);
@@ -1065,6 +1050,18 @@ 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
+ */
+void jfs_syncpt(struct jfs_log *log)
+{      LOG_LOCK(log);
+       lmLogSync(log, 1);
+       LOG_UNLOCK(log);
+}
 
 /*
  * NAME:       lmLogOpen()
@@ -1118,6 +1115,7 @@ int lmLogOpen(struct super_block *sb)
        }
        memset(log, 0, sizeof(struct jfs_log));
        INIT_LIST_HEAD(&log->sb_list);
+       init_waitqueue_head(&log->syncwait);
 
        /*
         *      external log as separate logical volume
@@ -1191,6 +1189,7 @@ static int open_inline_log(struct super_block *sb)
                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;
@@ -1228,6 +1227,7 @@ static int open_dummy_log(struct super_block *sb)
                }
                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;
@@ -1290,8 +1290,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;
 
@@ -1545,6 +1543,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)
@@ -1606,21 +1605,43 @@ 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));
+       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));
+               }
+//             current->state = TASK_INTERRUPTIBLE;
+//             schedule();
+       }
+       //assert(list_empty(&log->synclist));
        clear_bit(log_FLUSH, &log->flag);
 }
 
@@ -1668,6 +1689,7 @@ int lmLogShutdown(struct jfs_log * log)
        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
@@ -1818,20 +1840,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);
@@ -1856,12 +1892,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;
 }
 
 
@@ -1973,9 +2007,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;
@@ -2114,9 +2148,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;
@@ -2126,16 +2160,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
-                                      */
-       }
 }