NFSv4: Make DELEGRETURN an interruptible operation.
[safe/jmp/linux-2.6] / fs / jfs / jfs_logmgr.c
index e0f867d..d27bac6 100644 (file)
@@ -71,6 +71,7 @@
 #include "jfs_incore.h"
 #include "jfs_filsys.h"
 #include "jfs_metapage.h"
+#include "jfs_superblock.h"
 #include "jfs_txnmgr.h"
 #include "jfs_debug.h"
 
@@ -167,14 +168,6 @@ 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;
-
-/*
  * forward references
  */
 static int lmWriteRecord(struct jfs_log * log, struct tblock * tblk,
@@ -198,7 +191,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);
 
 
 
@@ -234,6 +227,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);
@@ -254,7 +248,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
@@ -310,7 +304,7 @@ int lmLog(struct jfs_log * log, struct tblock * tblk, struct lrd * lrd,
                }
        }
 
-       LOGSYNC_UNLOCK(log);
+       LOGSYNC_UNLOCK(log, flags);
 
        /*
         *      write the log record
@@ -334,7 +328,6 @@ int lmLog(struct jfs_log * log, struct tblock * tblk, struct lrd * lrd,
        return lsn;
 }
 
-
 /*
  * NAME:       lmWriteRecord()
  *
@@ -922,20 +915,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,6 +935,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
@@ -954,10 +960,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 {
@@ -965,7 +968,7 @@ static int lmLogSync(struct jfs_log * log, int nosyncwait)
                                        struct logsyncblk, synclist);
                        log->sync = lp->lsn;
                }
-               LOGSYNC_UNLOCK(log);
+               LOGSYNC_UNLOCK(log, flags);
 
        }
 
@@ -974,27 +977,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);
@@ -1044,16 +1026,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);
@@ -1066,6 +1045,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()
@@ -1547,6 +1539,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)
@@ -1608,12 +1601,18 @@ 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? */
+               for (i = 0; i < 200; i++) {     /* Too much? */
                        msleep(250);
                        if (list_empty(&log->cqueue) &&
                            list_empty(&log->synclist))
@@ -1621,7 +1620,25 @@ void jfs_flush_journal(struct jfs_log *log, int wait)
                }
        }
        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);
 }
 
@@ -2345,9 +2362,9 @@ int jfsIOWait(void *arg)
                        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);