swsusp for 2.5.8: infrastructure

From: Pavel Machek (pavel@ucw.cz)
Date: Sun Apr 21 2002 - 16:37:09 EST


Hi!

Swsusp needs a way to freeze just about everything. That's easy for
ordinary tasks, but needs some support for kernel threads. Please
apply,

[You'll need to > include/asm-i386/suspend.h to make it compile,
unless you also take the next patch].

                                                                        Pavel

--- clean.2.5/arch/i386/kernel/apm.c Thu Mar 21 11:35:51 2002
+++ linux-swsusp/arch/i386/kernel/apm.c Sun Apr 21 20:40:34 2002
@@ -1667,6 +1667,7 @@
         daemonize();
 
         strcpy(current->comm, "kapmd");
+ current->flags |= PF_IOTHREAD;
         sigfillset(&current->blocked);
 
         if (apm_info.connection_version == 0) {
--- clean.2.5/arch/i386/kernel/signal.c Thu Apr 18 22:45:22 2002
+++ linux-swsusp/arch/i386/kernel/signal.c Sun Apr 21 21:08:58 2002
@@ -21,6 +21,7 @@
 #include <linux/tty.h>
 #include <linux/personality.h>
 #include <linux/binfmts.h>
+#include <linux/suspend.h>
 #include <asm/ucontext.h>
 #include <asm/uaccess.h>
 #include <asm/i387.h>
@@ -594,6 +595,11 @@
         if ((regs->xcs & 3) != 3)
                 return 1;
 
+ if (current->flags & PF_FREEZE) {
+ refrigerator(0);
+ goto no_signal;
+ }
+
         if (!oldset)
                 oldset = &current->blocked;
 
@@ -701,6 +707,7 @@
                 return 1;
         }
 
+ no_signal:
         /* Did we come from a system call? */
         if (regs->orig_eax >= 0) {
                 /* Restart the system call - no handlers present */
--- clean.2.5/drivers/block/loop.c Thu Apr 18 22:45:31 2002
+++ linux-swsusp/drivers/block/loop.c Sun Apr 21 20:40:54 2002
@@ -71,11 +71,11 @@
 #include <linux/smp_lock.h>
 #include <linux/swap.h>
 #include <linux/slab.h>
+#include <linux/loop.h>
+#include <linux/suspend.h>
 
 #include <asm/uaccess.h>
 
-#include <linux/loop.h>
-
 #define MAJOR_NR LOOP_MAJOR
 
 static int max_loop = 8;
@@ -550,7 +550,7 @@
         atomic_inc(&lo->lo_pending);
         spin_unlock_irq(&lo->lo_lock);
 
- current->flags |= PF_NOIO;
+ current->flags |= PF_NOIO | PF_IOTHREAD;
 
         /*
          * up sem, we are running
--- clean.2.5/drivers/usb/storage/usb.c Tue Mar 5 21:52:43 2002
+++ linux-swsusp/drivers/usb/storage/usb.c Sun Apr 21 21:08:47 2002
@@ -319,6 +319,7 @@
         /* avoid getting signals */
         spin_lock_irq(&current->sigmask_lock);
         flush_signals(current);
+ current->flags |= PF_IOTHREAD;
         sigfillset(&current->blocked);
         recalc_sigpending();
         spin_unlock_irq(&current->sigmask_lock);
--- clean.2.5/fs/jbd/journal.c Thu Apr 18 22:46:03 2002
+++ linux-swsusp/fs/jbd/journal.c Sun Apr 21 20:40:55 2002
@@ -33,6 +33,7 @@
 #include <linux/init.h>
 #include <linux/mm.h>
 #include <linux/slab.h>
+#include <linux/suspend.h>
 #include <asm/uaccess.h>
 #include <linux/proc_fs.h>
 
@@ -225,6 +226,7 @@
                         journal->j_commit_interval / HZ);
         list_add(&journal->j_all_journals, &all_journals);
 
+ current->flags |= PF_KERNTHREAD;
         /* And now, wait forever for commit wakeup events. */
         while (1) {
                 if (journal->j_flags & JFS_UNMOUNT)
@@ -245,7 +247,15 @@
                 }
 
                 wake_up(&journal->j_wait_done_commit);
- interruptible_sleep_on(&journal->j_wait_commit);
+ if (current->flags & PF_FREEZE) { /* The simpler the better. Flushing journal isn't a
+ good idea, because that depends on threads that
+ may be already stopped. */
+ jbd_debug(1, "Now suspending kjournald\n");
+ refrigerator(PF_IOTHREAD);
+ jbd_debug(1, "Resuming kjournald\n");
+ } else /* we assume on resume that commits are already there,
+ so we don't sleep */
+ interruptible_sleep_on(&journal->j_wait_commit);
 
                 jbd_debug(1, "kjournald wakes\n");
 
--- clean.2.5/fs/reiserfs/journal.c Thu Apr 18 22:46:12 2002
+++ linux-swsusp/fs/reiserfs/journal.c Sun Apr 21 20:40:55 2002
@@ -58,6 +58,7 @@
 #include <linux/stat.h>
 #include <linux/string.h>
 #include <linux/smp_lock.h>
+#include <linux/suspend.h>
 
 /* the number of mounted filesystems. This is used to decide when to
 ** start and kill the commit thread
@@ -1887,6 +1888,7 @@
   spin_unlock_irq(&current->sigmask_lock);
 
   sprintf(current->comm, "kreiserfsd") ;
+ current->flags |= PF_KERNTHREAD;
   lock_kernel() ;
   while(1) {
 
@@ -1900,7 +1902,12 @@
       break ;
     }
     wake_up(&reiserfs_commit_thread_done) ;
- interruptible_sleep_on_timeout(&reiserfs_commit_thread_wait, 5 * HZ) ;
+#ifdef CONFIG_SOFTWARE_SUSPEND
+ if (current->flags & PF_FREEZE) {
+ refrigerator(PF_IOTHREAD);
+ } else
+#endif
+ interruptible_sleep_on_timeout(&reiserfs_commit_thread_wait, 5 * HZ) ;
   }
   unlock_kernel() ;
   wake_up(&reiserfs_commit_thread_done) ;
--- clean.2.5/include/asm-i386/bitops.h Thu Apr 18 22:46:15 2002
+++ linux-swsusp/include/asm-i386/bitops.h Sun Apr 21 21:15:07 2002
@@ -414,6 +414,12 @@
         return word;
 }
 
+/*
+ * fls: find last bit set.
+ */
+
+#define fls(x) generic_fls(x)
+
 #ifdef __KERNEL__
 
 /*
--- clean.2.5/include/linux/sched.h Thu Apr 18 22:46:17 2002
+++ linux-swsusp/include/linux/sched.h Sun Apr 21 21:15:07 2002
@@ -369,6 +369,10 @@
 #define PF_FREE_PAGES 0x00002000 /* per process page freeing */
 #define PF_NOIO 0x00004000 /* avoid generating further I/O */
 #define PF_FLUSHER 0x00008000 /* responsible for disk writeback */
+#define PF_FREEZE 0x00010000 /* this task should be frozen for suspend */
+#define PF_IOTHREAD 0x00020000 /* this thread is needed for doing I/O to swap */
+#define PF_KERNTHREAD 0x00040000 /* this thread is a kernel thread that cannot be sent signals to */
+#define PF_FROZEN 0x00080000 /* frozen for system suspend */
 
 /*
  * Ptrace flags
--- clean.2.5/include/linux/suspend.h Tue Feb 5 23:17:31 2002
+++ linux-swsusp/include/linux/suspend.h Sun Apr 21 21:16:16 2002
@@ -0,0 +1,65 @@
+#ifndef _LINUX_SWSUSP_H
+#define _LINUX_SWSUSP_H
+
+#include <asm/suspend.h>
+#include <linux/swap.h>
+#include <linux/notifier.h>
+#include <linux/config.h>
+
+extern unsigned char software_suspend_enabled;
+
+#define NORESUME 1
+#define RESUME_SPECIFIED 2
+
+#ifdef CONFIG_SOFTWARE_SUSPEND
+/* page backup entry */
+typedef struct pbe {
+ unsigned long address; /* address of the copy */
+ unsigned long orig_address; /* original address of page */
+ swp_entry_t swap_address;
+ swp_entry_t dummy; /* we need scratch space at
+ * end of page (see link, diskpage)
+ */
+} suspend_pagedir_t;
+
+#define SWAP_FILENAME_MAXLENGTH 32
+
+struct suspend_header {
+ __u32 version_code;
+ unsigned long num_physpages;
+ char machine[8];
+ char version[20];
+ int num_cpus;
+ int page_size;
+ unsigned long suspend_pagedir;
+ unsigned int num_pbes;
+ struct swap_location {
+ char filename[SWAP_FILENAME_MAXLENGTH];
+ } swap_location[MAX_SWAPFILES];
+};
+
+#define SUSPEND_PD_PAGES(x) (((x)*sizeof(struct pbe))/PAGE_SIZE+1)
+
+extern struct tq_struct suspend_tq;
+
+/* mm/vmscan.c */
+extern int shrink_mem(void);
+
+/* kernel/suspend.c */
+extern void software_suspend(void);
+extern void software_resume(void);
+extern int resume_setup(char *str);
+
+extern int register_suspend_notifier(struct notifier_block *);
+extern int unregister_suspend_notifier(struct notifier_block *);
+extern void refrigerator(unsigned long);
+
+#else
+#define software_suspend() do { } while(0)
+#define software_resume() do { } while(0)
+#define register_suspend_notifier(a) do { } while(0)
+#define unregister_suspend_notifier(a) do { } while(0)
+#define refrigerator(a) do { BUG(); } while(0)
+#endif
+
+#endif /* _LINUX_SWSUSP_H */
--- clean.2.5/kernel/context.c Tue Mar 5 21:52:50 2002
+++ linux-swsusp/kernel/context.c Sun Apr 21 20:40:55 2002
@@ -72,6 +72,7 @@
 
         daemonize();
         strcpy(curtask->comm, "keventd");
+ current->flags |= PF_IOTHREAD;
         keventd_running = 1;
         keventd_task = curtask;
 
--- clean.2.5/kernel/softirq.c Thu Jan 31 23:42:30 2002
+++ linux-swsusp/kernel/softirq.c Sun Apr 21 20:49:10 2002
@@ -365,6 +365,7 @@
 
         daemonize();
         set_user_nice(current, 19);
+ current->flags |= PF_IOTHREAD;
         sigfillset(&current->blocked);
 
         /* Migrate to the right CPU */
--- clean.2.5/mm/pdflush.c Thu Apr 18 22:46:20 2002
+++ linux-swsusp/mm/pdflush.c Sun Apr 21 23:16:46 2002
@@ -96,7 +96,7 @@
         recalc_sigpending();
         spin_unlock_irq(&current->sigmask_lock);
 
- current->flags |= PF_FLUSHER;
+ current->flags |= PF_FLUSHER | PF_KERNTHREAD;
         my_work->fn = NULL;
         my_work->who = current;
 
@@ -111,10 +111,13 @@
                 set_current_state(TASK_INTERRUPTIBLE);
                 spin_unlock_irq(&pdflush_lock);
 
+ if (current->flags & PF_FREEZE)
+ refrigerator(PF_IOTHREAD);
                 schedule();
 
                 preempt_enable();
- (*my_work->fn)(my_work->arg0);
+ if (my_work && my_work->fn)
+ (*my_work->fn)(my_work->arg0);
                 preempt_disable();
 
                 /*
--- clean.2.5/mm/vmscan.c Thu Apr 18 22:46:20 2002
+++ linux-swsusp/mm/vmscan.c Sun Apr 21 20:40:55 2002
@@ -22,6 +22,7 @@
 #include <linux/highmem.h>
 #include <linux/file.h>
 #include <linux/compiler.h>
+#include <linux/suspend.h>
 
 #include <asm/pgalloc.h>
 #include <asm/tlbflush.h>
@@ -737,18 +738,22 @@
          * us from recursively trying to free more memory as we're
          * trying to free the first piece of memory in the first place).
          */
- tsk->flags |= PF_MEMALLOC;
+ tsk->flags |= PF_MEMALLOC | PF_KERNTHREAD;
 
         /*
          * Kswapd main loop.
          */
         for (;;) {
+ if (current->flags & PF_FREEZE)
+ refrigerator(PF_IOTHREAD);
                 __set_current_state(TASK_INTERRUPTIBLE);
                 add_wait_queue(&kswapd_wait, &wait);
 
                 mb();
- if (kswapd_can_sleep())
+ if (kswapd_can_sleep()) {
                         schedule();
+ }
+
 
                 __set_current_state(TASK_RUNNING);
                 remove_wait_queue(&kswapd_wait, &wait);

-- 
(about SSSCA) "I don't say this lightly.  However, I really think that the U.S.
no longer is classifiable as a democracy, but rather as a plutocracy." --hpa
-
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to majordomo@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Please read the FAQ at  http://www.tux.org/lkml/



This archive was generated by hypermail 2b29 : Tue Apr 23 2002 - 22:00:30 EST