From 9a42edbb7841d458307d88d9ef4556b6733f81f4 Mon Sep 17 00:00:00 2001 From: pschwan Date: Sun, 18 May 2003 16:39:34 +0000 Subject: [PATCH] landing b_open onto b_devel: - kernel patches for bug 1203 - fixes directory open()s - re-enables metadata caching on the MDS - fixes bug in ext3_noread kernel patch - fixes some symbol export problems in other kernels - fixes compilation problems when running on Red Hat 2.4.20 kernels If you update past this merge, you will require kernel version 18 --- lustre/kernel_patches/patches/dsp.patch | 130 + .../patches/ext3-delete_thread-2.4.20.patch | 2 +- .../patches/ext3-noread-2.4.20.patch | 14 +- .../patches/ext3_orphan_lock-2.4.20-rh.patch | 82 + .../patches/iopen-chaos-2.4.18.patch | 400 +++ lustre/kernel_patches/patches/iopen.patch | 406 +++ .../patches/kmem_cache_validate_2.4.20.patch | 105 + lustre/kernel_patches/patches/mcore-2.4.20-8.patch | 2738 ++++++++++++++++++++ .../patches/uml-patch-2.4.20-4.patch | 13 - lustre/kernel_patches/pc/dsp.pc | 6 + .../pc/ext3_orphan_lock-2.4.20-rh.pc | 3 + lustre/kernel_patches/pc/iopen-chaos-2.4.18.pc | 8 + lustre/kernel_patches/pc/iopen.pc | 8 + .../pc/kmem_cache_validate_2.4.20.pc | 4 + lustre/kernel_patches/pc/mcore-2.4.20-8.pc | 34 + lustre/kernel_patches/pc/uml-patch-2.4.20-4.pc | 789 +++--- lustre/tests/fchdir_test.c | 41 + 17 files changed, 4367 insertions(+), 416 deletions(-) create mode 100644 lustre/kernel_patches/patches/dsp.patch create mode 100644 lustre/kernel_patches/patches/ext3_orphan_lock-2.4.20-rh.patch create mode 100644 lustre/kernel_patches/patches/iopen-chaos-2.4.18.patch create mode 100644 lustre/kernel_patches/patches/iopen.patch create mode 100644 lustre/kernel_patches/patches/kmem_cache_validate_2.4.20.patch create mode 100644 lustre/kernel_patches/patches/mcore-2.4.20-8.patch create mode 100644 lustre/kernel_patches/pc/dsp.pc create mode 100644 lustre/kernel_patches/pc/ext3_orphan_lock-2.4.20-rh.pc create mode 100644 lustre/kernel_patches/pc/iopen-chaos-2.4.18.pc create mode 100644 lustre/kernel_patches/pc/iopen.pc create mode 100644 lustre/kernel_patches/pc/kmem_cache_validate_2.4.20.pc create mode 100644 lustre/kernel_patches/pc/mcore-2.4.20-8.pc create mode 100644 lustre/tests/fchdir_test.c diff --git a/lustre/kernel_patches/patches/dsp.patch b/lustre/kernel_patches/patches/dsp.patch new file mode 100644 index 0000000..f2e5b93 --- /dev/null +++ b/lustre/kernel_patches/patches/dsp.patch @@ -0,0 +1,130 @@ + arch/i386/kernel/crash.c | 24 +++++++++++++++++------- + arch/i386/kernel/nmi.c | 2 +- + include/asm-i386/apic.h | 1 + + include/linux/crash.h | 2 +- + kernel/bootimg.c | 13 ++++++++++++- + kernel/bootimg_pic.c | 6 ++++-- + 6 files changed, 36 insertions(+), 12 deletions(-) + +--- linux-rh-2.4.20-8/kernel/bootimg.c~dsp 2003-05-07 19:30:47.000000000 +0800 ++++ linux-rh-2.4.20-8-root/kernel/bootimg.c 2003-05-07 19:31:12.000000000 +0800 +@@ -238,9 +238,20 @@ int boot_image() + int error = -ENOMEM; + + if (bootimg_checksum(__va(bootimg_dsc.page_dir),bootimg_dsc.pages) +- != bootimg_dsc.csum) ++ != bootimg_dsc.csum) { + printk("Checksum of kernel image failed. Rebooting via BIOS\n"); + ++ /* Before calling machine_restart(), make sure it will not ++ * simply call this function recursively. ++ */ ++ bootimg_dsc.page_dir = NULL; ++ machine_restart(NULL); ++ ++ /* We should never get here, but just in case... */ ++ for (; ; ) ++ __asm__ __volatile__ ("hlt"); ++ } ++ + code_page = get_identity_mapped_page(); + if (!code_page) goto out3; + code = (relocate_and_jump_t) virt_to_phys((void *) code_page); +--- linux-rh-2.4.20-8/kernel/bootimg_pic.c~dsp 2003-05-07 19:30:47.000000000 +0800 ++++ linux-rh-2.4.20-8-root/kernel/bootimg_pic.c 2003-05-07 19:31:12.000000000 +0800 +@@ -69,7 +69,8 @@ void __bootimg relocate_and_jump(void) + for (j = i+1; j < dsc.pages; j++) { + table = dsc.page_dir+FROM_TABLE(j); + if (((unsigned long) *table) == to) { +- copy_and_swap(*table,dsc.scratch); ++ copy_and_swap((unsigned long) (*table), ++ dsc.scratch); + break; + } + if ((*table)[PAGE_NR(j)] == to) { +@@ -79,7 +80,8 @@ void __bootimg relocate_and_jump(void) + } + table = dsc.page_dir+TO_TABLE(j); + if (((unsigned long) *table) == to) { +- copy_and_swap(*table,dsc.scratch); ++ copy_and_swap((unsigned long) (*table), ++ dsc.scratch); + break; + } + } +--- linux-rh-2.4.20-8/include/asm-i386/apic.h~dsp 2003-05-07 17:00:16.000000000 +0800 ++++ linux-rh-2.4.20-8-root/include/asm-i386/apic.h 2003-05-07 19:31:12.000000000 +0800 +@@ -86,6 +86,7 @@ extern struct pm_dev *apic_pm_register(p + extern void apic_pm_unregister(struct pm_dev*); + + extern int check_nmi_watchdog (void); ++extern void disable_apic_nmi_watchdog(void); + + extern unsigned int nmi_watchdog; + #define NMI_NONE 0 +--- linux-rh-2.4.20-8/include/linux/crash.h~dsp 2003-05-07 19:30:47.000000000 +0800 ++++ linux-rh-2.4.20-8-root/include/linux/crash.h 2003-05-07 19:31:12.000000000 +0800 +@@ -71,7 +71,7 @@ extern void stop_this_cpu(void *); + #define CRASH_ZALLOC_PAGES 16*5*2 /* 2 to handle crash in crash */ + #define CRASH_LOW_WATER_PAGES 100 + +-#define CRASH_CPU_TIMEOUT 5000 /* 5 sec wait for other cpus to stop */ ++#define CRASH_CPU_TIMEOUT 15000 /* 15 sec wait for other cpus to stop */ + + #define CRASH_MARK_RESERVED(addr) (set_bit(PG_reserved,&mem_map[MAP_NR(addr)].flags)) + #define CRASH_CLEAR_RESERVED(addr) (clear_bit(PG_reserved,&mem_map[MAP_NR(addr)].flags)) +--- linux-rh-2.4.20-8/arch/i386/kernel/crash.c~dsp 2003-05-07 19:30:47.000000000 +0800 ++++ linux-rh-2.4.20-8-root/arch/i386/kernel/crash.c 2003-05-07 19:31:39.000000000 +0800 +@@ -9,6 +9,8 @@ + #include + #include + #include ++#include ++#include + + inline void crash_save_regs(void) { + static unsigned long regs[8]; +@@ -30,15 +32,23 @@ inline void crash_save_regs(void) { + */ + void crash_save_current_state(struct task_struct *tp) + { ++ if (tp != NULL) { ++ /* ++ * Here we save ebp instead of esp just in case the compiler ++ * decides to put an extra push in before we execute this ++ * instruction (thus invalidating our frame pointer). ++ */ ++ asm volatile("movl %%ebp,%0":"=m" (*(u_long *)&tp->thread.esp)); ++ tp->thread.eip = (u_long)crash_save_current_state; ++ panic_ksp[smp_processor_id()] = tp->thread.esp; ++ mb(); ++ } ++ + /* +- * Here we save ebp instead of esp just in case the compiler +- * decides to put an extra push in before we execute this +- * instruction (thus invalidating our frame pointer). ++ * Just to be safe, disable the NMI watchdog on the calling CPU so it ++ * doesn't get in the way while we are trying to save a dump. + */ +- asm volatile("movl %%ebp,%0":"=m" (*(u_long *)&tp->thread.esp)); +- tp->thread.eip = (u_long)crash_save_current_state; +- panic_ksp[smp_processor_id()] = tp->thread.esp; +- mb(); ++ disable_apic_nmi_watchdog(); + + save_core(); + +--- linux-rh-2.4.20-8/arch/i386/kernel/nmi.c~dsp 2003-05-07 19:30:47.000000000 +0800 ++++ linux-rh-2.4.20-8-root/arch/i386/kernel/nmi.c 2003-05-07 19:31:12.000000000 +0800 +@@ -138,7 +138,7 @@ __setup("nmi_watchdog=", setup_nmi_watch + + struct pm_dev *nmi_pmdev; + +-static void disable_apic_nmi_watchdog(void) ++void disable_apic_nmi_watchdog(void) + { + switch (boot_cpu_data.x86_vendor) { + case X86_VENDOR_AMD: + +_ diff --git a/lustre/kernel_patches/patches/ext3-delete_thread-2.4.20.patch b/lustre/kernel_patches/patches/ext3-delete_thread-2.4.20.patch index 5f67fef..f989c2b 100644 --- a/lustre/kernel_patches/patches/ext3-delete_thread-2.4.20.patch +++ b/lustre/kernel_patches/patches/ext3-delete_thread-2.4.20.patch @@ -267,7 +267,7 @@ diff -puNr origin/include/linux/ext3_fs.h linux/include/linux/ext3_fs.h #define EXT3_MOUNT_UPDATE_JOURNAL 0x1000 /* Update the journal format */ #define EXT3_MOUNT_NO_UID32 0x2000 /* Disable 32-bit UIDs */ #define EXT3_MOUNT_XATTR_USER 0x4000 /* Extended user attributes */ -+#define EXT3_MOUNT_ASYNCDEL 0x10000 /* Delayed deletion */ ++#define EXT3_MOUNT_ASYNCDEL 0x20000 /* Delayed deletion */ /* Compatibility, for having both ext2_fs.h and ext3_fs.h included at once */ #ifndef _LINUX_EXT2_FS_H diff --git a/lustre/kernel_patches/patches/ext3-noread-2.4.20.patch b/lustre/kernel_patches/patches/ext3-noread-2.4.20.patch index 8c2fcd7..275c6df 100644 --- a/lustre/kernel_patches/patches/ext3-noread-2.4.20.patch +++ b/lustre/kernel_patches/patches/ext3-noread-2.4.20.patch @@ -3,8 +3,8 @@ include/linux/ext3_fs.h | 2 + 3 files changed, 121 insertions(+), 24 deletions(-) ---- linux-2.4.20/fs/ext3/ialloc.c~extN-noread-2.4.20 2003-05-04 16:41:22.000000000 +0800 -+++ linux-2.4.20-root/fs/ext3/ialloc.c 2003-05-04 17:19:29.000000000 +0800 +--- linux-2.4.20/fs/ext3/ialloc.c~ext3-noread-2.4.20 2003-05-16 12:21:39.000000000 +0800 ++++ linux-2.4.20-root/fs/ext3/ialloc.c 2003-05-16 12:21:46.000000000 +0800 @@ -289,6 +289,37 @@ error_return: } @@ -73,8 +73,8 @@ unlock_super (sb); if(DQUOT_ALLOC_INODE(inode)) { ---- linux-2.4.20/fs/ext3/inode.c~extN-noread-2.4.20 2003-05-04 16:41:26.000000000 +0800 -+++ linux-2.4.20-root/fs/ext3/inode.c 2003-05-04 17:22:49.000000000 +0800 +--- linux-2.4.20/fs/ext3/inode.c~ext3-noread-2.4.20 2003-05-16 12:21:41.000000000 +0800 ++++ linux-2.4.20-root/fs/ext3/inode.c 2003-05-16 12:22:15.000000000 +0800 @@ -2013,14 +2013,19 @@ out_stop: ext3_journal_stop(handle, inode); } @@ -158,7 +158,7 @@ + block_end = block + NUM_INODE_PREREAD; + if (block_end > itable_end) + block_end = itable_end; -+ ++ block++; + for (; block < block_end; block++) { + bh[count] = sb_getblk(inode->i_sb, block); + if (count && (buffer_uptodate(bh[count]) || @@ -203,8 +203,8 @@ void ext3_read_inode(struct inode * inode) { struct ext3_iloc iloc; ---- linux-2.4.20/include/linux/ext3_fs.h~extN-noread-2.4.20 2003-05-04 16:41:22.000000000 +0800 -+++ linux-2.4.20-root/include/linux/ext3_fs.h 2003-05-04 17:19:29.000000000 +0800 +--- linux-2.4.20/include/linux/ext3_fs.h~ext3-noread-2.4.20 2003-05-16 12:21:39.000000000 +0800 ++++ linux-2.4.20-root/include/linux/ext3_fs.h 2003-05-16 12:21:46.000000000 +0800 @@ -683,6 +683,8 @@ extern int ext3_forget(handle_t *, int, extern struct buffer_head * ext3_getblk (handle_t *, struct inode *, long, int, int *); extern struct buffer_head * ext3_bread (handle_t *, struct inode *, int, int, int *); diff --git a/lustre/kernel_patches/patches/ext3_orphan_lock-2.4.20-rh.patch b/lustre/kernel_patches/patches/ext3_orphan_lock-2.4.20-rh.patch new file mode 100644 index 0000000..d029650 --- /dev/null +++ b/lustre/kernel_patches/patches/ext3_orphan_lock-2.4.20-rh.patch @@ -0,0 +1,82 @@ + fs/ext3/namei.c | 15 +++++++-------- + fs/ext3/super.c | 1 + + include/linux/ext3_fs_sb.h | 1 + + 3 files changed, 9 insertions(+), 8 deletions(-) + +--- linux-rh-2.4.20-8/fs/ext3/namei.c~ext3_orphan_lock-2.4.20-rh 2003-05-05 19:49:15.000000000 +0800 ++++ linux-rh-2.4.20-8-root/fs/ext3/namei.c 2003-05-05 20:01:28.000000000 +0800 +@@ -1747,8 +1747,8 @@ int ext3_orphan_add(handle_t *handle, st + struct super_block *sb = inode->i_sb; + struct ext3_iloc iloc; + int err = 0, rc; +- +- lock_super(sb); ++ ++ down(&EXT3_SB(sb)->s_orphan_lock); + if (!list_empty(&EXT3_I(inode)->i_orphan)) + goto out_unlock; + +@@ -1796,7 +1796,7 @@ int ext3_orphan_add(handle_t *handle, st + jbd_debug(4, "orphan inode %ld will point to %d\n", + inode->i_ino, NEXT_ORPHAN(inode)); + out_unlock: +- unlock_super(sb); ++ up(&EXT3_SB(sb)->s_orphan_lock); + ext3_std_error(inode->i_sb, err); + return err; + } +@@ -1809,20 +1809,19 @@ int ext3_orphan_del(handle_t *handle, st + { + struct list_head *prev; + struct ext3_inode_info *ei = EXT3_I(inode); +- struct ext3_sb_info *sbi; ++ struct ext3_sb_info *sbi = EXT3_SB(inode->i_sb); + unsigned long ino_next; + struct ext3_iloc iloc; + int err = 0; + +- lock_super(inode->i_sb); ++ down(&sbi->s_orphan_lock); + if (list_empty(&ei->i_orphan)) { +- unlock_super(inode->i_sb); ++ up(&sbi->s_orphan_lock); + return 0; + } + + ino_next = NEXT_ORPHAN(inode); + prev = ei->i_orphan.prev; +- sbi = EXT3_SB(inode->i_sb); + + jbd_debug(4, "remove inode %lu from orphan list\n", inode->i_ino); + +@@ -1871,7 +1870,7 @@ int ext3_orphan_del(handle_t *handle, st + out_err: + ext3_std_error(inode->i_sb, err); + out: +- unlock_super(inode->i_sb); ++ up(&sbi->s_orphan_lock); + return err; + + out_brelse: +--- linux-rh-2.4.20-8/fs/ext3/super.c~ext3_orphan_lock-2.4.20-rh 2003-05-05 19:49:15.000000000 +0800 ++++ linux-rh-2.4.20-8-root/fs/ext3/super.c 2003-05-05 19:54:09.000000000 +0800 +@@ -1151,6 +1151,7 @@ struct super_block * ext3_read_super (st + */ + sb->s_op = &ext3_sops; + INIT_LIST_HEAD(&sbi->s_orphan); /* unlinked but open files */ ++ sema_init(&sbi->s_orphan_lock, 1); + + sb->s_root = 0; + +--- linux-rh-2.4.20-8/include/linux/ext3_fs_sb.h~ext3_orphan_lock-2.4.20-rh 2003-05-05 19:49:07.000000000 +0800 ++++ linux-rh-2.4.20-8-root/include/linux/ext3_fs_sb.h 2003-05-05 19:54:09.000000000 +0800 +@@ -69,6 +69,7 @@ struct ext3_sb_info { + struct inode * s_journal_inode; + struct journal_s * s_journal; + struct list_head s_orphan; ++ struct semaphore s_orphan_lock; + unsigned long s_commit_interval; + struct block_device *journal_bdev; + #ifdef CONFIG_JBD_DEBUG + +_ diff --git a/lustre/kernel_patches/patches/iopen-chaos-2.4.18.patch b/lustre/kernel_patches/patches/iopen-chaos-2.4.18.patch new file mode 100644 index 0000000..901ae0d --- /dev/null +++ b/lustre/kernel_patches/patches/iopen-chaos-2.4.18.patch @@ -0,0 +1,400 @@ + Documentation/filesystems/ext2.txt | 16 ++ + fs/ext3/Makefile | 2 + fs/ext3/inode.c | 4 + fs/ext3/iopen.c | 236 +++++++++++++++++++++++++++++++++++++ + fs/ext3/iopen.h | 15 ++ + fs/ext3/namei.c | 12 + + fs/ext3/super.c | 11 + + include/linux/ext3_fs.h | 2 + 8 files changed, 297 insertions(+), 1 deletion(-) + +--- linux-2.4.18-p4smp/Documentation/filesystems/ext2.txt~iopen-chaos-2.4.18 2002-05-07 15:53:59.000000000 -0600 ++++ linux-2.4.18-p4smp-braam/Documentation/filesystems/ext2.txt 2003-05-17 13:14:22.000000000 -0600 +@@ -35,6 +35,22 @@ resgid=n The group ID which may use th + + sb=n Use alternate superblock at this location. + ++iopen Makes an invisible pseudo-directory called ++ __iopen__ available in the root directory ++ of the filesystem. Allows open-by-inode- ++ number. i.e., inode 3145 can be accessed ++ via /mntpt/__iopen__/3145 ++ ++iopen_nopriv This option makes the iopen directory be ++ world-readable. This may be safer since it ++ allows daemons to run as an unprivileged user, ++ however it significantly changes the security ++ model of a Unix filesystem, since previously ++ all files under a mode 700 directory were not ++ generally avilable even if the ++ permissions on the file itself is ++ world-readable. ++ + grpquota,noquota,quota,usrquota Quota options are silently ignored by ext2. + + +--- linux-2.4.18-p4smp/fs/ext3/Makefile~iopen-chaos-2.4.18 2003-05-17 13:12:44.000000000 -0600 ++++ linux-2.4.18-p4smp-braam/fs/ext3/Makefile 2003-05-17 13:15:06.000000000 -0600 +@@ -11,7 +11,7 @@ O_TARGET := ext3.o + + export-objs := super.o inode.o xattr.o + +-obj-y := balloc.o bitmap.o dir.o file.o fsync.o ialloc.o inode.o \ ++obj-y := balloc.o bitmap.o dir.o file.o fsync.o ialloc.o inode.o iopen.o\ + ioctl.o namei.o super.o symlink.o xattr.o + obj-m := $(O_TARGET) + +--- linux-2.4.18-p4smp/fs/ext3/inode.c~iopen-chaos-2.4.18 2003-05-17 13:12:55.000000000 -0600 ++++ linux-2.4.18-p4smp-braam/fs/ext3/inode.c 2003-05-17 13:14:22.000000000 -0600 +@@ -31,6 +31,7 @@ + #include + #include + #include ++#include "iopen.h" + + /* + * SEARCH_FROM_ZERO forces each block allocation to search from the start +@@ -2135,6 +2136,9 @@ void ext3_read_inode(struct inode * inod + struct buffer_head *bh; + int block; + ++ if (ext3_iopen_get_inode(inode)) ++ return; ++ + if(ext3_get_inode_loc(inode, &iloc)) + goto bad_inode; + bh = iloc.bh; +--- /dev/null 2003-01-30 03:24:37.000000000 -0700 ++++ linux-2.4.18-p4smp-braam/fs/ext3/iopen.c 2003-05-17 13:14:22.000000000 -0600 +@@ -0,0 +1,236 @@ ++/* ++ * linux/fs/ext3/iopen.c ++ * ++ * Special support for open by inode number ++ * ++ * Copyright (C) 2001 by Theodore Ts'o (tytso@alum.mit.edu). ++ * ++ * This file may be redistributed under the terms of the GNU General ++ * Public License. ++ */ ++ ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include "iopen.h" ++ ++#ifndef assert ++#define assert(test) J_ASSERT(test) ++#endif ++ ++#define IOPEN_NAME_LEN 32 ++ ++/* ++ * This implements looking up an inode by number. ++ */ ++static struct dentry *iopen_lookup(struct inode * dir, struct dentry *dentry) ++{ ++ struct inode * inode; ++ unsigned long ino; ++ struct list_head *lp; ++ struct dentry *alternate; ++ char buf[IOPEN_NAME_LEN]; ++ ++ if (dentry->d_name.len >= IOPEN_NAME_LEN) ++ return ERR_PTR(-ENAMETOOLONG); ++ ++ memcpy(buf, dentry->d_name.name, dentry->d_name.len); ++ buf[dentry->d_name.len] = 0; ++ ++ if (strcmp(buf, ".") == 0) ++ ino = dir->i_ino; ++ else if (strcmp(buf, "..") == 0) ++ ino = EXT3_ROOT_INO; ++ else ++ ino = simple_strtoul(buf, 0, 0); ++ ++ if ((ino != EXT3_ROOT_INO && ++ //ino != EXT3_ACL_IDX_INO && ++ //ino != EXT3_ACL_DATA_INO && ++ ino < EXT3_FIRST_INO(dir->i_sb)) || ++ ino > le32_to_cpu(dir->i_sb->u.ext3_sb.s_es->s_inodes_count)) ++ return ERR_PTR(-ENOENT); ++ ++ inode = iget(dir->i_sb, ino); ++ if (!inode) ++ return ERR_PTR(-EACCES); ++ if (is_bad_inode(inode)) { ++ iput(inode); ++ return ERR_PTR(-ENOENT); ++ } ++ ++ /* preferrably return a connected dentry */ ++ spin_lock(&dcache_lock); ++ list_for_each(lp, &inode->i_dentry) { ++ alternate = list_entry(lp, struct dentry, d_alias); ++ if (!(alternate->d_flags & DCACHE_NFSD_DISCONNECTED)) { ++ dget_locked(alternate); ++ alternate->d_vfs_flags |= DCACHE_REFERENCED; ++ iput(inode); ++ spin_unlock(&dcache_lock); ++ return alternate; ++ } ++ } ++ dentry->d_flags |= DCACHE_NFSD_DISCONNECTED; ++ spin_unlock(&dcache_lock); ++ ++ d_add(dentry, inode); ++ return NULL; ++} ++ ++#define do_switch(x,y) do { \ ++ __typeof__ (x) __tmp = x; \ ++ x = y; y = __tmp; } while (0) ++ ++static inline void switch_names(struct dentry * dentry, struct dentry * target) ++{ ++ const unsigned char *old_name, *new_name; ++ ++ memcpy(dentry->d_iname, target->d_iname, DNAME_INLINE_LEN); ++ old_name = target->d_name.name; ++ new_name = dentry->d_name.name; ++ if (old_name == target->d_iname) ++ old_name = dentry->d_iname; ++ if (new_name == dentry->d_iname) ++ new_name = target->d_iname; ++ target->d_name.name = new_name; ++ dentry->d_name.name = old_name; ++} ++ ++ ++struct dentry *iopen_connect_dentry(struct dentry *de, struct inode *inode) ++{ ++ struct dentry *tmp, *goal = NULL; ++ struct list_head *lp; ++ ++ /* preferrably return a connected dentry */ ++ spin_lock(&dcache_lock); ++ /* verify this dentry is really new */ ++ assert(list_empty(&de->d_subdirs)); ++ assert(list_empty(&de->d_alias)); ++ //assert(list_empty(&inode->i_dentry)); ++ list_for_each(lp, &inode->i_dentry) { ++ tmp = list_entry(lp, struct dentry, d_alias); ++ if (tmp->d_flags & DCACHE_NFSD_DISCONNECTED) { ++ goal = tmp; ++ dget_locked(goal); ++ break; ++ } ++ } ++ if (!goal) { ++ spin_unlock(&dcache_lock); ++ return NULL; ++ } ++ ++ /* Move the goal to the de hash queue */ ++ goal->d_flags &= ~DCACHE_NFSD_DISCONNECTED; ++ list_del(&goal->d_hash); ++ list_add(&goal->d_hash, &de->d_hash); ++ ++ list_del(&goal->d_child); ++ list_del(&de->d_child); ++ ++ /* Switch the parents and the names.. */ ++ switch_names(goal, de); ++ do_switch(goal->d_parent, de->d_parent); ++ do_switch(goal->d_name.len, de->d_name.len); ++ do_switch(goal->d_name.hash, de->d_name.hash); ++ ++ /* And add them back to the (new) parent lists */ ++ list_add(&goal->d_child, &goal->d_parent->d_subdirs); ++ list_add(&de->d_child, &de->d_parent->d_subdirs); ++ ++ list_for_each(lp, &inode->i_dentry) { ++ goal = list_entry(lp, struct dentry, d_alias); ++ if (goal->d_flags & DCACHE_NFSD_DISCONNECTED) { ++ assert(1==0); ++ } ++ } ++ ++ spin_unlock(&dcache_lock); ++ return goal; ++} ++ ++/* ++ * These are the special structures for the iopen pseudo directory. ++ */ ++ ++static struct inode_operations iopen_inode_operations = { ++ lookup: iopen_lookup, /* BKL held */ ++}; ++ ++static struct file_operations iopen_file_operations = { ++ read: generic_read_dir, ++}; ++ ++static int match_dentry(struct dentry *dentry, const char *name) ++{ ++ int len; ++ ++ len = strlen(name); ++ if (dentry->d_name.len != len) ++ return 0; ++ if (strncmp(dentry->d_name.name, name, len)) ++ return 0; ++ return 1; ++} ++ ++/* ++ * This function is spliced into ext3_lookup and returns 1 the file ++ * name is __iopen__ and dentry has been filled in appropriately. ++ */ ++int ext3_check_for_iopen(struct inode * dir, struct dentry *dentry) ++{ ++ struct inode * inode; ++ ++ if (dir->i_ino != EXT3_ROOT_INO || ++ !test_opt(dir->i_sb, IOPEN) || ++ !match_dentry(dentry, "__iopen__")) ++ return 0; ++ ++ inode = iget(dir->i_sb, EXT3_BAD_INO); ++ ++ if (!inode) ++ return 0; ++ d_add(dentry, inode); ++ return 1; ++} ++ ++/* ++ * This function is spliced into read_inode; it returns 1 if inode ++ * number is the one for /__iopen__, in which case the inode is filled ++ * in appropriately. Otherwise, this fuction returns 0. ++ */ ++int ext3_iopen_get_inode(struct inode * inode) ++{ ++ if (inode->i_ino != EXT3_BAD_INO) ++ return 0; ++ ++ inode->i_mode = S_IFDIR | S_IRUSR | S_IXUSR; ++ if (test_opt(inode->i_sb, IOPEN_NOPRIV)) ++ inode->i_mode |= 0777; ++ inode->i_uid = 0; ++ inode->i_gid = 0; ++ inode->i_nlink = 1; ++ inode->i_size = 4096; ++ inode->i_atime = CURRENT_TIME; ++ inode->i_ctime = CURRENT_TIME; ++ inode->i_mtime = CURRENT_TIME; ++ inode->u.ext3_i.i_dtime = 0; ++ inode->i_blksize = PAGE_SIZE; /* This is the optimal IO size ++ * (for stat), not the fs block ++ * size */ ++ inode->i_blocks = 0; ++ inode->i_version = 1; ++ inode->i_generation = 0; ++ ++ inode->i_op = &iopen_inode_operations; ++ inode->i_fop = &iopen_file_operations; ++ inode->i_mapping->a_ops = 0; ++ ++ return 1; ++} +--- /dev/null 2003-01-30 03:24:37.000000000 -0700 ++++ linux-2.4.18-p4smp-braam/fs/ext3/iopen.h 2003-05-17 13:14:22.000000000 -0600 +@@ -0,0 +1,15 @@ ++/* ++ * iopen.h ++ * ++ * Special support for opening files by inode number. ++ * ++ * Copyright (C) 2001 by Theodore Ts'o (tytso@alum.mit.edu). ++ * ++ * This file may be redistributed under the terms of the GNU General ++ * Public License. ++ */ ++ ++extern int ext3_check_for_iopen(struct inode * dir, struct dentry *dentry); ++extern int ext3_iopen_get_inode(struct inode * inode); ++ ++ +--- linux-2.4.18-p4smp/fs/ext3/namei.c~iopen-chaos-2.4.18 2003-05-17 13:12:54.000000000 -0600 ++++ linux-2.4.18-p4smp-braam/fs/ext3/namei.c 2003-05-17 13:17:13.000000000 -0600 +@@ -34,6 +34,7 @@ + #include + #include + #include ++#include "iopen.h" + + /* + * define how far ahead to read directories while searching them. +@@ -704,15 +705,22 @@ cleanup_and_exit: + return ret; + } + ++struct dentry *iopen_connect_dentry(struct dentry *de, struct inode *inode); ++ + static struct dentry *ext3_lookup(struct inode * dir, struct dentry *dentry) + { + struct inode * inode; + struct ext3_dir_entry_2 * de; + struct buffer_head * bh; ++ struct dentry *alternate = NULL; ++ + + if (dentry->d_name.len > EXT3_NAME_LEN) + return ERR_PTR(-ENAMETOOLONG); + ++ if (ext3_check_for_iopen(dir, dentry)) ++ return NULL; ++ + bh = ext3_find_entry(dentry, &de); + inode = NULL; + if (bh) { +@@ -723,6 +731,10 @@ static struct dentry *ext3_lookup(struct + if (!inode) + return ERR_PTR(-EACCES); + } ++ ++ if (inode && (alternate = iopen_connect_dentry(dentry, inode))) ++ return alternate; ++ + d_add(dentry, inode); + return NULL; + } +--- linux-2.4.18-p4smp/fs/ext3/super.c~iopen-chaos-2.4.18 2003-05-17 13:12:50.000000000 -0600 ++++ linux-2.4.18-p4smp-braam/fs/ext3/super.c 2003-05-17 13:14:22.000000000 -0600 +@@ -605,6 +605,17 @@ static int parse_options (char * options + || !strcmp (this_char, "quota") + || !strcmp (this_char, "usrquota")) + /* Don't do anything ;-) */ ; ++ else if (!strcmp (this_char, "iopen")) { ++ set_opt (sbi->s_mount_opt, IOPEN); ++ clear_opt (sbi->s_mount_opt, IOPEN_NOPRIV); ++ } else if (!strcmp (this_char, "noiopen")) { ++ clear_opt (sbi->s_mount_opt, IOPEN); ++ clear_opt (sbi->s_mount_opt, IOPEN_NOPRIV); ++ } ++ else if (!strcmp (this_char, "iopen_nopriv")) { ++ set_opt (sbi->s_mount_opt, IOPEN); ++ set_opt (sbi->s_mount_opt, IOPEN_NOPRIV); ++ } + else if (!strcmp (this_char, "journal")) { + /* @@@ FIXME */ + /* Eventually we will want to be able to create +--- linux-2.4.18-p4smp/include/linux/ext3_fs.h~iopen-chaos-2.4.18 2003-05-17 13:12:56.000000000 -0600 ++++ linux-2.4.18-p4smp-braam/include/linux/ext3_fs.h 2003-05-17 13:25:20.000000000 -0600 +@@ -320,6 +320,8 @@ struct ext3_inode { + #define EXT3_MOUNT_UPDATE_JOURNAL 0x1000 /* Update the journal format */ + #define EXT3_MOUNT_NO_UID32 0x2000 /* Disable 32-bit UIDs */ + #define EXT3_MOUNT_INDEX 0x4000 /* Enable directory index */ ++#define EXT3_MOUNT_IOPEN 0x8000 /* Allow access via iopen */ ++#define EXT3_MOUNT_IOPEN_NOPRIV 0x10000 /* Make iopen world-readable */ + + /* Compatibility, for having both ext2_fs.h and ext3_fs.h included at once */ + #ifndef _LINUX_EXT2_FS_H + +_ diff --git a/lustre/kernel_patches/patches/iopen.patch b/lustre/kernel_patches/patches/iopen.patch new file mode 100644 index 0000000..af62a46 --- /dev/null +++ b/lustre/kernel_patches/patches/iopen.patch @@ -0,0 +1,406 @@ + Documentation/filesystems/ext2.txt | 16 ++ + fs/ext3/Makefile | 2 + fs/ext3/inode.c | 4 + fs/ext3/iopen.c | 240 +++++++++++++++++++++++++++++++++++++ + fs/ext3/iopen.h | 15 ++ + fs/ext3/namei.c | 13 +- + fs/ext3/super.c | 11 + + include/linux/ext3_fs.h | 2 + 8 files changed, 301 insertions(+), 2 deletions(-) + +--- linux-2.4.20/Documentation/filesystems/ext2.txt~iopen 2001-07-11 16:44:45.000000000 -0600 ++++ linux-2.4.20-braam/Documentation/filesystems/ext2.txt 2003-05-17 14:06:00.000000000 -0600 +@@ -35,6 +35,22 @@ resgid=n The group ID which may use th + + sb=n Use alternate superblock at this location. + ++iopen Makes an invisible pseudo-directory called ++ __iopen__ available in the root directory ++ of the filesystem. Allows open-by-inode- ++ number. i.e., inode 3145 can be accessed ++ via /mntpt/__iopen__/3145 ++ ++iopen_nopriv This option makes the iopen directory be ++ world-readable. This may be safer since it ++ allows daemons to run as an unprivileged user, ++ however it significantly changes the security ++ model of a Unix filesystem, since previously ++ all files under a mode 700 directory were not ++ generally avilable even if the ++ permissions on the file itself is ++ world-readable. ++ + grpquota,noquota,quota,usrquota Quota options are silently ignored by ext2. + + +--- linux-2.4.20/fs/ext3/Makefile~iopen 2003-05-17 14:05:57.000000000 -0600 ++++ linux-2.4.20-braam/fs/ext3/Makefile 2003-05-17 14:06:00.000000000 -0600 +@@ -11,7 +11,7 @@ O_TARGET := ext3.o + + export-objs := ext3-exports.o + +-obj-y := balloc.o bitmap.o dir.o file.o fsync.o ialloc.o inode.o \ ++obj-y := balloc.o bitmap.o dir.o file.o fsync.o ialloc.o inode.o iopen.o \ + ioctl.o namei.o super.o symlink.o hash.o ext3-exports.o + obj-m := $(O_TARGET) + +--- linux-2.4.20/fs/ext3/inode.c~iopen 2003-05-17 14:06:00.000000000 -0600 ++++ linux-2.4.20-braam/fs/ext3/inode.c 2003-05-17 14:06:00.000000000 -0600 +@@ -31,6 +31,7 @@ + #include + #include + #include ++#include "iopen.h" + + /* + * SEARCH_FROM_ZERO forces each block allocation to search from the start +@@ -2137,6 +2138,9 @@ void ext3_read_inode(struct inode * inod + struct buffer_head *bh; + int block; + ++ if (ext3_iopen_get_inode(inode)) ++ return; ++ + if(ext3_get_inode_loc(inode, &iloc)) + goto bad_inode; + bh = iloc.bh; +--- /dev/null 2003-01-30 03:24:37.000000000 -0700 ++++ linux-2.4.20-braam/fs/ext3/iopen.c 2003-05-17 22:18:55.000000000 -0600 +@@ -0,0 +1,240 @@ ++ ++ ++/* ++ * linux/fs/ext3/iopen.c ++ * ++ * Special support for open by inode number ++ * ++ * Copyright (C) 2001 by Theodore Ts'o (tytso@alum.mit.edu). ++ * ++ * This file may be redistributed under the terms of the GNU General ++ * Public License. ++ */ ++ ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include "iopen.h" ++ ++#ifndef assert ++#define assert(test) J_ASSERT(test) ++#endif ++ ++#define IOPEN_NAME_LEN 32 ++ ++/* ++ * This implements looking up an inode by number. ++ */ ++static struct dentry *iopen_lookup(struct inode * dir, struct dentry *dentry) ++{ ++ struct inode * inode; ++ unsigned long ino; ++ struct list_head *lp; ++ struct dentry *alternate; ++ char buf[IOPEN_NAME_LEN]; ++ ++ if (dentry->d_name.len >= IOPEN_NAME_LEN) ++ return ERR_PTR(-ENAMETOOLONG); ++ ++ memcpy(buf, dentry->d_name.name, dentry->d_name.len); ++ buf[dentry->d_name.len] = 0; ++ ++ if (strcmp(buf, ".") == 0) ++ ino = dir->i_ino; ++ else if (strcmp(buf, "..") == 0) ++ ino = EXT3_ROOT_INO; ++ else ++ ino = simple_strtoul(buf, 0, 0); ++ ++ if ((ino != EXT3_ROOT_INO && ++ //ino != EXT3_ACL_IDX_INO && ++ //ino != EXT3_ACL_DATA_INO && ++ ino < EXT3_FIRST_INO(dir->i_sb)) || ++ ino > le32_to_cpu(dir->i_sb->u.ext3_sb.s_es->s_inodes_count)) ++ return ERR_PTR(-ENOENT); ++ ++ inode = iget(dir->i_sb, ino); ++ if (!inode) ++ return ERR_PTR(-EACCES); ++ if (is_bad_inode(inode)) { ++ iput(inode); ++ return ERR_PTR(-ENOENT); ++ } ++ ++ /* preferrably return a connected dentry */ ++ spin_lock(&dcache_lock); ++ list_for_each(lp, &inode->i_dentry) { ++ alternate = list_entry(lp, struct dentry, d_alias); ++ assert(!(alternate->d_flags & DCACHE_NFSD_DISCONNECTED)); ++ } ++ ++ if (!list_empty(&inode->i_dentry)) { ++ alternate = list_entry(inode->i_dentry.next, ++ struct dentry, d_alias); ++ dget_locked(alternate); ++ alternate->d_vfs_flags |= DCACHE_REFERENCED; ++ iput(inode); ++ spin_unlock(&dcache_lock); ++ return alternate; ++ } ++ dentry->d_flags |= DCACHE_NFSD_DISCONNECTED; ++ spin_unlock(&dcache_lock); ++ ++ d_add(dentry, inode); ++ return NULL; ++} ++ ++#define do_switch(x,y) do { \ ++ __typeof__ (x) __tmp = x; \ ++ x = y; y = __tmp; } while (0) ++ ++static inline void switch_names(struct dentry * dentry, struct dentry * target) ++{ ++ const unsigned char *old_name, *new_name; ++ ++ memcpy(dentry->d_iname, target->d_iname, DNAME_INLINE_LEN); ++ old_name = target->d_name.name; ++ new_name = dentry->d_name.name; ++ if (old_name == target->d_iname) ++ old_name = dentry->d_iname; ++ if (new_name == dentry->d_iname) ++ new_name = target->d_iname; ++ target->d_name.name = new_name; ++ dentry->d_name.name = old_name; ++} ++ ++ ++struct dentry *iopen_connect_dentry(struct dentry *de, struct inode *inode) ++{ ++ struct dentry *tmp, *goal = NULL; ++ struct list_head *lp; ++ ++ /* preferrably return a connected dentry */ ++ spin_lock(&dcache_lock); ++ /* verify this dentry is really new */ ++ assert(!de->d_inode); ++ assert(list_empty(&de->d_subdirs)); ++ assert(list_empty(&de->d_alias)); ++ ++ ++ list_for_each(lp, &inode->i_dentry) { ++ tmp = list_entry(lp, struct dentry, d_alias); ++ if (tmp->d_flags & DCACHE_NFSD_DISCONNECTED) { ++ assert(tmp->d_alias.next == &inode->i_dentry); ++ assert(tmp->d_alias.prev == &inode->i_dentry); ++ goal = tmp; ++ dget_locked(goal); ++ break; ++ } ++ } ++ ++ if (!goal) { ++ spin_unlock(&dcache_lock); ++ return NULL; ++ } ++ ++ /* Move the goal to the de hash queue */ ++ goal->d_flags &= ~DCACHE_NFSD_DISCONNECTED; ++ list_del(&goal->d_hash); ++ list_add(&goal->d_hash, &de->d_hash); ++ ++ list_del(&goal->d_child); ++ list_del(&de->d_child); ++ ++ /* Switch the parents and the names.. */ ++ switch_names(goal, de); ++ do_switch(goal->d_parent, de->d_parent); ++ do_switch(goal->d_name.len, de->d_name.len); ++ do_switch(goal->d_name.hash, de->d_name.hash); ++ ++ /* And add them back to the (new) parent lists */ ++ list_add(&goal->d_child, &goal->d_parent->d_subdirs); ++ list_add(&de->d_child, &de->d_parent->d_subdirs); ++ ++ spin_unlock(&dcache_lock); ++ return goal; ++} ++ ++/* ++ * These are the special structures for the iopen pseudo directory. ++ */ ++ ++static struct inode_operations iopen_inode_operations = { ++ lookup: iopen_lookup, /* BKL held */ ++}; ++ ++static struct file_operations iopen_file_operations = { ++ read: generic_read_dir, ++}; ++ ++static int match_dentry(struct dentry *dentry, const char *name) ++{ ++ int len; ++ ++ len = strlen(name); ++ if (dentry->d_name.len != len) ++ return 0; ++ if (strncmp(dentry->d_name.name, name, len)) ++ return 0; ++ return 1; ++} ++ ++/* ++ * This function is spliced into ext3_lookup and returns 1 the file ++ * name is __iopen__ and dentry has been filled in appropriately. ++ */ ++int ext3_check_for_iopen(struct inode * dir, struct dentry *dentry) ++{ ++ struct inode * inode; ++ ++ if (dir->i_ino != EXT3_ROOT_INO || ++ !test_opt(dir->i_sb, IOPEN) || ++ !match_dentry(dentry, "__iopen__")) ++ return 0; ++ ++ inode = iget(dir->i_sb, EXT3_BAD_INO); ++ ++ if (!inode) ++ return 0; ++ d_add(dentry, inode); ++ return 1; ++} ++ ++/* ++ * This function is spliced into read_inode; it returns 1 if inode ++ * number is the one for /__iopen__, in which case the inode is filled ++ * in appropriately. Otherwise, this fuction returns 0. ++ */ ++int ext3_iopen_get_inode(struct inode * inode) ++{ ++ if (inode->i_ino != EXT3_BAD_INO) ++ return 0; ++ ++ inode->i_mode = S_IFDIR | S_IRUSR | S_IXUSR; ++ if (test_opt(inode->i_sb, IOPEN_NOPRIV)) ++ inode->i_mode |= 0777; ++ inode->i_uid = 0; ++ inode->i_gid = 0; ++ inode->i_nlink = 1; ++ inode->i_size = 4096; ++ inode->i_atime = CURRENT_TIME; ++ inode->i_ctime = CURRENT_TIME; ++ inode->i_mtime = CURRENT_TIME; ++ inode->u.ext3_i.i_dtime = 0; ++ inode->i_blksize = PAGE_SIZE; /* This is the optimal IO size ++ * (for stat), not the fs block ++ * size */ ++ inode->i_blocks = 0; ++ inode->i_version = 1; ++ inode->i_generation = 0; ++ ++ inode->i_op = &iopen_inode_operations; ++ inode->i_fop = &iopen_file_operations; ++ inode->i_mapping->a_ops = 0; ++ ++ return 1; ++} +--- /dev/null 2003-01-30 03:24:37.000000000 -0700 ++++ linux-2.4.20-braam/fs/ext3/iopen.h 2003-05-17 14:06:00.000000000 -0600 +@@ -0,0 +1,15 @@ ++/* ++ * iopen.h ++ * ++ * Special support for opening files by inode number. ++ * ++ * Copyright (C) 2001 by Theodore Ts'o (tytso@alum.mit.edu). ++ * ++ * This file may be redistributed under the terms of the GNU General ++ * Public License. ++ */ ++ ++extern int ext3_check_for_iopen(struct inode * dir, struct dentry *dentry); ++extern int ext3_iopen_get_inode(struct inode * inode); ++ ++ +--- linux-2.4.20/fs/ext3/namei.c~iopen 2003-05-17 14:05:59.000000000 -0600 ++++ linux-2.4.20-braam/fs/ext3/namei.c 2003-05-17 22:23:08.000000000 -0600 +@@ -35,7 +35,7 @@ + #include + #include + #include +- ++#include "iopen.h" + + /* + * define how far ahead to read directories while searching them. +@@ -921,16 +921,21 @@ errout: + return NULL; + } + #endif ++struct dentry *iopen_connect_dentry(struct dentry *de, struct inode *inode); + + static struct dentry *ext3_lookup(struct inode * dir, struct dentry *dentry) + { + struct inode * inode; + struct ext3_dir_entry_2 * de; + struct buffer_head * bh; ++ struct dentry *alternate = NULL; + + if (dentry->d_name.len > EXT3_NAME_LEN) + return ERR_PTR(-ENAMETOOLONG); + ++ if (ext3_check_for_iopen(dir, dentry)) ++ return NULL; ++ + bh = ext3_find_entry(dentry, &de); + inode = NULL; + if (bh) { +@@ -942,6 +947,12 @@ static struct dentry *ext3_lookup(struct + return ERR_PTR(-EACCES); + } + } ++ ++ if (inode && (alternate = iopen_connect_dentry(dentry, inode))) { ++ iput(inode); ++ return alternate; ++ } ++ + d_add(dentry, inode); + return NULL; + } +--- linux-2.4.20/fs/ext3/super.c~iopen 2003-05-17 14:05:59.000000000 -0600 ++++ linux-2.4.20-braam/fs/ext3/super.c 2003-05-17 14:06:00.000000000 -0600 +@@ -820,6 +820,17 @@ static int parse_options (char * options + || !strcmp (this_char, "quota") + || !strcmp (this_char, "usrquota")) + /* Don't do anything ;-) */ ; ++ else if (!strcmp (this_char, "iopen")) { ++ set_opt (sbi->s_mount_opt, IOPEN); ++ clear_opt (sbi->s_mount_opt, IOPEN_NOPRIV); ++ } else if (!strcmp (this_char, "noiopen")) { ++ clear_opt (sbi->s_mount_opt, IOPEN); ++ clear_opt (sbi->s_mount_opt, IOPEN_NOPRIV); ++ } ++ else if (!strcmp (this_char, "iopen_nopriv")) { ++ set_opt (sbi->s_mount_opt, IOPEN); ++ set_opt (sbi->s_mount_opt, IOPEN_NOPRIV); ++ } + else if (!strcmp (this_char, "journal")) { + /* @@@ FIXME */ + /* Eventually we will want to be able to create +--- linux-2.4.20/include/linux/ext3_fs.h~iopen 2003-05-17 14:05:59.000000000 -0600 ++++ linux-2.4.20-braam/include/linux/ext3_fs.h 2003-05-17 14:06:29.000000000 -0600 +@@ -322,6 +322,8 @@ struct ext3_inode { + #define EXT3_MOUNT_UPDATE_JOURNAL 0x1000 /* Update the journal format */ + #define EXT3_MOUNT_NO_UID32 0x2000 /* Disable 32-bit UIDs */ + #define EXT3_MOUNT_XATTR_USER 0x4000 /* Extended user attributes */ ++#define EXT3_MOUNT_IOPEN 0x8000 /* Allow access via iopen */ ++#define EXT3_MOUNT_IOPEN_NOPRIV 0x10000 /* Make iopen world-readable */ + #define EXT3_MOUNT_ASYNCDEL 0x20000 /* Delayed deletion */ + + /* Compatibility, for having both ext2_fs.h and ext3_fs.h included at once */ + +_ diff --git a/lustre/kernel_patches/patches/kmem_cache_validate_2.4.20.patch b/lustre/kernel_patches/patches/kmem_cache_validate_2.4.20.patch new file mode 100644 index 0000000..ee66c5a --- /dev/null +++ b/lustre/kernel_patches/patches/kmem_cache_validate_2.4.20.patch @@ -0,0 +1,105 @@ + arch/ia64/mm/init.c | 6 +++++ + include/linux/slab.h | 1 + kernel/ksyms.c | 1 + mm/slab.c | 53 +++++++++++++++++++++++++++++++++++++++++++++++++++ + 4 files changed, 61 insertions(+) + +--- linux/arch/ia64/mm/init.c~kmem_cache_validate_hp Wed Apr 9 11:09:46 2003 ++++ linux-mmonroe/arch/ia64/mm/init.c Wed Apr 9 11:12:23 2003 +@@ -45,6 +45,12 @@ unsigned long vmalloc_end = VMALLOC_END_ + static struct page *vmem_map; + static unsigned long num_dma_physpages; + ++struct page *check_get_page(unsigned long kaddr) ++{ ++#warning FIXME: Lustre team, is this solid? ++ return virt_to_page(kaddr); ++} ++ + int + do_check_pgt_cache (int low, int high) + { +--- linux/include/linux/slab.h~kmem_cache_validate_hp Wed Apr 9 11:08:48 2003 ++++ linux-mmonroe/include/linux/slab.h Wed Apr 9 11:12:23 2003 +@@ -56,6 +56,7 @@ extern kmem_cache_t *kmem_cache_create(c + extern int kmem_cache_destroy(kmem_cache_t *); + extern int kmem_cache_shrink(kmem_cache_t *); + extern void *kmem_cache_alloc(kmem_cache_t *, int); ++extern int kmem_cache_validate(kmem_cache_t *cachep, void *objp); + extern void kmem_cache_free(kmem_cache_t *, void *); + extern unsigned int kmem_cache_size(kmem_cache_t *); + +--- linux/kernel/ksyms.c~kmem_cache_validate_hp Wed Apr 9 11:12:20 2003 ++++ linux-mmonroe/kernel/ksyms.c Wed Apr 9 11:12:23 2003 +@@ -119,6 +119,7 @@ EXPORT_SYMBOL(kmem_find_general_cachep); + EXPORT_SYMBOL(kmem_cache_create); + EXPORT_SYMBOL(kmem_cache_destroy); + EXPORT_SYMBOL(kmem_cache_shrink); ++EXPORT_SYMBOL(kmem_cache_validate); + EXPORT_SYMBOL(kmem_cache_alloc); + EXPORT_SYMBOL(kmem_cache_free); + EXPORT_SYMBOL(kmem_cache_size); +--- linux/mm/slab.c~kmem_cache_validate_hp Wed Apr 9 11:08:47 2003 ++++ linux-mmonroe/mm/slab.c Wed Apr 9 11:12:23 2003 +@@ -1205,6 +1205,59 @@ failed: + * Called with the cache-lock held. + */ + ++extern struct page *check_get_page(unsigned long kaddr); ++struct page *page_mem_map(struct page *page); ++static int kmem_check_cache_obj (kmem_cache_t * cachep, ++ slab_t *slabp, void * objp) ++{ ++ int i; ++ unsigned int objnr; ++ ++#if DEBUG ++ if (cachep->flags & SLAB_RED_ZONE) { ++ objp -= BYTES_PER_WORD; ++ if ( *(unsigned long *)objp != RED_MAGIC2) ++ /* Either write before start, or a double free. */ ++ return 0; ++ if (*(unsigned long *)(objp+cachep->objsize - ++ BYTES_PER_WORD) != RED_MAGIC2) ++ /* Either write past end, or a double free. */ ++ return 0; ++ } ++#endif ++ ++ objnr = (objp-slabp->s_mem)/cachep->objsize; ++ if (objnr >= cachep->num) ++ return 0; ++ if (objp != slabp->s_mem + objnr*cachep->objsize) ++ return 0; ++ ++ /* Check slab's freelist to see if this obj is there. */ ++ for (i = slabp->free; i != BUFCTL_END; i = slab_bufctl(slabp)[i]) { ++ if (i == objnr) ++ return 0; ++ } ++ return 1; ++} ++ ++ ++int kmem_cache_validate(kmem_cache_t *cachep, void *objp) ++{ ++ struct page *page = check_get_page((unsigned long)objp); ++ ++ if (!VALID_PAGE(page)) ++ return 0; ++ ++ if (!PageSlab(page)) ++ return 0; ++ ++ /* XXX check for freed slab objects ? */ ++ if (!kmem_check_cache_obj(cachep, GET_PAGE_SLAB(page), objp)) ++ return 0; ++ ++ return (cachep == GET_PAGE_CACHE(page)); ++} ++ + #if DEBUG + static int kmem_extra_free_checks (kmem_cache_t * cachep, + slab_t *slabp, void * objp) + +_ diff --git a/lustre/kernel_patches/patches/mcore-2.4.20-8.patch b/lustre/kernel_patches/patches/mcore-2.4.20-8.patch new file mode 100644 index 0000000..c8b80eb --- /dev/null +++ b/lustre/kernel_patches/patches/mcore-2.4.20-8.patch @@ -0,0 +1,2738 @@ +? linux/.config +? linux/include/linux/autoconf.h +? linux/include/linux/modules +Index: linux/Makefile +=================================================================== +RCS file: /chaos/cvs/kernel-rh/linux/Makefile,v +retrieving revision 1.3.2.1 +retrieving revision 1.3.2.1.2.1 +diff -u -r1.3.2.1 -r1.3.2.1.2.1 +--- linux/Makefile 12 Mar 2003 19:48:52 -0000 1.3.2.1 ++++ linux/Makefile 1 Apr 2003 12:17:40 -0000 1.3.2.1.2.1 +@@ -99,6 +99,10 @@ + CFLAGS += -fomit-frame-pointer + endif + AFLAGS := -D__ASSEMBLY__ $(CPPFLAGS) ++ifeq ($(CONFIG_MCL_COREDUMP),y) ++ CFLAGS += -g ++endif ++ + + # + # ROOT_DEV specifies the default root-device when making the image. +Index: linux/Documentation/Configure.help +=================================================================== +RCS file: /chaos/cvs/kernel-rh/linux/Documentation/Configure.help,v +retrieving revision 1.3.2.1 +retrieving revision 1.3.2.1.2.1 +diff -u -r1.3.2.1 -r1.3.2.1.2.1 +--- linux/Documentation/Configure.help 12 Mar 2003 19:48:52 -0000 1.3.2.1 ++++ linux/Documentation/Configure.help 1 Apr 2003 12:17:40 -0000 1.3.2.1.2.1 +@@ -21660,6 +21660,35 @@ + This option allows you to run the kernel with data cache disabled. + Say Y if you experience CPM lock-ups. + ++Boot kernel image support ++CONFIG_BOOTIMG ++ Add support for booting a new Linux kernel from a running Linux ++ system. You need to download the bootimg(8) utility from ++ ftp://icaftp.epfl.ch/pub/people/almesber/misc/bootimg-current.tar.gz ++ in order to use this functionality. ++ ++Protect SMP configuration tables ++CONFIG_BOOTIMG_SMP ++ On SMP systems, the BIOS stores tables with configuration data in ++ memory and an SMP-enabled kernel reads these tables. However, a ++ kernel without SMP support will overwrite such tables. If a kernel ++ without SMP support used bootimg to boot an SMP-enabled kernel, the ++ latter will probably crash when trying to read the SMP tables. The ++ CONFIG_BOOTIMG_SMP option enables minimal support for scanning and ++ protecting of SMP configuration tables also for kernels without SMP ++ support. ++ ++In-memory kernel core dump facility ++CONFIG_MCL_COREDUMP ++ In conjunction with bootimg, this allows you to get kernel core dumps ++ of your system at panic() time. The panic call is modified so that it ++ calls the core dump facility and reboots the system. On the way back ++ up, the kernel dump image is written out to disk by the accompanying ++ init script. You can use the crash analysis tool to analyze the core ++ dump. This tool can be found at : ++ ++ http://www.missioncriticallinux.com/download ++ + # + # m68k-specific kernel options + # Documented by Chris Lawrence et al. +Index: linux/arch/i386/config.in +=================================================================== +RCS file: /chaos/cvs/kernel-rh/linux/arch/i386/config.in,v +retrieving revision 1.3.2.1 +retrieving revision 1.3.2.1.2.2 +diff -u -r1.3.2.1 -r1.3.2.1.2.2 +--- linux/arch/i386/config.in 12 Mar 2003 19:49:05 -0000 1.3.2.1 ++++ linux/arch/i386/config.in 1 Apr 2003 19:35:12 -0000 1.3.2.1.2.2 +@@ -502,6 +502,12 @@ + bool ' Magic SysRq key' CONFIG_MAGIC_SYSRQ + bool ' Spinlock debugging' CONFIG_DEBUG_SPINLOCK + bool ' Compile the kernel with frame pointers' CONFIG_FRAME_POINTER ++ if [ "$CONFIG_FRAME_POINTER " != "n" ]; then ++ bool ' Kernel Core Dump Facility' CONFIG_MCL_COREDUMP ++ if [ "$CONFIG_MCL_COREDUMP" = "y" ]; then ++ bool ' Reboot using bootimg' CONFIG_BOOTIMG ++ fi ++ fi + fi + + endmenu +Index: linux/arch/i386/vmlinux.lds +=================================================================== +RCS file: /chaos/cvs/kernel-rh/linux/arch/i386/vmlinux.lds,v +retrieving revision 1.1.1.1.4.1 +retrieving revision 1.1.1.1.4.1.2.1 +diff -u -r1.1.1.1.4.1 -r1.1.1.1.4.1.2.1 +--- linux/arch/i386/vmlinux.lds 12 Mar 2003 19:49:05 -0000 1.1.1.1.4.1 ++++ linux/arch/i386/vmlinux.lds 1 Apr 2003 12:17:40 -0000 1.1.1.1.4.1.2.1 +@@ -19,6 +19,13 @@ + .rodata : { *(.rodata) *(.rodata.*) } + .kstrtab : { *(.kstrtab) } + ++ . = ALIGN(16); /* Relocatable bootimage code */ ++ __bootimg_start = .; ++ .bootimg : { ++ *(.bootimg) ++ } ++ __bootimg_end = .; ++ + . = ALIGN(16); /* Exception table */ + __start___ex_table = .; + __ex_table : { *(__ex_table) } +Index: linux/arch/i386/boot/setup.S +=================================================================== +RCS file: /chaos/cvs/kernel-rh/linux/arch/i386/boot/setup.S,v +retrieving revision 1.2.2.1 +retrieving revision 1.2.2.1.2.1 +diff -u -r1.2.2.1 -r1.2.2.1.2.1 +--- linux/arch/i386/boot/setup.S 12 Mar 2003 19:49:05 -0000 1.2.2.1 ++++ linux/arch/i386/boot/setup.S 1 Apr 2003 12:17:40 -0000 1.2.2.1.2.1 +@@ -105,16 +105,22 @@ + # flags, unused bits must be zero (RFU) bit within loadflags + loadflags: + LOADED_HIGH = 1 # If set, the kernel is loaded high ++RELOADS_GDT = 2 # if set, kernel reloads GDT, such that ++ # boot loader does not have to provide ++ # GDT in a "safe" memory location + CAN_USE_HEAP = 0x80 # If set, the loader also has set + # heap_end_ptr to tell how much + # space behind setup.S can be used for + # heap purposes. + # Only the loader knows what is free +-#ifndef __BIG_KERNEL__ +- .byte 0 +-#else +- .byte LOADED_HIGH ++_FLAGS = 0 ++#ifdef __BIG_KERNEL__ ++ _FLAGS = _FLAGS | LOADED_HIGH + #endif ++#ifdef CONFIG_BOOTIMG ++ _FLAGS = _FLAGS | RELOADS_GDT ++#endif ++ .byte _FLAGS + + setup_move_size: .word 0x8000 # size to move, when setup is not + # loaded at 0x90000. We will move setup +Index: linux/arch/i386/kernel/Makefile +=================================================================== +RCS file: /chaos/cvs/kernel-rh/linux/arch/i386/kernel/Makefile,v +retrieving revision 1.2.2.1 +retrieving revision 1.2.2.1.2.1 +diff -u -r1.2.2.1 -r1.2.2.1.2.1 +--- linux/arch/i386/kernel/Makefile 12 Mar 2003 19:49:05 -0000 1.2.2.1 ++++ linux/arch/i386/kernel/Makefile 1 Apr 2003 12:17:40 -0000 1.2.2.1.2.1 +@@ -49,6 +49,7 @@ + obj-$(CONFIG_X86_LONGRUN) += longrun.o + obj-$(CONFIG_ELAN_CPUFREQ) += elanfreq.o + obj-$(CONFIG_PROFILING) += profile.o ++obj-$(CONFIG_MCL_COREDUMP) += crash.o + + + include $(TOPDIR)/Rules.make +Index: linux/arch/i386/kernel/crash.c +=================================================================== +RCS file: linux/arch/i386/kernel/crash.c +diff -N linux/arch/i386/kernel/crash.c +--- /dev/null 1 Jan 1970 00:00:00 -0000 ++++ linux/arch/i386/kernel/crash.c 1 Apr 2003 12:17:40 -0000 1.1.6.1 +@@ -0,0 +1,82 @@ ++/* ++ * linux/arch/i386/crash.c ++ * ++ * Architecture dependant code for MCL in-memory core dump. ++ */ ++#include ++#include ++#include ++#include ++#include ++#include ++ ++inline void crash_save_regs(void) { ++ static unsigned long regs[8]; ++ ++ __asm__ __volatile__("movl %%ebx,%0" : "=m"(regs[0])); ++ __asm__ __volatile__("movl %%ecx,%0" : "=m"(regs[1])); ++ __asm__ __volatile__("movl %%edx,%0" : "=m"(regs[2])); ++ __asm__ __volatile__("movl %%esi,%0" : "=m"(regs[3])); ++ __asm__ __volatile__("movl %%edi,%0" : "=m"(regs[4])); ++ __asm__ __volatile__("movl %%ebp,%0" : "=m"(regs[5])); ++ __asm__ __volatile__("movl %%eax,%0" : "=m"(regs[6])); ++ __asm__ __volatile__("movl %%esp,%0" : "=m"(regs[7])); ++ ++ panic_regs = regs; ++} ++ ++/* ++ * Save the current stack pointer and EIP. ++ */ ++void crash_save_current_state(struct task_struct *tp) ++{ ++ /* ++ * Here we save ebp instead of esp just in case the compiler ++ * decides to put an extra push in before we execute this ++ * instruction (thus invalidating our frame pointer). ++ */ ++ asm volatile("movl %%ebp,%0":"=m" (*(u_long *)&tp->thread.esp)); ++ tp->thread.eip = (u_long)crash_save_current_state; ++ panic_ksp[smp_processor_id()] = tp->thread.esp; ++ mb(); ++ ++ save_core(); ++ ++ crash_halt_or_reboot(1); ++} ++ ++/* ++ * If we are not the panicking thread, we simply halt. Otherwise, ++ * we take care of calling the reboot code. ++ */ ++void crash_halt_or_reboot(int boot_cpu) ++{ ++#ifdef CONFIG_SMP ++ if (!boot_cpu) { ++ stop_this_cpu(NULL); ++ /* NOTREACHED */ ++ } ++#endif ++ machine_restart(NULL); ++} ++ ++void crash_cleanup_smp_state(void) ++{ ++ /* ++ * Here we duplicate smp_send_stop. Crash_halt_or_reboot() calls ++ * stop_this_cpu. We now know that we are the only one running, ++ * so we finish off the smp_send_stop function. ++ */ ++ __cli(); ++#ifdef CONFIG_SMP ++ disable_local_APIC(); ++#endif ++} ++ ++/* ++ * Core dump IPI ++ */ ++void smp_crash_funnel_cpu(void) ++{ ++ crash_save_current_state(current); ++} +Index: linux/arch/i386/kernel/nmi.c +=================================================================== +RCS file: /chaos/cvs/kernel-rh/linux/arch/i386/kernel/nmi.c,v +retrieving revision 1.2.2.1 +retrieving revision 1.2.2.1.2.1 +diff -u -r1.2.2.1 -r1.2.2.1.2.1 +--- linux/arch/i386/kernel/nmi.c 12 Mar 2003 19:49:06 -0000 1.2.2.1 ++++ linux/arch/i386/kernel/nmi.c 1 Apr 2003 12:17:40 -0000 1.2.2.1.2.1 +@@ -374,11 +374,18 @@ + bust_spinlocks(1); + printk("NMI Watchdog detected LOCKUP on CPU%d, eip %08lx, registers:\n", cpu, regs->eip); + show_registers(regs); ++#ifdef CONFIG_MCL_COREDUMP ++ spin_unlock(&nmi_print_lock); ++ bust_spinlocks(0); ++ panic("die"); ++ /* NOTREACHED */ ++#else + printk("console shuts up ...\n"); + console_silent(); + spin_unlock(&nmi_print_lock); + bust_spinlocks(0); + do_exit(SIGSEGV); ++#endif + } + } else { + last_irq_sums[cpu] = sum; +Index: linux/arch/i386/kernel/process.c +=================================================================== +RCS file: /chaos/cvs/kernel-rh/linux/arch/i386/kernel/process.c,v +retrieving revision 1.2.2.2 +retrieving revision 1.2.2.2.2.1 +diff -u -r1.2.2.2 -r1.2.2.2.2.1 +--- linux/arch/i386/kernel/process.c 1 Apr 2003 02:11:17 -0000 1.2.2.2 ++++ linux/arch/i386/kernel/process.c 1 Apr 2003 12:17:40 -0000 1.2.2.2.2.1 +@@ -50,6 +50,9 @@ + #ifdef CONFIG_MATH_EMULATION + #include + #endif ++#ifdef CONFIG_BOOTIMG ++#include ++#endif + + #include + +@@ -377,7 +380,21 @@ + + void machine_restart(char * __unused) + { ++#ifdef CONFIG_MCL_COREDUMP ++ extern char *panicmsg; ++ /* ++ * Only call bootimg if we have a valid descriptor and ++ * we are in a panic() context. ++ */ ++ if (panicmsg) ++#endif ++#ifdef CONFIG_BOOTIMG ++ if (bootimg_dsc.page_dir) ++ boot_image(); ++#endif ++ + #if CONFIG_SMP ++{ + int cpuid; + + cpuid = GET_APIC_ID(apic_read(APIC_ID)); +@@ -413,6 +430,7 @@ + if (!netdump_func) + smp_send_stop(); + disable_IO_APIC(); ++} + #endif + + if(!reboot_thru_bios) { +Index: linux/arch/i386/kernel/setup.c +=================================================================== +RCS file: /chaos/cvs/kernel-rh/linux/arch/i386/kernel/setup.c,v +retrieving revision 1.3.2.1 +retrieving revision 1.3.2.1.2.2 +diff -u -r1.3.2.1 -r1.3.2.1.2.2 +--- linux/arch/i386/kernel/setup.c 12 Mar 2003 19:49:06 -0000 1.3.2.1 ++++ linux/arch/i386/kernel/setup.c 1 Apr 2003 17:55:35 -0000 1.3.2.1.2.2 +@@ -116,6 +116,9 @@ + #include + #include + #include ++#ifdef CONFIG_MCL_COREDUMP ++#include ++#endif + /* + * Machine setup.. + */ +@@ -973,6 +976,7 @@ + static unsigned long __init setup_memory(void) + { + unsigned long bootmap_size, start_pfn, max_low_pfn; ++ unsigned long bootmap_pages = 0UL, crash_pages = 0UL; + + /* + * partially used pages are not usable - thus +@@ -992,6 +996,21 @@ + printk(KERN_NOTICE "%ldMB HIGHMEM available.\n", + pages_to_mb(highend_pfn - highstart_pfn)); + #endif ++ ++#ifdef CONFIG_MCL_COREDUMP ++ bootmap_pages = bootmem_bootmap_pages(max_low_pfn); ++ crash_pages = crash_pages_needed(); ++ ++ printk("start_pfn: %d, bootmap_pages: %d\n", start_pfn, bootmap_pages); ++ ++ crash_init((u_long)phys_to_virt(PFN_PHYS(start_pfn)), ++ (u_long)phys_to_virt(PFN_PHYS(LOW_OFFSET + start_pfn)), ++ (u_long)phys_to_virt(PFN_PHYS(LOW_OFFSET + start_pfn + ++ crash_pages))); ++ ++ printk("new start_pfn: %08lx\n", PFN_PHYS(start_pfn)); ++ printk("crash map starts at %lx\n",(start_pfn+bootmap_pages)*PAGE_SIZE); ++#endif + printk(KERN_NOTICE "%ldMB LOWMEM available.\n", + pages_to_mb(max_low_pfn)); + /* +@@ -1007,8 +1026,8 @@ + * the (very unlikely) case of us accidentally initializing the + * bootmem allocator with an invalid RAM area. + */ +- reserve_bootmem(HIGH_MEMORY, (PFN_PHYS(start_pfn) + +- bootmap_size + PAGE_SIZE-1) - (HIGH_MEMORY)); ++ reserve_bootmem(HIGH_MEMORY, (PFN_PHYS(start_pfn) + bootmap_size + ++ ((1+crash_pages)*PAGE_SIZE) + PAGE_SIZE-1) - (HIGH_MEMORY)); + + /* + * reserve physical page 0 - it's a special BIOS page on many boxes, +@@ -1016,6 +1035,16 @@ + */ + reserve_bootmem(0, PAGE_SIZE); + ++#ifdef CONFIG_BOOTIMG ++ /* ++ * bootimg(8) reads the old parameter block. Note that the copy in ++ * empty_zero_page will vanish when mem_init runs. (Should we ++ * memcpy(phys_to_virt(0x90000), PARAM, PAGE_SIZE); ++ * now ?) ++ */ ++ reserve_bootmem(0x90000, PAGE_SIZE); ++#endif ++ + #ifdef CONFIG_SMP + /* + * But first pinch a few for the stack/trampoline stuff +@@ -1032,6 +1061,7 @@ + find_smp_config(); + #endif + #ifdef CONFIG_BLK_DEV_INITRD ++ printk("caution: initrd may overwrite dump\n"); /* phro */ + if (LOADER_TYPE && INITRD_START) { + if (INITRD_START + INITRD_SIZE <= (max_low_pfn << PAGE_SHIFT)) { + reserve_bootmem(INITRD_START, INITRD_SIZE); +@@ -1172,6 +1202,12 @@ + smp_alloc_memory(); /* AP processor realmode stacks in low memory*/ + #endif + paging_init(); ++#ifdef CONFIG_MCL_COREDUMP ++ /* ++ * Reserve crash pages ++ */ ++ crash_mark_dump_reserved(); ++#endif + #ifdef CONFIG_X86_LOCAL_APIC + /* + * get boot-time SMP configuration: +Index: linux/arch/i386/kernel/smp.c +=================================================================== +RCS file: /chaos/cvs/kernel-rh/linux/arch/i386/kernel/smp.c,v +retrieving revision 1.3.2.1 +retrieving revision 1.3.2.1.2.1 +diff -u -r1.3.2.1 -r1.3.2.1.2.1 +--- linux/arch/i386/kernel/smp.c 12 Mar 2003 19:49:06 -0000 1.3.2.1 ++++ linux/arch/i386/kernel/smp.c 1 Apr 2003 12:17:40 -0000 1.3.2.1.2.1 +@@ -23,6 +23,9 @@ + #include + #include + ++#ifdef CONFIG_MCL_COREDUMP ++#include ++#endif + /* + * Some notes on x86 processor bugs affecting SMP operation: + * +@@ -579,7 +582,7 @@ + return 0; + } + +-static void stop_this_cpu (void * dummy) ++void stop_this_cpu (void * dummy) + { + /* + * Remove this CPU: +Index: linux/arch/i386/kernel/traps.c +=================================================================== +RCS file: /chaos/cvs/kernel-rh/linux/arch/i386/kernel/traps.c,v +retrieving revision 1.3.2.1 +retrieving revision 1.3.2.1.2.1 +diff -u -r1.3.2.1 -r1.3.2.1.2.1 +--- linux/arch/i386/kernel/traps.c 12 Mar 2003 19:49:06 -0000 1.3.2.1 ++++ linux/arch/i386/kernel/traps.c 1 Apr 2003 12:17:40 -0000 1.3.2.1.2.1 +@@ -52,6 +52,10 @@ + #include + #include + ++#ifdef CONFIG_MCL_COREDUMP ++#include ++#endif ++ + asmlinkage int system_call(void); + asmlinkage void lcall7(void); + asmlinkage void lcall27(void); +@@ -309,7 +313,11 @@ + netdump_func(regs); + bust_spinlocks(0); + spin_unlock_irq(&die_lock); +- do_exit(SIGSEGV); ++#ifdef CONFIG_MCL_COREDUMP ++ if(panic_on_oops) ++ panic("die"); ++#endif ++ do_exit(SIGSEGV);/* NOTREACHED */ + } + + static inline void die_if_kernel(const char * str, struct pt_regs * regs, long err) +Index: linux/drivers/char/misc.c +=================================================================== +RCS file: /chaos/cvs/kernel-rh/linux/drivers/char/misc.c,v +retrieving revision 1.2 +retrieving revision 1.2.4.1 +diff -u -r1.2 -r1.2.4.1 +--- linux/drivers/char/misc.c 25 Sep 2002 17:11:05 -0000 1.2 ++++ linux/drivers/char/misc.c 1 Apr 2003 12:17:41 -0000 1.2.4.1 +@@ -78,6 +78,8 @@ + extern int i8k_init(void); + extern int lcd_init(void); + ++extern int crash_init_chrdev(void); ++ + static int misc_read_proc(char *buf, char **start, off_t offset, + int len, int *eof, void *private) + { +@@ -255,6 +257,9 @@ + int __init misc_init(void) + { + create_proc_read_entry("misc", 0, 0, misc_read_proc, NULL); ++#ifdef CONFIG_MCL_COREDUMP ++ crash_init_chrdev(); ++#endif + #ifdef CONFIG_MVME16x + rtc_MK48T08_init(); + #endif +Index: linux/drivers/char/sysrq.c +=================================================================== +RCS file: /chaos/cvs/kernel-rh/linux/drivers/char/sysrq.c,v +retrieving revision 1.2.2.1 +retrieving revision 1.2.2.1.2.2 +diff -u -r1.2.2.1 -r1.2.2.1.2.2 +--- linux/drivers/char/sysrq.c 12 Mar 2003 19:49:47 -0000 1.2.2.1 ++++ linux/drivers/char/sysrq.c 1 Apr 2003 17:55:35 -0000 1.2.2.1.2.2 +@@ -97,7 +97,18 @@ + action_msg: "Resetting", + }; + +- ++#ifdef CONFIG_MCL_COREDUMP ++/* kernel core dump sysrq */ ++static void sysrq_handle_coredump(int key, struct pt_regs *pt_regs, ++ struct kbd_struct *kbd, struct tty_struct *ttty) { ++ panic("sysrq"); ++} ++static struct sysrq_key_op sysrq_coredump_op = { ++ handler: sysrq_handle_coredump, ++ help_msg: "Crash", ++ action_msg: "Dumping core", ++}; ++#endif + + /* SYNC SYSRQ HANDLERS BLOCK */ + +@@ -334,7 +345,11 @@ + it is handled specially on the spark + and will never arive */ + /* b */ &sysrq_reboot_op, ++#ifdef CONFIG_MCL_COREDUMP ++/* c */ &sysrq_coredump_op, ++#else + /* c */ NULL, ++#endif + /* d */ NULL, + /* e */ &sysrq_term_op, + /* f */ NULL, +Index: linux/include/asm-i386/bootimg.h +=================================================================== +RCS file: linux/include/asm-i386/bootimg.h +diff -N linux/include/asm-i386/bootimg.h +--- /dev/null 1 Jan 1970 00:00:00 -0000 ++++ linux/include/asm-i386/bootimg.h 1 Apr 2003 12:17:41 -0000 1.1.6.1 +@@ -0,0 +1,141 @@ ++/* asm-i386/bootimg.h - Boot image, i386-specific code */ ++ ++/* Written 2000 by Werner Almesberger */ ++ ++/* ++ * When porting bootimg(2) to a new architcture, you need to adapt the ++ * functions and definitions in this file. ++ */ ++ ++ ++#ifndef _ASM_I386_BOOTIMG_H ++#define _ASM_I386_BOOTIMG_H ++ ++#include ++#include ++ ++#ifdef CONFIG_SMP ++#include ++#include ++#endif ++ ++ ++/* ++ * The memory page with the code currently executing has been copied from ++ * old_page to new_page. Jump there. ++ * ++ * Note: flush_icache_range has already been called on the new page. ++ */ ++ ++static inline void jump_relocated(unsigned long old_page,unsigned long new_page) ++{ ++ int tmp; ++ ++ __asm__ __volatile__( ++ "stc\n\t" ++ "call 1f\n" ++ "1:\tjnc 2f\n\t" ++ "popl %0\n\t" ++ "addl %1,%0\n\t" ++ "addl %1,%%esp\n\t" ++ "clc\n\t" ++ "jmp *%0\n" ++ "2:" ++ : "=&r" (tmp) : "r" (new_page-old_page)); ++} ++ ++ ++/* ++ * Stop paging, such that ++ * - page tables can be overwritten ++ * - all physical memory can be accessed ++ * - all physical memory is identity-mapped ++ * ++ * (Other rules are possible, but need to be encoded in bootimg(8).) ++ */ ++ ++static inline void stop_paging(void) ++{ ++ unsigned long msw; ++ ++ __asm__ __volatile__( ++ "movl %%cr0,%0\n\t" ++ "andl $0x7fffffff,%0\n\t" ++ "movl %0,%%cr0\n\t" ++ "jmp 1f\n\t" /* i486 and such */ ++ "1:" ++ ++/* Clear the PAE bit in register %cr4 if we were in PAE mode. The initial ++ * page table set up by the new kernel's bootstrap code is non-PAE regardless ++ * of whether the new kernel is a PAE kernel. By clearing the PAE bit here, ++ * we make sure the bootstrap code doesn't accidentally enable PAE mode when ++ * it turns on address translation. ++ */ ++#ifdef CONFIG_X86_PAE ++ "movl %%cr4,%0\n\t" ++ "andl $0xffffffdf,%0\n\t" ++ "movl %0,%%cr4\n\t" ++#endif ++ ++ : "=&r" (msw) : : "memory"); ++} ++ ++ ++/* ++ * Stop any remaining concurrency in the system. If become_only_thread fails ++ * but the system is still usable, become_only_thread should return an error ++ * code. If no recovery is possible, it may as well panic. ++ */ ++ ++static inline int become_only_thread(void) ++{ ++#ifdef CONFIG_SMP ++ smp_send_stop(); ++ disable_IO_APIC(); ++#endif ++ cli(); ++ return 0; ++} ++ ++ ++/* ++ * A conservative estimate of the number of bytes relocate_and_jump allocated ++ * on the stack. This is only used for sanity checking before running code, ++ * because we can't recover from failure in relocate_and_jump. ++ */ ++ ++#define RESERVE_MIN_RELOC_STACK 256 ++ ++ ++/* ++ * Change the stack pointer such that stack is at the end of the specified ++ * page. No data on the old stack will be accessed anymore, so no copying is ++ * required. ++ */ ++ ++static inline void stack_on_page(void *page) ++{ ++ __asm__ __volatile__( ++ "push %%ds\n\t" ++ "pop %%ss\n\t" ++ "movl %0,%%esp\n\t" ++ "addl $0x1000,%%esp\n\t" ++ : : "r" (page)); ++} ++ ++/* ++ * Set up things such that the kernel will be comfortable (e.g. some ++ * architectures expect the boot loader to set registers in certain ways), ++ * and then jump to the kernel's entry address. ++ */ ++ ++static inline void jump_to_kernel(void (*kernel_entry)(void)) ++{ ++ __asm__ __volatile__( ++ "mov $0x90000,%%esi\n\t" ++ : : ); ++ ++ kernel_entry(); ++} ++ ++#endif +Index: linux/include/asm-i386/crash.h +=================================================================== +RCS file: linux/include/asm-i386/crash.h +diff -N linux/include/asm-i386/crash.h +--- /dev/null 1 Jan 1970 00:00:00 -0000 ++++ linux/include/asm-i386/crash.h 1 Apr 2003 12:17:41 -0000 1.1.6.1 +@@ -0,0 +1,15 @@ ++#ifndef __ASM_CRASH_H ++#define __ASM_CRASH_H ++ ++#define UPPER_MEM_BACKUP 0 ++#define LOWER_MEM_FORWARD 0 ++#define LOW_OFFSET 100 ++ ++/* ++ * These two functions are inlined on alpha. That's why they appear ++ * in the arch dependent include file. ++ */ ++void crash_save_current_state(struct task_struct *); ++void crash_halt_or_reboot(int); ++ ++#endif +Index: linux/include/linux/bootimg.h +=================================================================== +RCS file: linux/include/linux/bootimg.h +diff -N linux/include/linux/bootimg.h +--- /dev/null 1 Jan 1970 00:00:00 -0000 ++++ linux/include/linux/bootimg.h 1 Apr 2003 12:17:41 -0000 1.1.6.1 +@@ -0,0 +1,84 @@ ++/* linux/bootimg.h - Boot image, general definitions */ ++ ++/* Written 2000 by Werner Almesberger */ ++ ++ ++#ifndef _LINUX_BOOTIMG_H ++#define _LINUX_BOOTIMG_H ++ ++ ++/* ++ * Constraints on image_map: ++ * - each image_map[n] is the virtual address of a page-sized memory region ++ * readable by the user ++ * - currently, image_map[n] is not required to be page-aligned, but this may ++ * change in the future if we want to map pages directly to lower memory ++ * pressure (NB: mapping works for ELF and plain binary images, but usually ++ * not for (b)zImages, because the prepended boot and setup sectors ++ * mis-align them) ++ * ++ * Constraints on load_map: ++ * - each load_map[] is the physical address of a page in RAM ++ */ ++ ++struct boot_image { ++ void **image_map; /* pointers to image pages in user memory */ ++ int pages; /* length in pages */ ++ unsigned long *load_map;/* list of destination pages (physical addr) */ ++ unsigned long start; /* jump to this physical address */ ++ int flags; /* for future use, must be zero for now */ ++}; ++ ++ ++#ifdef __KERNEL__ ++ ++#define __bootimg __attribute__ ((__section__ (".bootimg"))) ++ ++ ++struct bootimg_dsc { ++ unsigned long self; /* code page ALL ADDRESSES */ ++ unsigned long scratch; /* scratch page ARE PHYSICAL !*/ ++ unsigned long **page_dir; /* src & dst page tables */ ++ void (*jump_to)(void); /* start address */ ++ int pages; /* number of pages */ ++ unsigned long csum; /* Kernel Image checksum */ ++}; ++ ++/* ++ * page_dir contains pointers to pages containing pointers to pages. We call ++ * page_dir a "directory" and the page page_dir[n] points to a "table". The ++ * first PAGES_PER_TABLE/2 entries of page_dir are for source pages, and other ++ * half are for destination pages. ++ */ ++ ++/* ++ * Note that the definitions used here do not necessarily correspond to the ++ * architecture-specific PTRS_PER_PTE, __pte_offset, etc. ++ */ ++ ++#define PAGES_PER_TABLE (PAGE_SIZE/sizeof(void *)) ++#define FROM_TABLE(i) ((i)/PAGES_PER_TABLE) ++#define TO_TABLE(i) ((i)/PAGES_PER_TABLE+PAGES_PER_TABLE/2) ++#define PAGE_NR(i) ((i) % PAGES_PER_TABLE) ++ ++ ++extern char __bootimg_start,__bootimg_end; /* linker segment boundaries */ ++extern unsigned long *unity_page; /* unity-mapped page for i386 */ ++ ++/* ++ * relocate_and_jump runs in its own page with its own stack. This makes it ++ * difficult to pass parameters. The solution chosen here is to use the global ++ * variable bootimg_dsc, which is copied into an "auto" variable by ++ * relocate_and_jump before any copying or relocation takes place. ++ */ ++ ++extern struct bootimg_dsc bootimg_dsc; ++ ++typedef void (*relocate_and_jump_t)(void); ++ ++void relocate_and_jump(void); ++int boot_image(void); ++ ++#endif /* __KERNEL__ */ ++ ++#endif +Index: linux/include/linux/crash.h +=================================================================== +RCS file: linux/include/linux/crash.h +diff -N linux/include/linux/crash.h +--- /dev/null 1 Jan 1970 00:00:00 -0000 ++++ linux/include/linux/crash.h 1 Apr 2003 12:17:41 -0000 1.1.6.1 +@@ -0,0 +1,119 @@ ++#ifndef __LINUX_CRASH_H ++#define __LINUX_CRASH_H ++ ++/* defines for interfacing with user-space (ioctls, etc) */ ++struct ioctl_getdump { ++ unsigned long kva; ++ unsigned long buf; ++}; ++ ++#define CRASH_IOC_MAGIC 'C' ++ ++#define CRASH_IOCFREEDUMP _IO(CRASH_IOC_MAGIC, 0) ++#define CRASH_IOCGETDUMP _IOWR(CRASH_IOC_MAGIC, 1, struct ioctl_getdump) ++#define CRASH_IOCBOOTIMG _IOWR(CRASH_IOC_MAGIC, 2, struct boot_image) ++#define CRASH_IOCVERSION _IO(CRASH_IOC_MAGIC, 3) ++ ++/* kernel-only part of crash.h */ ++#ifdef __KERNEL__ ++#include ++ ++#define CRASH_K_MINOR (1) ++#define CRASH_K_MAJOR (0) ++ ++/* ++ * Crash prototypes. ++ */ ++void save_core(void); ++void crash_mark_dump_reserved(void); ++void crash_init(u_long bootmap_va, u_long crash_va, u_long end_alloc_va); ++u_long crash_pages_needed(void); ++void smp_crash_funnel_cpu(void); ++void crash_cleanup_smp_state(void); ++ ++/* ++ * Arch dependant crash.c funcs ++ */ ++void crash_save_current_state(struct task_struct *); ++void crash_halt_or_reboot(int); ++inline void crash_save_regs(void); ++ ++/* ++ * Crash globals ++ */ ++extern u_long crash_dump_header; ++extern volatile u_long panic_ksp[]; ++extern volatile int crash_release; ++extern int panic_on_oops; ++extern char *panicmsg; ++extern int panic_processor; ++extern int crash_perform_sync; ++extern unsigned long *panic_regs; ++ ++/* ++ * symbols not exported by linux header files ++ */ ++extern void stop_this_cpu(void *); ++ ++/* struct crash_map_hdr located at byte offset 0 */ ++/* on-disk formats */ ++ ++#define trunc_page(x) ((void *)(((unsigned long)(x)) & ~((unsigned long)(PAGE_SIZE - 1)))) ++#define round_page(x) trunc_page(((unsigned long)(x)) + ((unsigned long)(PAGE_SIZE - 1))) ++ ++#define CRASH_MAGIC 0x9a8bccdd ++#define CRASH_SOURCE_PAGES 128 ++#define CRASH_SUB_MAP_BYTES ((u_long)round_page((CRASH_SOURCE_PAGES+1)*sizeof(u_long))) ++#define CRASH_SUB_MAP_PAGES (CRASH_SUB_MAP_BYTES / PAGE_SIZE) ++#define CRASH_UNCOMPR_BUF_PAGES (CRASH_SOURCE_PAGES + CRASH_SUB_MAP_PAGES) ++#define CRASH_COMPR_BUF_PAGES (CRASH_UNCOMPR_BUF_PAGES + (CRASH_UNCOMPR_BUF_PAGES/4)) ++#define CRASH_COMPESS_PRIME_PAGES (2*CRASH_COMPR_BUF_PAGES) ++#define CRASH_ZALLOC_PAGES 16*5*2 /* 2 to handle crash in crash */ ++#define CRASH_LOW_WATER_PAGES 100 ++ ++#define CRASH_CPU_TIMEOUT 5000 /* 5 sec wait for other cpus to stop */ ++ ++#define CRASH_MARK_RESERVED(addr) (set_bit(PG_reserved,&mem_map[MAP_NR(addr)].flags)) ++#define CRASH_CLEAR_RESERVED(addr) (clear_bit(PG_reserved,&mem_map[MAP_NR(addr)].flags)) ++#define CRASH_MARK_BOOT_RESERVED(addr) reserve_bootmem(virt_to_phys((void *)addr), PAGE_SIZE); ++ ++typedef int boolean_t; ++ ++#define TRUE 1 ++#define FALSE 0 ++ ++/* mem structure */ ++struct mem_crash_map_hdr { ++ long magic[4]; /* identify crash dump */ ++ u_long map; /* location of map */ ++ u_long map_pages; ++ u_long data_pages; ++ u_long compr_units; ++ u_long boot_reserved_start; ++ u_long boot_reserved_end; ++}; ++struct mem_crash_map_entry { ++ u_long src_va; /* source start of larger non-contig ++ * block. a src_va of -1 means that ++ * the dest_page_va is the location of ++ * the next map page */ ++ u_long dest_page_va; /* dest of this sub block */ ++ u_long check_sum; /* check_sum for dest data */ ++}; ++ ++/* file structure */ ++struct crash_map_hdr { ++ long magic[4]; /* identify crash dump */ ++ int blk_size; /* block size for this device */ ++ int map_block; /* location of map */ ++ int map_blocks; /* number of blocks for map */ ++}; ++struct crash_map_entry { ++ u_long start_va; /* virtual address */ ++ char *exp_data; /* expanded data in memory */ ++ int start_blk; /* device location */ ++ int num_blks; ++}; ++ ++#endif /* __KERNEL__ */ ++#endif /* __LINUX_CRASH_H */ +Index: linux/include/linux/mm.h +=================================================================== +RCS file: /chaos/cvs/kernel-rh/linux/include/linux/mm.h,v +retrieving revision 1.2.2.1 +retrieving revision 1.2.2.1.2.2 +diff -u -r1.2.2.1 -r1.2.2.1.2.2 +--- linux/include/linux/mm.h 12 Mar 2003 19:51:27 -0000 1.2.2.1 ++++ linux/include/linux/mm.h 1 Apr 2003 17:55:35 -0000 1.2.2.1.2.2 +@@ -331,6 +331,11 @@ + #define PG_lru 18 + #define PG_active_cache 19 + #define PG_fs_1 20 /* Filesystem specific */ ++#ifdef CONFIG_MCL_COREDUMP ++#define PG_free 21 ++#define PG_shm 22 ++#define PG_anon 23 ++#endif + + /* Make it prettier to test the above... */ + #define UnlockPage(page) unlock_page(page) +@@ -452,6 +457,11 @@ + #define PageSetSlab(page) set_bit(PG_slab, &(page)->flags) + #define PageClearSlab(page) clear_bit(PG_slab, &(page)->flags) + #define PageReserved(page) test_bit(PG_reserved, &(page)->flags) ++#ifdef CONFIG_MCL_COREDUMP ++#define PageFree(page) (test_bit(PG_free, &(page)->flags)) ++#define PageAnon(page) (test_bit(PG_anon, &(page)->flags)) ++#define PageShm(page) (test_bit(PG_shm, &(page)->flags)) ++#endif + + #define PageActiveAnon(page) test_bit(PG_active_anon, &(page)->flags) + #define SetPageActiveAnon(page) set_bit(PG_active_anon, &(page)->flags) +Index: linux/include/linux/reboot.h +=================================================================== +RCS file: /chaos/cvs/kernel-rh/linux/include/linux/reboot.h,v +retrieving revision 1.1.1.1 +retrieving revision 1.1.1.1.10.2 +diff -u -r1.1.1.1 -r1.1.1.1.10.2 +--- linux/include/linux/reboot.h 7 May 2002 21:53:47 -0000 1.1.1.1 ++++ linux/include/linux/reboot.h 1 Apr 2003 17:55:35 -0000 1.1.1.1.10.2 +@@ -20,6 +20,7 @@ + * CAD_OFF Ctrl-Alt-Del sequence sends SIGINT to init task. + * POWER_OFF Stop OS and remove all power from system, if possible. + * RESTART2 Restart system using given command string. ++ * COREDUMP We're taking a core dump, secondary cpus already stopped. + */ + + #define LINUX_REBOOT_CMD_RESTART 0x01234567 +@@ -28,7 +29,9 @@ + #define LINUX_REBOOT_CMD_CAD_OFF 0x00000000 + #define LINUX_REBOOT_CMD_POWER_OFF 0x4321FEDC + #define LINUX_REBOOT_CMD_RESTART2 0xA1B2C3D4 +- ++#ifdef CONFIG_MCL_COREDUMP ++#define LINUX_REBOOT_CMD_COREDUMP 0x9A8BCCDD ++#endif + + #ifdef __KERNEL__ + +Index: linux/include/linux/sysctl.h +=================================================================== +RCS file: /chaos/cvs/kernel-rh/linux/include/linux/sysctl.h,v +retrieving revision 1.3.2.1 +retrieving revision 1.3.2.1.2.1 +diff -u -r1.3.2.1 -r1.3.2.1.2.1 +--- linux/include/linux/sysctl.h 12 Mar 2003 19:51:30 -0000 1.3.2.1 ++++ linux/include/linux/sysctl.h 1 Apr 2003 12:17:41 -0000 1.3.2.1.2.1 +@@ -126,6 +126,7 @@ + KERN_CADPID=54, /* int: PID of the process to notify on CAD */ + KERN_CORE_PATTERN=56, /* string: pattern for core-files */ + KERN_PID_MAX=55, /* int: max PID value of processes */ ++ KERN_PANIC_ON_OOPS /* int: panic on oops enabled */ + }; + + +Index: linux/init/main.c +=================================================================== +RCS file: /chaos/cvs/kernel-rh/linux/init/main.c,v +retrieving revision 1.2.2.1 +retrieving revision 1.2.2.1.2.1 +diff -u -r1.2.2.1 -r1.2.2.1.2.1 +--- linux/init/main.c 12 Mar 2003 19:51:35 -0000 1.2.2.1 ++++ linux/init/main.c 1 Apr 2003 12:17:41 -0000 1.2.2.1.2.1 +@@ -70,6 +70,10 @@ + #include + #endif + ++#ifdef CONFIG_BOOTIMG ++#include ++#endif ++ + /* + * Versions of gcc older than that listed below may actually compile + * and link okay, but the end product can have subtle run time bugs. +@@ -352,10 +356,14 @@ + { + char * command_line; + extern char saved_command_line[]; ++#if defined(CONFIG_BOOTIMG) && defined(CONFIG_X86_LOCAL_APIC) ++ unsigned long value; ++#endif + /* + * Interrupts are still disabled. Do necessary setups, then + * enable them + */ ++ printk("start_kernel\n"); + lock_kernel(); + printk(linux_banner); + setup_arch(&command_line); +@@ -373,12 +381,26 @@ + * this. But we do want output early, in case something goes wrong. + */ + console_init(); ++ ++#ifdef CONFIG_BOOTIMG ++ unity_page = alloc_bootmem_pages(PAGE_SIZE); ++ printk("unity_page addr: %p\n",unity_page); ++#endif + #ifdef CONFIG_MODULES + init_modules(); + #endif + profile_init(); + kmem_cache_init(); + sti(); ++#if defined(CONFIG_BOOTIMG) && defined(CONFIG_X86_LOCAL_APIC) ++ /* If we don't make sure the APIC is enabled, AND the LVT0 ++ * register is programmed properly, we won't get timer interrupts ++ */ ++ setup_local_APIC(); ++ ++ value = apic_read(APIC_LVT0); ++ apic_write_around(APIC_LVT0, value & ~APIC_LVT_MASKED); ++#endif + calibrate_delay(); + #ifdef CONFIG_BLK_DEV_INITRD + if (initrd_start && !initrd_below_start_ok && +Index: linux/kernel/Makefile +=================================================================== +RCS file: /chaos/cvs/kernel-rh/linux/kernel/Makefile,v +retrieving revision 1.1.1.1.4.1 +retrieving revision 1.1.1.1.4.1.2.1 +diff -u -r1.1.1.1.4.1 -r1.1.1.1.4.1.2.1 +--- linux/kernel/Makefile 12 Mar 2003 19:51:36 -0000 1.1.1.1.4.1 ++++ linux/kernel/Makefile 1 Apr 2003 12:17:41 -0000 1.1.1.1.4.1.2.1 +@@ -22,7 +22,8 @@ + obj-$(CONFIG_PM) += pm.o + obj-$(CONFIG_KALLSYMS) += kallsyms.o + obj-$(CONFIG_CPU_FREQ) += cpufreq.o +- ++obj-$(CONFIG_BOOTIMG) += bootimg.o bootimg_pic.o ++obj-$(CONFIG_MCL_COREDUMP) += crash.o + + ifneq ($(CONFIG_IA64),y) + # According to Alan Modra , the -fno-omit-frame-pointer is +Index: linux/kernel/bootimg.c +=================================================================== +RCS file: linux/kernel/bootimg.c +diff -N linux/kernel/bootimg.c +--- /dev/null 1 Jan 1970 00:00:00 -0000 ++++ linux/kernel/bootimg.c 1 Apr 2003 12:17:41 -0000 1.1.6.1 +@@ -0,0 +1,301 @@ ++/* bootimg.c - Boot another (kernel) image */ ++ ++/* Written 2000 by Werner Almesberger */ ++ ++ ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++ ++#if 0 ++#define DPRINTK_CONT(format,args...) printk(format,##args) ++#else ++#define DPRINTK_CONT(format,args...) ++#endif ++#define DPRINTK(format,args...) DPRINTK_CONT(KERN_DEBUG format,##args) ++ ++unsigned long **bootimg_page_dir; ++ ++struct bootimg_dsc bootimg_dsc; /* communication with PIC */ ++unsigned long *unity_page; /* unity-mapped page for i386 */ ++ ++static unsigned long bootimg_checksum(unsigned long **page_dir, int num_pages) ++{ ++ unsigned long checksum, *page; ++ int i, j; ++ ++ checksum = 0; ++ ++ for (i = 0; i < num_pages; i++) { ++ page = __va((unsigned long *) ++ page_dir[FROM_TABLE(i)][PAGE_NR(i)]); ++ ++ for (j = 0; j < PAGES_PER_TABLE; j++) ++ checksum ^= page[j]; ++ ++ checksum ^= page_dir[TO_TABLE(i)][PAGE_NR(i)]; ++ } ++ ++ return checksum; ++} ++ ++#ifdef CONFIG_X86_PAE ++ ++static unsigned long get_identity_mapped_page(void) ++{ ++ pgd_t *pgd; ++ pmd_t *pmd; ++ unsigned long phys_addr, page_base; ++ ++ /* Set up a 2 Mb identity-mapped page. */ ++ ++ phys_addr = virt_to_phys(unity_page); ++ pgd = pgd_offset(current->active_mm, phys_addr); ++ pmd = pmd_offset(pgd, phys_addr); ++ ++ /* We hardcode this rather than using PMD_MASK just in case the PAE ++ * mode setup ever changes so that 2 Mb pages are no longer used. ++ */ ++ page_base = phys_addr & ~((1 << 21) - 1); ++ ++ set_pmd(pmd, __pmd(page_base | _PAGE_PSE | _KERNPG_TABLE)); ++ __flush_tlb_one(phys_addr); ++ ++ return (unsigned long) unity_page; ++} ++ ++#else ++ ++static unsigned long get_identity_mapped_page(void) ++{ ++ set_pgd(pgd_offset(current->active_mm,virt_to_phys(unity_page)), ++ __pgd((_KERNPG_TABLE + _PAGE_PSE + (virt_to_phys(unity_page)&PGDIR_MASK)))); ++ __flush_tlb_one(virt_to_phys(unity_page)); ++ return (unsigned long)unity_page; ++} ++ ++#endif ++ ++#if 0 /* Perhaps we'll need this in the future? */ ++static void unmap_identity_mapped_page(void) ++{ ++ set_pgd(pgd_offset(current->active_mm,virt_to_phys(unity_page)),__pgd(0)); ++ __flush_tlb(); ++} ++#endif ++ ++static int fill_page_dir(unsigned long **page_dir,struct boot_image *image) ++{ ++ int i, count=0; ++ ++ memset(page_dir,0,PAGE_SIZE); ++ for (i = 0; i < image->pages; i += PAGES_PER_TABLE) { ++ unsigned long **table; ++ int bytes_left; ++ ++ table = page_dir+FROM_TABLE(i); ++ *table = (unsigned long *) get_free_page(GFP_KERNEL); ++ if (!*table) return -ENOMEM; ++ ++ memset(*table,0,PAGE_SIZE); ++ DPRINTK("page %d: from table %p @ %p\n",i,*table,table); ++ table = page_dir+TO_TABLE(i); ++ *table = (unsigned long *) get_free_page(GFP_KERNEL); ++ if (!*table) return -ENOMEM; ++ ++ bytes_left = (image->pages-i)*sizeof(unsigned long); ++ if (copy_from_user(*table,image->load_map+i, ++ bytes_left > PAGE_SIZE ? PAGE_SIZE : bytes_left)) ++ return -EFAULT; ++ DPRINTK("page %d: to table %p @ %p\n",i,*table,table); ++ count+=2; /* 2 pages per loop */ ++ } ++ ++ for (i = 0; i < image->pages; i++) { ++ unsigned long page = get_free_page(GFP_KERNEL); ++ void *src; ++ ++ if (!page) return -ENOMEM; ++ count++; ++ ++ page_dir[FROM_TABLE(i)][PAGE_NR(i)] = ++ virt_to_phys((void *) page); ++ if (get_user(src,image->image_map+i) || ++ copy_from_user((void *) page,src,PAGE_SIZE)) ++ return -EFAULT; ++ ++ DPRINTK("page %d: %p->%p->%p @ %p\n",i,src,(void *) page, ++ (void *) page_dir[FROM_TABLE(i)][PAGE_NR(i)], ++ &page_dir[FROM_TABLE(i)][PAGE_NR(i)]); ++ } ++ ++ DPRINTK("fill_page_dir: %d pages allocated\n", count); ++ ++ return 0; ++} ++ ++ ++static void free_page_dir(unsigned long **page_dir) ++{ ++ int i,j,count=0; ++ ++ for (i = 0; i < PAGES_PER_TABLE/2; i++) ++ if (page_dir[i]) ++ for (j = 0; j < PAGES_PER_TABLE; j++) ++ if (page_dir[i][j]) { ++ free_page((unsigned long) ++ phys_to_virt(page_dir[i][j])); ++ count++; ++ } ++ for (i = 0; i < PAGES_PER_TABLE; i++) ++ if (page_dir[i]) { ++ free_page((unsigned long) *page_dir[i]); ++ count++; ++ } ++ DPRINTK("free_page_dir: %d pages freed\n", count); ++} ++ ++ ++static void convert_table_refs_to_phys(unsigned long **page_dir) ++{ ++ int i; ++ ++ DPRINTK("PAGES_PER_TABLE: %d\n",PAGES_PER_TABLE); ++ for (i = 0; i < PAGES_PER_TABLE; i++) ++ if (page_dir[i]) { ++ DPRINTK("table %i: mapped %p -> ",i,page_dir[i]); ++ page_dir[i] = (unsigned long *) ++ virt_to_phys(page_dir[i]); ++ DPRINTK_CONT("%p\n",page_dir[i]); ++ } ++} ++ ++ ++ ++static int fill_bootimg_dsc(struct boot_image *image) ++{ ++ unsigned long scratch; ++ int error = -ENOMEM; ++ ++ if(bootimg_page_dir) { ++ /* free previously allocated memory */ ++ free_page_dir(bootimg_page_dir); ++ free_page((unsigned long) bootimg_page_dir); ++ DPRINTK("free_page (bootimg_page_dir)\n"); ++ } ++ ++ bootimg_page_dir = (unsigned long **) get_free_page(GFP_KERNEL); ++ if (!bootimg_page_dir) goto out0; ++ DPRINTK("get_free_page (bootimg_page_dir)\n"); ++ ++ error = fill_page_dir(bootimg_page_dir,image); ++ if (error) goto out1; ++ ++ if(!bootimg_dsc.scratch) { ++ scratch = get_free_page(GFP_KERNEL); ++ DPRINTK("get_free_page (scratch)\n"); ++ } else ++ scratch = 1; /* already allocated */ ++ ++ if (!scratch) goto out1; ++ /* ++ * Not all architectures need the code to be identity-mapped, but it ++ * can't hurt ... ++ */ ++ DPRINTK("bootimg_page_dir: mapped %p -> ",bootimg_page_dir); ++ bootimg_dsc.page_dir = (unsigned long **) virt_to_phys(bootimg_page_dir); ++ DPRINTK_CONT("%p\n",bootimg_dsc.page_dir); ++ if(!bootimg_dsc.scratch) ++ bootimg_dsc.scratch = virt_to_phys((void *) scratch); ++ bootimg_dsc.jump_to = (void (*)(void)) image->start; ++ bootimg_dsc.pages = image->pages; ++ bootimg_dsc.csum = bootimg_checksum(bootimg_page_dir, image->pages); ++ ++ return 0; ++ ++out1: ++ free_page_dir(bootimg_page_dir); ++ free_page((unsigned long) bootimg_page_dir); ++ DPRINTK("free_page (bootimg_page_dir)\n"); ++ bootimg_page_dir = 0; ++out0: ++ return error; ++} ++ ++extern char *panicmsg; ++int boot_image() ++{ ++ relocate_and_jump_t code; ++ unsigned long code_page; ++ int error = -ENOMEM; ++ ++ if (bootimg_checksum(__va(bootimg_dsc.page_dir),bootimg_dsc.pages) ++ != bootimg_dsc.csum) ++ printk("Checksum of kernel image failed. Rebooting via BIOS\n"); ++ ++ code_page = get_identity_mapped_page(); ++ if (!code_page) goto out3; ++ code = (relocate_and_jump_t) virt_to_phys((void *) code_page); ++ memcpy(code,&__bootimg_start,&__bootimg_end-&__bootimg_start); ++ flush_icache_range(&__bootimg_start, &__bootimg_end-&__bootimg_start); ++ ++ bootimg_dsc.self = (unsigned long) code; ++ printk(KERN_INFO "Running boot code at 0x%p\n",code); ++ ++ /* ++ * The point of no return. Not even printk may work after a successful ++ * return from become_only_thread. ++ */ ++ ++ if (!panicmsg) { ++ error = become_only_thread(); ++ if (error) goto out3; ++ } else { ++#ifdef CONFIG_SMP ++ disable_IO_APIC(); ++#endif ++ __cli(); ++ } ++ ++ convert_table_refs_to_phys((unsigned long **)__va(bootimg_dsc.page_dir)); ++ stack_on_page(code); ++ ++ code(); ++ ++ panic("PIC code exec failed"); ++out3: ++ printk("boot_image() failed!\n"); ++ for(;;); ++} ++ ++/* changed from asmlinkage because we're called via an IOCTL on /dev/crash now */ ++int sys_bootimg(struct boot_image *user_dsc) ++{ ++ struct boot_image dsc; ++ ++ if (!capable(CAP_SYS_ADMIN) || !capable(CAP_SYS_MODULE)) return -EPERM; ++ if (&__bootimg_end-&__bootimg_start > PAGE_SIZE-RESERVE_MIN_RELOC_STACK) ++ { ++ printk(KERN_ERR "boot_image: PIC too large (%d bytes)\n", ++ &__bootimg_end-&__bootimg_start); ++ return -EIO; ++ } ++ if ((void *) relocate_and_jump != (void *) &__bootimg_start) { ++ printk(KERN_ERR "boot_image: relocate_and_jump is mis-placed" ++ "(0x%p != 0x%p)\n",relocate_and_jump,&__bootimg_start); ++ return -EIO; ++ } ++ ++ if (copy_from_user(&dsc,user_dsc,sizeof(dsc))) return -EFAULT; ++ if (dsc.pages >= PAGES_PER_TABLE*PAGES_PER_TABLE/2) return -EFBIG; ++ if (dsc.flags) return -EINVAL; /* for future use */ ++ return fill_bootimg_dsc(&dsc); ++} +Index: linux/kernel/bootimg_pic.c +=================================================================== +RCS file: linux/kernel/bootimg_pic.c +diff -N linux/kernel/bootimg_pic.c +--- /dev/null 1 Jan 1970 00:00:00 -0000 ++++ linux/kernel/bootimg_pic.c 1 Apr 2003 12:17:41 -0000 1.1.6.1 +@@ -0,0 +1,91 @@ ++/* bootimg_pic.c - Boot image, position-independent code */ ++ ++/* Written 2000 by Werner Almesberger */ ++ ++/* ++ * Strongly inspired by FiPaBoL designed mainly by Otfried Cheong and Roger ++ * Gammans, and written by the latter. ++ */ ++ ++/* ++ * This code is position-independent and must fit in a single page ! ++ * Furthermore, everything (text+data+stack) has to go into the ++ * .bootimg segment. ++ */ ++ ++ ++#include ++#include ++#include ++#include ++#include ++#include ++ ++#include ++ ++#define copy_and_swap(from,to) \ ++ ( { my_copy_page(from,to); \ ++ tmp = from; \ ++ from = to; \ ++ to = tmp; } ) ++ ++ ++static inline void my_copy_page(unsigned long from,unsigned long to) ++{ ++ unsigned long end = from+PAGE_SIZE; ++ ++ do *((unsigned long *) to)++ = *((unsigned long *) from)++; ++ while (from != end); ++} ++ ++ ++void __bootimg relocate_and_jump(void) ++{ ++ struct bootimg_dsc dsc = bootimg_dsc; ++ int i; ++ ++ stop_paging(); ++ for (i = 0; i < dsc.pages; i++) { ++ unsigned long from,to,tmp; ++ ++ from = dsc.page_dir[FROM_TABLE(i)][PAGE_NR(i)]; ++ to = dsc.page_dir[TO_TABLE(i)][PAGE_NR(i)]; ++ if (from == to) continue; ++ if (to == dsc.self) { ++ copy_and_swap(dsc.self,dsc.scratch); ++ /* WARNING: flush_icache_range MUST BE INLINED !!! */ ++ flush_icache_range(dsc.self,dsc.self+PAGE_SIZE-1); ++ jump_relocated(dsc.scratch,dsc.self); ++ } ++ else if (to == (unsigned long) dsc.page_dir) ++ copy_and_swap((unsigned long) dsc.page_dir,dsc.scratch); ++ else { ++ /* ++ * O((n^2-n)/2), sigh ... ++ */ ++ unsigned long **table; ++ int j; ++ ++ for (j = i+1; j < dsc.pages; j++) { ++ table = dsc.page_dir+FROM_TABLE(j); ++ if (((unsigned long) *table) == to) { ++ copy_and_swap(*table,dsc.scratch); ++ break; ++ } ++ if ((*table)[PAGE_NR(j)] == to) { ++ copy_and_swap((*table)[PAGE_NR(j)], ++ dsc.scratch); ++ break; ++ } ++ table = dsc.page_dir+TO_TABLE(j); ++ if (((unsigned long) *table) == to) { ++ copy_and_swap(*table,dsc.scratch); ++ break; ++ } ++ } ++ } ++ my_copy_page(from,to); ++ dsc.scratch = from; ++ } ++ jump_to_kernel(dsc.jump_to); ++} +Index: linux/kernel/crash.c +=================================================================== +RCS file: linux/kernel/crash.c +diff -N linux/kernel/crash.c +--- /dev/null 1 Jan 1970 00:00:00 -0000 ++++ linux/kernel/crash.c 1 Apr 2003 12:17:41 -0000 1.1.6.1 +@@ -0,0 +1,886 @@ ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++ ++#ifdef CONFIG_BOOTIMG ++#include ++#endif ++ ++static void crash_print_data_around(u_long p); ++static void crash_free_page(u_long addr); ++static int crash_chksum_page(u_long pg_addr, u_long * sum_addr); ++static void *czalloc(void *arg, unsigned int items, unsigned int size); ++static void czfree(void *arg, void *ptr); ++static u_long crash_alloc_dest_page(void); ++static void crash_free_dest_page(u_long dest); ++static void init_dest_page_alloc(void); ++static int crash_audit_maps(void); ++static u_long crash_get_source_page(void); ++static u_long crash_update_map(u_long map, u_long src_base, u_long dest, u_long * pages); ++static int crash_reset_stream(z_stream * stream); ++static boolean_t crash_is_kseg(u_long addr); ++static u_long *crash_link(u_long p); ++static int crash_chksum(u_long limit, u_long * sum_addr); ++static int crash_audit_map_page(u_long map); ++static void crash_wait_cpus(void); ++static int crash_is_dir_page(struct page *page); ++ ++/* for the /dev/crash interface */ ++int crash_init_chrdev(void); ++static int crashdev_ioctl(struct inode *, struct file *, unsigned int, unsigned long); ++ ++#define CRASH_DEBUG 1 ++ ++#ifdef CONFIG_BOOTIMG ++extern int sys_bootimg(struct boot_image *); ++#endif ++ ++static u_long crash_compr_buf; ++static u_long crash_uncompr_buf; ++static u_long crash_dump_header = 0; ++static u_long crash_dest_free_list = 0; ++static u_long crash_debug = 0; ++ ++static u_long crash_cur_pfn; ++ ++static u_long src_pages_skipped = 0; ++static u_long src_pages_saved = 0; ++static u_long dest_pages_free = 0; ++ ++/* this information is saved from within panic() */ ++char *panicmsg = (char *)0; ++int panic_processor = 0; ++int crash_perform_sync = 0; ++ ++u_int console_crash = 0; /* should be moved to alpha branch */ ++ ++// typedef struct task_struct *task_t; ++ ++/* ++ * Threads active at time of panic: ++ */ ++volatile task_t *panic_threads[NR_CPUS]; ++volatile unsigned long panic_ksp[NR_CPUS]; ++unsigned long *panic_regs = NULL; ++ ++int panic_on_oops; /* for /proc/sys/kernel/panic_on_oops */ ++ ++extern unsigned long max_low_pfn; ++ ++u_long crash_zalloc_start; // , crash_zalloc_end, crash_zalloc_cur; ++ ++/* ++ * Crash Kernel API functions below ++ * crash_pages_needed, computes pages needed for header and compression temp ++ * crash_init, partitions out the allocated pages, sets defaults and ++ * initializes the character device. ++ * crash_mark_dump_reserved, marks pages reserved from a previous dump. ++ * save_core, called at panic time to save a dump to memory. ++ */ ++u_long crash_pages_needed(void) ++{ ++ /* one for the header */ ++ return (1 + CRASH_ZALLOC_PAGES + CRASH_UNCOMPR_BUF_PAGES + CRASH_COMPR_BUF_PAGES); ++} ++ ++void crash_init(u_long bootmap_va, u_long crash_va, u_long end_alloc_va) ++{ ++ struct mem_crash_map_hdr *header; ++ int i; ++ ++ /* the default behavior is not NOT panic on a kernel OOPS */ ++ panic_on_oops = 0; ++ ++ printk("crash_init (crash_va: %08lx)\n", crash_va); ++ for (i = 0; i < NR_CPUS; i++) ++ panic_threads[i] = 0; ++ crash_dump_header = crash_va; ++ crash_va += PAGE_SIZE; ++ crash_zalloc_start = crash_va; ++ crash_va += CRASH_ZALLOC_PAGES * PAGE_SIZE; ++ crash_uncompr_buf = crash_va; ++ crash_va += CRASH_UNCOMPR_BUF_PAGES * PAGE_SIZE; ++ crash_compr_buf = crash_va; ++ crash_va += CRASH_COMPR_BUF_PAGES * PAGE_SIZE; ++#if 0 ++ if (crash_va != end_alloc_va) ++ panic("crash_init inconsistency-1\n"); ++#endif ++ ++ header = (struct mem_crash_map_hdr *)crash_dump_header; ++#ifdef CRASH_DEBUG ++ printk("crash_dump_header %p {\n", header); ++ printk(" magic[0] = %lx\n", header->magic[0]); ++ printk(" map = %lx\n", header->map); ++ printk(" map_pages = %lx\n", header->map_pages); ++ printk(" data_pages = %lx\n", header->data_pages); ++ printk(" compr_units = %lx\n", header->compr_units); ++ printk(" boot_reserved_start = %lx\n", header->boot_reserved_start); ++ printk(" boot_reserved_end = %lx\n", header->boot_reserved_end); ++#endif ++ ++ if (header->magic[0] == CRASH_MAGIC) { ++ printk("crash found\n"); ++ if ((header->boot_reserved_start != bootmap_va) || ++ (header->boot_reserved_end != end_alloc_va)) { ++ /* crash audit will catch the corruption */ ++ printk("crash_init inconsistency, dump may be corrupted\n"); ++ } ++ } else { ++printk("memset..."); ++ memset(header, 0, sizeof(*header)); ++printk("done\n"); ++ } ++ ++ header->boot_reserved_start = bootmap_va; ++ header->boot_reserved_end = end_alloc_va; ++ ++} ++ ++void crash_mark_dump_reserved(void) ++{ ++ struct mem_crash_map_hdr *header; ++ struct mem_crash_map_entry *m; ++ ++ header = (struct mem_crash_map_hdr *)crash_dump_header; ++ if (header->magic[0] != CRASH_MAGIC) ++ return; ++ m = (struct mem_crash_map_entry *)header->map; ++#ifdef CRASH_DEBUG ++ printk("\n\n\ncrash_mark_dump_reserved\n\n"); ++ printk("crash_dump_header %p {\n", header); ++ printk(" magic[0] = %lx\n", header->magic[0]); ++ printk(" map = %lx\n", header->map); ++ printk(" map_pages = %lx\n", header->map_pages); ++ printk(" data_pages = %lx\n", header->data_pages); ++ printk(" compr_units = %lx\n", header->compr_units); ++ printk(" boot_reserved_start = %lx\n", header->boot_reserved_start); ++ printk(" boot_reserved_end = %lx\n", header->boot_reserved_end); ++ printk("mem_crash_map_entry %p {\n", m); ++ printk(" src_va = %lx\n", m->src_va); ++ printk(" dest_page_va = %lx\n", m->dest_page_va); ++ printk(" check_sum = %lx\n", m->check_sum); ++#endif ++ ++ if (crash_audit_maps()) { ++ header->magic[0] = 0; ++ return; ++ } ++ ++ m = (struct mem_crash_map_entry *)header->map; ++ again: ++ CRASH_MARK_BOOT_RESERVED(m); ++ for (; m->src_va; m++) { ++ if (m->src_va == -1) { ++ m = (struct mem_crash_map_entry *)m->dest_page_va; ++ goto again; ++ } ++ CRASH_MARK_BOOT_RESERVED(m->dest_page_va); ++ } ++ return; ++} ++ ++void save_core(void) ++{ ++ int i, j, k; ++ z_stream stream; ++ int err; ++ struct task_struct *tp; ++ struct mem_crash_map_hdr *header; ++ u_long *sub_map; ++ u_long map; ++ u_long src, dest, unc, cp, src_base, comp_pages; ++ ++ k = 0; ++ dest = 0; ++ __cli(); ++ tp = current; ++ mb(); ++ if (smp_processor_id() != 0) { /* boot_cpu_id is always 0, i think */ ++ panic_threads[smp_processor_id()] = tp; ++ crash_halt_or_reboot(0); ++ } else { ++ if (console_crash) ++ panic_threads[smp_processor_id()] = &init_task_union.task; ++ else ++ panic_threads[smp_processor_id()] = tp; ++ ++ crash_wait_cpus(); ++ } ++ ++ printk("save_core: started on CPU%d\n", smp_processor_id()); ++ if (!crash_dump_header) { ++ printk("save_core: not initialized\n"); ++ return; ++ } ++ ++ header = (struct mem_crash_map_hdr *)crash_dump_header; ++ header->magic[0] = 0; ++ header->map_pages = 0; ++ header->data_pages = 0; ++ header->compr_units = 0; ++ header->map = 0; ++ ++ stream.workspace=(void*)crash_zalloc_start; ++ // stream.zalloc = czalloc; ++ // stream.zfree = czfree; ++ // stream.opaque = (voidpf) 0; ++ stream.next_out = (Bytef *) crash_compr_buf; ++ stream.avail_out = (uInt) (CRASH_COMPR_BUF_PAGES * PAGE_SIZE); ++ stream.next_in = (Bytef *) crash_uncompr_buf; ++ stream.avail_in = (uInt) (CRASH_UNCOMPR_BUF_PAGES * PAGE_SIZE); ++ err = zlib_deflateInit(&stream, Z_BEST_SPEED); ++ if (err != Z_OK) { ++ printk("save_core: bad return %d from deflateInit\n", err); ++ return; ++ } ++ ++ init_dest_page_alloc(); ++ header->map = map = crash_update_map(0, 0, 0, &header->map_pages); ++ if (!map) { ++ printk("save_core: no dest pages\n"); ++ return; ++ } ++ crash_cur_pfn = 0; ++ src_base = 0; ++ src = 0; ++ for (;;) { ++ sub_map = (u_long *) crash_uncompr_buf; ++ unc = crash_uncompr_buf + CRASH_SUB_MAP_PAGES * PAGE_SIZE; ++ for (i = 0; i < CRASH_SOURCE_PAGES; i++) { ++ src = crash_get_source_page(); ++ if (!src) ++ break; ++ if (!i) ++ src_base = src; ++ if (!crash_is_kseg(unc) || !crash_is_kseg(src)) { ++ printk("unc = 0x%lx, src = 0x%lx, i = %d\n", unc, src, i); ++ i = src = 0; ++ break; ++ } ++ memcpy((void *)unc, (void *)src, PAGE_SIZE); ++ unc += PAGE_SIZE; ++ *sub_map++ = src; ++ } ++ *sub_map = 0; ++ if (!i && !src) ++ break; ++ err = zlib_deflate(&stream, Z_FINISH); ++ if (!(err == Z_STREAM_END)) { ++ zlib_deflateEnd(&stream); ++ printk("save_core: bad return %d from deflate, src_base = 0x%lx\n", err, ++ src_base); ++ return; ++ } ++ comp_pages = (u_long) round_page(stream.total_out) / PAGE_SIZE; ++ if (crash_debug) ++ printk("src_base = 0x%lx compressed data in 0x%lx pages\n", src_base, ++ comp_pages); ++ ++ cp = crash_compr_buf; ++ j = 0; ++ if (crash_debug) ++ printk("\nsrc = %lx\n", src_base); ++ else { ++ printk("."); ++ if (!(k++ % 64)) ++ printk("\n"); ++ } ++ for (i = 0; i < comp_pages; i++) { ++ dest = crash_alloc_dest_page(); ++ if (crash_debug) { ++ printk("%lx ", dest); ++ if (!(j++ % 8)) ++ printk("\n"); ++ } ++ header->data_pages++; ++ if (!dest) { ++ printk("save_core: no dest pages\n"); ++ return; ++ } ++ if (!crash_is_kseg(dest) || !crash_is_kseg(cp)) { ++ printk("dest = 0x%lx, cp = 0x%lx, i = %d, comp_pages = 0x%lx\n", ++ dest, cp, i, comp_pages); ++ src = 0; ++ break; ++ } ++ memcpy((void *)dest, (void *)cp, PAGE_SIZE); ++ cp += PAGE_SIZE; ++ map = crash_update_map(map, src_base, dest, &header->map_pages); /* links a new map page, if necessary */ ++ if (!map) { ++ printk("save_core: no map\n"); ++ return; ++ } ++ } ++ header->compr_units++; ++ if (!src) ++ break; ++ if (crash_reset_stream(&stream)) ++ return; ++ } ++ ++ map = crash_update_map(map, 0, 0, &header->map_pages); ++ header->magic[0] = CRASH_MAGIC; ++ ++ if (crash_audit_maps()) { ++ header->magic[0] = 0; ++ return; ++ } ++ ++ printk("\nsave_core: src pages skipped = 0x%lx src pages saved = 0x%lx\n", ++ src_pages_skipped, src_pages_saved); ++ printk("save_core: data_pages = 0x%lx map_pages = 0x%lx\n", header->data_pages, ++ header->map_pages); ++ printk("save_core: completed, crash_dump_header = 0x%lx\n", crash_dump_header); ++} ++ ++/* helper functions private to this file */ ++static int crash_reset_stream(z_stream * stream) ++{ ++ int err; ++ ++ stream->workspace=(void*)crash_zalloc_start; ++ // stream->zalloc = czalloc; ++ // stream->zfree = czfree; ++ // stream->opaque = (voidpf) 0; ++ stream->next_out = (Bytef *) crash_compr_buf; ++ stream->avail_out = (uInt) (CRASH_COMPR_BUF_PAGES * PAGE_SIZE); ++ stream->next_in = (Bytef *) crash_uncompr_buf; ++ stream->avail_in = (uInt) (CRASH_UNCOMPR_BUF_PAGES * PAGE_SIZE); ++ err = zlib_deflateReset(stream); ++ if (err != Z_OK) { ++ printk("crash_reset_stream: bad return %d from deflateReset\n", err); ++ return 1; ++ } ++ return 0; ++} ++ ++static u_long crash_alloc_dest_page(void) ++{ ++ u_long addr; ++ ++ addr = crash_dest_free_list; ++ if (addr) { ++ crash_dest_free_list = *(u_long *) addr; ++ dest_pages_free--; ++ } else ++ printk("crash_alloc_dest_page: free list empty\n"); ++ return addr; ++} ++ ++static void crash_free_dest_page(u_long dest) ++{ ++ if (!dest) { ++ printk("crash_free_dest_page: freeing addr 0\n"); ++ return; ++ } ++ dest_pages_free++; ++ dest = (u_long) trunc_page(dest); ++ *(u_long *) dest = crash_dest_free_list; ++ crash_dest_free_list = dest; ++} ++ ++/* ++ * Stolen from setup.c ++ */ ++#define PFN_PHYS(x) ((x) << PAGE_SHIFT) ++ ++static void init_dest_page_alloc(void) ++{ ++ u_long va; ++ long i; ++ struct page *page; ++ struct mem_crash_map_hdr *header; ++ ++ header = (struct mem_crash_map_hdr *)crash_dump_header; ++ for (i = ((1 << 24) >> PAGE_SHIFT) + LOWER_MEM_FORWARD; ++ i < (max_low_pfn - UPPER_MEM_BACKUP); i++) { ++ va = (u_long) phys_to_virt(PFN_PHYS(i)); ++ if ((va >= header->boot_reserved_start) && (va < header->boot_reserved_end)) ++ continue; ++ page = mem_map + i; ++ if (PageLocked(page) || PageReserved(page)) ++ continue; ++ if (PageFree(page) || PageAnon(page) || PageShm(page) || page->buffers) ++ crash_free_dest_page(va); ++ } ++ if (crash_debug) ++ printk("init_dest_page_alloc: dest_pages_free = 0x%lx\n", dest_pages_free); ++} ++ ++static int crash_is_dir_page(struct page *page) { ++ struct inode *tmp_inode; ++ ++ if(page->mapping && page->mapping->host) { ++ tmp_inode = (struct inode *)page->mapping->host; ++ if((tmp_inode->i_sb->s_magic == EXT2_SUPER_MAGIC) && ++ (S_ISDIR(tmp_inode->i_mode))) ++ return 1; ++ } ++ ++ return 0; ++} ++ ++static u_long crash_get_source_page(void) ++{ ++ struct page *page; ++ u_long va; ++ ++ while (crash_cur_pfn < max_low_pfn) { ++ page = mem_map + crash_cur_pfn; ++ if (!(PageFree(page) || PageAnon(page) || PageShm(page) || page->buffers)) ++ break; ++ src_pages_skipped++; ++ crash_cur_pfn++; ++ } ++ if (crash_cur_pfn == max_low_pfn) ++ return 0; ++ ++ va = (u_long) phys_to_virt(PFN_PHYS(crash_cur_pfn)); ++ src_pages_saved++; ++ crash_cur_pfn++; ++ return va; ++} ++ ++static u_long crash_update_map(u_long map, u_long src_base, u_long dest, u_long * pages) ++{ ++ struct mem_crash_map_entry *m; ++ ++ ++ if (!map) { ++ (*pages)++; ++ return crash_alloc_dest_page(); ++ } ++ m = (struct mem_crash_map_entry *)map; ++ m->src_va = src_base; ++ m->dest_page_va = dest; ++ if (dest) ++ if (crash_chksum_page(dest, &m->check_sum)) ++ return 0; ++ ++ map += sizeof(struct mem_crash_map_entry); ++ ++ m = (struct mem_crash_map_entry *)map; ++ if (!src_base) { /* end of list */ ++ if (crash_chksum((u_long) m, &m->src_va)) ++ return 0; ++ } else if ((map + 3 * sizeof(struct mem_crash_map_entry)) > (u_long) round_page(map)) { ++ m->src_va = -1; ++ map = m->dest_page_va = crash_alloc_dest_page(); ++ if (crash_debug) ++ printk("\nm = 0x%lx m->src_va = 0x%lx m->dest_page_va = 0x%lx\n", ++ (u_long) trunc_page(m), m->src_va, m->dest_page_va); ++ m++; ++ if (crash_chksum((u_long) m, &m->src_va)) ++ return 0; ++ if (crash_debug) ++ printk("m = 0x%lx chksum = m->src_va = 0x%lx\n", (u_long) trunc_page(m), ++ m->src_va); ++ if (crash_audit_map_page((u_long) m)) ++ return 0; ++ (*pages)++; ++ } ++ return map; ++} ++ ++static int crash_chksum(u_long limit, u_long * sum_addr) ++{ ++ u_long sum; ++ u_long *addr; ++ ++ if (!crash_is_kseg(limit)) { ++ printk("bad addr = 0x%lx to crash_chksum\n", limit); ++ return 1; ++ } ++ sum = 0; ++ addr = (u_long *) trunc_page(limit); ++ for (; (u_long) addr < limit; addr++) ++ sum += *addr; ++ *sum_addr = sum; ++ return 0; ++} ++ ++static int crash_chksum_page(u_long pg_addr, u_long * sum_addr) ++{ ++ u_long sum, limit; ++ u_long *addr; ++ ++ if (!crash_is_kseg(pg_addr)) { ++ printk("bad addr = 0x%lx to crash_chksum_page\n", pg_addr); ++ return 1; ++ } ++ ++ sum = 0; ++ addr = (u_long *) trunc_page(pg_addr); ++ limit = (u_long) addr + PAGE_SIZE; ++ for (; (u_long) addr < limit; addr++) ++ sum += *addr; ++ *sum_addr = sum; ++ return 0; ++} ++ ++static int crash_audit_maps(void) ++{ ++ u_long m, count; ++ u_long *link_addr; ++ struct mem_crash_map_hdr *header; ++ ++ header = (struct mem_crash_map_hdr *)crash_dump_header; ++ if (header->magic[0] != CRASH_MAGIC) ++ return 1; ++ ++ link_addr = &header->map; ++ m = header->map; ++ ++ count = 0; ++ for (;;) { ++ if (!crash_is_kseg(m)) { ++ printk("crash_audit_maps: bad link 0x%lx at 0x%lx\n", m, ++ (u_long) link_addr); ++ return 1; ++ } ++ if (crash_audit_map_page(m)) { ++ printk("audit failed while on map page %ld\n", count); ++ return 1; ++ } ++ if (!crash_link(m)) ++ break; ++ link_addr = crash_link(m); ++ m = *link_addr; ++ ++ count++; ++ } ++ return 0; ++} ++ ++static int crash_audit_map_page(u_long map) ++{ ++ struct mem_crash_map_entry *m; ++ u_long sum; ++ ++ if (!map || !crash_is_kseg(map)) { ++ printk("crash_audit_map_page: bad map = 0x%lx\n", map); ++ return 1; ++ } ++ map = (u_long) trunc_page((u_long) map); ++ m = (struct mem_crash_map_entry *)map; ++ for (;;) { ++ if ((m->src_va == -1) || (m->src_va == 0)) { ++ m++; ++ if (crash_chksum((u_long) m, &sum)) ++ return 1; ++ if (m->src_va != sum) { ++ printk("crash_audit_map_page: checksum failure1\n"); ++ printk("m = 0x%lx, sum = 0x%lx, m->src_va = 0x%lx\n", ++ (u_long) m, (u_long) sum, (u_long) m->src_va); ++ crash_print_data_around((u_long) & m->src_va); ++ return 1; ++ } else { ++ return 0; ++ } ++ } else { ++ if (crash_chksum_page((u_long) m->dest_page_va, &sum) ++ || (m->check_sum != sum)) { ++ printk("crash_audit_map_page: checksum failure2\n"); ++ printk ++ ("dest_page_va = 0x%lx, &dest_page_va = 0x%lx, sum = 0x%lx, m->check_sum = 0x%lx\n", ++ (u_long) m->dest_page_va, (u_long) (&m->check_sum), ++ (u_long) sum, (u_long) m->check_sum); ++ crash_print_data_around((u_long) & m->check_sum); ++ return 1; ++ } ++ } ++ m++; ++ } ++} ++ ++static void crash_print_data_around(u_long p) ++{ ++ u_long *a; ++ int i; ++ ++ if (!crash_is_kseg(p)) { ++ printk("crash_print_data_around: p = 0x%lx not kseg\n", p); ++ return; ++ } ++ a = (u_long *) p; ++ a -= 20; ++ for (i = 0; i < 40; i++) ++ printk("%lx\n", *a++); ++} ++ ++#ifdef CRASH_DEBUG ++static void crash_print_map_page(u_long map) ++{ ++ struct mem_crash_map_entry *m; ++ int j = 0; ++ u_long sum; ++ ++ map = (u_long) trunc_page((u_long) map); ++ m = (struct mem_crash_map_entry *)map; ++ for (;;) { ++ printk("%lx %lx %lx ", m->src_va, m->dest_page_va, m->check_sum); ++ if (!(j++ % 4)) ++ printk("\n"); ++ if ((m->src_va == -1) || (m->src_va == 0)) { ++ m++; ++ printk("%lx %lx ", m->src_va, m->dest_page_va); ++ if (crash_chksum((u_long) m, &sum)); ++ else ++ printk("\nchksum = 0x%lx\n", sum); ++ return; ++ } ++ m++; ++ } ++} ++#endif /* CRASH_DEBUG */ ++ ++static void crash_wait_cpus(void) ++{ ++ int i; ++ int msecs = 0; ++ ++ for (i = 0; i < smp_num_cpus; i++) { ++ if (i != smp_processor_id()) { ++ while (!panic_threads[i]) { ++ msecs++; ++ mdelay(1); ++ if (msecs > CRASH_CPU_TIMEOUT) { ++ /* if other cpus are still running ++ * we have to halt, otherwise we could ++ * risk using buffer cache pages which ++ * could subsequently get flushed to disk. ++ */ ++ printk("Unable to halt other CPUs, halting system.\n"); ++ crash_halt_or_reboot(0); ++ } ++ } ++ } ++ } ++ ++ crash_cleanup_smp_state(); ++} ++ ++ ++#if 0 ++static void *czalloc(void *arg, unsigned int items, unsigned int size) ++{ ++ u_long nbytes; ++ u_long addr; ++ ++ nbytes = (u_long) (items * size); ++ nbytes = (u_long) round_page(nbytes); ++ if ((crash_zalloc_cur + nbytes) > crash_zalloc_end) ++ return 0; ++ addr = crash_zalloc_cur; ++ crash_zalloc_cur += nbytes; ++ return ((void *)addr); ++} ++ ++static void czfree(void *arg, void *ptr) ++{ ++ printk("zfree: ptr = 0x%lx\n", (u_long) ptr); ++} ++#endif ++ ++static boolean_t crash_is_kseg(u_long addr) ++{ ++ u_long phys; ++ ++ phys = virt_to_phys((void *)addr); ++ if (phys < PFN_PHYS(max_low_pfn)) ++ return TRUE; ++ else ++ return FALSE; ++} ++ ++static u_long *crash_link(u_long p) ++{ ++ struct mem_crash_map_entry *m; ++ ++ p = (u_long) trunc_page(p); ++ m = (struct mem_crash_map_entry *)p; ++ for (; m->src_va; m++) ++ if (m->src_va == -1) ++ return &m->dest_page_va; ++ ++ return 0; ++} ++ ++/* Call this after data written to disk. */ ++static int crash_free_crashmem(void) ++{ ++ struct mem_crash_map_hdr *header; ++ struct mem_crash_map_entry *m, *last_m; ++ ++ if (crash_debug) ++ printk("crash_free_crashmem: \n"); ++ ++ header = (struct mem_crash_map_hdr *)crash_dump_header; ++ if (crash_audit_maps()) { ++ header->magic[0] = 0; ++ return 1; ++ } ++ m = (struct mem_crash_map_entry *)header->map; ++ again: ++ for (; m->src_va; m++) { ++ if (m->src_va == -1) { ++ last_m = m; ++ m = (struct mem_crash_map_entry *)m->dest_page_va; ++ crash_free_page((unsigned long)last_m); ++ goto again; ++ } ++ crash_free_page(m->dest_page_va); ++ } ++ if (crash_debug) ++ printk("crash_free_crashmem: 0x%lx freed\n", ++ (header->data_pages + header->map_pages) * PAGE_SIZE); ++ header->magic[0] = 0; ++ return 0; ++} ++ ++static void crash_free_page(u_long addr) ++{ ++ struct page *page; ++ ++ page = virt_to_page(addr); ++ ClearPageReserved(page); ++ set_page_count(page, 1); ++ __free_page(page); ++} ++ ++static int get_dump_helper(u_long kva, u_long buf) ++{ ++ struct page *page; ++ struct mem_crash_map_hdr *header; ++ ++ header = (struct mem_crash_map_hdr *)crash_dump_header; ++ if (header->magic[0] != CRASH_MAGIC) ++ return 1; ++ ++ if (!kva) { ++ if (crash_audit_maps()) { ++ printk("get_dump_helper: audit failure\n"); ++ header->magic[0] = 0; ++ return 1; ++ } ++ page = virt_to_page((u_long) crash_dump_header); ++ if (!PageReserved(page)) { ++ printk("not reserved: crash_dump_header = 0x%lx\n", crash_dump_header); ++ return 1; ++ } ++ if (copy_to_user((char *)buf, (char *)crash_dump_header, ++ sizeof(struct mem_crash_map_hdr))) { ++ printk("get_dump_helper: copy_to_user failed1\n"); ++ return 1; ++ } ++ } else { ++ page = virt_to_page(kva); ++ if (!PageReserved(page)) { ++ printk("not reserved: kva = 0x%lx\n", kva); ++ return 1; ++ } ++ if (copy_to_user((char *)buf, (char *)trunc_page(kva), PAGE_SIZE)) { ++ printk("get_dump_helper: copy_to_user failed2\n"); ++ return 1; ++ } ++ } ++ return 0; ++} ++ ++static void free_dump_helper(void) ++{ ++ struct mem_crash_map_hdr *header; ++ ++ header = (struct mem_crash_map_hdr *)crash_dump_header; ++ if (header->magic[0] != CRASH_MAGIC) ++ return; ++ if (crash_debug) ++ printk("free_dump_helper\n"); ++ crash_free_crashmem(); ++} ++ ++static int crashdev_open(struct inode *inode, struct file *file) ++{ ++ /* always return success -- nothing to do here */ ++ return 0; ++} ++ ++/* character device implementation */ ++static struct file_operations crashdev_fops = { ++ ioctl:crashdev_ioctl, ++ open:crashdev_open, ++}; ++ ++static struct miscdevice crash_miscdev = { ++ 190, "crash", &crashdev_fops ++}; ++ ++int crash_init_chrdev(void) ++{ ++ int result; ++ ++ result = misc_register(&crash_miscdev); ++ ++ if (result < 0) ++ printk(KERN_WARNING "crash: can't register crash device (c 10 190)\n"); ++ ++ return result; ++} ++ ++/* call the original syscalls, just to get things going */ ++static int crashdev_ioctl(struct inode *inode, struct file *file, ++ unsigned int cmd, unsigned long arg) ++{ ++ int retval = 0; ++ ++ switch (cmd) { ++ case CRASH_IOCFREEDUMP: ++ free_dump_helper(); ++ break; ++ ++ case CRASH_IOCGETDUMP: ++ if (crash_debug) { ++ printk("crashdev_ioctl: get dump\n"); ++ printk("vals: %08lx %08lx\n", ++ ((struct ioctl_getdump *)arg)->kva, ++ ((struct ioctl_getdump *)arg)->buf); ++ } ++ ++ retval = get_dump_helper((u_long) ((struct ioctl_getdump *)arg)->kva, ++ (u_long) ((struct ioctl_getdump *)arg)->buf); ++ break; ++ ++#ifdef CONFIG_BOOTIMG ++ case CRASH_IOCBOOTIMG: ++ if (crash_debug) ++ printk("crashdev_ioctl: bootimg\n"); ++ ++ retval = sys_bootimg((struct boot_image *)arg); ++ break; ++#endif ++ ++ case CRASH_IOCVERSION: ++ if (crash_debug) ++ printk("crashdev_ioctl: version\n"); ++ retval = CRASH_K_MINOR | (CRASH_K_MAJOR << 16); ++ break; ++ ++ default: ++ return -EINVAL; ++ } ++ ++ return retval; ++} +Index: linux/kernel/module.c +=================================================================== +RCS file: /chaos/cvs/kernel-rh/linux/kernel/module.c,v +retrieving revision 1.1.1.1.4.1 +retrieving revision 1.1.1.1.4.1.2.1 +diff -u -r1.1.1.1.4.1 -r1.1.1.1.4.1.2.1 +--- linux/kernel/module.c 12 Mar 2003 19:51:36 -0000 1.1.1.1.4.1 ++++ linux/kernel/module.c 1 Apr 2003 12:17:41 -0000 1.1.1.1.4.1.2.1 +@@ -311,7 +311,14 @@ + error = -EEXIST; + goto err1; + } ++#if defined(CONFIG_MCL_COREDUMP) ++ /* Call vmalloc_32 instead of module_map (vmalloc for i386) ++ * to avoid being mapped in highmem where mcore can't see us. ++ */ ++ if ((mod = (struct module *)vmalloc_32(size)) == NULL) { ++#else + if ((mod = (struct module *)module_map(size)) == NULL) { ++#endif + error = -ENOMEM; + goto err1; + } +Index: linux/kernel/panic.c +=================================================================== +RCS file: /chaos/cvs/kernel-rh/linux/kernel/panic.c,v +retrieving revision 1.3.2.1 +retrieving revision 1.3.2.1.2.1 +diff -u -r1.3.2.1 -r1.3.2.1.2.1 +--- linux/kernel/panic.c 12 Mar 2003 19:51:36 -0000 1.3.2.1 ++++ linux/kernel/panic.c 1 Apr 2003 12:17:41 -0000 1.3.2.1.2.1 +@@ -19,6 +19,10 @@ + #include + #include + ++#ifdef CONFIG_MCL_COREDUMP ++#include ++#endif ++ + asmlinkage void sys_sync(void); /* it's really int */ + + int panic_timeout; +@@ -197,20 +201,43 @@ + unsigned long caller = (unsigned long) __builtin_return_address(0); + #endif + ++#ifdef CONFIG_MCL_COREDUMP ++ crash_save_regs(); ++#endif ++ + bust_spinlocks(1); + va_start(args, fmt); + vsprintf(buf, fmt, args); + va_end(args); + printk(KERN_EMERG "Kernel panic: %s\n",buf); ++ ++#ifdef CONFIG_MCL_COREDUMP ++ if (!panicmsg) { ++ panicmsg = buf; ++ panic_processor = smp_processor_id(); ++ mb(); ++ } ++#endif ++ + if (netdump_func) + BUG(); + if (in_interrupt()) + printk(KERN_EMERG "In interrupt handler - not syncing\n"); + else if (!current->pid) + printk(KERN_EMERG "In idle task - not syncing\n"); ++#ifdef CONFIG_MCL_COREDUMP ++ else if (crash_perform_sync) ++#else + else ++#endif + sys_sync(); ++ + bust_spinlocks(0); ++ ++#ifdef CONFIG_MCL_COREDUMP ++ smp_call_function((void *)smp_crash_funnel_cpu,0,0,0); ++ crash_save_current_state(current); ++#endif + + #ifdef CONFIG_SMP + smp_send_stop(); +Index: linux/kernel/sysctl.c +=================================================================== +RCS file: /chaos/cvs/kernel-rh/linux/kernel/sysctl.c,v +retrieving revision 1.2.2.1 +retrieving revision 1.2.2.1.2.1 +diff -u -r1.2.2.1 -r1.2.2.1.2.1 +--- linux/kernel/sysctl.c 12 Mar 2003 19:51:36 -0000 1.2.2.1 ++++ linux/kernel/sysctl.c 1 Apr 2003 12:17:41 -0000 1.2.2.1.2.1 +@@ -37,6 +37,10 @@ + #include + #endif + ++#ifdef CONFIG_MCL_COREDUMP ++#include ++#endif ++ + #if defined(CONFIG_SYSCTL) + + /* External variables not in a header file. */ +@@ -247,6 +251,10 @@ + {KERN_SYSRQ, "sysrq", &sysrq_enabled, sizeof (int), + 0644, NULL, &proc_dointvec}, + #endif ++#ifdef CONFIG_MCL_COREDUMP ++ {KERN_PANIC_ON_OOPS, "panic_on_oops", &panic_on_oops, sizeof(int), ++ 0644, NULL, &proc_dointvec}, ++#endif + {KERN_CADPID, "cad_pid", &cad_pid, sizeof (int), + 0600, NULL, &proc_dointvec}, + {KERN_MAX_THREADS, "threads-max", &max_threads, sizeof(int), +Index: linux/lib/Config.in +=================================================================== +RCS file: /chaos/cvs/kernel-rh/linux/lib/Config.in,v +retrieving revision 1.2 +retrieving revision 1.2.4.1 +diff -u -r1.2 -r1.2.4.1 +--- linux/lib/Config.in 14 Feb 2003 22:59:23 -0000 1.2 ++++ linux/lib/Config.in 1 Apr 2003 12:17:41 -0000 1.2.4.1 +@@ -23,12 +23,14 @@ + fi + fi + +-if [ "$CONFIG_PPP_DEFLATE" = "y" -o \ ++if [ "$CONFIG_MCL_COREDUMP" = "y" -o \ ++ "$CONFIG_PPP_DEFLATE" = "y" -o \ + "$CONFIG_JFFS2_FS" = "y" ]; then + define_tristate CONFIG_ZLIB_DEFLATE y + else + if [ "$CONFIG_PPP_DEFLATE" = "m" -o \ +- "$CONFIG_JFFS2_FS" = "m" ]; then ++ "$CONFIG_JFFS2_FS" = "m" -o \ ++ "$CONFIG_MCL_COREDUMP" = "m" ]; then + define_tristate CONFIG_ZLIB_DEFLATE m + else + tristate 'zlib compression support' CONFIG_ZLIB_DEFLATE +Index: linux/mm/memory.c +=================================================================== +RCS file: /chaos/cvs/kernel-rh/linux/mm/memory.c,v +retrieving revision 1.3.2.1 +retrieving revision 1.3.2.1.2.1 +diff -u -r1.3.2.1 -r1.3.2.1.2.1 +--- linux/mm/memory.c 12 Mar 2003 19:51:37 -0000 1.3.2.1 ++++ linux/mm/memory.c 1 Apr 2003 12:17:41 -0000 1.3.2.1.2.1 +@@ -1381,6 +1381,10 @@ + } + lock_page(page); + ++#ifdef CONFIG_MCL_COREDUMP ++ set_bit(PG_anon, &page->flags); ++#endif ++ + /* + * Back out if somebody else faulted in this pte while we + * released the page table lock. +@@ -1470,6 +1474,9 @@ + mm->rss++; + flush_page_to_ram(page); + entry = pte_mkwrite(pte_mkdirty(mk_pte(page, vma->vm_page_prot))); ++#ifdef CONFIG_MCL_COREDUMP ++ set_bit(PG_anon, &page->flags); ++#endif + lru_cache_add(page); + } + +Index: linux/mm/page_alloc.c +=================================================================== +RCS file: /chaos/cvs/kernel-rh/linux/mm/page_alloc.c,v +retrieving revision 1.3.2.1 +retrieving revision 1.3.2.1.2.1 +diff -u -r1.3.2.1 -r1.3.2.1.2.1 +--- linux/mm/page_alloc.c 12 Mar 2003 19:51:37 -0000 1.3.2.1 ++++ linux/mm/page_alloc.c 1 Apr 2003 12:17:41 -0000 1.3.2.1.2.1 +@@ -95,6 +95,10 @@ + struct page *base; + per_cpu_t *per_cpu; + zone_t *zone; ++#ifdef CONFIG_MCL_COREDUMP ++ struct page *pagemap; ++ int count = 1<lock); + ++#ifdef CONFIG_MCL_COREDUMP ++ pagemap = page; ++ do { ++ pagemap->flags |= (1<flags &= ~((1<free_pages -= mask; + + while (mask + (1 << (MAX_ORDER-1))) { +@@ -268,6 +281,16 @@ + zone->free_pages -= 1UL << order; + + page = expand(zone, page, index, order, curr_order, area); ++#ifdef CONFIG_MCL_COREDUMP ++ { ++ struct page *pagemap = page; ++ int count = 1<flags &= ~(1<lock, flags); + + set_page_count(page, 1); +Index: linux/arch/i386//boot/compressed/head.S +=================================================================== +RCS file: /chaos/cvs/kernel-rh/linux/arch/i386/boot/compressed/head.S,v +retrieving revision 1.1.1.1 +retrieving revision 1.1.1.1.12.6 +diff -u -r1.1.1.1 -r1.1.1.1.12.6 +--- linux/arch/i386//boot/compressed/head.S 7 May 2002 21:53:54 -0000 1.1.1.1 ++++ linux/arch/i386//boot/compressed/head.S 5 Apr 2003 05:51:27 -0000 1.1.1.1.12.6 +@@ -23,6 +23,7 @@ + */ + .text + ++#include + #include + #include + +@@ -31,6 +32,55 @@ + startup_32: + cld + cli ++ ++#ifdef CONFIG_BOOTIMG ++/* ++ * GDT is invalid if we're booted by bootimg, so reload it now ++ */ ++ lgdt %cs:gdt_descr ++ ljmp $(__KERNEL_CS),$1f ++ ++gdt_table_limit = gdt_table_end - gdt_table - 1 ++gdt_descr: ++ .word gdt_table_limit ++ .long gdt_table ++ ++gdt_table: /* stolen from arch/i386/kernel/head.S */ ++ .quad 0x0000000000000000 /* NULL descriptor */ ++ .quad 0x0000000000000000 /* 0x0b reserved */ ++ .quad 0x0000000000000000 /* 0x13 reserved */ ++ .quad 0x0000000000000000 /* 0x1b reserved */ ++ .quad 0x00cffa000000ffff /* 0x23 user 4GB code at 0x00000000 */ ++ .quad 0x00cff2000000ffff /* 0x2b user 4GB data at 0x00000000 */ ++ .quad 0x0000000000000000 /* 0x33 TLS entry 1 */ ++ .quad 0x0000000000000000 /* 0x3b TLS entry 2 */ ++ .quad 0x0000000000000000 /* 0x43 TLS entry 3 */ ++ .quad 0x0000000000000000 /* 0x4b reserved */ ++ .quad 0x0000000000000000 /* 0x53 reserved */ ++ .quad 0x0000000000000000 /* 0x5b reserved */ ++ ++ .quad 0x00cf9a000000ffff /* 0x60 kernel 4GB code at 0x00000000 */ ++ .quad 0x00cf92000000ffff /* 0x68 kernel 4GB data at 0x00000000 */ ++ .quad 0x0000000000000000 /* 0x70 TSS descriptor */ ++ .quad 0x0000000000000000 /* 0x78 LDT descriptor */ ++ ++ /* Segments used for calling PnP BIOS */ ++ .quad 0x00c09a0000000000 /* 0x80 32-bit code */ ++ .quad 0x00809a0000000000 /* 0x88 16-bit code */ ++ .quad 0x0080920000000000 /* 0x90 16-bit data */ ++ .quad 0x0080920000000000 /* 0x98 16-bit data */ ++ .quad 0x0080920000000000 /* 0xa0 16-bit data */ ++ /* ++ * The APM segments have byte granularity and their bases ++ * and limits are set at run time. ++ */ ++ .quad 0x00409a0000000000 /* 0xa8 APM CS code */ ++ .quad 0x00009a0000000000 /* 0xb0 APM CS 16 code (16 bit) */ ++ .quad 0x0040920000000000 /* 0xb8 APM DS data */ ++gdt_table_end: ++ ++1: ++#endif + movl $(__KERNEL_DS),%eax + movl %eax,%ds + movl %eax,%es +@@ -92,7 +142,6 @@ + cld + rep + movsl +- + popl %esi # discard the address + popl %ebx # real mode pointer + popl %esi # low_buffer_start +@@ -124,5 +173,10 @@ + movsl + movl %ebx,%esi # Restore setup pointer + xorl %ebx,%ebx ++#ifdef CONFIG_BOOTIMG ++ movl $0x100000,%eax ++ jmpl *%eax ++#else + ljmp $(__KERNEL_CS), $0x100000 ++#endif + move_routine_end: +Index: linux/arch/i386//kernel/head.S +=================================================================== +RCS file: /chaos/cvs/kernel-rh/linux/arch/i386/kernel/head.S,v +retrieving revision 1.2.2.1 +retrieving revision 1.2.2.1.2.5 +diff -u -r1.2.2.1 -r1.2.2.1.2.5 +--- linux/arch/i386//kernel/head.S 12 Mar 2003 19:49:06 -0000 1.2.2.1 ++++ linux/arch/i386//kernel/head.S 5 Apr 2003 05:51:27 -0000 1.2.2.1.2.5 +@@ -42,6 +42,21 @@ + * On entry, %esi points to the real-mode code as a 32-bit pointer. + */ + startup_32: ++#ifdef CONFIG_BOOTIMG ++/* ++ * GDT is invalid if we're booted by bootimg, so reload it now ++ */ ++ lgdt %cs:_gdt_descr-__PAGE_OFFSET ++ ljmp $(__KERNEL_CS),$1f-__PAGE_OFFSET ++ ++gdt_limit = SYMBOL_NAME(cpu_gdt_table_end) - SYMBOL_NAME(cpu_gdt_table) - 1 ++ ++_gdt_descr: ++ .word gdt_limit ++ .long SYMBOL_NAME(cpu_gdt_table)-__PAGE_OFFSET ++ ++1: ++#endif + /* + * Set segments to known values + */ +@@ -452,6 +467,7 @@ + .quad 0x00409a0000000000 /* 0xa8 APM CS code */ + .quad 0x00009a0000000000 /* 0xb0 APM CS 16 code (16 bit) */ + .quad 0x0040920000000000 /* 0xb8 APM DS data */ ++ENTRY(cpu_gdt_table_end) + + #if CONFIG_SMP + .fill (NR_CPUS-1)*GDT_ENTRIES,8,0 /* other CPU's GDT */ diff --git a/lustre/kernel_patches/patches/uml-patch-2.4.20-4.patch b/lustre/kernel_patches/patches/uml-patch-2.4.20-4.patch index 06d0fff..b35fee0 100644 --- a/lustre/kernel_patches/patches/uml-patch-2.4.20-4.patch +++ b/lustre/kernel_patches/patches/uml-patch-2.4.20-4.patch @@ -39356,16 +39356,3 @@ diff -Naur -X ../exclude-files orig/mm/slab.c um/mm/slab.c seq_printf(m, "%-17s %6lu %6lu %6u %4lu %4lu %4u", name, active_objs, num_objs, cachep->objsize, -diff -puNr origin/arch/i386/kernel/sys_i386.c linux/arch/i386/kernel/sys_i386.c ---- origin/arch/i386/kernel/sys_i386.c 2001-03-19 23:35:09.000000000 +0300 -+++ linux/arch/i386/kernel/sys_i386.c 2003-05-04 11:44:54.000000000 +0400 -@@ -56,7 +56,7 @@ static inline long do_mmap2( - } - - down_write(¤t->mm->mmap_sem); -- error = do_mmap_pgoff(file, addr, len, prot, flags, pgoff); -+ error = do_mmap_pgoff(current->mm, file, addr, len, prot, flags, pgoff); - up_write(¤t->mm->mmap_sem); - - if (file) - diff --git a/lustre/kernel_patches/pc/dsp.pc b/lustre/kernel_patches/pc/dsp.pc new file mode 100644 index 0000000..fdbf418 --- /dev/null +++ b/lustre/kernel_patches/pc/dsp.pc @@ -0,0 +1,6 @@ +kernel/bootimg.c +kernel/bootimg_pic.c +include/asm-i386/apic.h +include/linux/crash.h +arch/i386/kernel/crash.c +arch/i386/kernel/nmi.c diff --git a/lustre/kernel_patches/pc/ext3_orphan_lock-2.4.20-rh.pc b/lustre/kernel_patches/pc/ext3_orphan_lock-2.4.20-rh.pc new file mode 100644 index 0000000..98aebb0 --- /dev/null +++ b/lustre/kernel_patches/pc/ext3_orphan_lock-2.4.20-rh.pc @@ -0,0 +1,3 @@ +fs/ext3/namei.c +fs/ext3/super.c +include/linux/ext3_fs_sb.h diff --git a/lustre/kernel_patches/pc/iopen-chaos-2.4.18.pc b/lustre/kernel_patches/pc/iopen-chaos-2.4.18.pc new file mode 100644 index 0000000..b40b1f3 --- /dev/null +++ b/lustre/kernel_patches/pc/iopen-chaos-2.4.18.pc @@ -0,0 +1,8 @@ +Documentation/filesystems/ext2.txt +fs/ext3/Makefile +fs/ext3/inode.c +fs/ext3/iopen.c +fs/ext3/iopen.h +fs/ext3/namei.c +fs/ext3/super.c +include/linux/ext3_fs.h diff --git a/lustre/kernel_patches/pc/iopen.pc b/lustre/kernel_patches/pc/iopen.pc new file mode 100644 index 0000000..b40b1f3 --- /dev/null +++ b/lustre/kernel_patches/pc/iopen.pc @@ -0,0 +1,8 @@ +Documentation/filesystems/ext2.txt +fs/ext3/Makefile +fs/ext3/inode.c +fs/ext3/iopen.c +fs/ext3/iopen.h +fs/ext3/namei.c +fs/ext3/super.c +include/linux/ext3_fs.h diff --git a/lustre/kernel_patches/pc/kmem_cache_validate_2.4.20.pc b/lustre/kernel_patches/pc/kmem_cache_validate_2.4.20.pc new file mode 100644 index 0000000..42028bc --- /dev/null +++ b/lustre/kernel_patches/pc/kmem_cache_validate_2.4.20.pc @@ -0,0 +1,4 @@ +arch/ia64/mm/init.c +include/linux/slab.h +kernel/ksyms.c +mm/slab.c diff --git a/lustre/kernel_patches/pc/mcore-2.4.20-8.pc b/lustre/kernel_patches/pc/mcore-2.4.20-8.pc new file mode 100644 index 0000000..b290f60 --- /dev/null +++ b/lustre/kernel_patches/pc/mcore-2.4.20-8.pc @@ -0,0 +1,34 @@ +Makefile +Documentation/Configure.help +arch/i386/config.in +arch/i386/vmlinux.lds +arch/i386/boot/setup.S +arch/i386/kernel/Makefile +arch/i386/kernel/crash.c +arch/i386/kernel/nmi.c +arch/i386/kernel/process.c +arch/i386/kernel/setup.c +arch/i386/kernel/smp.c +arch/i386/kernel/traps.c +drivers/char/misc.c +drivers/char/sysrq.c +include/asm-i386/bootimg.h +include/asm-i386/crash.h +include/linux/bootimg.h +include/linux/crash.h +include/linux/mm.h +include/linux/reboot.h +include/linux/sysctl.h +init/main.c +kernel/Makefile +kernel/bootimg.c +kernel/bootimg_pic.c +kernel/crash.c +kernel/module.c +kernel/panic.c +kernel/sysctl.c +lib/Config.in +mm/memory.c +mm/page_alloc.c +arch/i386//boot/compressed/head.S +arch/i386//kernel/head.S diff --git a/lustre/kernel_patches/pc/uml-patch-2.4.20-4.pc b/lustre/kernel_patches/pc/uml-patch-2.4.20-4.pc index 8e6b473..887e3fa 100644 --- a/lustre/kernel_patches/pc/uml-patch-2.4.20-4.pc +++ b/lustre/kernel_patches/pc/uml-patch-2.4.20-4.pc @@ -1,395 +1,394 @@ -um/CREDITS -um/Documentation/Configure.help -um/MAINTAINERS -um/Makefile -um/arch/um/Makefile -um/arch/um/Makefile-i386 -um/arch/um/Makefile-ia64 -um/arch/um/Makefile-os-Linux -um/arch/um/Makefile-ppc -um/arch/um/Makefile-skas -um/arch/um/Makefile-tt -um/arch/um/common.ld.in -um/arch/um/config.in -um/arch/um/config.release -um/arch/um/config_block.in -um/arch/um/config_char.in -um/arch/um/config_net.in -um/arch/um/config_scsi.in -um/arch/um/defconfig -um/arch/um/drivers/Makefile -um/arch/um/drivers/chan_kern.c -um/arch/um/drivers/chan_user.c -um/arch/um/drivers/daemon.h -um/arch/um/drivers/daemon_kern.c -um/arch/um/drivers/daemon_user.c -um/arch/um/drivers/fd.c -um/arch/um/drivers/harddog_kern.c -um/arch/um/drivers/harddog_user.c -um/arch/um/drivers/hostaudio_kern.c -um/arch/um/drivers/hostaudio_user.c -um/arch/um/drivers/line.c -um/arch/um/drivers/mcast.h -um/arch/um/drivers/mcast_kern.c -um/arch/um/drivers/mcast_user.c -um/arch/um/drivers/mconsole_kern.c -um/arch/um/drivers/mconsole_user.c -um/arch/um/drivers/mmapper_kern.c -um/arch/um/drivers/net_kern.c -um/arch/um/drivers/net_user.c -um/arch/um/drivers/null.c -um/arch/um/drivers/pcap_kern.c -um/arch/um/drivers/pcap_user.c -um/arch/um/drivers/pcap_user.h -um/arch/um/drivers/port.h -um/arch/um/drivers/port_kern.c -um/arch/um/drivers/port_user.c -um/arch/um/drivers/pty.c -um/arch/um/drivers/slip.h -um/arch/um/drivers/slip_kern.c -um/arch/um/drivers/slip_proto.h -um/arch/um/drivers/slip_user.c -um/arch/um/drivers/slirp.h -um/arch/um/drivers/slirp_kern.c -um/arch/um/drivers/slirp_user.c -um/arch/um/drivers/ssl.c -um/arch/um/drivers/ssl.h -um/arch/um/drivers/stdio_console.c -um/arch/um/drivers/stdio_console.h -um/arch/um/drivers/tty.c -um/arch/um/drivers/ubd_kern.c -um/arch/um/drivers/ubd_user.c -um/arch/um/drivers/xterm.c -um/arch/um/drivers/xterm.h -um/arch/um/drivers/xterm_kern.c -um/arch/um/dyn_link.ld.in -um/arch/um/fs/Makefile -um/arch/um/fs/hostfs/Makefile -um/arch/um/fs/hostfs/hostfs.h -um/arch/um/fs/hostfs/hostfs_kern.c -um/arch/um/fs/hostfs/hostfs_user.c -um/arch/um/fs/hppfs/Makefile -um/arch/um/fs/hppfs/hppfs_kern.c -um/arch/um/include/2_5compat.h -um/arch/um/include/Makefile -um/arch/um/include/chan_kern.h -um/arch/um/include/chan_user.h -um/arch/um/include/choose-mode.h -um/arch/um/include/frame.h -um/arch/um/include/frame_kern.h -um/arch/um/include/frame_user.h -um/arch/um/include/helper.h -um/arch/um/include/hostaudio.h -um/arch/um/include/init.h -um/arch/um/include/initrd.h -um/arch/um/include/irq_user.h -um/arch/um/include/kern.h -um/arch/um/include/kern_util.h -um/arch/um/include/line.h -um/arch/um/include/mconsole.h -um/arch/um/include/mconsole_kern.h -um/arch/um/include/mem.h -um/arch/um/include/mem_user.h -um/arch/um/include/mode.h -um/arch/um/include/mode_kern.h -um/arch/um/include/net_kern.h -um/arch/um/include/net_user.h -um/arch/um/include/os.h -um/arch/um/include/process.h -um/arch/um/include/ptrace_user.h -um/arch/um/include/sigcontext.h -um/arch/um/include/sigio.h -um/arch/um/include/signal_kern.h -um/arch/um/include/signal_user.h -um/arch/um/include/skas_ptrace.h -um/arch/um/include/syscall_user.h -um/arch/um/include/sysdep-i386/checksum.h -um/arch/um/include/sysdep-i386/frame.h -um/arch/um/include/sysdep-i386/frame_kern.h -um/arch/um/include/sysdep-i386/frame_user.h -um/arch/um/include/sysdep-i386/ptrace.h -um/arch/um/include/sysdep-i386/ptrace_user.h -um/arch/um/include/sysdep-i386/sigcontext.h -um/arch/um/include/sysdep-i386/syscalls.h -um/arch/um/include/sysdep-ia64/ptrace.h -um/arch/um/include/sysdep-ia64/sigcontext.h -um/arch/um/include/sysdep-ia64/syscalls.h -um/arch/um/include/sysdep-ppc/ptrace.h -um/arch/um/include/sysdep-ppc/sigcontext.h -um/arch/um/include/sysdep-ppc/syscalls.h -um/arch/um/include/sysrq.h -um/arch/um/include/tempfile.h -um/arch/um/include/time_user.h -um/arch/um/include/tlb.h -um/arch/um/include/ubd_user.h -um/arch/um/include/um_mmu.h -um/arch/um/include/um_uaccess.h -um/arch/um/include/umid.h -um/arch/um/include/uml_uaccess.h -um/arch/um/include/umn.h -um/arch/um/include/user.h -um/arch/um/include/user_util.h -um/arch/um/kernel/Makefile -um/arch/um/kernel/checksum.c -um/arch/um/kernel/config.c.in -um/arch/um/kernel/exec_kern.c -um/arch/um/kernel/exitcode.c -um/arch/um/kernel/frame.c -um/arch/um/kernel/frame_kern.c -um/arch/um/kernel/gmon_syms.c -um/arch/um/kernel/gprof_syms.c -um/arch/um/kernel/helper.c -um/arch/um/kernel/init_task.c -um/arch/um/kernel/initrd_kern.c -um/arch/um/kernel/initrd_user.c -um/arch/um/kernel/irq.c -um/arch/um/kernel/irq_user.c -um/arch/um/kernel/ksyms.c -um/arch/um/kernel/mem.c -um/arch/um/kernel/mem_user.c -um/arch/um/kernel/mprot.h -um/arch/um/kernel/process.c -um/arch/um/kernel/process_kern.c -um/arch/um/kernel/ptrace.c -um/arch/um/kernel/reboot.c -um/arch/um/kernel/resource.c -um/arch/um/kernel/sigio_kern.c -um/arch/um/kernel/sigio_user.c -um/arch/um/kernel/signal_kern.c -um/arch/um/kernel/signal_user.c -um/arch/um/kernel/skas/Makefile -um/arch/um/kernel/skas/exec_kern.c -um/arch/um/kernel/skas/exec_user.c -um/arch/um/kernel/skas/include/mmu.h -um/arch/um/kernel/skas/include/mode.h -um/arch/um/kernel/skas/include/mode_kern.h -um/arch/um/kernel/skas/include/proc_mm.h -um/arch/um/kernel/skas/include/ptrace-skas.h -um/arch/um/kernel/skas/include/skas.h -um/arch/um/kernel/skas/include/uaccess.h -um/arch/um/kernel/skas/mem.c -um/arch/um/kernel/skas/mem_user.c -um/arch/um/kernel/skas/mmu.c -um/arch/um/kernel/skas/process.c -um/arch/um/kernel/skas/process_kern.c -um/arch/um/kernel/skas/sys-i386/Makefile -um/arch/um/kernel/skas/sys-i386/sigcontext.c -um/arch/um/kernel/skas/syscall_kern.c -um/arch/um/kernel/skas/syscall_user.c -um/arch/um/kernel/skas/time.c -um/arch/um/kernel/skas/tlb.c -um/arch/um/kernel/skas/trap_user.c -um/arch/um/kernel/skas/util/Makefile -um/arch/um/kernel/skas/util/mk_ptregs.c -um/arch/um/kernel/smp.c -um/arch/um/kernel/sys_call_table.c -um/arch/um/kernel/syscall_kern.c -um/arch/um/kernel/syscall_user.c -um/arch/um/kernel/sysrq.c -um/arch/um/kernel/tempfile.c -um/arch/um/kernel/time.c -um/arch/um/kernel/time_kern.c -um/arch/um/kernel/tlb.c -um/arch/um/kernel/trap_kern.c -um/arch/um/kernel/trap_user.c -um/arch/um/kernel/tt/Makefile -um/arch/um/kernel/tt/exec_kern.c -um/arch/um/kernel/tt/exec_user.c -um/arch/um/kernel/tt/gdb.c -um/arch/um/kernel/tt/gdb_kern.c -um/arch/um/kernel/tt/include/debug.h -um/arch/um/kernel/tt/include/mmu.h -um/arch/um/kernel/tt/include/mode.h -um/arch/um/kernel/tt/include/mode_kern.h -um/arch/um/kernel/tt/include/ptrace-tt.h -um/arch/um/kernel/tt/include/tt.h -um/arch/um/kernel/tt/include/uaccess.h -um/arch/um/kernel/tt/ksyms.c -um/arch/um/kernel/tt/mem.c -um/arch/um/kernel/tt/mem_user.c -um/arch/um/kernel/tt/process_kern.c -um/arch/um/kernel/tt/ptproxy/Makefile -um/arch/um/kernel/tt/ptproxy/proxy.c -um/arch/um/kernel/tt/ptproxy/ptproxy.h -um/arch/um/kernel/tt/ptproxy/ptrace.c -um/arch/um/kernel/tt/ptproxy/sysdep.c -um/arch/um/kernel/tt/ptproxy/sysdep.h -um/arch/um/kernel/tt/ptproxy/wait.c -um/arch/um/kernel/tt/ptproxy/wait.h -um/arch/um/kernel/tt/sys-i386/Makefile -um/arch/um/kernel/tt/sys-i386/sigcontext.c -um/arch/um/kernel/tt/syscall_kern.c -um/arch/um/kernel/tt/syscall_user.c -um/arch/um/kernel/tt/time.c -um/arch/um/kernel/tt/tlb.c -um/arch/um/kernel/tt/tracer.c -um/arch/um/kernel/tt/trap_user.c -um/arch/um/kernel/tt/uaccess_user.c -um/arch/um/kernel/tt/unmap.c -um/arch/um/kernel/tty_log.c -um/arch/um/kernel/uaccess_user.c -um/arch/um/kernel/um_arch.c -um/arch/um/kernel/umid.c -um/arch/um/kernel/user_syms.c -um/arch/um/kernel/user_util.c -um/arch/um/link.ld.in -um/arch/um/main.c -um/arch/um/os-Linux/Makefile -um/arch/um/os-Linux/drivers/Makefile -um/arch/um/os-Linux/drivers/etap.h -um/arch/um/os-Linux/drivers/ethertap_kern.c -um/arch/um/os-Linux/drivers/ethertap_user.c -um/arch/um/os-Linux/drivers/tuntap.h -um/arch/um/os-Linux/drivers/tuntap_kern.c -um/arch/um/os-Linux/drivers/tuntap_user.c -um/arch/um/os-Linux/file.c -um/arch/um/os-Linux/include/file.h -um/arch/um/os-Linux/process.c -um/arch/um/os-Linux/tty.c -um/arch/um/sys-i386/Makefile -um/arch/um/sys-i386/bugs.c -um/arch/um/sys-i386/checksum.S -um/arch/um/sys-i386/fault.c -um/arch/um/sys-i386/ksyms.c -um/arch/um/sys-i386/ldt.c -um/arch/um/sys-i386/ptrace.c -um/arch/um/sys-i386/ptrace_user.c -um/arch/um/sys-i386/sigcontext.c -um/arch/um/sys-i386/syscalls.c -um/arch/um/sys-i386/sysrq.c -um/arch/um/sys-i386/util/Makefile -um/arch/um/sys-i386/util/mk_sc.c -um/arch/um/sys-i386/util/mk_thread_kern.c -um/arch/um/sys-i386/util/mk_thread_user.c -um/arch/um/sys-ia64/Makefile -um/arch/um/sys-ppc/Makefile -um/arch/um/sys-ppc/misc.S -um/arch/um/sys-ppc/miscthings.c -um/arch/um/sys-ppc/ptrace.c -um/arch/um/sys-ppc/ptrace_user.c -um/arch/um/sys-ppc/sigcontext.c -um/arch/um/sys-ppc/sysrq.c -um/arch/um/util/Makefile -um/arch/um/util/mk_constants_kern.c -um/arch/um/util/mk_constants_user.c -um/arch/um/util/mk_task_kern.c -um/arch/um/util/mk_task_user.c -um/drivers/char/Makefile -um/drivers/char/tty_io.c -um/drivers/net/setup.c -um/include/asm-i386/hardirq.h -um/include/asm-um/a.out.h -um/include/asm-um/arch-signal-i386.h -um/include/asm-um/archparam-i386.h -um/include/asm-um/archparam-ppc.h -um/include/asm-um/atomic.h -um/include/asm-um/bitops.h -um/include/asm-um/boot.h -um/include/asm-um/bugs.h -um/include/asm-um/byteorder.h -um/include/asm-um/cache.h -um/include/asm-um/checksum.h -um/include/asm-um/cobalt.h -um/include/asm-um/current.h -um/include/asm-um/delay.h -um/include/asm-um/desc.h -um/include/asm-um/div64.h -um/include/asm-um/dma.h -um/include/asm-um/elf.h -um/include/asm-um/errno.h -um/include/asm-um/fcntl.h -um/include/asm-um/fixmap.h -um/include/asm-um/floppy.h -um/include/asm-um/hardirq.h -um/include/asm-um/hdreg.h -um/include/asm-um/highmem.h -um/include/asm-um/hw_irq.h -um/include/asm-um/ide.h -um/include/asm-um/init.h -um/include/asm-um/io.h -um/include/asm-um/ioctl.h -um/include/asm-um/ioctls.h -um/include/asm-um/ipc.h -um/include/asm-um/ipcbuf.h -um/include/asm-um/irq.h -um/include/asm-um/keyboard.h -um/include/asm-um/kmap_types.h -um/include/asm-um/linux_logo.h -um/include/asm-um/locks.h -um/include/asm-um/mca_dma.h -um/include/asm-um/mman.h -um/include/asm-um/mmu.h -um/include/asm-um/mmu_context.h -um/include/asm-um/module.h -um/include/asm-um/msgbuf.h -um/include/asm-um/mtrr.h -um/include/asm-um/namei.h -um/include/asm-um/page.h -um/include/asm-um/page_offset.h -um/include/asm-um/param.h -um/include/asm-um/pci.h -um/include/asm-um/pgalloc.h -um/include/asm-um/pgtable.h -um/include/asm-um/poll.h -um/include/asm-um/posix_types.h -um/include/asm-um/processor-generic.h -um/include/asm-um/processor-i386.h -um/include/asm-um/processor-ppc.h -um/include/asm-um/ptrace-generic.h -um/include/asm-um/ptrace-i386.h -um/include/asm-um/resource.h -um/include/asm-um/rwlock.h -um/include/asm-um/rwsem.h -um/include/asm-um/scatterlist.h -um/include/asm-um/segment.h -um/include/asm-um/semaphore.h -um/include/asm-um/sembuf.h -um/include/asm-um/serial.h -um/include/asm-um/shmbuf.h -um/include/asm-um/shmparam.h -um/include/asm-um/sigcontext-generic.h -um/include/asm-um/sigcontext-i386.h -um/include/asm-um/sigcontext-ppc.h -um/include/asm-um/siginfo.h -um/include/asm-um/signal.h -um/include/asm-um/smp.h -um/include/asm-um/smplock.h -um/include/asm-um/socket.h -um/include/asm-um/sockios.h -um/include/asm-um/softirq.h -um/include/asm-um/spinlock.h -um/include/asm-um/stat.h -um/include/asm-um/statfs.h -um/include/asm-um/string.h -um/include/asm-um/system-generic.h -um/include/asm-um/system-i386.h -um/include/asm-um/system-ppc.h -um/include/asm-um/termbits.h -um/include/asm-um/termios.h -um/include/asm-um/timex.h -um/include/asm-um/tlb.h -um/include/asm-um/types.h -um/include/asm-um/uaccess.h -um/include/asm-um/ucontext.h -um/include/asm-um/unaligned.h -um/include/asm-um/unistd.h -um/include/asm-um/user.h -um/include/asm-um/vga.h -um/include/asm-um/xor.h -um/include/linux/blk.h -um/include/linux/fs.h -um/include/linux/hostfs_fs_i.h -um/include/linux/hppfs_fs_i.h -um/include/linux/kernel.h -um/include/linux/kernel_stat.h -um/include/linux/mm.h -um/include/linux/proc_mm.h -um/include/linux/tty.h -um/init/do_mounts.c -um/kernel/panic.c -um/mm/Makefile -um/mm/mmap.c -um/mm/mprotect.c -um/mm/proc_mm.c -um/mm/slab.c -linux/arch/i386/kernel/sys_i386.c +CREDITS +Documentation/Configure.help +MAINTAINERS +Makefile +arch/um/Makefile +arch/um/Makefile-i386 +arch/um/Makefile-ia64 +arch/um/Makefile-os-Linux +arch/um/Makefile-ppc +arch/um/Makefile-skas +arch/um/Makefile-tt +arch/um/common.ld.in +arch/um/config.in +arch/um/config.release +arch/um/config_block.in +arch/um/config_char.in +arch/um/config_net.in +arch/um/config_scsi.in +arch/um/defconfig +arch/um/drivers/Makefile +arch/um/drivers/chan_kern.c +arch/um/drivers/chan_user.c +arch/um/drivers/daemon.h +arch/um/drivers/daemon_kern.c +arch/um/drivers/daemon_user.c +arch/um/drivers/fd.c +arch/um/drivers/harddog_kern.c +arch/um/drivers/harddog_user.c +arch/um/drivers/hostaudio_kern.c +arch/um/drivers/hostaudio_user.c +arch/um/drivers/line.c +arch/um/drivers/mcast.h +arch/um/drivers/mcast_kern.c +arch/um/drivers/mcast_user.c +arch/um/drivers/mconsole_kern.c +arch/um/drivers/mconsole_user.c +arch/um/drivers/mmapper_kern.c +arch/um/drivers/net_kern.c +arch/um/drivers/net_user.c +arch/um/drivers/null.c +arch/um/drivers/pcap_kern.c +arch/um/drivers/pcap_user.c +arch/um/drivers/pcap_user.h +arch/um/drivers/port.h +arch/um/drivers/port_kern.c +arch/um/drivers/port_user.c +arch/um/drivers/pty.c +arch/um/drivers/slip.h +arch/um/drivers/slip_kern.c +arch/um/drivers/slip_proto.h +arch/um/drivers/slip_user.c +arch/um/drivers/slirp.h +arch/um/drivers/slirp_kern.c +arch/um/drivers/slirp_user.c +arch/um/drivers/ssl.c +arch/um/drivers/ssl.h +arch/um/drivers/stdio_console.c +arch/um/drivers/stdio_console.h +arch/um/drivers/tty.c +arch/um/drivers/ubd_kern.c +arch/um/drivers/ubd_user.c +arch/um/drivers/xterm.c +arch/um/drivers/xterm.h +arch/um/drivers/xterm_kern.c +arch/um/dyn_link.ld.in +arch/um/fs/Makefile +arch/um/fs/hostfs/Makefile +arch/um/fs/hostfs/hostfs.h +arch/um/fs/hostfs/hostfs_kern.c +arch/um/fs/hostfs/hostfs_user.c +arch/um/fs/hppfs/Makefile +arch/um/fs/hppfs/hppfs_kern.c +arch/um/include/2_5compat.h +arch/um/include/Makefile +arch/um/include/chan_kern.h +arch/um/include/chan_user.h +arch/um/include/choose-mode.h +arch/um/include/frame.h +arch/um/include/frame_kern.h +arch/um/include/frame_user.h +arch/um/include/helper.h +arch/um/include/hostaudio.h +arch/um/include/init.h +arch/um/include/initrd.h +arch/um/include/irq_user.h +arch/um/include/kern.h +arch/um/include/kern_util.h +arch/um/include/line.h +arch/um/include/mconsole.h +arch/um/include/mconsole_kern.h +arch/um/include/mem.h +arch/um/include/mem_user.h +arch/um/include/mode.h +arch/um/include/mode_kern.h +arch/um/include/net_kern.h +arch/um/include/net_user.h +arch/um/include/os.h +arch/um/include/process.h +arch/um/include/ptrace_user.h +arch/um/include/sigcontext.h +arch/um/include/sigio.h +arch/um/include/signal_kern.h +arch/um/include/signal_user.h +arch/um/include/skas_ptrace.h +arch/um/include/syscall_user.h +arch/um/include/sysdep-i386/checksum.h +arch/um/include/sysdep-i386/frame.h +arch/um/include/sysdep-i386/frame_kern.h +arch/um/include/sysdep-i386/frame_user.h +arch/um/include/sysdep-i386/ptrace.h +arch/um/include/sysdep-i386/ptrace_user.h +arch/um/include/sysdep-i386/sigcontext.h +arch/um/include/sysdep-i386/syscalls.h +arch/um/include/sysdep-ia64/ptrace.h +arch/um/include/sysdep-ia64/sigcontext.h +arch/um/include/sysdep-ia64/syscalls.h +arch/um/include/sysdep-ppc/ptrace.h +arch/um/include/sysdep-ppc/sigcontext.h +arch/um/include/sysdep-ppc/syscalls.h +arch/um/include/sysrq.h +arch/um/include/tempfile.h +arch/um/include/time_user.h +arch/um/include/tlb.h +arch/um/include/ubd_user.h +arch/um/include/um_mmu.h +arch/um/include/um_uaccess.h +arch/um/include/umid.h +arch/um/include/uml_uaccess.h +arch/um/include/umn.h +arch/um/include/user.h +arch/um/include/user_util.h +arch/um/kernel/Makefile +arch/um/kernel/checksum.c +arch/um/kernel/config.c.in +arch/um/kernel/exec_kern.c +arch/um/kernel/exitcode.c +arch/um/kernel/frame.c +arch/um/kernel/frame_kern.c +arch/um/kernel/gmon_syms.c +arch/um/kernel/gprof_syms.c +arch/um/kernel/helper.c +arch/um/kernel/init_task.c +arch/um/kernel/initrd_kern.c +arch/um/kernel/initrd_user.c +arch/um/kernel/irq.c +arch/um/kernel/irq_user.c +arch/um/kernel/ksyms.c +arch/um/kernel/mem.c +arch/um/kernel/mem_user.c +arch/um/kernel/mprot.h +arch/um/kernel/process.c +arch/um/kernel/process_kern.c +arch/um/kernel/ptrace.c +arch/um/kernel/reboot.c +arch/um/kernel/resource.c +arch/um/kernel/sigio_kern.c +arch/um/kernel/sigio_user.c +arch/um/kernel/signal_kern.c +arch/um/kernel/signal_user.c +arch/um/kernel/skas/Makefile +arch/um/kernel/skas/exec_kern.c +arch/um/kernel/skas/exec_user.c +arch/um/kernel/skas/include/mmu.h +arch/um/kernel/skas/include/mode.h +arch/um/kernel/skas/include/mode_kern.h +arch/um/kernel/skas/include/proc_mm.h +arch/um/kernel/skas/include/ptrace-skas.h +arch/um/kernel/skas/include/skas.h +arch/um/kernel/skas/include/uaccess.h +arch/um/kernel/skas/mem.c +arch/um/kernel/skas/mem_user.c +arch/um/kernel/skas/mmu.c +arch/um/kernel/skas/process.c +arch/um/kernel/skas/process_kern.c +arch/um/kernel/skas/sys-i386/Makefile +arch/um/kernel/skas/sys-i386/sigcontext.c +arch/um/kernel/skas/syscall_kern.c +arch/um/kernel/skas/syscall_user.c +arch/um/kernel/skas/time.c +arch/um/kernel/skas/tlb.c +arch/um/kernel/skas/trap_user.c +arch/um/kernel/skas/util/Makefile +arch/um/kernel/skas/util/mk_ptregs.c +arch/um/kernel/smp.c +arch/um/kernel/sys_call_table.c +arch/um/kernel/syscall_kern.c +arch/um/kernel/syscall_user.c +arch/um/kernel/sysrq.c +arch/um/kernel/tempfile.c +arch/um/kernel/time.c +arch/um/kernel/time_kern.c +arch/um/kernel/tlb.c +arch/um/kernel/trap_kern.c +arch/um/kernel/trap_user.c +arch/um/kernel/tt/Makefile +arch/um/kernel/tt/exec_kern.c +arch/um/kernel/tt/exec_user.c +arch/um/kernel/tt/gdb.c +arch/um/kernel/tt/gdb_kern.c +arch/um/kernel/tt/include/debug.h +arch/um/kernel/tt/include/mmu.h +arch/um/kernel/tt/include/mode.h +arch/um/kernel/tt/include/mode_kern.h +arch/um/kernel/tt/include/ptrace-tt.h +arch/um/kernel/tt/include/tt.h +arch/um/kernel/tt/include/uaccess.h +arch/um/kernel/tt/ksyms.c +arch/um/kernel/tt/mem.c +arch/um/kernel/tt/mem_user.c +arch/um/kernel/tt/process_kern.c +arch/um/kernel/tt/ptproxy/Makefile +arch/um/kernel/tt/ptproxy/proxy.c +arch/um/kernel/tt/ptproxy/ptproxy.h +arch/um/kernel/tt/ptproxy/ptrace.c +arch/um/kernel/tt/ptproxy/sysdep.c +arch/um/kernel/tt/ptproxy/sysdep.h +arch/um/kernel/tt/ptproxy/wait.c +arch/um/kernel/tt/ptproxy/wait.h +arch/um/kernel/tt/sys-i386/Makefile +arch/um/kernel/tt/sys-i386/sigcontext.c +arch/um/kernel/tt/syscall_kern.c +arch/um/kernel/tt/syscall_user.c +arch/um/kernel/tt/time.c +arch/um/kernel/tt/tlb.c +arch/um/kernel/tt/tracer.c +arch/um/kernel/tt/trap_user.c +arch/um/kernel/tt/uaccess_user.c +arch/um/kernel/tt/unmap.c +arch/um/kernel/tty_log.c +arch/um/kernel/uaccess_user.c +arch/um/kernel/um_arch.c +arch/um/kernel/umid.c +arch/um/kernel/user_syms.c +arch/um/kernel/user_util.c +arch/um/link.ld.in +arch/um/main.c +arch/um/os-Linux/Makefile +arch/um/os-Linux/drivers/Makefile +arch/um/os-Linux/drivers/etap.h +arch/um/os-Linux/drivers/ethertap_kern.c +arch/um/os-Linux/drivers/ethertap_user.c +arch/um/os-Linux/drivers/tuntap.h +arch/um/os-Linux/drivers/tuntap_kern.c +arch/um/os-Linux/drivers/tuntap_user.c +arch/um/os-Linux/file.c +arch/um/os-Linux/include/file.h +arch/um/os-Linux/process.c +arch/um/os-Linux/tty.c +arch/um/sys-i386/Makefile +arch/um/sys-i386/bugs.c +arch/um/sys-i386/checksum.S +arch/um/sys-i386/fault.c +arch/um/sys-i386/ksyms.c +arch/um/sys-i386/ldt.c +arch/um/sys-i386/ptrace.c +arch/um/sys-i386/ptrace_user.c +arch/um/sys-i386/sigcontext.c +arch/um/sys-i386/syscalls.c +arch/um/sys-i386/sysrq.c +arch/um/sys-i386/util/Makefile +arch/um/sys-i386/util/mk_sc.c +arch/um/sys-i386/util/mk_thread_kern.c +arch/um/sys-i386/util/mk_thread_user.c +arch/um/sys-ia64/Makefile +arch/um/sys-ppc/Makefile +arch/um/sys-ppc/misc.S +arch/um/sys-ppc/miscthings.c +arch/um/sys-ppc/ptrace.c +arch/um/sys-ppc/ptrace_user.c +arch/um/sys-ppc/sigcontext.c +arch/um/sys-ppc/sysrq.c +arch/um/util/Makefile +arch/um/util/mk_constants_kern.c +arch/um/util/mk_constants_user.c +arch/um/util/mk_task_kern.c +arch/um/util/mk_task_user.c +drivers/char/Makefile +drivers/char/tty_io.c +drivers/net/setup.c +include/asm-i386/hardirq.h +include/asm-um/a.out.h +include/asm-um/arch-signal-i386.h +include/asm-um/archparam-i386.h +include/asm-um/archparam-ppc.h +include/asm-um/atomic.h +include/asm-um/bitops.h +include/asm-um/boot.h +include/asm-um/bugs.h +include/asm-um/byteorder.h +include/asm-um/cache.h +include/asm-um/checksum.h +include/asm-um/cobalt.h +include/asm-um/current.h +include/asm-um/delay.h +include/asm-um/desc.h +include/asm-um/div64.h +include/asm-um/dma.h +include/asm-um/elf.h +include/asm-um/errno.h +include/asm-um/fcntl.h +include/asm-um/fixmap.h +include/asm-um/floppy.h +include/asm-um/hardirq.h +include/asm-um/hdreg.h +include/asm-um/highmem.h +include/asm-um/hw_irq.h +include/asm-um/ide.h +include/asm-um/init.h +include/asm-um/io.h +include/asm-um/ioctl.h +include/asm-um/ioctls.h +include/asm-um/ipc.h +include/asm-um/ipcbuf.h +include/asm-um/irq.h +include/asm-um/keyboard.h +include/asm-um/kmap_types.h +include/asm-um/linux_logo.h +include/asm-um/locks.h +include/asm-um/mca_dma.h +include/asm-um/mman.h +include/asm-um/mmu.h +include/asm-um/mmu_context.h +include/asm-um/module.h +include/asm-um/msgbuf.h +include/asm-um/mtrr.h +include/asm-um/namei.h +include/asm-um/page.h +include/asm-um/page_offset.h +include/asm-um/param.h +include/asm-um/pci.h +include/asm-um/pgalloc.h +include/asm-um/pgtable.h +include/asm-um/poll.h +include/asm-um/posix_types.h +include/asm-um/processor-generic.h +include/asm-um/processor-i386.h +include/asm-um/processor-ppc.h +include/asm-um/ptrace-generic.h +include/asm-um/ptrace-i386.h +include/asm-um/resource.h +include/asm-um/rwlock.h +include/asm-um/rwsem.h +include/asm-um/scatterlist.h +include/asm-um/segment.h +include/asm-um/semaphore.h +include/asm-um/sembuf.h +include/asm-um/serial.h +include/asm-um/shmbuf.h +include/asm-um/shmparam.h +include/asm-um/sigcontext-generic.h +include/asm-um/sigcontext-i386.h +include/asm-um/sigcontext-ppc.h +include/asm-um/siginfo.h +include/asm-um/signal.h +include/asm-um/smp.h +include/asm-um/smplock.h +include/asm-um/socket.h +include/asm-um/sockios.h +include/asm-um/softirq.h +include/asm-um/spinlock.h +include/asm-um/stat.h +include/asm-um/statfs.h +include/asm-um/string.h +include/asm-um/system-generic.h +include/asm-um/system-i386.h +include/asm-um/system-ppc.h +include/asm-um/termbits.h +include/asm-um/termios.h +include/asm-um/timex.h +include/asm-um/tlb.h +include/asm-um/types.h +include/asm-um/uaccess.h +include/asm-um/ucontext.h +include/asm-um/unaligned.h +include/asm-um/unistd.h +include/asm-um/user.h +include/asm-um/vga.h +include/asm-um/xor.h +include/linux/blk.h +include/linux/fs.h +include/linux/hostfs_fs_i.h +include/linux/hppfs_fs_i.h +include/linux/kernel.h +include/linux/kernel_stat.h +include/linux/mm.h +include/linux/proc_mm.h +include/linux/tty.h +init/do_mounts.c +kernel/panic.c +mm/Makefile +mm/mmap.c +mm/mprotect.c +mm/proc_mm.c +mm/slab.c diff --git a/lustre/tests/fchdir_test.c b/lustre/tests/fchdir_test.c new file mode 100644 index 0000000..83c096e --- /dev/null +++ b/lustre/tests/fchdir_test.c @@ -0,0 +1,41 @@ +#include +#include +#include +#include +#include +#include +#include +#include + + +int main(int argc, char **argv) +{ + int fd; + int rc; + + fd = open(".", O_RDONLY); + if (fd < 0) { + perror("opening '.' :"); + exit(2); + } + + rc = chdir("/mnt/lustre/subdir/subdir"); + if (rc) { + perror("cannot chdir subdir:"); + exit(3); + } + + rc = fchdir(fd); + if (rc) { + perror("cannot fchdir back\n"); + exit(4); + } + + rc = close(fd); + if (rc) { + perror("cannot close '.'\n"); + exit(5); + } + + return(0); +} -- 1.8.3.1